1-- Divisibility of natural numbers2-- 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.NumberTheory.Divisibility8import Nat910predicate Divides (a b : Nat) :=∃ k, Nat(k) ∧ mul(a, k) = b11notationinfix50"∣"=> Divides1213theorem divides.definition (a b : Nat)14shows a ∣ b ↔∃ k, Nat(k) ∧ mul(a, k) = b15proof16simp [Divides]1718theorem divides.reflexive (a : Nat)19shows a ∣ a20proof21witness122simp [mul.right_unit]2324theorem one.divides (a : Nat)25shows1 ∣ a26proof27witness a28simp [mul.left_unit]2930theorem divides.zero (a : Nat)31shows a ∣ 032proof33witness034simp [mul.right_zero]3536theorem zero.divides_only_zero (a : Nat)37requires h : 0 ∣ a38shows a =039proof40obtain⟨k, hkNat, hkEq⟩:= h41rw← hkEq42simp [mul.left_zero]4344theorem divides.one_only (a : Set)45requires haNat : Nat(a)46requires h : a ∣ 147shows a =148proof49obtain⟨k, hkNat, hProduct⟩:= h50apply mul.left_factor_one at k, a51 . exact hProduct5253theorem divides.transitive (a b c : Nat)54requires hab : a ∣ b55requires hbc : b ∣ c56shows a ∣ c57proof58obtain⟨k, hkNat, hkEq⟩:= hab59obtain⟨l, hlNat, hlEq⟩:= hbc60witness mul(k, l)61simp [mul.associative_reverse]6263theorem divides.multiply_right (a b c : Nat)64requires hab : a ∣ b65shows a ∣ mul(b, c)66proof67obtain⟨k, hkNat, hkEq⟩:= hab68witness mul(k, c)69simp [mul.associative_reverse]7071theorem divides.multiply_left (a b c : Set)72requires haNat : Nat(a)73requires hbNat : Nat(b)74requires hcNat : Nat(c)75requires hab : a ∣ b76shows a ∣ mul(c, b)77proof78haveright:= divides.multiply_right with haNat, hbNat, hcNat, hab79have commute := mul.commutative with hcNat, hbNat80 rwa commute atright8182theorem divides.add (a b c : Nat)83requires hab : a ∣ b84requires hac : a ∣ c85shows a ∣ add(b, c)86proof87obtain⟨k, hkNat, hkEq⟩:= hab88obtain⟨l, hlNat, hlEq⟩:= hac89witness add(k, l)90simp [mul.distributes_left]9192lemma divides.successor_product_one (p : Set, k : Nat)93requires hpNat : Nat(p)94shows p ∣ succ(mul(p, k)) → p =195proof96induction k97| zero =>98intro h99have zero := mul.right_zero with hpNat100rw zero at h101apply divides.one_only102 . exact hpNat103 . exact h104| succ(j) using ih =>105intro h106obtain⟨l, hlNat, hEquation⟩:= h107have lShape := natural.zero_or_successor with hlNat108cases lShape with hlZero | hlSuccessor109 . exfalso110rw hlZero at hEquation111have productZero := mul.right_zero with hpNat112rw productZero at hEquation113have impossible := Naturals.disjoint.zero.succ at mul(p, succ(j))114apply impossible115exact hEquation116 . obtain⟨q, hq⟩:= hlSuccessor117rcases hq with⟨hqNat, hlSucc⟩118rw hlSucc at hEquation119have leftStep := mul.succ_right with hqNat, hpNat120rw leftStep at hEquation121have innerStep := mul.succ_right with h_j, hpNat122rw innerStep at hEquation123have rightStep := add.succ_right at mul(p, j), p with hpNat124rw← rightStep at hEquation125have cancel := add.left_cancel with hpNat, hEquation126apply ih127refine⟨q, hqNat, cancel⟩128129-- This is the arithmetic fact Euclid's proof needs. Its statement contains130-- no representation-level membership: common divisors of n and n+1 are one.131theorem divides.consecutive_one (p n : Set)132requires hpNat : Nat(p)133requires hnNat : Nat(n)134requires hn : p ∣ n135requires hNext : p ∣ succ(n)136shows p =1137proof138obtain⟨k, hkNat, hProduct⟩:= hn139rw← hProduct at hNext140apply divides.successor_product_one at p, k141 . exact hNext142143theorem factorial.successor_divides (n : Nat)144shows succ(n) ∣ succ(n)!145proof146witness n!147simp [factorial]148149-- Every positive natural at most n occurs among the factors of n!.150theorem factorial.divisible_through (p : Set, n : Nat)151requires hpNat : Nat(p)152shows0∈ p → p ∈ succ(n) → p ∣ n!153proof154induction n155| zero =>156intros hpPositive hpBound157exfalso158have membership := membership.one.forward at p with hpBound159rw membership at hpPositive160simp [nat.zero, set.empty]161| succ(k) using ih =>162intros hpPositive hpBound163have bound := membership.successor_forward{n := succ(k)} at p164cases bound with hpEarlier | hpNewest165 . have dividesPrevious := ih with hpPositive, hpEarlier166settlewith divides.multiply_left, factorial, factorial.closed,167 Naturals.constructor.succ168 . rw hpNewest169simp [factorial.successor_divides]170171-- A nonzero multiple is at least its divisor.172theorem divides.le (a b : Nat)173requires divides : a ∣ b174requires nonzero : b ≠0175shows a ≤ b176proof177obtain⟨k, kNat, product⟩:= divides178have shape := natural.zero_or_successor at k with*179cases shape with zero | successor180 . exfalso181rw zero at product182have value := mul.right_zero at a with*183rw value at product184apply nonzero185 symm186exact product187 . obtain⟨j, jNat, step⟩:= successor188rw step at product189witness a * j190have expand := mul.succ_right at j, a with*191 rwa expand at product192193theorem divides.antisymmetric (a b : Nat)194requires forward : a ∣ b195requires backward : b ∣ a196shows a = b197proof198have splitA : a =0∨ a ≠0199 . tauto200cases splitA with az | az201 . rw az at forward202have bz := zero.divides_only_zero with*203simp204 . have splitB : b =0∨ b ≠0205 . tauto206cases splitB with bz | bz207 . rw bz at backward208have aZero := zero.divides_only_zero with*209simp210 . have ab := divides.le at a, b with*211have ba := divides.le at b, a with*212exact LessEqual.antisymmetric with*213214-- Cancel a known divisible summand without introducing signed naturals.215theorem divides.add_cancel_left (d a b : Nat)216requires dividesLeft : d ∣ a217requires dividesSum : d ∣ a + b218shows d ∣ b219proof220have splitD : d =0∨ d ≠0221 . tauto222cases splitD with dz | dz223 . rw dz at dividesSum224have sumZero := zero.divides_only_zero with*225have bZero := add.eq_zero_right with*, sumZero226rw bZero227exact divides.zero with*228 . obtain⟨k, kNat, left⟩:= dividesLeft229obtain⟨l, lNat, sum⟩:= dividesSum230have notLess : ¬l < k231 . intro less232have strict := Less.mul_left with*233rw [sum, left] at strict234have bound : a ≤ a + b235witness b236rfl237have cycle := Less.transitive_LessEqual with*238exact Less.irreflexive with*, cycle239have order := LessEqual.of_not_Less with*240obtain⟨r, rNat, gap⟩:= order241have expanded : d * k + d * r = d * l242 . rw← gap243ring244rw [left, sum] at expanded245have remainder := add.left_cancel with*, expanded246unfold Divides247refine⟨r, rNat, remainder⟩248249theorem divides.add_cancel_right (d a b : Nat)250requires dividesRight : d ∣ b251requires dividesSum : d ∣ a + b252shows d ∣ a253proof254have commute := add.commutative at a, b with*255rw← commute at dividesSum256exact divides.add_cancel_left with*257258-- Common divisors are unchanged by a Euclidean remainder equation.259theorem divides.remainder_iff (d a b q r : Nat)260requires equation : a = b * q + r261requires dividesB : d ∣ b262shows d ∣ a ↔ d ∣ r263proof264have multiple := divides.multiply_right at d, b, q with*265constructor266 . intro dividesA267rw equation at dividesA268exact divides.add_cancel_left with*269 . intro dividesR270rw equation271exact divides.add with*272273lemma divides.sample274shows7 ∣ 42275proof276witness6277compute278