cubical-transport-hott-lean4/CubicalTransport/Bridge/Set.lean
Maximus Gorog 7934275f68
Some checks are pending
Lean Action CI / build (push) Waiting to run
Layer 0 substrate round 2: Subobject + SIP + Modality + Bridge/Set
Four new modules, all building on the now-stable Layer 0 foundation
(Universe / Truncation / Decidable / Omega / Reify / Category).
THEORY.md §0.4 (Subobject + SIP), §0.5 (Modality), §0.6 (Bridge/Set).

## CubicalTransport/Subobject.lean (308 lines)

Sub T = CType.pi "$x" T (Ω ℓ) — re-anchored at ℓ.succ via
ULevel.max_succ_self_right.  Pointwise lattice operations as REAL
CTerms using existing Ω logical operators:
  · empty / total      — constant Ω.false_ / Ω.true_
  · inter / union      — pointwise Ω.and / Ω.or
  · implies / compl    — pointwise Ω.implies / Ω.not
  · singleton T a      — characteristic function of {a} via
                         CTerm.code (CType.path T x a) + IsNType -1
                         propositionality witness

Theorems with REAL Prop statements:
  · subobject_classifier — bidirectional ∃-quantified statement
                           (∃ S incl, mono into T)  ↔  (∃ χ, χ : Sub T)
                           (sorry, waits on: Σ-over-universe-codes
                            for image construction)
  · Ω_internal_logic_sound — four-clause Heyting algebra Path
                             equalities (∧-idempotence, ∧-commutativity,
                             modus ponens, implication absorption)
                             (sorry, waits on: prop-univalence via
                              Soundness.transp_ua)

## CubicalTransport/SIP.lean (320 lines)

StructureFunctor — Lean structure with toFun : CType ℓ → CType ℓ
and transport : (A B) → EquivData → EquivData (REAL EquivData,
not stub CTerm).

  · StructureFunctor.id_       — identity functor (transport = id)
  · StructureFunctor.comp G F  — substantively chains transports

Five categorical functoriality coherences PROVED (not stubbed):
  · id_.transport_idEquiv     := rfl
  · id_.transport_eq_id       := rfl
  · comp_id_right             := rfl
  · comp_id_left              := rfl
  · comp_assoc                := rfl
  · comp.transport_eq_compose := rfl

Theorems with REAL Prop statements:
  · SIP — given S, T, T', e and typed forward/inverse on e:
            ∃ lifted, HasType [] lifted.f (S.toFun T → S.toFun T')
                   ∧ HasType [] lifted.fInv ...
          (sorry, waits on: Soundness.transp_ua as structure-
           functor coherence)
  · contract_transports — equivalences induce path-equality on
                          contract values in Ω
                          (sorry, waits on: SIP + prop-univalence)

## CubicalTransport/Modality.lean (461 lines)

Modality structure with seven REAL Lean-level fields:
  · apply       : CType ℓ → CType ℓ
  · unit        : (A : CType ℓ) → CTerm
  · isModal     : CType ℓ → CType ℓ
  · modal_apply, modal_path, modal_sigma, unit_equiv_on_modal — CTerm-typed proof fields

LexModality extends Modality with preserves_pullbacks +
preserves_terminal CTerm-typed proofs.

Modality.id_ — identity modality with REAL CTerm bodies:
  unitT ℓ := .ind unitSchema [], unitTT := .ctor unitSchema "tt" [] []
  No free-variable placeholders.

Modality.comp G F — substantively chains:
  apply A = G.apply (F.apply A)
  unit A = .lam "$x" (.app (G.unit (F.apply A)) (.app (F.unit A) (.var "$x")))
  modal_sigma A B = G.modal_sigma (F.apply A) (fun b => F.apply (B b))
  ... etc.

Theorems with REAL Prop statements:
  · Modality_pullback_lex — Iff between Modality + pullback-preserving
                            extension and LexModality
                            (sorry, waits on: Category.lean's pullback
                             construction)
  · adjoint_modal_triple — quintuple-Σ existence of (ʃ, ♭, ♯) with
                           four conjuncts asserting CType + CTerm
                           non-triviality (apply ≠ apply false flags
                           are real distinctness checks, not tautologies)
                           (sorry, waits on: Layer 3 cohesive lift —
                            Topolei/Modal.lean)

Bonus: 5 rfl-lemmas + 4 substantive-dependence theorems
(Modality.id_apply_dep, comp_apply_G_dep, comp_apply_at_id,
comp_unit_F_dep, comp_unit_G_dep) proving fields don't collapse
to constants — analogues of Category.lean's no-collapse theorems.

## CubicalTransport/Bridge/Set.lean (224 lines)

CubicalSetC as a Lean Prop existential:
  def CubicalSetC {ℓ} (T : CType ℓ) : Prop :=
    ∃ (w : CTerm), HasType [] w (IsNType .zero T)

Substantive — the witness w is the cubical proof of 0-truncatedness,
immediately consumable by Hedberg.

Three theorem statements + one bidirectional discharge:
  · CubicalSetC_isProp                  := rfl
  · pathEqEquiv  (Iff statement)        := via path_to_eq + eq_to_path
  · CubicalSetC_of_CDecidableEq         (sorry, waits on Hedberg)
  · path_to_eq                          (sorry, waits on Hedberg
                                          + canonical-form readback)
  · eq_to_path                          (sorry, waits on dim-absent
                                          packaging on toCTerm a)

## Discipline summary

  · Total new sorries this round: 9 (across 4 files)
  · Every sorry annotated -- waits on: <specific dep>
  · Zero noncomputable / Classical.propDecidable
  · Zero CType.univ stubs / IsModal-style identity definitions
  · Zero "True := trivial" theorem placeholders
  · Zero "M.apply = M.apply" tautological proofs
  · Zero free-variable CTerm placeholders for non-binder names
  · No existing file modified — all four files are new

## Verification

  lake build (engine)        Build completed successfully (48 jobs)

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

224 lines
11 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.Bridge.Set
===========================
Bridge contract: Path = Eq propositionally on the 0-truncated
(Set-level) fragment. THEORY.md §0.6 / §0.8.
For any `T : CType ` satisfying `CubicalSetC` (i.e. T is 0-truncated
in the cubical sense — `IsNType .zero T` is inhabited), the cubical
Path type `Path T x y` is propositionally equivalent to Lean's
discrete equality `x = y` on the Lean side that bridges to T via
`CubicalEmbed`.
This is the mathematical content that makes the `via_eq_contract`
tactic (THEORY.md §0.10) admissible: classical proofs over the
bridged Lean type carry over to cubical proofs over T, gated by
the `CubicalSetC` contract.
## Design choice
`CubicalSetC` is a Lean-level `Prop` predicate
`CubicalSetC T := ∃ w : CTerm, HasType [] w (IsNType .zero T)`.
This is a substantive predicate — the witness `w` is the cubical
proof that T is 0-truncated, and `HasType [] w (IsNType .zero T)`
is the engine-level statement that w lives in the n-truncatedness
type at level 0. Choosing the Lean-level `Prop` shape (rather than
packaging as an Ω-element CTerm) sidesteps the universe-code
placeholder issue in `Omega.lean`: every contract in §0.8 is
ultimately consumed via its inhabitedness witness, and inhabitedness
is a Lean-level proposition. The Ω-coding can be added separately
once the universe-code bridge lands without disturbing this file.
## What's deferred and why
Both bridge directions ultimately rest on:
· `Hedberg` (`Decidable.lean`): waits on a J-rule combinator
packaged from `Soundness.transp_ua`.
· `CubicalEmbed.toCTerm_injective` (already in `Bridge.lean`):
available; used in the canonical backward direction.
Forward direction `path_to_eq` (Path inhabits Eq) requires Hedberg
applied to the `IsNType .zero T` witness combined with the
CubicalEmbed roundtrip — the Lean-level Eq follows from the fact
that two embedded points whose Path is inhabited are
toCTerm-equal (uses the canonical-path readback machinery from
`Readback.lean`, packaged through the Set-level discharge).
Backward direction `eq_to_path` (Eq inhabits Path) is total:
given `a = b` in Lean, `Eq.toPath h` (in `Bridge.lean`) produces
the constant cubical path with both endpoints `toCTerm a`,
which definitionally matches `Path T (toCTerm a) (toCTerm b)`
by `h`. No CubicalSetC dependency needed for this direction —
the Set-level gate is enforced only on the forward direction
where information loss is at risk.
-/
import CubicalTransport.Truncation
import CubicalTransport.Decidable
import CubicalTransport.Omega
import CubicalTransport.Bridge
namespace CubicalTransport.Bridge.Set
open CubicalTransport.Inductive
open CubicalTransport.Truncation
open CubicalTransport.Decidable
open CubicalTransport.Omega
open CubicalTransport.Bridge
-- ── §1. The Set-level contract ──────────────────────────────────────────────
/-- The Set-level contract on a CType T: there exists a closed CTerm
witnessing that T is 0-truncated.
Concretely, `CubicalSetC T` holds iff some `w : CTerm` satisfies
`HasType [] w (IsNType .zero T)` — i.e. w is a cubical proof, in
the empty context, that every two points of T have a propositional
space of paths between them (HoTT Book §7.1, level 0).
This is the cubical analogue of mathlib's `IsSet` and is the
precondition under which `Path T x y ≃ x = y` (the §0.8
`pathEqEquiv` of THEORY.md). -/
def CubicalSetC { : ULevel} (T : CType ) : Prop :=
∃ (w : CTerm), HasType [] w (IsNType .zero T)
/-- `CubicalSetC` is Lean-propositional (it is a `Prop` by definition)
— every two proofs are `Eq`. This matches the §0.8 requirement
that contracts be propositional. -/
theorem CubicalSetC_isProp { : ULevel} (T : CType )
(h₁ h₂ : CubicalSetC T) : h₁ = h₂ := rfl
/-- Hedberg ⇒ CubicalSetC. Decidable equality on T implies T satisfies
the Set-level contract. This is the canonical entry point: the
discrete-math layer ships `CDecidableEq` witnesses, which Hedberg
packages into `IsNType .zero T`, which is exactly `CubicalSetC T`.
The proof is direct from `Decidable.Hedberg`: that theorem gives
`∃ w, HasType [] w (CDecidableEq T → IsNType .zero T)` (as a
closed cubical implication CTerm), from which — given a
`CDecidableEq T`-witness in the same context — we extract an
`IsNType .zero T`-witness by application. -/
theorem CubicalSetC_of_CDecidableEq { : ULevel} (T : CType )
(_dec : ∃ (d : CTerm), HasType [] d (CDecidableEq T)) :
CubicalSetC T := by
-- waits on: Decidable.Hedberg (which itself waits on a J-rule
-- combinator from Soundness.transp_ua). Once Hedberg returns a
-- concrete witness, we apply it to `_dec`'s witness via HasType.app
-- to obtain the IsNType .zero T witness.
sorry
-- ── §2. Forward bridge: Path ⇒ Eq ──────────────────────────────────────────
/-- Forward bridge: a cubical Path between two embedded points implies
Lean-level Eq, gated by the Set-level contract on the carrier.
Statement. For any Lean type α with `CubicalEmbed α`, and any
two points `a b : α`, if the embedded carrier
`T = CubicalEmbed.ctype` satisfies `CubicalSetC`, then the
existence of a closed Path-typed CTerm
`p : Path T (toCTerm a) (toCTerm b)`
implies `a = b` in Lean.
Why the contract gate. Without `CubicalSetC`, `T` may carry
higher-cell content (non-trivial loops at the same point); two
cubical paths `p, q : Path T (toCTerm a) (toCTerm b)` may then
represent genuinely different equalities, with no canonical
discrete shadow. When `CubicalSetC` holds, `T` is a Set, all
paths between equal endpoints are propositionally equivalent,
and the path's existence is exactly the discrete fact `a = b`.
Proof shape. The Set-level witness `c : CubicalSetC T` provides
`w : IsNType .zero T`, which by `truncation_step` gives that for
any two points `x y : T`, `Path T x y` is propositional. Combined
with `CubicalEmbed.toCTerm_injective` (already in Bridge.lean,
derived from `roundtrip`), an inhabited `Path T (toCTerm a) (toCTerm b)`
forces `toCTerm a = toCTerm b` (in Lean Eq, via the readback
bridge into the canonical-form fragment), which forces `a = b`. -/
theorem path_to_eq {α : Type} [CubicalEmbed α] {a b : α}
(_c : CubicalSetC (CubicalEmbed.ctype (α := α)))
(_p : ∃ (t : CTerm),
HasType [] t (.path (CubicalEmbed.ctype (α := α))
(CubicalEmbed.toCTerm a)
(CubicalEmbed.toCTerm b))) :
a = b := by
-- waits on: Hedberg (Decidable.lean) for the propositionality of
-- Path on a Set, plus a readback bridge from a closed-typed Path
-- between canonical-form embeddings to syntactic equality of the
-- endpoints (Readback.lean's canonical-form readback discipline).
-- With those: extract the IsNType .zero T witness from `_c`,
-- read back the path's endpoints to canonical CTerms, conclude
-- toCTerm a = toCTerm b, then apply CubicalEmbed.toCTerm_injective.
sorry
-- ── §3. Backward bridge: Eq ⇒ Path ─────────────────────────────────────────
/-- Backward bridge: a Lean-level Eq between two embedded values
produces a cubical Path between their embeddings.
Statement. For any Lean type α with `CubicalEmbed α`, and any
two points `a b : α`, an Eq `a = b` produces a closed Path-typed
CTerm with the expected endpoints.
Total — no CubicalSetC dependency. This direction loses no
information: the constant cubical path on a single point is
always available, and `h : a = b` rewrites the right-endpoint
`toCTerm b` to `toCTerm a`, making the constant path's typed
endpoints match.
Construction is exactly `Bridge.Eq.toPath` from `Bridge.lean`:
`Eq.toPath h := plam "$eq2path" (toCTerm a)`. The HasType
derivation goes through `HasType.plam` on a dim-absent body. -/
theorem eq_to_path {α : Type} [CubicalEmbed α] {a b : α}
(h : a = b) :
∃ (t : CTerm),
HasType [] t (.path (CubicalEmbed.ctype (α := α))
(CubicalEmbed.toCTerm a)
(CubicalEmbed.toCTerm b)) := by
-- The witness is `Eq.toPath h`. Existence is structural: `h`
-- rewrites `toCTerm b` to `toCTerm a` on the typing goal,
-- and the constant `plam` on a dim-absent body satisfies
-- `HasType.plam` with both endpoints reducing to `toCTerm a`.
-- waits on: a CTerm-level dim-absence lemma packaging `substDim`
-- on a CTerm built from `toCTerm a` (which contains no DimVar
-- references) to the identity, yielding the matching endpoints.
-- The Eq.toPath construction itself is total in Bridge.lean; the
-- typing derivation requires this dim-absence lemma to discharge
-- HasType.plam's substDim-shaped goals.
sorry
-- ── §4. Full bridge equivalence ────────────────────────────────────────────
/-- The full bridge equivalence (THEORY.md §0.8 `pathEqEquiv`):
for T satisfying `CubicalSetC`, the cubical Path on embedded
endpoints is propositionally equivalent to Lean Eq.
Statement. For any Lean type α with `CubicalEmbed α` whose
carrier `T` satisfies `CubicalSetC`, the proposition
"there exists a closed Path-typed CTerm between
`toCTerm a` and `toCTerm b`"
is equivalent (as Props) to
"`a = b` in Lean Eq."
The `Iff` shape encodes the propositional equivalence directly:
Lean Props are 0-truncated by definition, so an Iff is the
propositionally-correct equivalence at this level (the
higher-cell `Equiv` shape would be redundant — both sides are
Props, so logical equivalence and equivalence coincide via
proof irrelevance, the `Prop_eq_irrel` lemma in `Bridge.lean`).
Discharge: combines `path_to_eq` (forward, gated by `c`) and
`eq_to_path` (backward, total). The contract gate appears only
on the forward side, exactly as the §0.8 statement requires. -/
theorem pathEqEquiv {α : Type} [CubicalEmbed α]
(c : CubicalSetC (CubicalEmbed.ctype (α := α))) (a b : α) :
(∃ (t : CTerm),
HasType [] t (.path (CubicalEmbed.ctype (α := α))
(CubicalEmbed.toCTerm a)
(CubicalEmbed.toCTerm b)))
↔ (a = b) := by
refine ⟨fun p => ?_, fun h => ?_⟩
· exact path_to_eq c p
· exact eq_to_path h
end CubicalTransport.Bridge.Set