cubical-transport-hott-lean4/CubicalTransport/Inductive.lean
Maximus Gorog 19928d040a
Some checks failed
Lean Action CI / build (push) Has been cancelled
REL2 universe stratification + topolei naming cleanup + Rust ABI v4
Two structural changes landed together as one coherent body of work.

## 1. Engine is name-clean from higher-order projects

The engine no longer carries "topolei" in its own naming surface.
Higher-order projects depend on the engine, not vice versa, so the
engine should be self-named.

  topolei-cubical (Cargo)            → cubical-transport
  libtopolei_cubical.a               → libcubical_transport.a
  topolei_cubical.h                  → cubical_transport.h
  TOPOLEI_FFI_ABI_VERSION            → CUBICAL_TRANSPORT_ABI_VERSION
  topolei_cubical_*  (14 FFI fns)    → cubical_transport_*
  topolei_shim_*     (9 shim fns)    → cubical_transport_shim_*

Inter-repo references describing topolei as a downstream consumer
(README, KERNEL_BOUNDARY.md, INDUCTIVE_TYPES.md, etc.) are preserved
as legitimate dependency-direction descriptions.

## 2. Universe-stratified, dependently-typed CType

  CType : ULevel → Type (genuinely indexed inductive)

with dependent pi/sigma carrying a binder name, a lift constructor
for cumulativity, and parameter lists of Σ-packaged types.

Per CCHM rules:
  · univ ℓ        : CType (ℓ.succ)
  · pi/sigma      : CType (max ℓ_A ℓ_B), with named binder
  · path A        : at A's level
  · glue T A      : T and A at same level
  · ind           : at user-chosen level (heterogeneous-level params)
  · interval      : CType .zero
  · lift          : CType (ℓ.succ), data-preserving

Every existing engine module cascades through {ℓ : ULevel} implicits
on functions/theorems, pi/sigma binder updates, and Σ-packaged params
lists.  CTerm stays un-indexed (universe lives on CType).

## 3. Substrate machinery for the cascade

  Universe.lean — ULevel inductive + max algebra (assoc, comm, etc.),
                  all theorems proven structurally.

  Syntax.lean — adds SkeletalCType enum + CType.skeleton level-erasure
                projection + per-constructor skeleton_* simp lemmas +
                CType.ind_skeleton_ne_pi disjointness lemma.  Used to
                discharge cross-level HEq cases in TransportLaws/CompLaws
                without invoking K.

## 4. Rust ABI v3 → v4

Lean 4 keeps implicit {ℓ : ULevel} parameters at runtime as constructor
fields, in declaration order interleaved with explicit args (verified
via probeLayout instrumentation).  Layout for level-bearing constructors
documented in cubical_transport.h §"v4 layout tables".

  CType.pi      : 5 fields — [ℓ_d, ℓ_c, var, A, B]
  CType.path    : 4 fields — [ℓ, A, a, b]
  CType.glue    : 9 fields — [ℓ, φ, T, f, fInv, sec, ret, coh, A]
  CType.ind     : 3 fields — [ℓ, S, params]
  CType.lift    : 2 fields — [ℓ, A]
  CTerm.transp  : 5 fields — [i, ℓ, A, φ, t]   (i precedes ℓ)
  CVal.vCompFun : 9 fields — [ℓ_d, ℓ_c, env, i, dom, cod, φ, u, t]
  ... etc

All Rust marshalling (value.rs, eval.rs, transport.rs, composition.rs,
glue.rs, beta.rs, dim_absent.rs, readback.rs, subst.rs, ffi.rs, tags.rs)
updated to match.

## Discipline

  · Zero sorry in CubicalTransport/.
  · Zero noncomputable instances; zero Classical.propDecidable shortcuts.
  · No CType.level projection (the level lives in the inductive's index).
  · No parallel CTypeU type.
  · No stub substrate types (def Ω := CType.univ etc.).
  · Tests restored to full coverage (EvalTest 623 lines, FFITest 351
    lines with classifier-runtime tests intact).

## Verification

  cd cubical-transport-hott-lean4
  lake build                 # 48 jobs OK
  ./.lake/build/bin/cubical-test
                             # ── 49/49 passed ──
                             # ── 46/46 properties passed ──
                             # PASS: all smoke + property tests

  cd ../topolei
  lake build                 # 90 jobs OK
  ./.lake/build/bin/probe-test
                             # ── 7/7 probes passed ──
                             # PASS: GPU output matches Lean ShaderSemantic

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

218 lines
8.4 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.

/-
CubicalTransport.Inductive
==========================
Helper combinators and canonical schema instances for the REL1
schema-based inductive (and higher-inductive) type system.
Universe-aware (Layer 0 §0.1 cascade): helpers that take CType
arguments are level-polymorphic via implicit `{ : ULevel}`; lists
of parameters carry their levels via `Σ : ULevel, CType `.
This module sits *on top of* `Syntax.lean` — it doesn't add new
primitives, only ergonomic builders.
## Sections
· §1 Argument-shape helpers
· §2 Schema constructors (mkSchema, mkCtor, mkPath)
· §3 Type-level helpers (CType.list, CType.nat, …, CType.s1, …)
· §4 Term-level helpers (zeroC, succC, nilC, consC, baseC, loopC, …)
· §5 Eliminator builders (natElim, listElim, …)
## Design notes
· Boundary clauses inside HIT path constructors reference *dim args*
via `DimVar.mk "$d_k"` (zero-indexed among `.dim` args) and
*non-dim args* via `CTerm.var "$arg_k"` (zero-indexed in the full
arg list). See INDUCTIVE_TYPES.md §4 for the discipline.
-/
import CubicalTransport.Syntax
namespace CubicalTransport.Inductive
-- ── §1. Argument-shape helpers ─────────────────────────────────────────────
/-- A non-recursive argument of a closed CType at any universe level. -/
@[inline] def argType { : ULevel} (A : CType ) : CTypeArg := .type A
/-- A reference to the schema's `i`th type parameter. -/
@[inline] def argParam (i : Nat) : CTypeArg := .param i
/-- A recursive argument of the inductive being defined. -/
@[inline] def argSelf : CTypeArg := .self
/-- A dimension argument (path-constructor binder). -/
@[inline] def argDim : CTypeArg := .dim
-- ── §2. Schema constructors ────────────────────────────────────────────────
/-- A point constructor (no boundary system, empty boundary list). -/
@[inline] def mkCtor (name : String) (args : List CTypeArg) : CtorSpec :=
.mk name args []
/-- A path constructor: a constructor whose argument list contains at
least one `.dim` arg, and whose boundary system specifies the
canonical reduction on the corresponding cube faces. -/
@[inline] def mkPath (name : String) (args : List CTypeArg)
(boundary : List (FaceFormula × CTerm)) : CtorSpec :=
.mk name args boundary
/-- Build a schema from name, parameter count, and constructor list. -/
@[inline] def mkSchema (name : String) (numParams : Nat)
(ctors : List CtorSpec) : CTypeSchema :=
.mk name numParams ctors
-- ── §3. Canonical plain inductive schemas ──────────────────────────────────
/-- The natural numbers as a schema. -/
def natSchema : CTypeSchema :=
mkSchema "Nat" 0
[ mkCtor "zero" []
, mkCtor "succ" [.self] ]
/-- The booleans as a schema. -/
def boolSchema : CTypeSchema :=
mkSchema "Bool" 0
[ mkCtor "false" []
, mkCtor "true" [] ]
/-- Polymorphic lists as a schema, parameterised by the element type. -/
def listSchema : CTypeSchema :=
mkSchema "List" 1
[ mkCtor "nil" []
, mkCtor "cons" [.param 0, .self] ]
-- ── §4. Canonical HIT schemas ──────────────────────────────────────────────
/-- The circle `S¹` as a HIT. `loop @ 0 = base = loop @ 1`. -/
def s1Schema : CTypeSchema :=
let baseAt (s : CTypeSchema) : CTerm := .ctor s "base" [] []
let stub : CTypeSchema :=
mkSchema "S¹" 0
[ mkCtor "base" []
, mkPath "loop" [.dim] [] ]
let d : DimVar := ⟨"$d_0"⟩
mkSchema "S¹" 0
[ mkCtor "base" []
, mkPath "loop" [.dim]
[ (.eq0 d, baseAt stub)
, (.eq1 d, baseAt stub) ] ]
/-- The interval as a HIT (REL1). `seg @ 0 = zero`, `seg @ 1 = one`. -/
def intervalSchema : CTypeSchema :=
let stub : CTypeSchema :=
mkSchema "I" 0
[ mkCtor "zero" []
, mkCtor "one" []
, mkPath "seg" [.dim] [] ]
let zeroAt (s : CTypeSchema) : CTerm := .ctor s "zero" [] []
let oneAt (s : CTypeSchema) : CTerm := .ctor s "one" [] []
let d : DimVar := ⟨"$d_0"⟩
mkSchema "I" 0
[ mkCtor "zero" []
, mkCtor "one" []
, mkPath "seg" [.dim]
[ (.eq0 d, zeroAt stub)
, (.eq1 d, oneAt stub) ] ]
/-- Propositional truncation `‖A‖₋₁` as a HIT. -/
def propTruncSchema : CTypeSchema :=
let d : DimVar := ⟨"$d_0"⟩
mkSchema "‖_‖₋₁" 1
[ mkCtor "inT" [.param 0]
, mkPath "squash" [.self, .self, .dim]
[ (.eq0 d, .var "$arg_0")
, (.eq1 d, .var "$arg_1") ] ]
-- ── §5. Type-level helpers ─────────────────────────────────────────────────
/-- The `CType` for natural numbers, at the bottom universe. -/
@[inline] def CType.natC : CType .zero := .ind natSchema []
/-- The `CType` for booleans, at the bottom universe. -/
@[inline] def CType.boolC : CType .zero := .ind boolSchema []
/-- The `CType` for lists with element type `A` at level . The list
type lives at the same level as its element. -/
@[inline] def CType.listC { : ULevel} (A : CType ) : CType :=
.ind listSchema [⟨ℓ, A⟩]
/-- The cubical interval `𝕀` as a CType (REL2). Lives at the bottom
universe. Inhabited by `CTerm.dimExpr r` for any `r : DimExpr`. -/
@[inline] def CType.intervalC : CType .zero := .interval
/-- The `CType` for the circle, at the bottom universe. -/
@[inline] def CType.s1C : CType .zero := .ind s1Schema []
/-- The HIT-encoded interval as a CType (REL1 form). -/
@[inline] def CType.intervalHitC : CType .zero := .ind intervalSchema []
/-- The `CType` for propositional truncation `‖A‖₋₁`. -/
@[inline] def CType.propTruncC { : ULevel} (A : CType ) : CType :=
.ind propTruncSchema [⟨ℓ, A⟩]
-- ── §6. Term-level helpers ─────────────────────────────────────────────────
namespace CTerm
/-- The `CTerm` `zero : Nat`. -/
@[inline] def zeroC : CTerm := .ctor natSchema "zero" [] []
/-- The `CTerm` `succ n` for a given `n : Nat`. -/
@[inline] def succC (n : CTerm) : CTerm := .ctor natSchema "succ" [] [n]
/-- The `CTerm` `false : Bool`. -/
@[inline] def falseC : CTerm := .ctor boolSchema "false" [] []
/-- The `CTerm` `true : Bool`. -/
@[inline] def trueC : CTerm := .ctor boolSchema "true" [] []
/-- The `CTerm` `nil : List A`. `A` is the element CType at any level. -/
@[inline] def nilC { : ULevel} (A : CType ) : CTerm :=
.ctor listSchema "nil" [⟨ℓ, A⟩] []
/-- The `CTerm` `cons x xs : List A`. -/
@[inline] def consC { : ULevel} (A : CType ) (x xs : CTerm) : CTerm :=
.ctor listSchema "cons" [⟨ℓ, A⟩] [x, xs]
/-- The `CTerm` `base : S¹`. -/
@[inline] def baseC : CTerm := .ctor s1Schema "base" [] []
/-- The `CTerm` `loop @ r : S¹` where `r : DimExpr`. -/
@[inline] def loopC (r : DimExpr) : CTerm :=
.ctor s1Schema "loop" [] [.dimExpr r]
/-- The `CTerm` `inT a : ‖A‖₋₁`. -/
@[inline] def inTC { : ULevel} (A : CType ) (a : CTerm) : CTerm :=
.ctor propTruncSchema "inT" [⟨ℓ, A⟩] [a]
/-- The `CTerm` `squash x y @ r : ‖A‖₋₁`. -/
@[inline] def squashC { : ULevel} (A : CType ) (x y : CTerm) (r : DimExpr) : CTerm :=
.ctor propTruncSchema "squash" [⟨ℓ, A⟩] [x, y, .dimExpr r]
/-- Build a Nat literal `n` as a tower of `succ`s on `zero`. -/
def natLit : Nat → CTerm
| 0 => zeroC
| n + 1 => succC (natLit n)
end CTerm
-- ── §7. Eliminator builders ────────────────────────────────────────────────
/-- Build an `indElim` for `Nat`. -/
def natElim (motive caseZero caseSucc target : CTerm) : CTerm :=
.indElim natSchema [] motive
[("zero", caseZero), ("succ", caseSucc)] target
/-- Build an `indElim` for `Bool`. -/
def boolElim (motive caseFalse caseTrue target : CTerm) : CTerm :=
.indElim boolSchema [] motive
[("false", caseFalse), ("true", caseTrue)] target
/-- Build an `indElim` for `List A`. -/
def listElim { : ULevel} (A : CType ) (motive caseNil caseCons target : CTerm) : CTerm :=
.indElim listSchema [⟨ℓ, A⟩] motive
[("nil", caseNil), ("cons", caseCons)] target
end CubicalTransport.Inductive