1-- Distance between 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.Nat.Distance8import SubtractionLemmas9import MinMax1011def natDist (a b : Nat) : Nat:= (a - b) + (b - a)1213theorem natDist.value (a b : Nat)14shows natDist(a, b) = (a - b) + (b - a)15proof16simp [natDist]1718theorem natDist.natural (a b : Nat)19showsNat(natDist(a, b))20proof21haveleft:= sub.closed at a, b22haveright:= sub.closed at b, a23rw natDist.value24typecheck2526theorem natDist.commutative (a b : Nat)27shows natDist(a, b) = natDist(b, a)28proof29haveleft:= sub.closed at a, b30haveright:= sub.closed at b, a31rw [natDist.value, natDist.value]32ring3334theorem natDist.self (a : Nat)35shows natDist(a, a) =036proof37rw [natDist.value, sub.self]38ring3940theorem natDist.of_le (a b : Nat)41requires below : a ≤ b42shows natDist(a, b) = b - a43proof44have zero := sub.eq_zero_of_le with below45haveright:= sub.closed at b, a46rw [natDist.value, zero]47exact add.left_unit with*4849theorem natDist.of_ge (a b : Nat)50requires above : b ≤ a51shows natDist(a, b) = a - b52proof53have zero := sub.eq_zero_of_le with above54haveleft:= sub.closed at a, b55rw [natDist.value, zero]56exact add.right_unit with*5758theorem natDist.zero_right (a : Nat)59shows natDist(a, 0) = a60proof61have zero : 0≤ a bylinarith62have value1 := natDist.of_ge with zero63rw [value1, sub.zero_right]64rfl6566theorem natDist.zero_left (a : Nat)67shows natDist(0, a) = a68proof69rw natDist.commutative70exact natDist.zero_right with*7172theorem natDist.eq_zero_iff (a b : Nat)73shows natDist(a, b) =0↔ a = b74proof75constructor76 . intro zero77haveleft:= sub.closed at a, b78haveright:= sub.closed at b, a79rw natDist.value at zero80have both := add.eq_zero with zero81have below := sub.eq_zero_iff.forward with both.left82have above := sub.eq_zero_iff.forward with both.right83exact LessEqual.antisymmetric with below, above84 . intro same85rw same86exact natDist.self with*8788theorem natDist.positive_iff (a b : Nat)89shows0 < natDist(a, b) ↔ a ≠ b90proof91have distNat := natDist.natural at a, b92constructor93 . intro positive94intro same95have zero := natDist.eq_zero_iff.backward with same96rw zero at positive97exact Less.irreflexive with positive98 . intro distinct99have nonzero : natDist(a, b) ≠0100intro zero101have same := natDist.eq_zero_iff.forward with zero102exact distinct with same103exact Less.positive_of_ne_zero with nonzero104105theorem natDist.eq_iff (a b d : Nat)106shows natDist(a, b) = d ↔ b = a + d ∨ a = b + d107proof108constructor109 . intro same110have total := LessEqual.total at a, b111cases total with below | above112 . left113have value := natDist.of_le with below114rw value at same115have cancel := sub.add_cancel_left with below116rw [← cancel, same]117rfl118 . right119have value := natDist.of_ge with above120rw value at same121have cancel := sub.add_cancel_left with above122rw [← cancel, same]123rfl124 . introsplit125casessplitwith first | second126 . have below : a ≤ b bylinarith127have value2 := natDist.of_le with below128rw [value2, first]129exact sub.add_left with*130 . have above : b ≤ a bylinarith131have value3 := natDist.of_ge with above132rw [value3, second]133exact sub.add_left with*134135theorem natDist.add_left (a b k : Nat)136shows natDist(k + a, k + b) = natDist(a, b)137proof138have swapA := add.commutative at a, k with*139have swapB := add.commutative at b, k with*140rw [natDist.value, natDist.value, swapA, swapB, sub.add_add, sub.add_add]141rfl142143theorem natDist.add_right (a b k : Nat)144shows natDist(a + k, b + k) = natDist(a, b)145proof146rw [natDist.value, natDist.value, sub.add_add, sub.add_add]147rfl148149theorem natDist.add_one (a b : Nat)150shows natDist(a +1, b +1) = natDist(a, b)151proof152exact natDist.add_right at a, b, 1153154theorem natDist.mul_left (a b k : Nat)155shows natDist(k * a, k * b) = k * natDist(a, b)156proof157haveleft:= sub.closed at a, b158haveright:= sub.closed at b, a159have first := sub.mul_left at a, b, k160have second := sub.mul_left at b, a, k161rw [natDist.value, natDist.value, ← first, ← second]162ring163164theorem natDist.mul_right (a b k : Nat)165shows natDist(a * k, b * k) = natDist(a, b) * k166proof167have distNat := natDist.natural at a, b168have swapA := mul.commutative at k, a with*169have swapB := mul.commutative at k, b with*170have swap := mul.commutative at k, natDist(a, b) with*171rw [swapA, swapB, swap]172exact natDist.mul_left with*173174theorem natDist.le_add (a b : Nat)175shows natDist(a, b) ≤ a + b176proof177haveleft:= sub.le_self at a, b178haveright:= sub.le_self at b, a179have leftNat := sub.closed at a, b180have rightNat := sub.closed at b, a181rw natDist.value182linarith183184theorem natDist.triangle (a b c : Nat)185shows natDist(a, c) ≤ natDist(a, b) + natDist(b, c)186proof187have ab := sub.closed at a, b188have ba := sub.closed at b, a189have bc := sub.closed at b, c190have cb := sub.closed at c, b191have ac := sub.closed at a, c192have ca := sub.closed at c, a193have reflexiveAB := LessEqual.reflexive at a - b194have reflexiveBC := LessEqual.reflexive at b - c195have reflexiveCB := LessEqual.reflexive at c - b196have reflexiveBA := LessEqual.reflexive at b - a197have boundA : a ≤ b + (a - b) := sub.le_iff.forward with reflexiveAB198have boundB : b ≤ c + (b - c) := sub.le_iff.forward with reflexiveBC199have boundC : c ≤ b + (c - b) := sub.le_iff.forward with reflexiveCB200have boundB2 : b ≤ a + (b - a) := sub.le_iff.forward with reflexiveBA201have forward : a - c ≤ (a - b) + (b - c)202apply sub.le_iff.backward203linarith204have backward : c - a ≤ (c - b) + (b - a)205apply sub.le_iff.backward206linarith207rw [natDist.value, natDist.value, natDist.value]208linarith209210theorem natDist.max_sub_min (a b : Nat)211shows natDist(a, b) = natMax(a, b) - natMin(a, b)212proof213have total := LessEqual.total at a, b214cases total with below | above215 . have minValue := natMin.of_le with below216have maxValue := natMax.of_le with below217have value4 := natDist.of_le with below218rw [value4, minValue, maxValue]219rfl220 . have minValue := natMin.of_ge with above221have maxValue := natMax.of_ge with above222have value5 := natDist.of_ge with above223rw [value5, minValue, maxValue]224rfl225226theorem natMin.add_natDist (a b : Nat)227shows natMin(a, b) + natDist(a, b) = natMax(a, b)228proof229have total := LessEqual.total at a, b230cases total with below | above231 . have minValue := natMin.of_le with below232have maxValue := natMax.of_le with below233have value6 := natDist.of_le with below234rw [value6, minValue, maxValue]235exact sub.add_cancel_left with below236 . have minValue := natMin.of_ge with above237have maxValue := natMax.of_ge with above238have value7 := natDist.of_ge with above239rw [value7, minValue, maxValue]240exact sub.add_cancel_left with above241