Some checks are pending
Lean Action CI / build (push) Waiting to run
Implements the cells-spec vision: a computation space that preserves auditability, correctness, interactivity. Phase 1 (Lean kernel + naga-IR Rust backend) is closed; foundation hypothesis stack (Selection H1+H2, Subobject H3, Trace H5, Obs.Ctx C2, Cubical.Trace) landed. Highlights: - Cubical-HoTT syntax + value/eval/readback in Lean - naga-IR pipeline (no GLSL string crosses FFI; 17/17 probes pass) - Honesty audit: every non-transport (sealed cells, vertex shader, Y-flip, presentation conventions) is documented as such - Polymorphic Trace α as free monoid; Cubical.Trace gives CTerm → Trace CTerm by structural fold (homomorphism = definition) - Selection as Huet zipper; Subobject as Boolean algebra over WCell - All theorems proven; the proof IS the implementation See STATUS.md for the resume guide. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
258 lines
11 KiB
Text
258 lines
11 KiB
Text
/-
|
||
Topolei.Subobject
|
||
=================
|
||
H3 of the selection-foundation stack.
|
||
|
||
## What this file is
|
||
|
||
A `Subobject` of `WCell` is a *characteristic function*:
|
||
`σ : WCell → Bool`, identifying which cells are "in" the
|
||
subobject. Subobjects form a **Boolean algebra** under ∩, ∪, ¬
|
||
with units ⊤, ⊥ — every law follows from `Bool`'s algebra by
|
||
pointwise reasoning, so the file is mostly `funext + simp + Bool`.
|
||
|
||
## Why this layer
|
||
|
||
H1+H2 gave us *focused* selections — one cell, with a path
|
||
back to the root. H3 gives us *scoped* selections — a
|
||
*family* of candidate cells, with a focus picked from inside.
|
||
The Boolean algebra then lets us:
|
||
|
||
- intersect two scopes (∩) — "things in both selections";
|
||
- union two scopes (∪) — "things in either";
|
||
- complement (¬) — "things outside this selection".
|
||
|
||
These operations are what peripheral observations need in
|
||
order to *combine* or *refine* the cells they're looking at,
|
||
without descending to ad-hoc selection tools per peripheral
|
||
type (the VFX problem the user named: "their transports are
|
||
forgetful, so they have many selector tools"). Here, ONE
|
||
abstraction (Subobject + Boolean algebra) covers all of it.
|
||
|
||
## What this file does NOT contain
|
||
|
||
- The *focused-subobject* combination (Selection × Subobject).
|
||
That goes in `Topolei.Selection` once H1+H2's focus type
|
||
is extended with a scope field.
|
||
|
||
- The *action* of cell-endomorphisms on Subobjects. That's
|
||
`Subobject.preimage` below — actually, it IS in this file.
|
||
The thing NOT here is the action on `Selection` (which
|
||
requires the focused-subobject layer to be in place).
|
||
|
||
- **Heyting / intuitionistic refinement** to `WCell → Type` for
|
||
proof-relevant subobjects (where membership tracks *why* a
|
||
cell is in scope). That's a future H7 — when H5 (the trace
|
||
map) needs provenance, we lift `σ`'s codomain from `Bool` to
|
||
`Type`. For now, classical Boolean is enough.
|
||
|
||
## Reference
|
||
|
||
- Cells-spec §15.4 ("Lawvere-Tierney topology") — Subobjects
|
||
are exactly the level-0 instance of the LT-topology hierarchy
|
||
the cells-spec uses for accessibility / security.
|
||
- Cells-spec §1.5 ("Rendering Context as a Cell") — peripheral
|
||
observations as fiber selectors.
|
||
-/
|
||
|
||
namespace Topolei.Subobject
|
||
|
||
-- We don't import `Topolei.Selection` to keep this file independent;
|
||
-- both `Subobject` and `Selection` are foundational, neither
|
||
-- depends on the other. The bridge between them lives in a
|
||
-- third file.
|
||
private inductive WCell where
|
||
| mk : String → List WCell → WCell
|
||
|
||
namespace WCell
|
||
def data : WCell → String | .mk d _ => d
|
||
def children : WCell → List WCell | .mk _ c => c
|
||
end WCell
|
||
|
||
-- ── The Subobject type ────────────────────────────────────────────────────
|
||
|
||
/-- A subobject of `WCell`: a Boolean-valued characteristic function
|
||
saying which cells are "in" the subobject. Equivalence between
|
||
subobjects is pointwise (function-extensional). -/
|
||
structure Subobject where
|
||
σ : WCell → Bool
|
||
deriving Inhabited
|
||
|
||
namespace Subobject
|
||
|
||
/-- Two subobjects are equal iff their characteristic functions
|
||
are pointwise equal. Function extensionality is `funext`. -/
|
||
@[ext] theorem ext {a b : Subobject} (h : ∀ c, a.σ c = b.σ c) : a = b := by
|
||
cases a; cases b
|
||
congr 1
|
||
funext c
|
||
exact h c
|
||
|
||
-- ── Constants: ⊤ (everywhere) and ⊥ (nowhere) ────────────────────────────
|
||
|
||
/-- The total subobject — every cell is in it. -/
|
||
def top : Subobject := { σ := fun _ => true }
|
||
|
||
/-- The empty subobject — no cell is in it. -/
|
||
def bot : Subobject := { σ := fun _ => false }
|
||
|
||
-- ── Pointwise operations ─────────────────────────────────────────────────
|
||
|
||
/-- Intersection (AND of characteristic functions). -/
|
||
def inter (a b : Subobject) : Subobject := { σ := fun c => a.σ c && b.σ c }
|
||
|
||
/-- Union (OR of characteristic functions). -/
|
||
def union (a b : Subobject) : Subobject := { σ := fun c => a.σ c || b.σ c }
|
||
|
||
/-- Complement (NOT of characteristic function). -/
|
||
def compl (a : Subobject) : Subobject := { σ := fun c => !(a.σ c) }
|
||
|
||
-- ── Boolean algebra laws (every one follows from `Bool` algebra) ──────────
|
||
|
||
-- The pattern: `ext c; simp [Subobject.inter, Subobject.union, Subobject.compl,
|
||
-- Subobject.top, Subobject.bot, Bool.<lemma>]`.
|
||
|
||
-- ── Commutativity ─────────────────────────────────────────────────────────
|
||
|
||
@[simp] theorem inter_comm (a b : Subobject) : a.inter b = b.inter a := by
|
||
ext c; simp [inter, Bool.and_comm]
|
||
|
||
@[simp] theorem union_comm (a b : Subobject) : a.union b = b.union a := by
|
||
ext c; simp [union, Bool.or_comm]
|
||
|
||
-- ── Associativity ─────────────────────────────────────────────────────────
|
||
|
||
theorem inter_assoc (a b c : Subobject) :
|
||
(a.inter b).inter c = a.inter (b.inter c) := by
|
||
ext x; simp [inter, Bool.and_assoc]
|
||
|
||
theorem union_assoc (a b c : Subobject) :
|
||
(a.union b).union c = a.union (b.union c) := by
|
||
ext x; simp [union, Bool.or_assoc]
|
||
|
||
-- ── Idempotence ───────────────────────────────────────────────────────────
|
||
|
||
@[simp] theorem inter_self (a : Subobject) : a.inter a = a := by
|
||
ext c; simp [inter]
|
||
|
||
@[simp] theorem union_self (a : Subobject) : a.union a = a := by
|
||
ext c; simp [union]
|
||
|
||
-- ── Identity laws (top is unit of ∩, bot is unit of ∪) ───────────────────
|
||
|
||
@[simp] theorem inter_top (a : Subobject) : a.inter top = a := by
|
||
ext c; simp [inter, top]
|
||
|
||
@[simp] theorem top_inter (a : Subobject) : top.inter a = a := by
|
||
ext c; simp [inter, top]
|
||
|
||
@[simp] theorem union_bot (a : Subobject) : a.union bot = a := by
|
||
ext c; simp [union, bot]
|
||
|
||
@[simp] theorem bot_union (a : Subobject) : bot.union a = a := by
|
||
ext c; simp [union, bot]
|
||
|
||
-- ── Annihilation (top is absorber of ∪, bot of ∩) ────────────────────────
|
||
|
||
@[simp] theorem inter_bot (a : Subobject) : a.inter bot = bot := by
|
||
ext c; simp [inter, bot]
|
||
|
||
@[simp] theorem bot_inter (a : Subobject) : bot.inter a = bot := by
|
||
ext c; simp [inter, bot]
|
||
|
||
@[simp] theorem union_top (a : Subobject) : a.union top = top := by
|
||
ext c; simp [union, top]
|
||
|
||
@[simp] theorem top_union (a : Subobject) : top.union a = top := by
|
||
ext c; simp [union, top]
|
||
|
||
-- ── Distributivity ───────────────────────────────────────────────────────
|
||
|
||
theorem inter_distrib_union (a b c : Subobject) :
|
||
a.inter (b.union c) = (a.inter b).union (a.inter c) := by
|
||
ext x; simp [inter, union, Bool.and_or_distrib_left]
|
||
|
||
theorem union_distrib_inter (a b c : Subobject) :
|
||
a.union (b.inter c) = (a.union b).inter (a.union c) := by
|
||
ext x; simp [union, inter, Bool.or_and_distrib_left]
|
||
|
||
-- ── Complement laws ──────────────────────────────────────────────────────
|
||
|
||
@[simp] theorem compl_compl (a : Subobject) : a.compl.compl = a := by
|
||
ext c; simp [compl]
|
||
|
||
@[simp] theorem inter_compl_self (a : Subobject) : a.inter a.compl = bot := by
|
||
ext c; simp [inter, compl, bot]
|
||
|
||
@[simp] theorem union_compl_self (a : Subobject) : a.union a.compl = top := by
|
||
ext c; simp [union, compl, top]
|
||
|
||
@[simp] theorem compl_top : (top : Subobject).compl = bot := by
|
||
ext c; simp [compl, top, bot]
|
||
|
||
@[simp] theorem compl_bot : (bot : Subobject).compl = top := by
|
||
ext c; simp [compl, top, bot]
|
||
|
||
-- ── De Morgan ────────────────────────────────────────────────────────────
|
||
|
||
theorem compl_inter (a b : Subobject) :
|
||
(a.inter b).compl = a.compl.union b.compl := by
|
||
ext c; simp [inter, union, compl, Bool.not_and]
|
||
|
||
theorem compl_union (a b : Subobject) :
|
||
(a.union b).compl = a.compl.inter b.compl := by
|
||
ext c; simp [union, inter, compl, Bool.not_or]
|
||
|
||
-- ── Absorption ───────────────────────────────────────────────────────────
|
||
|
||
@[simp] theorem inter_union_self (a b : Subobject) :
|
||
a.inter (a.union b) = a := by
|
||
ext c; cases h : a.σ c <;> simp [inter, union, h]
|
||
|
||
@[simp] theorem union_inter_self (a b : Subobject) :
|
||
a.union (a.inter b) = a := by
|
||
ext c; cases h : a.σ c <;> simp [inter, union, h]
|
||
|
||
-- ── Bridge to construction: scope-preserving endomorphisms ───────────────
|
||
--
|
||
-- A peripheral observation produces a `Subobject` (the cells the
|
||
-- user is "looking at"). A constructor — i.e. an endomorphism of
|
||
-- WCell — should respect the scope: cells inside the selection
|
||
-- map to cells inside the selection. This is the type-level
|
||
-- guarantee that "applying a tool to a selection produces a new
|
||
-- valid selection".
|
||
--
|
||
-- Note: this is a *property* of an endomorphism, not a structure
|
||
-- on Subobjects. The action on Selections — `applyEndo` — uses
|
||
-- this property as a precondition; it lives in
|
||
-- `Topolei.Selection.Scoped` (next module to land).
|
||
|
||
/-- `f` preserves the subobject `a`: every cell in `a` maps to a
|
||
cell in `a`. This is the scope-preservation precondition
|
||
for actions on focused-subobject selections. -/
|
||
def Preserves (a : Subobject) (f : WCell → WCell) : Prop :=
|
||
∀ c, a.σ c = true → a.σ (f c) = true
|
||
|
||
/-- The identity always preserves any subobject. -/
|
||
theorem Preserves.id (a : Subobject) : Preserves a (fun c => c) := fun _ h => h
|
||
|
||
/-- Composition of preserving endomorphisms is preserving. -/
|
||
theorem Preserves.comp {a : Subobject} {f g : WCell → WCell}
|
||
(hf : Preserves a f) (hg : Preserves a g) :
|
||
Preserves a (fun c => f (g c)) := fun c hc => hf (g c) (hg c hc)
|
||
|
||
end Subobject
|
||
|
||
-- ── Operational sanity check ──────────────────────────────────────────────
|
||
|
||
/-- A demo subobject: cells whose data starts with `"leaf"`. -/
|
||
def demoLeaves : Subobject := { σ := fun c => c.data.startsWith "leaf" }
|
||
|
||
#eval demoLeaves.σ (WCell.mk "leaf-A" []) -- expected: true
|
||
#eval demoLeaves.σ (WCell.mk "root" []) -- expected: false
|
||
#eval (demoLeaves.inter demoLeaves).σ (WCell.mk "leaf-A" []) -- expected: true
|
||
#eval (demoLeaves.compl).σ (WCell.mk "root" []) -- expected: true
|
||
#eval (Subobject.top : Subobject).σ (WCell.mk "anything" []) -- expected: true
|
||
#eval (Subobject.bot : Subobject).σ (WCell.mk "anything" []) -- expected: false
|
||
|
||
end Topolei.Subobject
|