1-- Core natural-number mathematics2-- Part of Cumulus, the Grace17 mathematics library.3-- Copyright (c) 2026 Grant Passmore.4-- Released under the Apache License 2.0. See LICENSE in the repository root.5-- Authors: Grant Passmore67module Grace.Cumulus.Nat.Core8import Core.Nat.Order910-- Arithmetic lemmas belong in Cumulus; Core retains only the bootstrap laws.11theorem one.ne_zero12shows1≠013proof14intro equal15have distinct := Naturals.disjoint.zero.succ at016apply distinct17 symm18exact equal1920theorem add.left_cancel (b c : Set, a : Nat)21shows add(a, b) = add(a, c) → b = c22proof23induction a24| zero =>25intro h26simp [add] at h27exact h28| succ(k) using ih =>29intro h30simp [add] at h31have inject := Naturals.injective.succ with h32apply ih33exact inject3435theorem add.right_cancel (a b c : Nat)36shows add(a, c) = add(b, c) → a = b37proof38intro h39have cancel := add.left_cancel at a, b, c40apply cancel41have commuteA := add.commutative at a, c42have commuteB := add.commutative at b, c43rewrite commuteA44 rwa commuteB4546theorem add.swap_last (a b c : Nat)47shows add(add(a, b), c) = add(add(a, c), b)48proof49haveleft:= add.associative at b, c, a50have middle := add.commutative at c, b with*51haveright:= add.associative at c, b, a52simp5354theorem add.four_shuffle (a b c d : Nat)55shows add(add(a, b), add(c, d)) = add(add(a, c), add(b, d))56proof57simp [add.associative, add.swap]5859theorem add.eq_zero (b a : Nat)60shows add(a, b) =0→ (a =0∧ b =0)61proof62induction a63| zero =>64intro h65constructor66rfl67simp [add] at h68exact h69| succ(k) using ih =>70intro h71simp [add] at h72exfalso73have impossible := Naturals.disjoint.zero.succ at add(k, b)74apply impossible75simp7677lemma add.zero_successor_case (b : Set, a : Nat)78requires hbNat : Nat(b)79shows add(a, b) =0→ (succ(a) =1∧ b =0)80proof81induction a82| zero =>83intro h84constructor85 . rfl86 . simp [add] at h87exact h88| succ(k) using ih =>89intro h90simp [add] at h91exfalso92have impossible := Naturals.disjoint.zero.succ at add(k, b)93apply impossible94simp9596theorem add.eq_one (b : Set, a : Nat)97requires hbNat : Nat(b)98shows add(a, b) =1→ ((a =0∧ b =1) ∨ (a =1∧ b =0))99proof100induction a101| zero =>102intro h103left104constructor105 . rfl106 . simp [add] at h107exact h108| succ(k) using ih =>109intro h110right111simp [add] at h112have inject := Naturals.injective.succ at add(k, b), 0with h113apply add.zero_successor_case at b, k114 . exact inject115116theorem add.eq_zero_right (b : Set, a : Nat)117requires hbNat : Nat(b)118shows add(a, b) =0→ b =0119proof120induction a121| zero =>122intro h123simp [add] at h124exact h125| succ(k) using ih =>126intro h127simp [add] at h128exfalso129have impossible := Naturals.disjoint.zero.succ at add(k, b)130apply impossible131simp132133theorem add.eq_zero_left (b : Set, a : Nat)134requires hbNat : Nat(b)135shows add(a, b) =0→ a =0136proof137induction a138| zero =>139intro h140rfl141| succ(k) using ih =>142intro h143simp [add] at h144exfalso145have impossible := Naturals.disjoint.zero.succ at add(k, b)146apply impossible147simp148149theorem mul.left_zero (n : Nat)150shows mul(0, n) =0151proof152simp [mul]153154theorem mul.succ_left (n m : Nat)155shows mul(succ(n), m) = add(m, mul(n, m))156proof157simp [mul]158159theorem mul.two_left (n : Nat)160shows mul(2, n) = add(n, n)161proof162simp [mul, add, add.right_unit]163164theorem mul.two_right (n : Nat)165shows mul(n, 2) = add(n, n)166proof167induction n168| zero =>settlewith mul, add169| succ(k) using ih =>settlewith mul, add, add.succ_right, ih170171theorem mul.left_factor_one (b : Set, a : Nat)172requires hbNat : Nat(b)173shows mul(a, b) =1→ a =1174proof175induction a176| zero =>177intro h178simp [mul] at h179| succ(k) using ih =>180intro h181simp [mul] at h182have productNat := mul.closed with hbNat, h_k183have shape := add.eq_one with hbNat, productNat, h184cases shape with hLeft | hRight185 . rcases hLeft with⟨hbZero, hProductOne⟩186exfalso187rw hbZero at hProductOne188have zero := mul.right_zero with h_k189rw zero at hProductOne190have impossible := Naturals.disjoint.zero.succ at0191apply impossible192exact hProductOne193 . rcases hRight with⟨hbOne, hProductZero⟩194rw hbOne at hProductZero195have unit := mul.right_unit with h_k196rw unit at hProductZero197rw hProductZero198rfl199200theorem mul.eq_zero (b : Set, a : Nat)201requires hbNat : Nat(b)202shows mul(a, b) =0→ (a =0∨ b =0)203proof204induction a205| zero =>206intro h207left208rfl209| succ(k) using ih =>210intro h211right212simp [mul] at h213apply add.eq_zero_left at mul(k, b), b214 . settlewith mul.closed215216theorem mul.nonzero (a b : Nat)217requires aNonzero : a ≠0218requires bNonzero : b ≠0219shows a * b ≠0220proof221intro productZero222have zeroFactor := mul.eq_zero with*, productZero223cases zeroFactor with aZero | bZero224 . apply aNonzero225exact aZero226 . apply bNonzero227exact bZero228229theorem mul.associative_reverse (y z : Nat, x : Nat)230shows mul(x, mul(y, z)) = mul(mul(x, y), z)231proof232simp [mul.associative]233234theorem factorial.closed (n : Nat)235showsNat(n!)236proof237induction n238| zero =>settlewith factorial, Naturals.constructor.zero, Naturals.constructor.succ239| succ(k) using ih =>settlewith factorial, mul.closed, Naturals.constructor.succ, ih240241-- The step law in the form a proof about n + 1 uses: (n + 1)! = (n + 1) · n!.242theorem factorial.succ (n : Nat)243shows (n +1)! = (n +1) * n!244proof245have one : n +1= succ(n) := add.right_one with*246rw one247simp [factorial]248249theorem factorial.nonzero (n : Nat)250shows n! ≠0251proof252induction n253| zero =>254intro h255simp [factorial] at h256| k +1using ih =>257intro h258have step := factorial.succ with*259rw step at h260have zeroProduct := mul.eq_zero with h261cases zeroProduct with hSucc | hFact262 . have one := add.right_one with*263rw one at hSucc264have impossible := Naturals.disjoint.zero.succ at k265apply impossible266simp267 . exact ih with hFact268269lemma arithmetic.sample270shows (17+25) *3=126271proof272compute273274eval (17+25) *3275