Realization Boundaries · Lean source

RationalComputability.lean

Declared contract recorded Coverage and evidence

The cited release explicitly reports completion of its registered formal contract, under its exact hypotheses.

This viewer reads the retained source; it does not run Lean or assign new claim mappings.

Local imports (1)

RealizationBoundaries/RationalComputability.lean261 lines

Original source pathRealizationBoundaries/RationalComputability.lean
Skip declarations and read code

Skip source text

1 import RealizationBoundaries.PrimeComputability
2 import Mathlib.FieldTheory.Finite.Basic
3 import Mathlib.Data.Rat.Lemmas
4 import Mathlib.Tactic.Ring
5 import Mathlib.Tactic.FieldSimp
6 
7 /-! # Native rational-code arithmetic and total prime reduction -/
8 set_option autoImplicit false
9 noncomputable section
10 namespace RealizationBoundaries
11 
12 /-- Positive-minus-negative numerator and positive denominator predecessor.
13 The carrier is an ordinary native primitive-codable product of naturals. -/
14 abbrev RationalCode := (ℕ × ℕ) × ℕ
15 namespace RationalCode
16 
17 def positive (c : RationalCode) : ℕ := c.1.1
18 def negative (c : RationalCode) : ℕ := c.1.2
19 def denominator (c : RationalCode) : ℕ := c.2 + 1
20 def value (c : RationalCode) : ℚ :=
21   mkRat ((positive c : ℤ) - (negative c : ℤ)) (denominator c)
22 
23 theorem value_eq (c : RationalCode) :
24     value c = ((positive c : ℚ) - (negative c : ℚ)) / (denominator c : ℚ) := by
25   simp only [value, Rat.mkRat_eq_div, Int.cast_sub, Int.cast_natCast]
26 
27 theorem denominator_pos (c : RationalCode) : 0 < denominator c := Nat.succ_pos _
28 
29 theorem value_surjective : Function.Surjective value := by
30   intro q
31   refine ⟨((q.num.toNat, (-q.num).toNat), q.den - 1), ?_⟩
32   unfold value positive negative denominator
33   rw [Int.toNat_sub_toNat_neg, Nat.sub_add_cancel q.den_pos, Rat.mkRat_self]
34 
35 def add (c e : RationalCode) : RationalCode :=
36   ((positive c * denominator e + positive e * denominator c,
37     negative c * denominator e + negative e * denominator c),
38     denominator c * denominator e - 1)
39 
40 def neg (c : RationalCode) : RationalCode := ((negative c, positive c), c.2)
41 
42 @[simp] theorem value_add (c e : RationalCode) : value (add c e) = value c + value e := by
43   rw [value_eq, value_eq, value_eq]
44   have hd : 0 < denominator c * denominator e := Nat.mul_pos (denominator_pos c) (denominator_pos e)
45   simp only [add, positive, negative, denominator]
46   simp only [denominator] at hd
47   rw [Nat.sub_add_cancel hd]
48   push_cast
49   have hc : (c.2 + 1 : ℚ) ≠ 0 := by positivity
50   have he : (e.2 + 1 : ℚ) ≠ 0 := by positivity
51   field_simp
52   ring
53 
54 @[simp] theorem value_neg (c : RationalCode) : value (neg c) = -value c := by
55   simp only [value_eq, neg, positive, negative, denominator]
56   ring
57 
58 /-- Cross multiplication decides equality of the decoded rational values. -/
59 def equal (c e : RationalCode) : Bool := decide
60   (positive c * denominator e + negative e * denominator c =
61     positive e * denominator c + negative c * denominator e)
62 
63 theorem equal_iff (c e : RationalCode) : equal c e = true ↔ value c = value e := by
64   simp only [equal, decide_eq_true_eq, value_eq]
65   have hc : (denominator c : ℚ) ≠ 0 := by exact_mod_cast (denominator_pos c).ne'
66   have he : (denominator e : ℚ) ≠ 0 := by exact_mod_cast (denominator_pos e).ne'
67   rw [div_eq_div_iff hc he]
68   constructor
69   · intro h
70     have h' : (positive c : ℚ) * denominator e + negative e * denominator c =
71         positive e * denominator c + negative c * denominator e := by exact_mod_cast h
72     nlinarith
73   · intro h
74     have h' : (positive c : ℚ) * denominator e + negative e * denominator c =
75         positive e * denominator c + negative c * denominator e := by nlinarith
76     exact_mod_cast h'
77 
78 theorem primrec_positive : Primrec positive := Primrec.fst.comp Primrec.fst
79 theorem primrec_negative : Primrec negative := Primrec.snd.comp Primrec.fst
80 theorem primrec_denominator : Primrec denominator := Primrec.succ.comp Primrec.snd
81 
82 theorem primrec_add : Primrec₂ add := by
83   let a : Primrec (fun p : RationalCode × RationalCode => positive p.1) := primrec_positive.comp Primrec.fst
84   let b : Primrec (fun p : RationalCode × RationalCode => negative p.1) := primrec_negative.comp Primrec.fst
85   let d : Primrec (fun p : RationalCode × RationalCode => denominator p.1) := primrec_denominator.comp Primrec.fst
86   let e : Primrec (fun p : RationalCode × RationalCode => positive p.2) := primrec_positive.comp Primrec.snd
87   let f : Primrec (fun p : RationalCode × RationalCode => negative p.2) := primrec_negative.comp Primrec.snd
88   let g : Primrec (fun p : RationalCode × RationalCode => denominator p.2) := primrec_denominator.comp Primrec.snd
89   exact ((Primrec.nat_add.comp (Primrec.nat_mul.comp a g) (Primrec.nat_mul.comp e d)).pair
90     (Primrec.nat_add.comp (Primrec.nat_mul.comp b g) (Primrec.nat_mul.comp f d))).pair
91     (Primrec.nat_sub.comp (Primrec.nat_mul.comp d g) (Primrec.const 1))
92 
93 theorem primrec_neg : Primrec neg :=
94   (primrec_negative.pair primrec_positive).pair Primrec.snd
95 
96 theorem primrec_equal : Primrec₂ equal := by
97   let a : Primrec (fun p : RationalCode × RationalCode => positive p.1) := primrec_positive.comp Primrec.fst
98   let b : Primrec (fun p : RationalCode × RationalCode => negative p.1) := primrec_negative.comp Primrec.fst
99   let d : Primrec (fun p : RationalCode × RationalCode => denominator p.1) := primrec_denominator.comp Primrec.fst
100   let e : Primrec (fun p : RationalCode × RationalCode => positive p.2) := primrec_positive.comp Primrec.snd
101   let f : Primrec (fun p : RationalCode × RationalCode => negative p.2) := primrec_negative.comp Primrec.snd
102   let g : Primrec (fun p : RationalCode × RationalCode => denominator p.2) := primrec_denominator.comp Primrec.snd
103   exact (Primrec.eq.comp
104     (Primrec.nat_add.comp (Primrec.nat_mul.comp a g) (Primrec.nat_mul.comp f d))
105     (Primrec.nat_add.comp (Primrec.nat_mul.comp e d) (Primrec.nat_mul.comp b g))).decide
106 
107 end RationalCode
108 
109 /-- Euclid's gcd is native primitive recursive: bounded common-divisor search
110 returns the same greatest common divisor. The both-zero case is retained. -/
111 theorem primrec_nat_gcd : Primrec₂ Nat.gcd := by
112   have hpred : PrimrecRel (fun p : ℕ × ℕ => fun d : ℕ => d ∣ p.1 ∧ d ∣ p.2) :=
113     (primrec_nat_dvd.comp Primrec.snd (Primrec.fst.comp Primrec.fst)).and
114       (primrec_nat_dvd.comp Primrec.snd (Primrec.snd.comp Primrec.fst))
115   refine (Primrec.nat_findGreatest Primrec.nat_add hpred).of_eq ?_
116   intro p
117   apply Nat.findGreatest_eq_iff.mpr
118   refine ⟨?_, fun _ => ⟨Nat.gcd_dvd_left _ _, Nat.gcd_dvd_right _ _⟩, ?_⟩
119   · by_cases hb : p.2 = 0
120     · simp [hb]
121     · exact (Nat.gcd_le_right p.1 (Nat.pos_of_ne_zero hb)).trans (Nat.le_add_left _ _)
122   · intro n hlt hle hn
123     have hdn : n ∣ Nat.gcd p.1 p.2 := Nat.dvd_gcd hn.1 hn.2
124     by_cases hg : Nat.gcd p.1 p.2 = 0
125     · have hz := Nat.gcd_eq_zero_iff.mp hg
126       have hsum : p.1 + p.2 = 0 := by simp [hz.1, hz.2]
127       change n ≤ p.1 + p.2 at hle
128       omega
129     · exact (not_lt_of_ge (Nat.le_of_dvd (Nat.pos_of_ne_zero hg) hdn)) hlt
130 
131 namespace RationalCode
132 
133 def magnitude (c : RationalCode) : ℕ :=
134   (positive c - negative c) + (negative c - positive c)
135 def divisor (c : RationalCode) : ℕ := Nat.gcd (denominator c) (magnitude c)
136 def normalPositive (c : RationalCode) : ℕ := (positive c - negative c) / divisor c
137 def normalNegative (c : RationalCode) : ℕ := (negative c - positive c) / divisor c
138 def normalDenominator (c : RationalCode) : ℕ := denominator c / divisor c
139 
140 theorem primrec_magnitude : Primrec magnitude :=
141   Primrec.nat_add.comp (Primrec.nat_sub.comp primrec_positive primrec_negative)
142     (Primrec.nat_sub.comp primrec_negative primrec_positive)
143 theorem primrec_divisor : Primrec divisor :=
144   primrec_nat_gcd.comp primrec_denominator primrec_magnitude
145 theorem primrec_normalPositive : Primrec normalPositive :=
146   Primrec.nat_div.comp (Primrec.nat_sub.comp primrec_positive primrec_negative) primrec_divisor
147 theorem primrec_normalNegative : Primrec normalNegative :=
148   Primrec.nat_div.comp (Primrec.nat_sub.comp primrec_negative primrec_positive) primrec_divisor
149 theorem primrec_normalDenominator : Primrec normalDenominator :=
150   Primrec.nat_div.comp primrec_denominator primrec_divisor
151 
152 /-- The native normalized fields are the literal reduced Rat numerator and
153 denominator, including zero and negative numerators. -/
154 theorem normal_fields (c : RationalCode) :
155     (value c).num = (normalPositive c : ℤ) - (normalNegative c : ℤ) ∧
156     (value c).den = normalDenominator c := by
157   by_cases h : negative c ≤ positive c
158   · have hsub : negative c - positive c = 0 := Nat.sub_eq_zero_of_le h
159     have he : (positive c : ℤ) - (negative c : ℤ) = ((positive c - negative c : ℕ) : ℤ) :=
160       (Int.ofNat_sub h).symm
161     simp only [value, he, Rat.num_mkRat, Rat.den_mkRat,
162       (denominator_pos c).ne', ↓reduceIte, Int.natAbs_natCast,
163       normalPositive, normalNegative, normalDenominator, divisor, magnitude,
164       hsub, Nat.add_zero, Nat.zero_div, Int.natCast_ediv, Nat.cast_zero, sub_zero]
165     exact ⟨trivial, trivial⟩
166   · have hle : positive c ≤ negative c := Nat.le_of_lt (Nat.lt_of_not_ge h)
167     have hsub : positive c - negative c = 0 := Nat.sub_eq_zero_of_le hle
168     have he : (positive c : ℤ) - (negative c : ℤ) = -((negative c - positive c : ℕ) : ℤ) := by
169       rw [Int.ofNat_sub hle]
170       ring
171     have hdvd : (divisor c : ℤ) ∣ ((negative c - positive c : ℕ) : ℤ) := by
172       apply Int.ofNat_dvd.mpr
173       simpa [divisor, magnitude, hsub] using Nat.gcd_dvd_right (denominator c) (negative c - positive c)
174     simp only [value, he, Rat.num_mkRat, Rat.den_mkRat,
175       (denominator_pos c).ne', ↓reduceIte, Int.natAbs_neg, Int.natAbs_natCast,
176       normalPositive, normalNegative, normalDenominator, divisor, magnitude,
177       hsub, Nat.zero_add, Nat.zero_div, Nat.cast_zero, zero_sub]
178     constructor
179     · have hdvd' : ((denominator c).gcd (negative c - positive c) : ℤ) ∣
180           ((negative c - positive c : ℕ) : ℤ) := by
181         simpa [divisor, magnitude, hsub] using hdvd
182       rw [Int.neg_ediv_of_dvd hdvd', Int.natCast_ediv]
183     · trivial
184 
185 /-- A nonnegative representative of the reduced signed numerator modulo `p`. -/
186 def numeratorResidue (c : RationalCode) (p : ℕ) : ℕ :=
187   (normalPositive c % p + p - normalNegative c % p) % p
188 
189 /-- Fermat inversion is a total natural-number operation. The zero-denominator
190 branch is explicit and agrees with the Rat-to-ZMod cast at denominator primes. -/
191 def primeResidue (c : RationalCode) (p : ℕ) : ℕ :=
192   if normalDenominator c % p = 0 then 0
193   else (numeratorResidue c p * normalDenominator c ^ (p - 2)) % p
194 
195 theorem primrec_numeratorResidue : Primrec₂ numeratorResidue := by
196   let a : Primrec (fun z : RationalCode × ℕ => normalPositive z.1) :=
197     primrec_normalPositive.comp Primrec.fst
198   let b : Primrec (fun z : RationalCode × ℕ => normalNegative z.1) :=
199     primrec_normalNegative.comp Primrec.fst
200   exact Primrec.nat_mod.comp
201     (Primrec.nat_sub.comp (Primrec.nat_add.comp (Primrec.nat_mod.comp a Primrec.snd) Primrec.snd)
202       (Primrec.nat_mod.comp b Primrec.snd)) Primrec.snd
203 
204 theorem primrec_primeResidue : Primrec₂ primeResidue := by
205   have hpow : Primrec₂ (fun a b : ℕ => a ^ b) := Primrec₂.unpaired'.mp Nat.Primrec.pow
206   let d : Primrec (fun z : RationalCode × ℕ => normalDenominator z.1) :=
207     primrec_normalDenominator.comp Primrec.fst
208   exact Primrec.ite
209     (Primrec.eq.comp (Primrec.nat_mod.comp d Primrec.snd) (Primrec.const 0))
210     (Primrec.const 0)
211     (Primrec.nat_mod.comp
212       (Primrec.nat_mul.comp primrec_numeratorResidue
213         (hpow.comp d (Primrec.nat_sub.comp Primrec.snd (Primrec.const 2)))) Primrec.snd)
214 
215 /-- The natural numerator residue casts to the literal normalized Rat numerator. -/
216 theorem numeratorResidue_cast (c : RationalCode) {p : ℕ} (hp : p.Prime) :
217     (numeratorResidue c p : ZMod p) = ((value c).num : ZMod p) := by
218   have hb : normalNegative c % p ≤ normalPositive c % p + p :=
219     (Nat.mod_lt _ hp.pos).le.trans (Nat.le_add_left _ _)
220   rw [numeratorResidue, ZMod.natCast_mod, Nat.cast_sub hb, Nat.cast_add,
221     ZMod.natCast_mod, ZMod.natCast_mod, ZMod.natCast_self, add_zero, (normal_fields c).1]
222   push_cast
223   rfl
224 
225 /-- Exact reduction at every prime, including all exceptional denominator primes.
226 This is the total Rat cast used by the actual rational sections. -/
227 theorem primeResidue_cast (c : RationalCode) {p : ℕ} [Fact p.Prime] :
228     (primeResidue c p : ZMod p) = ((value c : ℚ) : ZMod p) := by
229   have hp : p.Prime := Fact.out
230   by_cases hden : normalDenominator c % p = 0
231   · have hd : (normalDenominator c : ZMod p) = 0 :=
232       (ZMod.natCast_eq_zero_iff _ _).mpr (Nat.dvd_of_mod_eq_zero hden)
233     simp only [primeResidue, hden, ↓reduceIte, Nat.cast_zero]
234     rw [Rat.cast_def, (normal_fields c).2, hd, div_zero]
235   · have hd : (normalDenominator c : ZMod p) ≠ 0 := by
236       intro hz
237       exact hden (Nat.mod_eq_zero_of_dvd ((ZMod.natCast_eq_zero_iff _ _).mp hz))
238     have hinv : (normalDenominator c : ZMod p) ^ (p - 2) =
239         (normalDenominator c : ZMod p)⁻¹ := by
240       symm
241       apply ZMod.inv_eq_of_mul_eq_one
242       have he : p - 2 + 1 = p - 1 := by have := hp.two_le; omega
243       rw [mul_comm, ← pow_succ, he]
244       exact ZMod.pow_card_sub_one_eq_one hd
245     rw [primeResidue, ite_eq_right hden, ZMod.natCast_mod, Nat.cast_mul,
246       numeratorResidue_cast c hp, Nat.cast_pow, hinv, Rat.cast_def, (normal_fields c).2,
247       div_eq_mul_inv]
248 
249 /-- The emitted representative is canonical in the finite field. -/
250 theorem primeResidue_lt (c : RationalCode) {p : ℕ} (hp : p.Prime) : primeResidue c p < p := by
251   unfold primeResidue
252   split
253   · exact hp.pos
254   · exact Nat.mod_lt _ hp.pos
255 
256 theorem primeResidue_eq_val (c : RationalCode) {p : ℕ} [Fact p.Prime] :
257     primeResidue c p = (((value c : ℚ) : ZMod p)).val := by
258   rw [← primeResidue_cast c, ZMod.val_natCast_of_lt (primeResidue_lt c (Fact.out : p.Prime))]
259 
260 end RationalCode
261 end RealizationBoundaries

Back to source controls

Original file and source record

This copy matches the recorded source file. Its publication here does not change the work’s review status.

SHA-256: a912908e18e654ef13c6a267b837480198183af843cb13b13f6b0e6c5ceec788

Original source on GitHub

Back to Realization Boundaries