Some checks are pending
Lean Action CI / build (push) Waiting to run
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>
315 lines
15 KiB
Text
315 lines
15 KiB
Text
/-
|
||
Topolei.Cubical.Soundness
|
||
=========================
|
||
The Phase 1 Week 6 closeout — soundness theorems that tie transport,
|
||
composition, and glue into a coherent story (cells-spec §14 "Key
|
||
Theorems", Cubical Core section).
|
||
|
||
**What this file does:** restate the critical proof obligations from
|
||
§14 as Lean theorems, prove what is derivable from the existing axiom
|
||
base (T1–T5, C1/C2/C4, the six glueIn/unglue face-disjoint axioms,
|
||
the eval-level axioms), and clearly mark remaining obligations with
|
||
their discharge conditions.
|
||
|
||
**Why this file exists:** to make the "Phase 1 complete" claim
|
||
auditable. Every obligation is either proved or stated as a named
|
||
axiom with a documented discharge path. Future work (Glue transport,
|
||
Phase 2 cells) slots in by *proving* these axioms rather than by
|
||
restructuring the module layout.
|
||
|
||
## Proved theorems (from existing axioms)
|
||
|
||
§3 `transp_refl_eval` — eval-level constant-line transport identity
|
||
(combines `eval_transp_top` and `eval_transp_const`).
|
||
§4 `hcomp_face_top` — C1: composition under full face = tube at 1.
|
||
§5 `ua_endpoints_zero / _one` — univalence line endpoints (re-export).
|
||
§6 `glue_beta_bot` — unglue-of-glue on the empty face is identity.
|
||
§7 `glue_eta_bot` — glue-of-unglue on the empty face is identity.
|
||
|
||
Step-level T1/T2/C1 wrappers (`transp_refl_step`, `transp_refl_const_step`,
|
||
`hcomp_face_top_step`) have been removed — their underlying axioms are
|
||
now NbE theorems in `Readback.lean` (`readback_transp_id`,
|
||
`readback_transp_const_id`, `readback_comp_full`).
|
||
|
||
## Proof obligations (axioms to be discharged later)
|
||
|
||
- `transp_ua` — transport along a `uaLine e A B` at `.bot` computes as
|
||
`e.f`. Needs a Glue transport rule on `CTerm.transp i (.glue …) φ t`
|
||
(the CCHM formula using half-adjoint structure). Currently outside
|
||
scope; stated here so `Soundness.lean` can be pointed at when the
|
||
Glue transport rule lands.
|
||
|
||
- `glue_beta_top`, `glue_eta_top` — full CCHM glue β/η on the `.top`
|
||
face. These hold only up to the equivalence's *coherence* rules
|
||
(`e.f ∘ e.fInv ~ id`, etc.), which are terms in the calculus, not
|
||
rewrite rules. A term-evaluator with conversion modulo β would
|
||
discharge them; our syntactic `eval` cannot.
|
||
|
||
- `cell_*` laws (idL / idR / assoc / inv / interchange) — Phase 2
|
||
cells-layer work; stated briefly below for completeness.
|
||
-/
|
||
|
||
import CubicalTransport.TransportLaws
|
||
import CubicalTransport.CompLaws
|
||
import CubicalTransport.Glue
|
||
|
||
namespace Soundness
|
||
|
||
-- ── §1–2. Transport identity at NbE level ───────────────────────────────────
|
||
-- The step-level T1 (`transp_id`) and T2 (`transp_const_id`) wrappers
|
||
-- formerly here have been removed; their NbE equivalents live in
|
||
-- `Readback.lean` as `readback_transp_id` and `readback_transp_const_id`.
|
||
-- The eval-level identity below (`transp_refl_eval`) is the convenient
|
||
-- downstream surface.
|
||
|
||
-- ── §3. Eval-level constant-line transport ───────────────────────────────────
|
||
|
||
/-- Eval-level constant-line identity. Combines `eval_transp_top` with
|
||
`eval_transp_const` to cover every face. -/
|
||
theorem transp_refl_eval (env : CEnv) (i : DimVar) (A : CType)
|
||
(φ : FaceFormula) (t : CTerm) (hA : CType.dimAbsent i A = true) :
|
||
eval env (.transp i A φ t) = eval env t := by
|
||
by_cases hφ : φ = .top
|
||
· subst hφ; exact eval_transp_top env i A t
|
||
· exact eval_transp_const env i A φ t hφ hA
|
||
|
||
-- ── §4. Composition agrees with the tube on full face (C1) ───────────────────
|
||
|
||
/-- `hcomp_faces` (cells-spec §14): composition under a full face
|
||
reduces to the tube body substituted at the 1-endpoint. This is the
|
||
"composition agrees with tube on constrained face" obligation;
|
||
at `.top` the constraint is total. -/
|
||
theorem hcomp_face_top (env : CEnv) (i : DimVar) (A : CType) (u t : CTerm) :
|
||
eval env (.comp i A .top u t) = eval env (u.substDim i .one) :=
|
||
eval_comp_top env i A u t
|
||
|
||
-- The step-level C1 wrapper (`hcomp_face_top_step`, formerly using
|
||
-- `comp_full`) has been removed alongside the C1 axiom; the NbE form
|
||
-- `readback_comp_full` in `Readback.lean` is now the canonical statement.
|
||
|
||
-- ── §5. Univalence line endpoints ────────────────────────────────────────────
|
||
|
||
/-- `ua_endpoints` (cells-spec §14, half 1): the left endpoint of the
|
||
univalence line is the full-face glue, which computationally behaves
|
||
like `A` via `e`. -/
|
||
theorem ua_endpoints_zero (e : EquivData) (A B : CType) :
|
||
uaLine e A B .zero = e.toGlueType .top A B :=
|
||
uaLine_zero e A B
|
||
|
||
/-- `ua_endpoints` (half 2): the right endpoint is the empty-face glue,
|
||
which computationally is just `B`. -/
|
||
theorem ua_endpoints_one (e : EquivData) (A B : CType) :
|
||
uaLine e A B .one = e.toGlueType .bot A B :=
|
||
uaLine_one e A B
|
||
|
||
/-- The univalence line, evaluated at `r = 0`, has inhabitants that
|
||
behave like `A` (via `e.f`) under `unglue`. Consumers of the left
|
||
endpoint can rely on this without unfolding `uaLine`. -/
|
||
theorem ua_endpoint_zero_unglue (env : CEnv) (f g : CTerm) :
|
||
eval env (.unglue .top f g) = vApp (eval env f) (eval env g) :=
|
||
eval_unglue_top env f g
|
||
|
||
/-- At `r = 1`, `unglue` is the identity — inhabitants behave like `B`. -/
|
||
theorem ua_endpoint_one_unglue (env : CEnv) (f g : CTerm) :
|
||
eval env (.unglue .bot f g) = eval env g :=
|
||
eval_unglue_bot env f g
|
||
|
||
-- ── §6. glue β on the empty face ─────────────────────────────────────────────
|
||
|
||
/-- `glue_beta` (cells-spec §14), restricted to the empty face:
|
||
`unglue [.bot ↦ f] (glueIn [.bot ↦ t] a) = a`.
|
||
|
||
Derivation:
|
||
· `glueIn .bot t a` evaluates to `a` (by `eval_glueIn_bot`).
|
||
· `unglue .bot f a` evaluates to `a` (by `eval_unglue_bot`).
|
||
|
||
Under the `.bot` face the glue type is definitionally `A`, so glue-
|
||
formation and elimination are both identity — the β-rule holds
|
||
*definitionally* on this face. -/
|
||
theorem glue_beta_bot (env : CEnv) (f t a : CTerm) :
|
||
eval env (.unglue .bot f (.glueIn .bot t a)) = eval env a := by
|
||
-- We can't rewrite under the `.glueIn` literal inside `eval` without
|
||
-- unfolding `eval`, so we work via the axiom set directly: the two
|
||
-- operations combine at the value level, not the term level.
|
||
-- But: the outer `.unglue .bot f (.glueIn .bot t a)` evaluates via
|
||
-- `eval_unglue_bot`, which produces `eval env (.glueIn .bot t a)`,
|
||
-- which then reduces via `eval_glueIn_bot` to `eval env a`.
|
||
rw [eval_unglue_bot env f (.glueIn .bot t a),
|
||
eval_glueIn_bot env t a]
|
||
|
||
-- ── §7. glue η on the empty face ─────────────────────────────────────────────
|
||
|
||
/-- `glue_eta` (cells-spec §14), restricted to the empty face:
|
||
`glueIn [.bot ↦ t] (unglue [.bot ↦ f] g) = g`.
|
||
|
||
Derivation:
|
||
· `glueIn .bot t (unglue .bot f g)` evaluates via `eval_glueIn_bot`
|
||
to `eval env (.unglue .bot f g)`.
|
||
· That reduces via `eval_unglue_bot` to `eval env g`.
|
||
|
||
The η rule holds definitionally on `.bot`: glue and unglue are both
|
||
identity there, so their composition is identity. -/
|
||
theorem glue_eta_bot (env : CEnv) (t f g : CTerm) :
|
||
eval env (.glueIn .bot t (.unglue .bot f g)) = eval env g := by
|
||
rw [eval_glueIn_bot env t (.unglue .bot f g),
|
||
eval_unglue_bot env f g]
|
||
|
||
-- ── §8. Outstanding proof obligations ────────────────────────────────────────
|
||
|
||
/-!
|
||
### Proof obligations awaiting later work
|
||
|
||
The remaining theorems from cells-spec §14 cannot be discharged from the
|
||
current axiom base. Each is stated here as an **axiom** with a
|
||
documented discharge path; later modules will prove them by providing
|
||
the missing rule and rewriting the axiom statement as a theorem.
|
||
|
||
-/
|
||
|
||
/-- `transp_ua` (cells-spec §14, Critical): transport along the univalence
|
||
line at the empty face computes as the forward map of the equivalence.
|
||
|
||
**Now discharged as a theorem.** Proof chain:
|
||
1. Unfold `uaLine e A B (.var i)` to
|
||
`.glue (.eq0 i) A e.f e.fInv e.sec e.ret e.coh B`.
|
||
2. Observe `(.eq0 i).substDim i .one = dimExprEq0 .one = .bot`, so the
|
||
restricted-form Glue-transport axiom applies.
|
||
3. Apply `eval_transp_glue_const_at_bot` to reduce the transport to
|
||
`.transp i B .bot (.unglue ((.eq0 i).substDim i .zero) e.f t)`.
|
||
4. Observe `(.eq0 i).substDim i .zero = dimExprEq0 .zero = .top`, so
|
||
the inner unglue is `unglue .top e.f t`.
|
||
5. `B` is dim-absent from `i` (hypothesis), so the outer transport
|
||
reduces to the identity via T2 (`eval_transp_const`).
|
||
6. `unglue .top e.f t` evaluates to `vApp (eval e.f) (eval t)` via
|
||
`eval_unglue_top`.
|
||
|
||
The dim-absence hypotheses formalise the well-scopedness assumption
|
||
that `e`, `A`, `B` are supplied from outside the transport binder. -/
|
||
theorem transp_ua (env : CEnv) (i : DimVar) (e : EquivData) (A B : CType)
|
||
(t : CTerm)
|
||
(hA : A.dimAbsent i = true)
|
||
(hB : B.dimAbsent i = true)
|
||
(hf : e.f.dimAbsent i = true)
|
||
(hfInv : e.fInv.dimAbsent i = true)
|
||
(hsec : e.sec.dimAbsent i = true)
|
||
(hret : e.ret.dimAbsent i = true)
|
||
(hcoh : e.coh.dimAbsent i = true) :
|
||
eval env (.transp i (uaLine e A B (.var i)) .bot t) =
|
||
vApp (eval env e.f) (eval env t) := by
|
||
-- Step 1: unfold `uaLine` / `toGlueType` / `dimExprEq0 (.var i)` — all rfl.
|
||
show eval env (.transp i
|
||
(.glue (FaceFormula.eq0 i) A e.f e.fInv e.sec e.ret e.coh B) .bot t) = _
|
||
-- Step 2: compute the substDim facts about the inner face.
|
||
have hφ1 : (FaceFormula.eq0 i).substDim i .one = .bot := by
|
||
show (if i = i then FaceFormula.dimExprEq0 DimExpr.one else FaceFormula.eq0 i) = .bot
|
||
simp [FaceFormula.dimExprEq0]
|
||
have hφ0 : (FaceFormula.eq0 i).substDim i .zero = .top := by
|
||
show (if i = i then FaceFormula.dimExprEq0 DimExpr.zero else FaceFormula.eq0 i) = .top
|
||
simp [FaceFormula.dimExprEq0]
|
||
-- Step 3: apply the restricted-form Glue-transport axiom.
|
||
rw [eval_transp_glue_const_at_bot env i (FaceFormula.eq0 i) A
|
||
e.f e.fInv e.sec e.ret e.coh B .bot t
|
||
(by intro h; nomatch h)
|
||
hA hB hf hfInv hsec hret hcoh hφ1]
|
||
-- Step 4: simplify the inner face at `i = 0` to `.top`.
|
||
rw [hφ0]
|
||
-- Step 5: T2 on the constant `B` line, at `.bot ≠ .top`.
|
||
rw [eval_transp_const env i B .bot _ (by intro h; nomatch h) hB]
|
||
-- Step 6: `unglue .top` is forward-map application.
|
||
exact eval_unglue_top env e.f t
|
||
|
||
/-- `transp_ua_inverse` (companion to `transp_ua`): transport along the
|
||
"reversed" univalence line at the empty face computes as the inverse
|
||
map of the equivalence.
|
||
|
||
Construction: `uaLine e A B (.inv (.var i))` carries the inner glue
|
||
face `dimExprEq0 (.inv (.var i)) = dimExprEq1 (.var i) = .eq1 i`
|
||
(rather than `.eq0 i` for the forward `(.var i)` direction). At
|
||
`i := 1` this collapses to `.top`, triggering
|
||
`eval_transp_glue_const_at_top` and producing the T-side witness via
|
||
`e.fInv`. At `i := 0` the inner face is `.bot`, so the inner
|
||
`unglue` is identity; `B` is constant in `i`, so the outer transport
|
||
is identity (T2); the result is `e.fInv` applied to the input.
|
||
|
||
Together with `transp_ua`, this exhibits the two principal directions
|
||
of the equivalence as the computational content of Glue transport at
|
||
the constant-component sub-cases. -/
|
||
theorem transp_ua_inverse (env : CEnv) (i : DimVar) (e : EquivData) (A B : CType)
|
||
(t : CTerm)
|
||
(hA : A.dimAbsent i = true)
|
||
(hB : B.dimAbsent i = true)
|
||
(hf : e.f.dimAbsent i = true)
|
||
(hfInv : e.fInv.dimAbsent i = true)
|
||
(hsec : e.sec.dimAbsent i = true)
|
||
(hret : e.ret.dimAbsent i = true)
|
||
(hcoh : e.coh.dimAbsent i = true) :
|
||
eval env (.transp i (uaLine e A B (.inv (.var i))) .bot t) =
|
||
vApp (eval env e.fInv) (eval env t) := by
|
||
-- Step 1: unfold `uaLine` / `toGlueType` / `dimExprEq0 (.inv (.var i))`.
|
||
-- `dimExprEq0 (.inv r) = dimExprEq1 r` and `dimExprEq1 (.var i) = .eq1 i`,
|
||
-- both by rfl on the case-splits in `Face.lean`.
|
||
show eval env (.transp i
|
||
(.glue (FaceFormula.eq1 i) A e.f e.fInv e.sec e.ret e.coh B) .bot t) = _
|
||
-- Step 2: compute the substDim facts about the inner face.
|
||
have hφ1 : (FaceFormula.eq1 i).substDim i .one = .top := by
|
||
show (if i = i then FaceFormula.dimExprEq1 DimExpr.one else FaceFormula.eq1 i) = .top
|
||
simp [FaceFormula.dimExprEq1]
|
||
have hφ0 : (FaceFormula.eq1 i).substDim i .zero = .bot := by
|
||
show (if i = i then FaceFormula.dimExprEq1 DimExpr.zero else FaceFormula.eq1 i) = .bot
|
||
simp [FaceFormula.dimExprEq1]
|
||
-- Step 3: apply the `_at_top` axiom.
|
||
rw [eval_transp_glue_const_at_top env i (FaceFormula.eq1 i) A
|
||
e.f e.fInv e.sec e.ret e.coh B .bot t
|
||
(by intro h; nomatch h)
|
||
hA hB hf hfInv hsec hret hcoh hφ1]
|
||
-- Step 4: simplify the inner face at `i = 0` to `.bot`.
|
||
rw [hφ0]
|
||
-- Step 5: peel the outer `.app` so we can rewrite under it.
|
||
rw [eval_app env e.fInv
|
||
(.transp i B .bot (.unglue .bot e.f t))]
|
||
-- Step 6: T2 on the constant `B` line.
|
||
rw [eval_transp_const env i B .bot _ (by intro h; nomatch h) hB]
|
||
-- Step 7: `unglue .bot` is identity.
|
||
rw [eval_unglue_bot env e.f t]
|
||
|
||
/-- `glue_beta` (cells-spec §14, full statement): on any face, `unglue` of
|
||
`glueIn` returns the A-side, provided the equivalence's overlap
|
||
condition `e.f t = a` holds (implicit in glueIn's well-typedness).
|
||
|
||
**Discharged via `eval_unglue_of_glueIn`** (Eval.lean, Stage 1.3,
|
||
2026-04-23). The eval-level β-rule recognises the redex shape
|
||
and short-circuits under the `h_overlap` hypothesis. This is no
|
||
longer an axiom at the Soundness layer — the axiom provenance is
|
||
now a single eval-level Rust-discharge rule. -/
|
||
theorem glue_beta (env : CEnv) (φ : FaceFormula) (f t a : CTerm)
|
||
(h_overlap :
|
||
eval env (.app f t) = eval env a) :
|
||
eval env (.unglue φ f (.glueIn φ t a)) = eval env a :=
|
||
eval_unglue_of_glueIn env φ f t a h_overlap
|
||
|
||
/-- `glue_eta` (cells-spec §14, full statement): on any face, `glueIn`
|
||
of `unglue` returns the original term, under the overlap condition
|
||
`t = e.f g`.
|
||
|
||
**Discharged via `eval_glueIn_of_unglue`** (Eval.lean, Stage 1.3,
|
||
2026-04-23). Dual to `glue_beta`; same discipline. -/
|
||
theorem glue_eta (env : CEnv) (φ : FaceFormula) (f t g : CTerm)
|
||
(h_overlap :
|
||
eval env t = eval env (.app f g)) :
|
||
eval env (.glueIn φ t (.unglue φ f g)) = eval env g :=
|
||
eval_glueIn_of_unglue env φ f t g h_overlap
|
||
|
||
/-!
|
||
### Phase 2 cells-layer laws (deferred)
|
||
|
||
The cell-layer laws (`cell_left_unit`, `cell_right_unit`, `cell_assoc`,
|
||
`cell_inv_left`, `par_seq_interchange`) are Phase 2 material — they
|
||
require a `Cell` structure with composition operations, which we haven't
|
||
built. The cells-spec §14 Cell Layer rows are therefore neither proved
|
||
nor stated as axioms in this module; they will arise as theorems (not
|
||
axioms) in `Cell/Basic.lean` and `Cell/Compose.lean` once those exist,
|
||
with the cell structure itself being defined in terms of the cubical
|
||
primitives proved here.
|
||
-/
|
||
|
||
end Soundness
|