Skip to content

Commit ac1b4db

Browse files
committed
feat(NumberTheory/EllipticDivisibilitySequence): add some lemmas and grind some proofs (#42477)
Also rename `odd` to `neg` because `odd` will be reserved for odd elliptic relations.
1 parent dda78df commit ac1b4db

2 files changed

Lines changed: 95 additions & 53 deletions

File tree

Mathlib/Data/Nat/DvdSequence.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ protected theorem smul [Dvd α] [Monoid β] [Monoid γ] {f : α → γ} [SMul β
6666
IsDvdSequence (b • f) :=
6767
.smul' (.const α b) hg
6868

69+
protected theorem comp [Dvd α] [Dvd β] [Dvd γ] {f : α → β} {g : β → γ} (hf : IsDvdSequence f)
70+
(hg : IsDvdSequence g) : IsDvdSequence (g ∘ f) :=
71+
fun _ _ ↦ hg _ _ ∘ hf _ _
72+
6973
end IsDvdSequence
7074

7175
@[deprecated (since := "2026-06-30")] alias IsDivSequence.smul := IsDvdSequence.smul

Mathlib/NumberTheory/EllipticDivisibilitySequence.lean

Lines changed: 91 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ public import Mathlib.Algebra.Group.EvenFunction
99
public import Mathlib.Data.Nat.DvdSequence
1010
public import Mathlib.Data.Nat.EvenOddRec
1111
public import Mathlib.Tactic.Linarith
12-
public import Mathlib.Tactic.LinearCombination
1312
public import Mathlib.Tactic.Ring
1413
import Mathlib.Algebra.Group.Int.Even
15-
import Mathlib.Data.Int.ModEq
1614

1715
/-!
1816
# Elliptic divisibility sequences
@@ -117,18 +115,18 @@ lemma atom_same (a : ℤ) : atom W a a = W a * W 0 := by
117115

118116
variable {W} in
119117
@[simp]
120-
lemma neg_atom (odd : W.Odd) (a b : ℤ) : -atom W a b = atom W b a := by
121-
rw [atom, atom, add_comm, ← neg_sub a, Int.neg_tdiv, odd, mul_neg]
118+
lemma neg_atom (neg : W.Odd) (a b : ℤ) : -atom W a b = atom W b a := by
119+
rw [atom, atom, add_comm, ← neg_sub a, Int.neg_tdiv, neg, mul_neg]
122120

123121
variable {W} in
124-
lemma atom_mul_atom (odd : W.Odd) (a b c d : ℤ) :
122+
lemma atom_mul_atom (neg : W.Odd) (a b c d : ℤ) :
125123
atom W a b * atom W c d = atom W b a * atom W d c := by
126-
rw [← neg_atom odd a b, ← neg_atom odd c d, neg_mul_neg]
124+
rw [← neg_atom neg a b, ← neg_atom neg c d, neg_mul_neg]
127125

128126
variable {W} in
129127
@[simp]
130-
lemma atom_neg_left (odd : W.Odd) (a b : ℤ) : atom W (-a) b = atom W a b := by
131-
rw [atom, atom, neg_add_eq_sub, ← neg_sub a, ← neg_add', Int.neg_tdiv, odd, Int.neg_tdiv, odd,
128+
lemma atom_neg_left (neg : W.Odd) (a b : ℤ) : atom W (-a) b = atom W a b := by
129+
rw [atom, atom, neg_add_eq_sub, ← neg_sub a, ← neg_add', Int.neg_tdiv, neg, Int.neg_tdiv, neg,
132130
neg_mul_neg, mul_comm]
133131

134132
@[simp]
@@ -137,8 +135,8 @@ lemma atom_neg_right (a b : ℤ) : atom W a (-b) = atom W a b := by
137135

138136
variable {W} in
139137
@[simp]
140-
lemma atom_abs_left (odd : W.Odd) (a b : ℤ) : atom W |a| b = atom W a b := by
141-
rcases abs_choice a with h | h <;> simp only [h, atom_neg_left odd]
138+
lemma atom_abs_left (neg : W.Odd) (a b : ℤ) : atom W |a| b = atom W a b := by
139+
rcases abs_choice a with h | h <;> simp only [h, atom_neg_left neg]
142140

143141
@[simp]
144142
lemma atom_abs_right (a b : ℤ) : atom W a |b| = atom W a b := by
@@ -162,77 +160,106 @@ def atomRel (a b c d : ℤ) : R :=
162160

163161
@[simp]
164162
lemma atomRel_same₁₂ (a b c : ℤ) : atomRel W a a b c = W a * W 0 * atom W b c := by
165-
simp_rw [atomRel, atom_same, mul_comm <| atom W a b, sub_add_cancel]
163+
grind only [atomRel, atom_same]
166164

167165
variable {W} in
168166
@[simp]
169-
lemma atomRel_same₁₃ (odd : W.Odd) (a b c : ℤ) : atomRel W a b a c = W a * W 0 * atom W c b := by
170-
linear_combination (norm := (simp_rw [atomRel, atom_same]; ring1))
171-
W a * W 0 * neg_atom odd c b - atom W a c * neg_atom odd a b
167+
lemma atomRel_same₁₃ (neg : W.Odd) (a b c : ℤ) : atomRel W a b a c = W a * W 0 * atom W c b := by
168+
grind only [atomRel, atom_same, neg_atom]
172169

173170
variable {W} in
174171
@[simp]
175-
lemma atomRel_same₁₄ (odd : W.Odd) (a b c : ℤ) : atomRel W a b c a = W a * W 0 * atom W b c := by
176-
simp_rw [atomRel, atom_mul_atom odd a b, mul_comm <| atom W b a, sub_self, zero_add, atom_same]
172+
lemma atomRel_same₁₄ (neg : W.Odd) (a b c : ℤ) : atomRel W a b c a = W a * W 0 * atom W b c := by
173+
grind only [atomRel, atom_same, neg_atom]
177174

178175
@[simp]
179176
lemma atomRel_same₂₃ (a b c : ℤ) : atomRel W a b b c = W b * W 0 * atom W a c := by
180-
simp_rw [atomRel, atom_same, sub_self, zero_add, mul_comm]
177+
grind only [atomRel, atom_same, neg_atom]
181178

182179
variable {W} in
183180
@[simp]
184-
lemma atomRel_same₂₄ (odd : W.Odd) (a b c : ℤ) : atomRel W a b c b = W b * W 0 * atom W c a := by
185-
linear_combination (norm := (simp_rw [atomRel, atom_same]; ring1))
186-
W b * W 0 * neg_atom odd a c - atom W a b * neg_atom odd b c
181+
lemma atomRel_same₂₄ (neg : W.Odd) (a b c : ℤ) : atomRel W a b c b = W b * W 0 * atom W c a := by
182+
grind only [atomRel, atom_same, neg_atom]
187183

188184
@[simp]
189185
lemma atomRel_same₃₄ (a b c : ℤ) : atomRel W a b c c = W c * W 0 * atom W a b := by
190-
simp_rw [atomRel, atom_same, mul_comm, sub_add_cancel]
186+
grind only [atomRel, atom_same]
187+
188+
variable {W} in
189+
lemma neg_atomRel₁₂ (neg : W.Odd) (a b c d : ℤ) : -atomRel W a b c d = atomRel W b a c d := by
190+
grind only [atomRel, neg_atom]
191+
192+
variable {W} in
193+
lemma neg_atomRel₂₃ (neg : W.Odd) (a b c d : ℤ) : -atomRel W a b c d = atomRel W a c b d := by
194+
grind only [atomRel, neg_atom]
195+
196+
variable {W} in
197+
lemma neg_atomRel₃₄ (neg : W.Odd) (a b c d : ℤ) : -atomRel W a b c d = atomRel W a b d c := by
198+
grind only [atomRel, neg_atom]
191199

192200
variable {W} in
193201
@[simp]
194-
lemma atomRel_neg₁ (odd : W.Odd) (a b c d : ℤ) : atomRel W (-a) b c d = atomRel W a b c d := by
195-
simp_rw [atomRel, atom_neg_left odd]
202+
lemma atomRel_neg₁ (neg : W.Odd) (a b c d : ℤ) : atomRel W (-a) b c d = atomRel W a b c d := by
203+
simp_rw [atomRel, atom_neg_left neg]
196204

197205
variable {W} in
198206
@[simp]
199-
lemma atomRel_neg₂ (odd : W.Odd) (a b c d : ℤ) : atomRel W a (-b) c d = atomRel W a b c d := by
200-
simp_rw [atomRel, atom_neg_left odd, atom_neg_right]
207+
lemma atomRel_neg₂ (neg : W.Odd) (a b c d : ℤ) : atomRel W a (-b) c d = atomRel W a b c d := by
208+
simp_rw [atomRel, atom_neg_left neg, atom_neg_right]
201209

202210
variable {W} in
203211
@[simp]
204-
lemma atomRel_neg₃ (odd : W.Odd) (a b c d : ℤ) : atomRel W a b (-c) d = atomRel W a b c d := by
205-
simp_rw [atomRel, atom_neg_left odd, atom_neg_right]
212+
lemma atomRel_neg₃ (neg : W.Odd) (a b c d : ℤ) : atomRel W a b (-c) d = atomRel W a b c d := by
213+
simp_rw [atomRel, atom_neg_left neg, atom_neg_right]
206214

207215
@[simp]
208216
lemma atomRel_neg₄ (a b c d : ℤ) : atomRel W a b c (-d) = atomRel W a b c d := by
209217
simp_rw [atomRel, atom_neg_right]
210218

219+
variable {W} in
220+
lemma atomRel_neg (neg : W.Odd) (a b c d : ℤ) :
221+
atomRel W (-a) (-b) (-c) (-d) = atomRel W a b c d := by
222+
rw [atomRel_neg₁ neg, atomRel_neg₂ neg, atomRel_neg₃ neg, atomRel_neg₄]
223+
211224
variable {W} in
212225
@[simp]
213-
lemma atomRel_abs₁ (odd : W.Odd) (a b c d : ℤ) : atomRel W |a| b c d = atomRel W a b c d := by
214-
simp_rw [atomRel, atom_abs_left odd]
226+
lemma atomRel_abs₁ (neg : W.Odd) (a b c d : ℤ) : atomRel W |a| b c d = atomRel W a b c d := by
227+
simp_rw [atomRel, atom_abs_left neg]
215228

216229
variable {W} in
217230
@[simp]
218-
lemma atomRel_abs₂ (odd : W.Odd) (a b c d : ℤ) : atomRel W a |b| c d = atomRel W a b c d := by
219-
simp_rw [atomRel, atom_abs_left odd, atom_abs_right]
231+
lemma atomRel_abs₂ (neg : W.Odd) (a b c d : ℤ) : atomRel W a |b| c d = atomRel W a b c d := by
232+
simp_rw [atomRel, atom_abs_left neg, atom_abs_right]
220233

221234
variable {W} in
222235
@[simp]
223-
lemma atomRel_abs₃ (odd : W.Odd) (a b c d : ℤ) : atomRel W a b |c| d = atomRel W a b c d := by
224-
simp_rw [atomRel, atom_abs_left odd, atom_abs_right]
236+
lemma atomRel_abs₃ (neg : W.Odd) (a b c d : ℤ) : atomRel W a b |c| d = atomRel W a b c d := by
237+
simp_rw [atomRel, atom_abs_left neg, atom_abs_right]
225238

226239
@[simp]
227240
lemma atomRel_abs₄ (a b c d : ℤ) : atomRel W a b c |d| = atomRel W a b c d := by
228241
simp_rw [atomRel, atom_abs_right]
229242

230-
lemma atomRel_avg_sub {a b c d : ℤ} (parity : d % 2 = a % 2 ∧ d % 2 = b % 2 ∧ d % 2 = c % 2) :
243+
variable {W} in
244+
lemma atomRel_abs (neg : W.Odd) (a b c d : ℤ) : atomRel W |a| |b| |c| |d| = atomRel W a b c d := by
245+
rw [atomRel_abs₁ neg, atomRel_abs₂ neg, atomRel_abs₃ neg, atomRel_abs₄]
246+
247+
lemma atomRel_avg_sub {a b c d : ℤ} (parity : [a, b, c, d].Pairwise (· % 2 = · % 2)) :
231248
atomRel W ((a + b + c + d) / 2 - d) ((a + b + c + d) / 2 - c) ((a + b + c + d) / 2 - b)
232249
((a + b + c + d) / 2 - a) = atomRel W a b c d := by
233250
simp_rw [add_assoc <| a + b, atomRel, atom, sub_add_sub_comm, ← two_mul]
234251
repeat rw [Int.mul_ediv_cancel'] <;> grind
235252

253+
/-- The even elliptic relator `ERₐ(2 * m + 2, 2 * m - 2, 2, 0)` for all `m ∈ ℤ`. -/
254+
lemma atomRel_even (m : ℤ) : atomRel W (2 * m + 2) (2 * m - 2) 2 0 = W (2 * m) * W 2 * W 1 ^ 2 -
255+
W (m - 1) ^ 2 * W m * W (m + 2) + W (m - 2) * W m * W (m + 1) ^ 2 := by
256+
grind only [atomRel, atom]
257+
258+
/-- The odd elliptic relator `ERₐ(2 * m + 2, 2 * m, 2, 0)` for all `m ∈ ℤ`. -/
259+
lemma atomRel_odd (m : ℤ) : atomRel W (2 * m + 2) (2 * m) 2 0 =
260+
W (2 * m + 1) * W 1 ^ 3 - W (m + 2) * W m ^ 3 + W (m - 1) * W (m + 1) ^ 3 := by
261+
grind only [atomRel, atom]
262+
236263
lemma map_atomRel (a b c d : ℤ) : f (atomRel W a b c d) = atomRel (f ∘ W) a b c d := by
237264
simp_rw [atomRel, map_add, map_sub, map_mul, map_atom]
238265

@@ -250,28 +277,24 @@ lemma atomRel_two_mul (a b c d : ℤ) :
250277
atomRel W (2 * a) (2 * b) (2 * c) (2 * d) = rel W (a - d) (b - d) (c - d) (2 * d) := by
251278
simp_rw [rel_eq, mul_sub, sub_add_cancel]
252279

253-
lemma atomRel_eq {a b c d : ℤ} (parity : d % 2 = a % 2 ∧ d % 2 = b % 2 ∧ d % 2 = c % 2) :
280+
lemma atomRel_eq {a b c d : ℤ} (parity : [a, b, c, d].Pairwise (· % 2 = · % 2)) :
254281
atomRel W a b c d = rel W ((a - d) / 2) ((b - d) / 2) ((c - d) / 2) d := by
255-
simp only [rel_eq, Int.mul_ediv_cancel', Int.ModEq.dvd parity.1, Int.ModEq.dvd parity.2.1,
256-
Int.ModEq.dvd parity.2.2, sub_add_cancel]
282+
grind [rel_eq]
257283

258284
variable {W} in
259285
@[simp]
260-
lemma rel_neg (odd : W.Odd) (p q r s : ℤ) : rel W (-p) (-q) (-r) (-s) = rel W p q r s := by
261-
simp_rw [rel_eq, mul_neg, ← neg_add, atomRel_neg₁ odd, atomRel_neg₂ odd, atomRel_neg₃ odd,
262-
atomRel_neg₄]
286+
lemma rel_neg (neg : W.Odd) (p q r s : ℤ) : rel W (-p) (-q) (-r) (-s) = rel W p q r s := by
287+
simp_rw [rel_eq, mul_neg, ← neg_add, atomRel_neg neg]
263288

264-
/-- The even elliptic relator `ER(m + 1, m - 1, 1, 0)` for `m ∈ ℤ`. -/
289+
/-- The even elliptic relator `ER(m + 1, m - 1, 1, 0)` for all `m ∈ ℤ`. -/
265290
lemma rel_even (m : ℤ) : rel W (m + 1) (m - 1) 1 0 = W (2 * m) * W 2 * W 1 ^ 2 -
266291
W (m - 1) ^ 2 * W m * W (m + 2) + W (m - 2) * W m * W (m + 1) ^ 2 := by
267-
rw [rel]
268-
ring_nf
292+
grind only [rel]
269293

270-
/-- The odd elliptic relator `ER(m + 1, m, 1, 0)` for `m ∈ ℤ`. -/
294+
/-- The odd elliptic relator `ER(m + 1, m, 1, 0)` for all `m ∈ ℤ`. -/
271295
lemma rel_odd (m : ℤ) : rel W (m + 1) m 1 0 =
272296
W (2 * m + 1) * W 1 ^ 3 - W (m + 2) * W m ^ 3 + W (m - 1) * W (m + 1) ^ 3 := by
273-
rw [rel]
274-
ring_nf
297+
grind only [rel]
275298

276299
lemma map_rel (p q r s : ℤ) : f (rel W p q r s) = rel (f ∘ W) p q r s := by
277300
simp_rw [rel, map_add, map_sub, map_mul, Function.comp]
@@ -304,8 +327,11 @@ lemma isEllipticSequence (h : IsEllipticNet W) : IsEllipticSequence W :=
304327
protected lemma id : IsEllipticNet (id : ℤ → ℤ) :=
305328
fun _ _ _ _ ↦ by simp_rw [rel, id_eq]; ring1
306329

307-
protected lemma smul (h : IsEllipticNet W) (x : R) : IsEllipticNet <| x • W := fun p q r s ↦ by
308-
linear_combination (norm := (simp_rw [rel, Pi.smul_apply, smul_eq_mul]; ring1)) x ^ 4 * h p q r s
330+
protected lemma smul (h : IsEllipticNet W) (x : R) : IsEllipticNet <| x • W :=
331+
fun p q r s ↦ by grind [rel, h p q r s, Pi.smul_apply, smul_eq_mul]
332+
333+
protected lemma comp (h : IsEllipticNet W) (f : F) : IsEllipticNet <| f ∘ W :=
334+
fun _ _ _ _ ↦ by rw [← map_rel, h, map_zero]
309335

310336
end IsEllipticNet
311337

@@ -317,7 +343,10 @@ protected lemma id : IsEllipticSequence (id : ℤ → ℤ) :=
317343
IsEllipticNet.id.isEllipticSequence
318344

319345
protected lemma smul (h : IsEllipticSequence W) (x : R) : IsEllipticSequence <| x • W :=
320-
fun p q r ↦ by linear_combination (norm := (simp [IsEllipticNet.rel]; ring1)) x ^ 4 * h p q r
346+
fun p q r ↦ by grind [IsEllipticNet.rel, h p q r, Pi.smul_apply, smul_eq_mul]
347+
348+
protected lemma comp (h : IsEllipticSequence W) (f : F) : IsEllipticSequence <| f ∘ W :=
349+
fun _ _ _ ↦ by rw [← IsEllipticNet.map_rel, h, map_zero]
321350

322351
end IsEllipticSequence
323352

@@ -335,6 +364,9 @@ protected theorem id : IsEllipticDvdSequence (id : ℤ → ℤ) :=
335364
protected lemma smul (h : IsEllipticDvdSequence W) (x : R) : IsEllipticDvdSequence <| x • W :=
336365
⟨h.left.smul x, h.right.smul x⟩
337366

367+
protected lemma comp (h : IsEllipticDvdSequence W) (f : F) : IsEllipticDvdSequence <| f ∘ W :=
368+
⟨h.left.comp f, h.right.comp fun _ _ ↦ map_dvd _⟩
369+
338370
end IsEllipticDvdSequence
339371

340372
@[deprecated (since := "2026-06-30")] alias isEllDivSequence_id := IsEllipticDvdSequence.id
@@ -357,8 +389,7 @@ def preNormEDS' : ℕ → R
357389
preNormEDS' (m + 4) * preNormEDS' (m + 2) ^ 3 * (if Even m then b else 1) -
358390
preNormEDS' (m + 1) * preNormEDS' (m + 3) ^ 3 * (if Even m then 1 else b)
359391
else
360-
have : m + 5 < n + 5 := by
361-
gcongr; exact Nat.div_lt_self (Nat.not_even_iff_odd.mp hn).pos one_lt_two
392+
have : m + 5 < n + 5 := by grind
362393
preNormEDS' (m + 2) ^ 2 * preNormEDS' (m + 3) * preNormEDS' (m + 5) -
363394
preNormEDS' (m + 1) * preNormEDS' (m + 3) * preNormEDS' (m + 4) ^ 2
364395

@@ -573,6 +604,14 @@ lemma normEDS_odd (m : ℤ) : normEDS b c d (2 * m + 1) =
573604
even_two, iff_true, Int.not_even_one, iff_false]
574605
split_ifs <;> ring1
575606

607+
lemma normEDS_atomRel_even (m : ℤ) :
608+
IsEllipticNet.atomRel (normEDS b c d) (2 * m + 2) (2 * m - 2) 2 0 = 0 := by
609+
simp [IsEllipticNet.atomRel_even, normEDS_even]
610+
611+
lemma normEDS_atomRel_odd (m : ℤ) :
612+
IsEllipticNet.atomRel (normEDS b c d) (2 * m + 2) (2 * m) 2 0 = 0 := by
613+
simp [IsEllipticNet.atomRel_odd, normEDS_odd]
614+
576615
/--
577616
Strong recursion principle for a normalised EDS: if we have
578617
* `P 0`, `P 1`, `P 2`, `P 3`, and `P 4`,
@@ -621,8 +660,7 @@ def complEDS' : ℕ → R
621660
| 1 => 1
622661
| (n + 2) => let m := n / 2 + 1
623662
if hn : Even n then complEDS' m * complEDS₂ b c d (m * k) else
624-
have : m + 1 < n + 2 :=
625-
add_lt_add_left (Nat.div_lt_self (Nat.not_even_iff_odd.mp hn).pos one_lt_two) 2
663+
have : m + 1 < n + 2 := by grind
626664
complEDS' m ^ 2 * normEDS b c d ((m + 1) * k + 1) * normEDS b c d ((m + 1) * k - 1) -
627665
complEDS' (m + 1) ^ 2 * normEDS b c d (m * k + 1) * normEDS b c d (m * k - 1)
628666

0 commit comments

Comments
 (0)