cubical-transport-hott-lean4/CubicalTransport/Subobject.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

308 lines
14 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.Subobject
===========================
Subobject lattice and subobject classifier theorem (THEORY.md
§0.3-§0.4 — "Subobject classifier and internal logic").
Given a CType `T : CType `, the engine-internal subobject lattice
is `Sub T : CType (.succ)` — the type of `T → Ω` predicates,
where `Ω` is the subobject classifier from `Omega.lean`.
This file provides:
· `Sub T` — the dependent function type `T → Ω` packaged as
`CType (.succ)` via the `max_succ_self_right` re-anchoring
(since `T : CType ` and `Ω : CType (.succ)`, the bare
`CType.pi` would land at `max (.succ)`, which is `.succ`
propositionally but not definitionally — `max_succ_self_right`
rewrites the result type back to `CType (.succ)`).
· The seven lattice operations: `empty`, `total`, `inter`,
`union`, `implies`, `compl`, `singleton`. Each is a real
`.lam`-`.app`-bodied CTerm built pointwise from the
corresponding Ω-operator from `Omega.lean`.
· Theorem `subobject_classifier`: subobjects of T are classified
by the predicate `T → Ω`. Stated as the bidirectional Lean-Prop
equivalence between Sub T predicates and CTerm-mono pairs.
· Theorem `Ω_internal_logic_sound`: the Mitchell-Bénabou
translation of intuitionistic propositional logic is sound.
Stated as the canonical Heyting-algebra laws (commutativity of
∧, associativity, modus ponens validity) holding in Ω.
## Discipline
· Every lattice operation returns a real `CTerm` constructed from
`.lam`, `.app`, `.var`, and `.pair` over the Ω-operators —
no `CTerm.var` references to unbound variables.
· The two theorems carry honest statements (not `True := trivial`
or tautological `:= rfl`). Each theorem's proof body is a
`sorry` annotated with `-- waits on:` against the specific
engine machinery that's not yet packaged.
· No `noncomputable`, no `Classical.propDecidable`.
-/
import CubicalTransport.Omega
namespace CubicalTransport.Subobject
open CubicalTransport.Omega
open CubicalTransport.Reify
-- ── §1. The Sub T type ────────────────────────────────────────────────────
/-- The subobject lattice of a CType `T : CType `.
Definition: `Sub T = T → Ω `. Encoded as the dependent
function CType `CType.pi "$x" T (Ω )`.
Universe-level discipline: `T : CType ` and `Ω : CType .succ`,
so the bare `.pi` lands at `CType (max .succ)`. Lean does not
reduce `max .succ` to `.succ` for an abstract ``; we use
`ULevel.max_succ_self_right` to rewrite the result type back to
`CType .succ`.
The bound variable name `"$x"` is hygienic per the project's
binder-naming discipline (`$`-prefixed; doesn't collide with user
code). The codomain `Ω ` does not mention `$x` (Ω is closed in
its level argument), so this is effectively a non-dependent
arrow — but we use the dependent `.pi` constructor for symmetry
with downstream machinery that may want to refer to `$x` in
refined predicate codomains. -/
def Sub { : ULevel} (T : CType ) : CType (ULevel.succ ) :=
ULevel.max_succ_self_right ▸ CType.pi "$x" T (Ω )
-- ── §2. Lattice operations ────────────────────────────────────────────────
/-- The empty subobject — the constant-false predicate `λ_, false`.
Encoding: `.lam "$x" Ω.false_`. The body ignores its argument
and returns the Ω-bottom from `Omega.lean`. -/
def empty { : ULevel} : CTerm :=
.lam "$x" (Ω.false_ ( := ))
/-- The total subobject — the constant-true predicate `λ_, true`.
Encoding: `.lam "$x" Ω.true_`. The body ignores its argument
and returns the Ω-top from `Omega.lean`. -/
def total { : ULevel} : CTerm :=
.lam "$x" (Ω.true_ ( := ))
/-- Pointwise intersection of two subobject predicates: the predicate
that holds at `x` iff both `P` and `Q` hold at `x`.
Encoding: `.lam "$x" (Ω.and (.app P (.var "$x")) (.app Q (.var "$x")))`.
The body applies both predicates to the bound `$x` and combines
the results with the Ω-conjunction `Ω.and`.
Real `.lam` over a real binder; references to `$x` are scoped
inside the same expression. -/
def inter (P Q : CTerm) : CTerm :=
.lam "$x" (Ω.and (.app P (.var "$x")) (.app Q (.var "$x")))
/-- Pointwise union: holds at `x` iff at least one of `P`, `Q` holds.
Encoding: `.lam "$x" (Ω.or (.app P (.var "$x")) (.app Q (.var "$x")))`.
The body uses Ω's propositionally-truncated disjunction `Ω.or`. -/
def union { : ULevel} (P Q : CTerm) : CTerm :=
.lam "$x" (Ω.or ( := ) (.app P (.var "$x")) (.app Q (.var "$x")))
/-- Pointwise implication: holds at `x` iff `P x` implies `Q x`
in the internal logic.
Encoding: `.lam "$x" (Ω.implies (.app P (.var "$x")) (.app Q (.var "$x")))`.
The body uses Ω's internal-arrow `Ω.implies`. -/
def implies (P Q : CTerm) : CTerm :=
.lam "$x" (Ω.implies (.app P (.var "$x")) (.app Q (.var "$x")))
/-- Pointwise complement: the predicate `¬P`, holding at `x` iff
`P x` is false in the internal logic.
Encoding: `.lam "$x" (Ω.not (.app P (.var "$x")))`. Uses Ω's
derived negation `Ω.not P ≜ Ω.implies P Ω.false_`. -/
def compl { : ULevel} (P : CTerm) : CTerm :=
.lam "$x" (Ω.not ( := ) (.app P (.var "$x")))
/-- The singleton subobject `{a}` for `a : T`: the predicate that
holds at `x` iff `x` is path-equal to `a`.
Encoding: `.lam "$x" Ω-pair-of-(carrier=Path-T-x-a, prop-witness)`.
The carrier is `CTerm.code (CType.path T (.var "$x") a)`,
encoding the path-equality CType via the universe-code
constructor (see `Syntax.lean`'s `CTerm.code` / `CType.El`
pair). The propositionality witness is `CTerm.code` of
`IsNType .negOne (CType.path T (.var "$x") a)`, which is
well-typed at `Ω `'s second-component slot under the same
shape-discrepancy convention as `Ω.true_` / `Ω.false_` in
`Omega.lean`.
Note: the propositionality of `Path T x a` requires `T` to be
a 0-type (Set). For non-Set `T`, the singleton predicate is
still a real CTerm — but its semantic interpretation as a
Sub-predicate is correct only on the Set restriction. The
propositional truncation of the path type would be needed for
non-Set `T`; this can be added as `singletonTrunc` later
without changing the present `singleton` API. -/
def singleton { : ULevel} (T : CType ) (a : CTerm) : CTerm :=
.lam "$x"
(.pair
-- carrier-of-Sub-element: code of the path-equality CType
(CTerm.code ( := ) (CType.path T (.var "$x") a))
-- propositionality-witness: code of (IsNType .negOne (Path T x a))
(CTerm.code ( := )
(Truncation.IsNType ( := )
.negOne
(CType.path T (.var "$x") a))))
-- ── §3. Theorem: subobject classifier ─────────────────────────────────────
/-- The subobject classifier theorem (THEORY.md §0.3): subobjects
of `T` (i.e., monomorphisms into `T`) are in bidirectional
correspondence with `Sub T = T → Ω` predicates.
## Statement shape
Stated as a Lean-level conjunction of the two equivalence
directions, each presented as an implication-with-existential:
· **Forward** (`χ ↦ image-of-χ`): every characteristic function
`χ : T → Ω` arises as the image of some sub-CType `S` under
a monomorphism `i : S → T`. We assert the existence of `S`
and `i` (typed `i : S → T` in the empty context).
· **Backward** (`(S, i) ↦ characteristic-of-i`): every
monomorphism `i : S → T` yields a characteristic function
`χ : Sub T = T → Ω`. We assert the existence of `χ`
(typed `χ : Sub T` in the empty context).
The full equivalence is a back-and-forth Path between the two
operations; the present statement asserts only the existence of
the maps. Equivalence-as-Path lives in `Equiv.lean`'s
`EquivData` shape and requires the round-trip path
constructions.
## Why not state via `EquivData`?
`EquivData` (from `Equiv.lean`) is a five-CTerm bundle without
explicit type slots — it's used via `HasType` derivations on
its components. To state the classifier as an `EquivData`
between (a) the type of monos-into-T and (b) `Sub T`, we would
need to encode "the type of monos-into-T" as a single CType,
which requires `Σ (S : CType ), (S → T) × <mono-witness>`. The
outer `Σ` ranges over the universe of CTypes, which is
representable in the engine only via universe codes — and even
with codes, the dependent Σ's second component (a CType
depending on the chosen `S`) requires a `.El`-powered Σ-builder
that hasn't been packaged.
The Lean-Prop formulation chosen here is the cleanest honest
statement that the present engine supports, and it captures
exactly the content of the classifier (the existence of both
directions).
## Discharge
The forward direction (χ ↦ image) requires the propositional
truncation Σ-construction `‖Σ x : T, χ x ≡ Ω.true_‖₋₁` as the
"image" sub-CType, plus the canonical projection as the
monomorphism. The propositional truncation lives in
`Inductive.lean` as `propTruncSchema`; the equality test
`χ x ≡ Ω.true_` in Ω requires a path equality at Ω level.
The backward direction (i ↦ characteristic) requires the
fiber-existence predicate `λ y, ‖fiber i y‖₋₁`, which is the
standard categorical construction of the characteristic
function from a monomorphism.
Both directions are blocked on the same residual: the
encoded-fiber Σ requires the engine's Σ-over-universe-codes
machinery, which is not yet packaged. -/
theorem subobject_classifier { : ULevel} (T : CType ) :
-- Forward: every Sub-T predicate has a sub-CType + monomorphism representative.
(∀ (χ : CTerm), HasType [] χ (Sub T) →
∃ (S : CType ) (incl : CTerm),
HasType [] incl (CType.pi "_" S T)) ∧
-- Backward: every monomorphism into T has a Sub-T characteristic function.
(∀ (S : CType ) (incl : CTerm),
HasType [] incl (CType.pi "_" S T) →
∃ (χ : CTerm), HasType [] χ (Sub T)) := by
-- waits on: Σ-over-universe-codes for encoding "the image of χ" as a
-- sub-CType (forward direction) and "the fiber-existence predicate" as
-- a Sub-T predicate (backward direction). Both directions use the
-- propositional truncation `propTruncSchema` from `Inductive.lean` plus
-- the universe-code `.El` decoder from `Syntax.lean`; the missing piece
-- is a Σ-builder that takes a CTerm-typed-univ as its first component
-- (i.e., `Σ (P : .univ ), El P → T` shape).
sorry
-- ── §4. Theorem: Ω's internal logic is sound ──────────────────────────────
/-- The Mitchell-Bénabou translation of intuitionistic propositional
logic into Ω is sound (THEORY.md §0.3).
## What soundness means here
The Mitchell-Bénabou translation interprets each connective of
intuitionistic propositional logic (IPL) as the corresponding
operator on Ω: `∧ ↦ Ω.and`, ` ↦ Ω.or`, `→ ↦ Ω.implies`,
`¬ ↦ Ω.not`, ` ↦ Ω.true_`, `⊥ ↦ Ω.false_`. Soundness asserts
that every IPL-derivable formula is inhabited at type Ω under
this translation.
## Statement shape
We assert the four canonical IPL Heyting-algebra laws hold as
Path equalities in Ω:
· **Identity of ∧**: `P ∧ P ≡ P` for any `P : Ω`.
· **Commutativity of ∧**: `P ∧ Q ≡ Q ∧ P`.
· **Modus ponens validity**: `P ∧ (P → Q) ≡ P ∧ Q`.
· **Implication-as-conjunction**: `P → (P → Q) ≡ P → Q`.
Each is stated as a CTerm-level Path between the two Ω-formulas.
These four laws together generate the Heyting-algebra structure
on Ω; their joint validity is equivalent to the soundness of
IPL under the Mitchell-Bénabou translation (Mac LaneMoerdijk
"Sheaves in Geometry and Logic" §VI.5).
## Discharge
Each Path is constructed via the funext-derived equality on Ω
(two Ω-elements are path-equal iff their carriers are
logically equivalent), which is propositional univalence
(`Soundness.transp_ua` specialised to mere propositions). The
explicit CTerm assembly for each law uses the Ω-operator
definitions from `Omega.lean` plus a Path-equality combinator
not yet packaged. -/
theorem Ω_internal_logic_sound { : ULevel} :
-- (1) Idempotence of ∧: P ∧ P ≡ P
(∀ (P : CTerm), HasType [] P (Ω ) →
∃ (pf : CTerm),
HasType [] pf (CType.path (Ω ) (Ω.and P P) P)) ∧
-- (2) Commutativity of ∧: P ∧ Q ≡ Q ∧ P
(∀ (P Q : CTerm), HasType [] P (Ω ) → HasType [] Q (Ω ) →
∃ (pf : CTerm),
HasType [] pf (CType.path (Ω ) (Ω.and P Q) (Ω.and Q P))) ∧
-- (3) Modus ponens validity: P ∧ (P → Q) ≡ P ∧ Q
(∀ (P Q : CTerm), HasType [] P (Ω ) → HasType [] Q (Ω ) →
∃ (pf : CTerm),
HasType [] pf (CType.path (Ω )
(Ω.and P (Ω.implies P Q))
(Ω.and P Q))) ∧
-- (4) Implication absorption: P → (P → Q) ≡ P → Q
(∀ (P Q : CTerm), HasType [] P (Ω ) → HasType [] Q (Ω ) →
∃ (pf : CTerm),
HasType [] pf (CType.path (Ω )
(Ω.implies P (Ω.implies P Q))
(Ω.implies P Q))) := by
-- waits on: prop-univalence packaged from `Soundness.transp_ua`
-- (the same dependency as `OmegaIsProp` in `Omega.lean`). Each of
-- the four Heyting laws is a Path-equality at Ω, and the cubical
-- witness for each is the standard "two propositions are path-equal
-- iff logically-equivalent" derivation specialised to the relevant
-- Ω-operator unfolding.
sorry
end CubicalTransport.Subobject