pith. machine review for the scientific record. sign in

IndisputableMonolith.NumberTheory.Primes.Modular

IndisputableMonolith/NumberTheory/Primes/Modular.lean · 191 lines · 17 declarations

show as:
view math explainer →

open module explainer GitHub source

Explainer status: pending

   1import Mathlib
   2import IndisputableMonolith.NumberTheory.Primes.Basic
   3import IndisputableMonolith.NumberTheory.Primes.RSConstants
   4
   5/-!
   6# Modular arithmetic and wheel filters (prime-friendly)
   7
   8This file is the starting point for modular/character tooling motivated by the theory docs
   9(e.g. mod-8 gating and wheel factorization like “wheel-840”).
  10
  11In this first slice we only formalize **soundness** of a wheel: if a number is coprime to `840`,
  12then it is not divisible by the small primes `2,3,5,7` that make up the wheel.
  13-/
  14
  15namespace IndisputableMonolith
  16namespace NumberTheory
  17namespace Primes
  18
  19open Nat
  20
  21/-- The wheel modulus `840 = 2^3 * 3 * 5 * 7`. -/
  22def wheel840 : ℕ := 840
  23
  24/-! ### The mod-8 character χ₈ (as used in the theory docs) -/
  25
  26/-- The mod-8 character χ₈ from the theory doc:
  27
  28- χ₈(n) = 0 for `n ≡ 0,2,4,6 (mod 8)` (i.e. even residues)
  29- χ₈(n) = +1 for `n ≡ 1,7 (mod 8)`
  30- χ₈(n) = -1 for `n ≡ 3,5 (mod 8)`
  31
  32We define it on naturals using `n % 8`. -/
  33def chi8 (n : ℕ) : ℤ :=
  34  match n % 8 with
  35  | 0 | 2 | 4 | 6 => 0
  36  | 1 | 7 => 1
  37  | 3 | 5 => -1
  38  | _ => 0
  39
  40theorem chi8_periodic (n k : ℕ) : chi8 (n + 8 * k) = chi8 n := by
  41  -- `chi8` depends only on `n % 8`.
  42  unfold chi8
  43  have : (n + 8 * k) % 8 = n % 8 := by
  44    simp [Nat.add_mod]
  45  -- rewrite by the mod-8 equality and the result is definitional
  46  simp [this]
  47
  48@[simp] theorem chi8_mod0 (k : ℕ) : chi8 (8 * k) = 0 := by
  49  unfold chi8
  50  simp
  51
  52@[simp] theorem chi8_mod1 (k : ℕ) : chi8 (8 * k + 1) = 1 := by
  53  unfold chi8
  54  simp [Nat.add_mod]
  55
  56@[simp] theorem chi8_mod2 (k : ℕ) : chi8 (8 * k + 2) = 0 := by
  57  unfold chi8
  58  simp [Nat.add_mod]
  59
  60@[simp] theorem chi8_mod3 (k : ℕ) : chi8 (8 * k + 3) = -1 := by
  61  unfold chi8
  62  simp [Nat.add_mod]
  63
  64@[simp] theorem chi8_mod4 (k : ℕ) : chi8 (8 * k + 4) = 0 := by
  65  unfold chi8
  66  simp [Nat.add_mod]
  67
  68@[simp] theorem chi8_mod5 (k : ℕ) : chi8 (8 * k + 5) = -1 := by
  69  unfold chi8
  70  simp [Nat.add_mod]
  71
  72@[simp] theorem chi8_mod6 (k : ℕ) : chi8 (8 * k + 6) = 0 := by
  73  unfold chi8
  74  simp [Nat.add_mod]
  75
  76@[simp] theorem chi8_mod7 (k : ℕ) : chi8 (8 * k + 7) = 1 := by
  77  unfold chi8
  78  simp [Nat.add_mod]
  79
  80/-- `chi8 n = 0` exactly when `n` is even. -/
  81theorem chi8_eq_zero_iff_even (n : ℕ) : chi8 n = 0 ↔ Even n := by
  82  -- Reduce to the remainder `r = n % 8`, which is bounded (`r < 8`).
  83  set r := n % 8 with hr
  84  have hr_lt : r < 8 := by
  85    have : n % 8 < 8 := Nat.mod_lt n (by decide)
  86    simpa [hr] using this
  87  have hchi : chi8 n = chi8 r := by
  88    -- Both sides reduce to the same `match r with ...` form.
  89    simp [chi8, hr.symm, Nat.mod_eq_of_lt hr_lt]
  90  have hhelp : (chi8 r = 0 ↔ r % 2 = 0) := by
  91    interval_cases r <;> decide
  92  have hmod : r % 2 = n % 2 := by
  93    -- `r = n % 8`, and `2 ∣ 8`, so `(n % 8) % 2 = n % 2`.
  94    simpa [hr.symm] using (mod_mod_of_dvd n (by decide : 2 ∣ 8))
  95  calc
  96    chi8 n = 0 ↔ chi8 r = 0 := by
  97      constructor
  98      · intro hn0
  99        simpa [hchi.symm] using hn0
 100      · intro hr0
 101        simpa [hchi] using hr0
 102    _ ↔ r % 2 = 0 := hhelp
 103    _ ↔ n % 2 = 0 := by
 104      constructor
 105      · intro hr0
 106        simpa [hmod] using hr0
 107      · intro hn0
 108        simpa [hmod.symm] using hn0
 109    _ ↔ Even n := by
 110      simpa using (Nat.even_iff (n := n)).symm
 111
 112/-- `chi8 n ≠ 0` exactly when `n` is odd. -/
 113theorem chi8_ne_zero_iff_odd (n : ℕ) : chi8 n ≠ 0 ↔ Odd n := by
 114  -- `chi8 n = 0 ↔ Even n`, so negate and rewrite `¬Even ↔ Odd`.
 115  simpa [Nat.not_even_iff_odd] using (not_congr (chi8_eq_zero_iff_even n))
 116
 117/-- If `n` is coprime to `840`, then none of `2,3,5,7` divide `n`. -/
 118theorem wheel840_accepts (n : ℕ) (h : Nat.Coprime n wheel840) :
 119    (¬ 2 ∣ n) ∧ (¬ 3 ∣ n) ∧ (¬ 5 ∣ n) ∧ (¬ 7 ∣ n) := by
 120  have h2 : Nat.Coprime 2 n := (h.coprime_dvd_right (by native_decide : 2 ∣ wheel840)).symm
 121  have h3 : Nat.Coprime 3 n := (h.coprime_dvd_right (by native_decide : 3 ∣ wheel840)).symm
 122  have h5 : Nat.Coprime 5 n := (h.coprime_dvd_right (by native_decide : 5 ∣ wheel840)).symm
 123  have h7 : Nat.Coprime 7 n := (h.coprime_dvd_right (by native_decide : 7 ∣ wheel840)).symm
 124  refine ⟨?_, ?_, ?_, ?_⟩
 125  · exact (Nat.Prime.coprime_iff_not_dvd prime_two).1 h2
 126  · exact (Nat.Prime.coprime_iff_not_dvd prime_three).1 h3
 127  · exact (Nat.Prime.coprime_iff_not_dvd prime_five).1 h5
 128  · exact (Nat.Prime.coprime_iff_not_dvd (by decide : Nat.Prime 7)).1 h7
 129
 130/-! ### Complement: rejection when not coprime -/
 131
 132/-- Any prime divisor of `wheel840` is one of `2,3,5,7`. -/
 133theorem prime_dvd_wheel840 {p : ℕ} (hp : Prime p) (h : p ∣ wheel840) :
 134    p = 2 ∨ p = 3 ∨ p = 5 ∨ p = 7 := by
 135  have hp' : Nat.Prime p := (prime_iff p).1 hp
 136  have h840 : p ∣ (840 : ℕ) := by
 137    simpa [wheel840] using h
 138  have hprod : p ∣ 2^3 * 3 * 5 * 7 := by
 139    simpa [wheel840_factorization] using h840
 140  have h1 : p ∣ (2^3 * 3 * 5) ∨ p ∣ 7 := (hp'.dvd_mul).1 hprod
 141  rcases h1 with h235 | h7
 142  · have h2 : p ∣ (2^3 * 3) ∨ p ∣ 5 := (hp'.dvd_mul).1 h235
 143    rcases h2 with h23 | h5
 144    · have h3 : p ∣ 2^3 ∨ p ∣ 3 := (hp'.dvd_mul).1 h23
 145      rcases h3 with h2pow | h3
 146      · have h2 : p ∣ 2 := hp'.dvd_of_dvd_pow (m := 2) (n := 3) h2pow
 147        exact Or.inl ((Nat.prime_dvd_prime_iff_eq hp' prime_two).1 h2)
 148      · exact Or.inr (Or.inl ((Nat.prime_dvd_prime_iff_eq hp' prime_three).1 h3))
 149    ·
 150      have h5prime : Nat.Prime 5 := (prime_iff 5).1 prime_five
 151      exact Or.inr (Or.inr (Or.inl ((Nat.prime_dvd_prime_iff_eq hp' h5prime).1 h5)))
 152  ·
 153    have h7prime : Nat.Prime 7 := by decide
 154    exact Or.inr (Or.inr (Or.inr ((Nat.prime_dvd_prime_iff_eq hp' h7prime).1 h7)))
 155
 156/-- If `n` is **not** coprime to `840`, then at least one of `2,3,5,7` divides `n`. -/
 157theorem wheel840_rejects (n : ℕ) (h : ¬ Nat.Coprime n wheel840) :
 158    2 ∣ n ∨ 3 ∣ n ∨ 5 ∣ n ∨ 7 ∣ n := by
 159  have hg_ne_one : Nat.gcd n wheel840 ≠ 1 := by
 160    intro hg
 161    apply h
 162    exact (Nat.coprime_iff_gcd_eq_one).2 hg
 163  obtain ⟨p, hpprime, hpdvg⟩ :=
 164    (Nat.ne_one_iff_exists_prime_dvd (n := Nat.gcd n wheel840)).1 hg_ne_one
 165  have hpdvn : p ∣ n := hpdvg.trans (Nat.gcd_dvd_left n wheel840)
 166  have hpdv840 : p ∣ wheel840 := hpdvg.trans (Nat.gcd_dvd_right n wheel840)
 167  have hp : Prime p := by
 168    simpa [Prime] using hpprime
 169  have hp_cases : p = 2 ∨ p = 3 ∨ p = 5 ∨ p = 7 :=
 170    prime_dvd_wheel840 (p := p) hp hpdv840
 171  rcases hp_cases with hp2 | hp_rest
 172  · left
 173    simpa [hp2] using hpdvn
 174  · rcases hp_rest with hp3 | hp_rest2
 175    · exact Or.inr (Or.inl (by simpa [hp3] using hpdvn))
 176    · rcases hp_rest2 with hp5 | hp7
 177      · exact Or.inr (Or.inr (Or.inl (by simpa [hp5] using hpdvn)))
 178      · exact Or.inr (Or.inr (Or.inr (by simpa [hp7] using hpdvn)))
 179
 180/-- A gcd-form of `wheel840_rejects` (sometimes more convenient in proofs). -/
 181theorem wheel840_rejects_of_gcd_ne_one (n : ℕ) (h : Nat.gcd n wheel840 ≠ 1) :
 182    2 ∣ n ∨ 3 ∣ n ∨ 5 ∣ n ∨ 7 ∣ n := by
 183  apply wheel840_rejects (n := n)
 184  intro hc
 185  apply h
 186  exact (Nat.coprime_iff_gcd_eq_one).1 hc
 187
 188end Primes
 189end NumberTheory
 190end IndisputableMonolith
 191

source mirrored from github.com/jonwashburn/shape-of-logic