Skip to content

Commit 06ace73

Browse files
committed
feat(AlgebraicGeometry/EllipticCurve/Weierstrass): elliptic curves with specified j-invariant (#5935)
Main changes: - [x] Define specific Weierstrass curves, whose j-invariants should be 0, 1728, or ≠ 0 and 1728. - [x] Prove the quantities c₄, Δ and j for them (whenever they are defined). - [x] Define an elliptic curve from an element j in a field, whose j-invariant is equal to j. - [x] Generalize `Inhabited (EllipticCurve ℚ)` to `Inhabited (EllipticCurve F)` for any field `F` (computable if `F` has `DecidableEq`).
1 parent daafa2f commit 06ace73

File tree

3 files changed

+182
-6
lines changed

3 files changed

+182
-6
lines changed

Mathlib/AlgebraicGeometry/EllipticCurve/Weierstrass.lean

Lines changed: 172 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ splitting field of `R` are precisely the $X$-coordinates of the non-zero 2-torsi
3232
3333
* `WeierstrassCurve`: a Weierstrass curve over a commutative ring.
3434
* `WeierstrassCurve.Δ`: the discriminant of a Weierstrass curve.
35+
* `WeierstrassCurve.ofJ0`, `WeierstrassCurve.ofJ1728`, `WeierstrassCurve.ofJ`:
36+
Weierstrass curves whose $j$-invariants are $0$, $1728$ and $j\neq 0,1728$, respectively.
3537
* `WeierstrassCurve.VariableChange`: a change of variables of Weierstrass curves.
3638
* `WeierstrassCurve.variableChange`: the Weierstrass curve induced by a change of variables.
3739
* `WeierstrassCurve.baseChange`: the Weierstrass curve base changed over an algebra.
@@ -44,6 +46,9 @@ splitting field of `R` are precisely the $X$-coordinates of the non-zero 2-torsi
4446
* `WeierstrassCurve.CoordinateRing.basis`: the power basis of the coordinate ring over `R[X]`.
4547
* `EllipticCurve`: an elliptic curve over a commutative ring.
4648
* `EllipticCurve.j`: the j-invariant of an elliptic curve.
49+
* `EllipticCurve.ofJ0`, `EllipticCurve.ofJ1728`, `EllipticCurve.ofJ'`: elliptic curves whose
50+
$j$-invariants are $0$, $1728$ and $j\neq 0,1728$, respectively.
51+
* `EllipticCurve.ofJ`: an elliptic curve over a field $F$, whose $j$-invariant equal to $j$.
4752
4853
## Main statements
4954
@@ -58,6 +63,7 @@ splitting field of `R` are precisely the $X$-coordinates of the non-zero 2-torsi
5863
* `EllipticCurve.nonsingular`: an elliptic curve is nonsingular at every point.
5964
* `EllipticCurve.variableChange_j`: the j-invariant of an elliptic curve is invariant under an
6065
admissible linear change of variables.
66+
* `EllipticCurve.ofJ_j`: the $j$-invariant of `EllipticCurve.ofJ` is equal to $j$.
6167
6268
## Implementation notes
6369
@@ -179,6 +185,53 @@ lemma c_relation : 1728 * W.Δ = W.c₄ ^ 3 - W.c₆ ^ 2 := by
179185

180186
end Quantity
181187

188+
section ModelsWithJ
189+
190+
variable (R)
191+
192+
/-- The Weierstrass curve $Y^2 + Y = X^3$.
193+
It is of $j$-invariant $0$ if it is an elliptic curve. -/
194+
def ofJ0 : WeierstrassCurve R :=
195+
0, 0, 1, 0, 0
196+
197+
lemma ofJ0_c₄ : (ofJ0 R).c₄ = 0 := by
198+
rw [ofJ0, c₄, b₂, b₄]
199+
norm_num1
200+
201+
lemma ofJ0_Δ : (ofJ0 R).Δ = -27 := by
202+
rw [ofJ0, Δ, b₂, b₄, b₆, b₈]
203+
norm_num1
204+
205+
/-- The Weierstrass curve $Y^2 = X^3 + X$.
206+
It is of $j$-invariant $1728$ if it is an elliptic curve. -/
207+
def ofJ1728 : WeierstrassCurve R :=
208+
0, 0, 0, 1, 0
209+
210+
lemma ofJ1728_c₄ : (ofJ1728 R).c₄ = -48 := by
211+
rw [ofJ1728, c₄, b₂, b₄]
212+
norm_num1
213+
214+
lemma ofJ1728_Δ : (ofJ1728 R).Δ = -64 := by
215+
rw [ofJ1728, Δ, b₂, b₄, b₆, b₈]
216+
norm_num1
217+
218+
variable {R} (j : R)
219+
220+
/-- The Weierstrass curve $Y^2 + (j - 1728)XY = X^3 - 36(j - 1728)^3X - (j - 1728)^5$.
221+
It is of $j$-invariant $j$ if it is an elliptic curve. -/
222+
def ofJ : WeierstrassCurve R :=
223+
⟨j - 1728, 0, 0, -36 * (j - 1728) ^ 3, -(j - 1728) ^ 5
224+
225+
lemma ofJ_c₄ : (ofJ j).c₄ = j * (j - 1728) ^ 3 := by
226+
simp only [ofJ, c₄, b₂, b₄]
227+
ring1
228+
229+
lemma ofJ_Δ : (ofJ j).Δ = j ^ 2 * (j - 1728) ^ 9 := by
230+
simp only [ofJ, Δ, b₂, b₄, b₆, b₈]
231+
ring1
232+
233+
end ModelsWithJ
234+
182235
section VariableChange
183236

184237
/-! ### Variable changes -/
@@ -1065,12 +1118,6 @@ add_decl_doc Δ'
10651118
/-- The discriminant of `E` is equal to the discriminant of `E` as a Weierstrass curve. -/
10661119
add_decl_doc coe_Δ'
10671120

1068-
instance instInhabitedEllipticCurve : Inhabited <| EllipticCurve ℚ :=
1069-
⟨⟨⟨0, 0, 1, -1, 0⟩, ⟨37, 37⁻¹, by norm_num1, by norm_num1⟩,
1070-
by simp only [WeierstrassCurve.b₂, WeierstrassCurve.b₄, WeierstrassCurve.b₆,
1071-
WeierstrassCurve.b₈, WeierstrassCurve.Δ]; ring1⟩⟩
1072-
#align elliptic_curve.inhabited EllipticCurve.instInhabitedEllipticCurve
1073-
10741121
variable [CommRing R] (E : EllipticCurve R)
10751122

10761123
-- porting note: removed `@[simp]` to avoid a `simpNF` linter error
@@ -1088,6 +1135,125 @@ lemma nonsingular [Nontrivial R] {x y : R} (h : E.equation x y) : E.nonsingular
10881135
E.nonsingular_of_Δ_ne_zero h <| E.coe_Δ' ▸ E.Δ'.ne_zero
10891136
#align elliptic_curve.nonsingular EllipticCurve.nonsingular
10901137

1138+
section ModelsWithJ
1139+
1140+
variable (R)
1141+
1142+
/-- When $3$ is invertible, $Y^2 + Y = X^3$ is an elliptic curve.
1143+
It is of $j$-invariant $0$ (see `EllipticCurve.ofJ0_j`). -/
1144+
def ofJ0 [Invertible (3 : R)] : EllipticCurve R :=
1145+
have := invertibleNeg (3 ^ 3 : R)
1146+
⟨WeierstrassCurve.ofJ0 R, unitOfInvertible (-3 ^ 3 : R),
1147+
by rw [unitOfInvertible_val, WeierstrassCurve.ofJ0_Δ R]; norm_num1⟩
1148+
1149+
lemma ofJ0_j [Invertible (3 : R)] : (ofJ0 R).j = 0 := by
1150+
simp only [j, ofJ0, WeierstrassCurve.ofJ0_c₄]
1151+
ring1
1152+
1153+
/-- When $2$ is invertible, $Y^2 = X^3 + X$ is an elliptic curve.
1154+
It is of $j$-invariant $1728$ (see `EllipticCurve.ofJ1728_j`). -/
1155+
def ofJ1728 [Invertible (2 : R)] : EllipticCurve R :=
1156+
have := invertibleNeg (2 ^ 6 : R)
1157+
⟨WeierstrassCurve.ofJ1728 R, unitOfInvertible (-2 ^ 6 : R),
1158+
by rw [unitOfInvertible_val, WeierstrassCurve.ofJ1728_Δ R]; norm_num1⟩
1159+
1160+
lemma ofJ1728_j [Invertible (2 : R)] : (ofJ1728 R).j = 1728 := by
1161+
field_simp [j, ofJ1728, @unitOfInvertible_val _ _ _ <| invertibleNeg _,
1162+
WeierstrassCurve.ofJ1728_c₄]
1163+
norm_num1
1164+
1165+
variable {R}
1166+
1167+
/-- When $j$ and $j - 1728$ are both invertible,
1168+
$Y^2 + (j - 1728)XY = X^3 - 36(j - 1728)^3X - (j - 1728)^5$ is an elliptic curve.
1169+
It is of $j$-invariant $j$ (see `EllipticCurve.ofJ'_j`). -/
1170+
def ofJ' (j : R) [Invertible j] [Invertible (j - 1728)] : EllipticCurve R :=
1171+
have := invertibleMul (j ^ 2) ((j - 1728) ^ 9)
1172+
⟨WeierstrassCurve.ofJ j, unitOfInvertible <| j ^ 2 * (j - 1728) ^ 9,
1173+
(WeierstrassCurve.ofJ_Δ j).symm⟩
1174+
1175+
lemma ofJ'_j (j : R) [Invertible j] [Invertible (j - 1728)] : (ofJ' j).j = j := by
1176+
field_simp [EllipticCurve.j, ofJ', @unitOfInvertible_val _ _ _ <| invertibleMul _ _,
1177+
WeierstrassCurve.ofJ_c₄]
1178+
ring1
1179+
1180+
variable {F : Type u} [Field F] (j : F)
1181+
1182+
private lemma two_or_three_ne_zero : (2 : F) ≠ 0 ∨ (3 : F) ≠ 0 :=
1183+
ne_zero_or_ne_zero_of_nat_coprime (show Nat.coprime 2 3 by norm_num1)
1184+
1185+
variable [DecidableEq F]
1186+
1187+
/-- For any element $j$ of a field $F$, there exists an elliptic curve over $F$
1188+
with $j$-invariant equal to $j$ (see `EllipticCurve.ofJ_j`).
1189+
Its coefficients are given explicitly (see `EllipticCurve.ofJ0`, `EllipticCurve.ofJ1728`
1190+
and `EllipticCurve.ofJ'`). -/
1191+
def ofJ : EllipticCurve F :=
1192+
if h0 : j = 0 then
1193+
if h3 : (3 : F) = 0 then @ofJ1728 _ _ <| invertibleOfNonzero <|
1194+
two_or_three_ne_zero.neg_resolve_right h3
1195+
else @ofJ0 _ _ <| invertibleOfNonzero h3
1196+
else if h1728 : j = 1728 then
1197+
@ofJ1728 _ _ <| invertibleOfNonzero fun h => h0 <|
1198+
by rw [h1728, show (1728 : F) = 2 * 864 by norm_num1, h, zero_mul]
1199+
else @ofJ' _ _ j (invertibleOfNonzero h0) (invertibleOfNonzero <| sub_ne_zero_of_ne h1728)
1200+
1201+
lemma ofJ_0_of_three_ne_zero [h3 : NeZero (3 : F)] :
1202+
ofJ 0 = @ofJ0 _ _ (invertibleOfNonzero h3.out) := by
1203+
rw [ofJ, dif_pos rfl, dif_neg h3.out]
1204+
1205+
lemma ofJ_0_of_three_eq_zero (h3 : (3 : F) = 0) :
1206+
ofJ 0 = @ofJ1728 _ _ (invertibleOfNonzero <| two_or_three_ne_zero.neg_resolve_right h3) := by
1207+
rw [ofJ, dif_pos rfl, dif_pos h3]
1208+
1209+
lemma ofJ_0_of_two_eq_zero (h2 : (2 : F) = 0) :
1210+
ofJ 0 = @ofJ0 _ _ (invertibleOfNonzero <| two_or_three_ne_zero.neg_resolve_left h2) :=
1211+
have := neZero_iff.2 <| two_or_three_ne_zero.neg_resolve_left h2
1212+
ofJ_0_of_three_ne_zero
1213+
1214+
lemma ofJ_1728_of_three_eq_zero (h3 : (3 : F) = 0) :
1215+
ofJ 1728 = @ofJ1728 _ _ (invertibleOfNonzero <| two_or_three_ne_zero.neg_resolve_right h3) := by
1216+
rw [ofJ, dif_pos <| by rw [show (1728 : F) = 3 * 576 by norm_num1, h3, zero_mul], dif_pos h3]
1217+
1218+
lemma ofJ_1728_of_two_ne_zero [h2 : NeZero (2 : F)] :
1219+
ofJ 1728 = @ofJ1728 _ _ (invertibleOfNonzero h2.out) := by
1220+
by_cases h3 : (3 : F) = 0
1221+
· exact ofJ_1728_of_three_eq_zero h3
1222+
· have h : (1728 : F) ≠ 0 := fun h => or_iff_not_and_not.mp
1223+
(mul_eq_zero.mp <| by rwa [show 2 ^ 6 * 3 ^ 3 = (1728 : F) by norm_num1])
1224+
⟨pow_ne_zero 6 h2.out, pow_ne_zero 3 h3⟩
1225+
rw [ofJ, dif_neg h, dif_pos rfl]
1226+
1227+
lemma ofJ_1728_of_two_eq_zero (h2 : (2 : F) = 0) :
1228+
ofJ 1728 = @ofJ0 _ _ (invertibleOfNonzero <| two_or_three_ne_zero.neg_resolve_left h2) := by
1229+
rw [ofJ, dif_pos <| by rw [show (1728 : F) = 2 * 864 by norm_num1, h2, zero_mul], dif_neg]
1230+
1231+
lemma ofJ_ne_0_ne_1728 (h0 : j ≠ 0) (h1728 : j ≠ 1728) :
1232+
ofJ j =
1233+
@ofJ' _ _ j (invertibleOfNonzero h0) (invertibleOfNonzero <| sub_ne_zero_of_ne h1728) := by
1234+
rw [ofJ, dif_neg h0, dif_neg h1728]
1235+
1236+
lemma ofJ_j : (ofJ j).j = j := by
1237+
by_cases h0 : j = 0
1238+
· by_cases h3 : (3 : F) = 0
1239+
· rw [h0, ofJ_0_of_three_eq_zero h3,
1240+
@ofJ1728_j _ _ <| invertibleOfNonzero <| two_or_three_ne_zero.neg_resolve_right h3,
1241+
show (1728 : F) = 3 * 576 by norm_num1, h3, zero_mul]
1242+
· rw [h0, ofJ_0_of_three_ne_zero (h3 := neZero_iff.2 h3), @ofJ0_j _ _ <| invertibleOfNonzero h3]
1243+
· by_cases h1728 : j = 1728
1244+
· have h2 : (2 : F) ≠ 0 :=
1245+
fun h => h0 <| by rw [h1728, show (1728 : F) = 2 * 864 by norm_num1, h, zero_mul]
1246+
rw [h1728, ofJ_1728_of_two_ne_zero (h2 := neZero_iff.2 h2),
1247+
@ofJ1728_j _ _ <| invertibleOfNonzero h2]
1248+
· rw [ofJ_ne_0_ne_1728 j h0 h1728,
1249+
@ofJ'_j _ _ _ (invertibleOfNonzero h0) (invertibleOfNonzero <| sub_ne_zero_of_ne h1728)]
1250+
1251+
instance instInhabitedEllipticCurve : Inhabited <| EllipticCurve F :=
1252+
⟨ofJ 37
1253+
#align elliptic_curve.inhabited EllipticCurve.instInhabitedEllipticCurve
1254+
1255+
end ModelsWithJ
1256+
10911257
section VariableChange
10921258

10931259
/-! ### Variable changes -/

Mathlib/RingTheory/Coprime/Basic.lean

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ theorem IsCoprime.ne_zero [Nontrivial R] {p : Fin 2 → R} (h : IsCoprime (p 0)
7676
exact not_isCoprime_zero_zero h
7777
#align is_coprime.ne_zero IsCoprime.ne_zero
7878

79+
theorem IsCoprime.ne_zero_or_ne_zero [Nontrivial R] (h : IsCoprime x y) : x ≠ 0 ∨ y ≠ 0 := by
80+
apply not_or_of_imp
81+
rintro rfl rfl
82+
exact not_isCoprime_zero_zero h
83+
7984
theorem isCoprime_one_left : IsCoprime 1 x :=
8085
1, 0, by rw [one_mul, zero_mul, add_zero]⟩
8186
#align is_coprime_one_left isCoprime_one_left

Mathlib/RingTheory/Coprime/Lemmas.lean

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ alias Nat.isCoprime_iff_coprime ↔ IsCoprime.nat_coprime Nat.coprime.isCoprime
4747
#align is_coprime.nat_coprime IsCoprime.nat_coprime
4848
#align nat.coprime.is_coprime Nat.coprime.isCoprime
4949

50+
theorem ne_zero_or_ne_zero_of_nat_coprime {A : Type u} [CommRing A] [Nontrivial A] {a b : ℕ}
51+
(h : Nat.coprime a b) : (a : A) ≠ 0 ∨ (b : A) ≠ 0 :=
52+
IsCoprime.ne_zero_or_ne_zero (R := A) <| by
53+
simpa only [map_natCast] using IsCoprime.map (Nat.coprime.isCoprime h) (Int.castRingHom A)
54+
5055
theorem IsCoprime.prod_left : (∀ i ∈ t, IsCoprime (s i) x) → IsCoprime (∏ i in t, s i) x :=
5156
Finset.induction_on t (fun _ ↦ isCoprime_one_left) fun b t hbt ih H ↦ by
5257
rw [Finset.prod_insert hbt]

0 commit comments

Comments
 (0)