/- Topolei.Cubical.Interval ======================== The interval I: free de Morgan algebra on dimension variables. Reference: CCHM §3 Grammar: r, s ::= 0 | 1 | i | 1−r | r∧s | r∨s Strategy: prove the de Morgan laws *semantically* — they hold for every Boolean assignment of the dimension variables. Sound because Bool is itself a de Morgan algebra and DimExpr is freely generated over it. -/ -- ── Dimension variables ─────────────────────────────────────────────────────── structure DimVar where name : String deriving DecidableEq, Repr -- ── The Interval ────────────────────────────────────────────────────────────── inductive DimExpr where | zero : DimExpr | one : DimExpr | var (i : DimVar) : DimExpr | inv (r : DimExpr) : DimExpr -- 1 − r | meet (r s : DimExpr) : DimExpr -- r ∧ s | join (r s : DimExpr) : DimExpr -- r ∨ s deriving Repr, Inhabited -- ── Semantic evaluation ─────────────────────────────────────────────────────── def DimExpr.eval (env : DimVar → Bool) : DimExpr → Bool | .zero => false | .one => true | .var i => env i | .inv r => !(r.eval env) | .meet r s => r.eval env && s.eval env | .join r s => r.eval env || s.eval env -- ── de Morgan algebra laws ──────────────────────────────────────────────────── -- All proved by simp-unfolding eval and then Bool case analysis. -- We use `simp only [eval]` (not plain `simp`) to avoid over-simplification -- that would leave `<;> rfl` with no goals. namespace DimExpr theorem inv_zero (env : DimVar → Bool) : (inv zero).eval env = (one).eval env := by simp only [eval]; rfl theorem inv_one (env : DimVar → Bool) : (inv one).eval env = (zero).eval env := by simp only [eval]; rfl theorem inv_inv (r : DimExpr) (env : DimVar → Bool) : (inv (inv r)).eval env = r.eval env := by simp only [eval]; cases r.eval env <;> rfl theorem inv_meet (r s : DimExpr) (env : DimVar → Bool) : (inv (meet r s)).eval env = (join (inv r) (inv s)).eval env := by simp only [eval]; cases r.eval env <;> cases s.eval env <;> rfl theorem inv_join (r s : DimExpr) (env : DimVar → Bool) : (inv (join r s)).eval env = (meet (inv r) (inv s)).eval env := by simp only [eval]; cases r.eval env <;> cases s.eval env <;> rfl theorem meet_comm (r s : DimExpr) (env : DimVar → Bool) : (meet r s).eval env = (meet s r).eval env := by simp only [eval]; cases r.eval env <;> cases s.eval env <;> rfl theorem join_comm (r s : DimExpr) (env : DimVar → Bool) : (join r s).eval env = (join s r).eval env := by simp only [eval]; cases r.eval env <;> cases s.eval env <;> rfl theorem meet_assoc (r s t : DimExpr) (env : DimVar → Bool) : (meet r (meet s t)).eval env = (meet (meet r s) t).eval env := by simp only [eval] cases r.eval env <;> cases s.eval env <;> cases t.eval env <;> rfl theorem join_assoc (r s t : DimExpr) (env : DimVar → Bool) : (join r (join s t)).eval env = (join (join r s) t).eval env := by simp only [eval] cases r.eval env <;> cases s.eval env <;> cases t.eval env <;> rfl theorem meet_one (r : DimExpr) (env : DimVar → Bool) : (meet r one).eval env = r.eval env := by simp only [eval]; cases r.eval env <;> rfl theorem one_meet (r : DimExpr) (env : DimVar → Bool) : (meet one r).eval env = r.eval env := by simp only [eval]; cases r.eval env <;> rfl theorem join_zero (r : DimExpr) (env : DimVar → Bool) : (join r zero).eval env = r.eval env := by simp only [eval]; cases r.eval env <;> rfl theorem zero_join (r : DimExpr) (env : DimVar → Bool) : (join zero r).eval env = r.eval env := by simp only [eval]; cases r.eval env <;> rfl theorem meet_zero (r : DimExpr) (env : DimVar → Bool) : (meet r zero).eval env = false := by simp only [eval]; cases r.eval env <;> rfl theorem join_one (r : DimExpr) (env : DimVar → Bool) : (join r one).eval env = true := by simp only [eval]; cases r.eval env <;> rfl theorem meet_distrib_join (r s t : DimExpr) (env : DimVar → Bool) : (meet r (join s t)).eval env = (join (meet r s) (meet r t)).eval env := by simp only [eval] cases r.eval env <;> cases s.eval env <;> cases t.eval env <;> rfl theorem join_distrib_meet (r s t : DimExpr) (env : DimVar → Bool) : (join r (meet s t)).eval env = (meet (join r s) (join r t)).eval env := by simp only [eval] cases r.eval env <;> cases s.eval env <;> cases t.eval env <;> rfl -- r ∧ (1−r) = 0 and r ∨ (1−r) = 1 hold semantically (not in the free algebra) theorem meet_inv_self (r : DimExpr) (env : DimVar → Bool) : (meet r (inv r)).eval env = false := by simp only [eval]; cases r.eval env <;> rfl theorem join_inv_self (r : DimExpr) (env : DimVar → Bool) : (join r (inv r)).eval env = true := by simp only [eval]; cases r.eval env <;> rfl -- ── Substitution ────────────────────────────────────────────────────────────── def subst (i : DimVar) (r : DimExpr) : DimExpr → DimExpr | .zero => .zero | .one => .one | .var j => if j = i then r else .var j | .inv s => .inv (subst i r s) | .meet s t => .meet (subst i r s) (subst i r t) | .join s t => .join (subst i r s) (subst i r t) theorem eval_subst (i : DimVar) (r s : DimExpr) (env : DimVar → Bool) : (subst i r s).eval env = s.eval (fun j => if j = i then r.eval env else env j) := by induction s with | zero => rfl | one => rfl | var j => simp only [subst, eval] by_cases h : j = i <;> simp [h, eval] | inv s ih => simp only [subst, eval, ih] | meet s t ih_s ih_t => simp only [subst, eval, ih_s, ih_t] | join s t ih_s ih_t => simp only [subst, eval, ih_s, ih_t] theorem eval_subst_zero (i : DimVar) (s : DimExpr) (env : DimVar → Bool) : (subst i zero s).eval env = s.eval (fun j => if j = i then false else env j) := by simp [eval_subst, eval] theorem eval_subst_one (i : DimVar) (s : DimExpr) (env : DimVar → Bool) : (subst i one s).eval env = s.eval (fun j => if j = i then true else env j) := by simp [eval_subst, eval] theorem eval_subst_inv (i : DimVar) (s : DimExpr) (env : DimVar → Bool) : (subst i (inv (var i)) s).eval env = s.eval (fun j => if j = i then !(env i) else env j) := by simp [eval_subst, eval] -- ── Dimension absence ──────────────────────────────────────────────────────── /-- Syntactic check: `i` does not appear in the dim expression. -/ def dimAbsent (i : DimVar) : DimExpr → Bool | .zero => true | .one => true | .var j => j != i | .inv r => r.dimAbsent i | .meet r s => r.dimAbsent i && s.dimAbsent i | .join r s => r.dimAbsent i && s.dimAbsent i /-- Bool endpoints have `dimAbsent = true` for every dimension. -/ theorem dimAbsent_endpoint (i : DimVar) (b : Bool) : (if b then DimExpr.one else DimExpr.zero).dimAbsent i = true := by cases b <;> rfl -- ── Normalisation (Stage 4.1, 2026-04-23) ──────────────────────────────────── -- -- Reduce DimExprs to a canonical form by pushing `inv` reductions to -- the literals. Rust's cubical evaluator needs this to canonicalise -- face formulas (otherwise `.inv .zero ≠ .one` structurally, and face -- dispatch becomes unreliable). -- -- Reductions implemented: -- · `.inv .zero → .one` -- · `.inv .one → .zero` -- · `.inv (.inv r) → r` (double-negation cancellation) -- -- The `.meet` / `.join` sub-terms are themselves normalised recursively -- so that iterated inversion reduces through layers of conjunction / -- disjunction. Unit / absorption laws (e.g. `.meet .zero _ → .zero`) -- are semantically valid but deliberately *not* implemented here — they -- don't discharge any Lean-side axiom, and adding them would complicate -- structural termination. A future `DimExpr.normalize_full` can add -- them when a well-founded measure is introduced. -- -- Semantic correctness: `normalize_preserves_eval` shows the normal -- form has the same Boolean evaluation under every environment. @[extern "topolei_cubical_dimexpr_normalize"] private opaque normalizeRust : DimExpr → DimExpr /-- Canonical form under `inv`-reduction. Idempotent: `normalize (normalize r) = normalize r`. -/ @[implemented_by normalizeRust] def normalize : DimExpr → DimExpr | .zero => .zero | .one => .one | .var i => .var i | .inv r => match normalize r with | .zero => .one -- `.inv .zero` → `.one` | .one => .zero -- `.inv .one` → `.zero` | .inv s => s -- double-negation cancel | nr => .inv nr -- opaque; keep wrapped | .meet r s => .meet (normalize r) (normalize s) | .join r s => .join (normalize r) (normalize s) -- ── Preservation of evaluation ────────────────────────────────────────────── /-- Auxiliary lemma: the four-way match inside `normalize (.inv r)` produces a DimExpr whose `eval` equals the logical negation of `(normalize r).eval env`. Each literal reduction (`.inv .zero → .one`, `.inv .one → .zero`, double-negation cancel) preserves this equation under Boolean semantics. -/ private theorem normalize_inv_aux (r : DimExpr) (env : DimVar → Bool) : (normalize (.inv r)).eval env = !((normalize r).eval env) := by show (match normalize r with | .zero => DimExpr.one | .one => DimExpr.zero | .inv s => s | nr => DimExpr.inv nr).eval env = !((normalize r).eval env) cases hnr : normalize r with | zero => rfl | one => rfl | var j => rfl | inv s => -- match returns s; RHS is !((.inv s).eval env) = !(!(s.eval env)). show s.eval env = !((DimExpr.inv s).eval env) simp [eval] | meet a b => rfl | join a b => rfl /-- Normalisation is semantically transparent: the normalised form has the same `eval` as the original, under every Bool environment. -/ theorem normalize_preserves_eval (r : DimExpr) (env : DimVar → Bool) : (normalize r).eval env = r.eval env := by induction r with | zero => rfl | one => rfl | var i => rfl | inv r ih => rw [normalize_inv_aux, ih] rfl | meet a b ih_a ih_b => show (DimExpr.meet (normalize a) (normalize b)).eval env = (DimExpr.meet a b).eval env simp only [eval, ih_a, ih_b] | join a b ih_a ih_b => show (DimExpr.join (normalize a) (normalize b)).eval env = (DimExpr.join a b).eval env simp only [eval, ih_a, ih_b] -- ── Canonical-form literals ───────────────────────────────────────────────── /-- `.inv .zero` normalises to `.one` — the fundamental literal rule. -/ theorem normalize_inv_zero : normalize (.inv .zero) = .one := rfl /-- `.inv .one` normalises to `.zero`. -/ theorem normalize_inv_one : normalize (.inv .one) = .zero := rfl /-- `.inv (.inv r)` normalises to the same value as `r` (semantically). Stated via eval rather than syntactically because structural double- negation cancellation depends on `r`'s post-normalisation shape. -/ theorem normalize_inv_inv_eval (r : DimExpr) (env : DimVar → Bool) : (normalize (.inv (.inv r))).eval env = r.eval env := by rw [normalize_preserves_eval] simp [eval] end DimExpr