cubical-transport-hott-lean4/Topolei/EML.lean
Maximus Gorog c2e3ecb3e3
Some checks are pending
Lean Action CI / build (push) Waiting to run
Initial commit: topolei — cubical-transport HoTT in Lean 4 + Rust FFI
Implements the cells-spec vision: a computation space that preserves
auditability, correctness, interactivity. Phase 1 (Lean kernel +
naga-IR Rust backend) is closed; foundation hypothesis stack
(Selection H1+H2, Subobject H3, Trace H5, Obs.Ctx C2, Cubical.Trace)
landed.

Highlights:
- Cubical-HoTT syntax + value/eval/readback in Lean
- naga-IR pipeline (no GLSL string crosses FFI; 17/17 probes pass)
- Honesty audit: every non-transport (sealed cells, vertex shader,
  Y-flip, presentation conventions) is documented as such
- Polymorphic Trace α as free monoid; Cubical.Trace gives
  CTerm → Trace CTerm by structural fold (homomorphism = definition)
- Selection as Huet zipper; Subobject as Boolean algebra over WCell
- All theorems proven; the proof IS the implementation

See STATUS.md for the resume guide.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 20:40:45 -06:00

90 lines
4.1 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- EML tree: S → 1 | eml(S, S)
-- eml(x, y) = exp(x) ln(y)
--
-- Single binary primitive that generates all elementary functions.
-- (Odrzywolek 2026, arXiv:2603.21852)
-- ── Core inductive ────────────────────────────────────────────────────────────
inductive EMLExpr where
| one : EMLExpr
| var (name : String) : EMLExpr -- free variable resolved in the rendering env
| eml (l r : EMLExpr) : EMLExpr
-- ── Derived forms ─────────────────────────────────────────────────────────────
-- exp(x) = eml(x, 1) since exp(x) ln(1) = exp(x) 0 = exp(x)
def EMLExpr.expOf (x : EMLExpr) : EMLExpr := .eml x .one
-- ln(x) = eml(1, eml(eml(1, x), 1))
def EMLExpr.lnOf (x : EMLExpr) : EMLExpr :=
.eml .one (.eml (.eml .one x) .one)
-- ── Plot configuration ────────────────────────────────────────────────────────
/-- A path config: an EML expression plus its distinguished path-dimension
variable. `dimName` is the name that ranges over `{0, 1}` when the
config is interpreted as an `EMLPath` (see `EML/Path.lean`'s
`PlotConfig.toEMLPath`). When `dimName` does not occur in `expr`,
the path is *constant* (its value is the same at both endpoints);
when it does, the path is genuinely parametric. -/
structure PlotConfig where
expr : EMLExpr
dimName : String := "t"
-- ── Named demo expressions (probe test fixtures) ─────────────────────────────
-- exp(x): depth-1 EML tree, one node.
def plotExp : PlotConfig := {
expr := EMLExpr.expOf (.var "px")
}
-- ln(x): depth-3 EML tree, three nodes.
--
-- Historical note: an earlier `plotLn` used the variable name
-- `"max(px, 0.001)"` to clamp negative inputs on the GPU side. That
-- made the GPU shader evaluate `max(px, 0.001)` as a GLSL expression
-- but left Lean's `shaderVar` hitting the fallback `0.0` — the two
-- sides disagreed on the semantic of the variable. The probe test
-- surfaced the divergence; the fix is to use a real variable `px`
-- and accept that `ln` of negative `px` produces `NaN` on both sides
-- (the two sides agree, which is what `render_faithful` cares about).
def plotLn : PlotConfig := {
expr := EMLExpr.lnOf (.var "px")
}
-- ── Continuous-homotopy demo: a genuinely parametric path ────────────────────
-- `exp(px) t` translates the exponential curve down by `t`. At `t=0`
-- the curve is `y = exp(x)`; at `t=1` it's `y = exp(x) 1`; in between it
-- smoothly slides. EML-expressible because `exp(px) - log(exp(t))` reduces
-- (via `log ∘ exp = id`) to `exp(px) - t`; body is
-- `eml(var "px", eml(var "t", one))`.
def plotTransp : PlotConfig := {
expr := .eml (.var "px") (.eml (.var "t") .one)
dimName := "t"
}
-- ── Clean fibers in [0, 1] for greyscale demos ──────────────────────────────
-- These bodies are picked specifically so their image lies in `[0, 1]`,
-- matching the framebuffer's natural display range. Each is a 1-cell;
-- their shape under different `pathParam` values shows the transport
-- in action with no clamping artifacts.
/-- The 1-cell whose body IS the dim variable: at `pathParam = c` every
pixel evaluates to `c`. Different fibers display as solid-color
panels with brightness equal to the fiber's parameter.
`at0 = solid black`, `at1 = solid white`, `mid = solid 50% grey`. -/
def plotT : PlotConfig := {
expr := .var "t"
dimName := "t"
}
/-- The 1-cell whose body is `px`: image is the horizontal coordinate
itself, a black-to-white left-to-right gradient. Constant
1-cell (no `t` dependence) — every fiber is the same gradient.
Useful as a sanity check: fibers should NOT differ. -/
def plotPx : PlotConfig := {
expr := .var "px"
dimName := "t"
}