cubical-transport-hott-lean4/CubicalTransport/Transport.lean
Maximus Gorog 31d19f655e
Some checks are pending
Lean Action CI / build (push) Waiting to run
Split: engine = cubical-transport HoTT only
Restructure to engine-only contents.  Application code (Topolei.*
namespace, canvas-rs / render Rust crates, Main / ProbeTest, naga IR
pipeline, Selection / Subobject / Trace / Obs.Ctx hypothesis stack,
cells-spec / HYPOTHESES / STATUS / NAGA_IR_PLAN docs) moves to the
sibling repo max/topolei.

What moved:
- `Topolei/Cubical/*.lean` (22 files) → `CubicalTransport/*.lean`
  with namespace `Topolei.Cubical.*` renamed to `CubicalTransport.*`.
  Fully-qualified test types `TopoleiCubical{FFI,Property}Test` →
  `CubicalTransport{FFI,Property}Test` for consistency.
- New root file `CubicalTransport.lean` re-exporting all 22 modules.
- Lakefile: package `cubicalTransport`; lib `CubicalTransport`; only
  `cubical-test` and `cubical-bench` exes (no GPU link path).

The split criterion: anything an AI shortcut could break that would
cascade-corrupt downstream proofs lives here.  Anything that would
only break the application stays in the topolei interface repo.

cubical-test passes 62/62 (smoke + properties) on the renamed engine.

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

153 lines
6.8 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.

/-
Topolei.Cubical.Transport
=========================
Value-level transport (cells-spec §5.5, Phase 1 Weeks 34).
`vTransp i A φ v` reduces `transp^i A φ v` at the value level.
Reducing cases (in match order, highest priority first):
1. **φ = .top** — full face — return `v` unchanged.
Evaluator-level analogue of axiom `transp_id` (T1).
2. **`CType.dimAbsent i A = true`** — line is constant — return `v`
unchanged. Evaluator-level analogue of `transp_const_id` (T2).
Covers `univ`, fully-constant `pi`, fully-constant `path`.
3. **`A = pi domA codA`** — produce a `vTranspFun i domA codA φ v`
closure. This is the **full CCHM Π rule** — when the closure is
later applied to an argument, `vApp` inversely transports the
argument through `domA` and forward-transports the result through
`codA`. Both constant-domain and varying-domain lines are handled
by the same constructor; `vTranspInv` degenerates to identity in
the constant-domain case via `CType.substDimExpr_of_absent` + T2,
so no special-case logic is needed at this level.
4. **Otherwise** — stuck. Produce `vneu (.ntransp i A φ v)`.
Deferred to later passes:
· Σ case — `CType` has no Σ yet.
· Path case — Week 4, alongside homogeneous composition.
vTransp is a `partial def` for the same reason as `eval`. Its reduction
equations are stated as axioms below. `vTranspInv` is a *total `def`*
because it is a thin wrapper that delegates to `vTransp` after line
reversal.
-/
import CubicalTransport.Value
import CubicalTransport.DimLine -- for CType.dimAbsent and substDimExpr
-- ── Rust FFI declaration (Phase C.2) ──────────────────────────────────────
@[extern "topolei_cubical_vtransp"]
opaque vTranspRust (i : DimVar) (A : CType) (φ : FaceFormula) (v : CVal) : CVal
/-- Value-level transport. Dispatches in priority order; see file header. -/
@[implemented_by vTranspRust]
partial def vTransp (i : DimVar) (A : CType) (φ : FaceFormula) (v : CVal) :
CVal :=
match φ with
| .top => v -- (1) T1 at eval level.
| _ =>
if CType.dimAbsent i A then
v -- (2) T2 at eval level.
else
match A with
| .pi domA codA =>
-- (3) Full CCHM Π rule — no specialisation here. The behaviour
-- at constant-domain vs. varying-domain is absorbed into the
-- later reduction of `vApp` on `vTranspFun`, which calls
-- `vTranspInv` on `domA` (identity when `domA` is constant).
.vTranspFun i domA codA φ v
| _ =>
-- (4) non-pi stuck (e.g. path with varying endpoints).
.vneu (.ntransp i A φ v)
/-- **Inverse transport** along the line `(i, A)`: transport `v : A(1)` back
to `A(0)`. Implemented as forward transport along the *reversed* line
`A[i := inv i]`.
Line reversal properties at the endpoints:
`A[i := inv i] at 0` = `A at (inv 0)` = `A at 1`
`A[i := inv i] at 1` = `A at (inv 1)` = `A at 0`
So forward transport along the reversed line takes `A(1) ↦ A(0)`,
which is exactly the inverse of forward transport along `A`. -/
def vTranspInv (i : DimVar) (A : CType) (φ : FaceFormula) (v : CVal) : CVal :=
vTransp i (A.substDimExpr i (.inv (.var i))) φ v
/-!
## Reduction axioms and theorems
One axiom per reducing match arm of `vTransp`. The arms are disjoint
(ordered pattern match), so the axiom set is consistent.
-/
/-- (1) Reduction under a full face: transport is identity. -/
axiom vTransp_top (i : DimVar) (A : CType) (v : CVal) :
vTransp i A .top v = v
/-- (2) Reduction under a constant line. -/
axiom vTransp_const (i : DimVar) (A : CType) (φ : FaceFormula) (v : CVal)
(h : CType.dimAbsent i A = true) :
vTransp i A φ v = v
/-- (3) Π case (full CCHM rule): produces a transported-function closure
that stores both domain and codomain. Preconditions:
· `φ ≠ .top` — else (1) fires,
· `CType.dimAbsent i (.pi domA codA) = false` — else (2) fires.
When `dimAbsent i domA = true`, the inverse transport inside the
later `vApp` reduction degenerates to identity by `vTranspInv_const`
below, recovering the const-domain specialisation. -/
axiom vTransp_pi
(i : DimVar) (domA codA : CType) (φ : FaceFormula) (v : CVal)
(hφ : φ ≠ .top)
(hA : CType.dimAbsent i (.pi domA codA) = false) :
vTransp i (.pi domA codA) φ v = .vTranspFun i domA codA φ v
/-- (4) Stuck: not face-top, not constant, and not a `.pi`. The third
precondition rules out arm (3). -/
axiom vTransp_stuck (i : DimVar) (A : CType) (φ : FaceFormula) (v : CVal)
(hφ : φ ≠ .top)
(hA : CType.dimAbsent i A = false)
(h_not_pi : ∀ domA codA, A ≠ .pi domA codA) :
vTransp i A φ v = .vneu (.ntransp i A φ v)
-- ── vTranspInv on constant domain ────────────────────────────────────────────
/-- Inverse transport along a line whose body is absent from `i` is the
identity. Proof: the reversed line `A[i := inv i] = A` when `i ∉ A`
(by `CType.substDimExpr_of_absent`), so the outer `vTransp` call has a
constant line and reduces via T2 to `v`. This lemma is what makes the
unified `vTranspFun` constructor degenerate correctly when the domain
is constant. -/
theorem vTranspInv_const (i : DimVar) (A : CType) (φ : FaceFormula) (v : CVal)
(h : CType.dimAbsent i A = true) :
vTranspInv i A φ v = v := by
-- `vTranspInv` unfolds to `vTransp i (A[i := inv i]) φ v`.
unfold vTranspInv
-- Line reversal is a no-op on constant-in-`i` types.
rw [CType.substDimExpr_of_absent i _ A h]
-- T2 on the (unchanged) constant line.
exact vTransp_const i A φ v h
/-- Inverse transport under a full face is identity — direct consequence of
T1 composed with reversal. -/
theorem vTranspInv_top (i : DimVar) (A : CType) (v : CVal) :
vTranspInv i A .top v = v := by
unfold vTranspInv
exact vTransp_top i _ v
-- ── Convenience wrappers ──────────────────────────────────────────────────────
/-- Transport along a `DimLine` with an already-evaluated argument. Unpacks
the line's binder and body and dispatches through `vTransp`. -/
def vTranspLine (L : DimLine) (φ : FaceFormula) (v : CVal) : CVal :=
vTransp L.binder L.body φ v
@[simp] theorem vTranspLine_top (L : DimLine) (v : CVal) :
vTranspLine L .top v = v := by
simp [vTranspLine, vTransp_top]
theorem vTranspLine_const (L : DimLine) (φ : FaceFormula) (v : CVal)
(h : CType.dimAbsent L.binder L.body = true) :
vTranspLine L φ v = v := by
simp [vTranspLine, vTransp_const _ _ _ _ h]