|
| 1 | +/- |
| 2 | +Copyright (c) 2022 David Kurniadi Angdinata. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: David Kurniadi Angdinata |
| 5 | +-/ |
| 6 | + |
| 7 | +import field_theory.splitting_field |
| 8 | + |
| 9 | +/-! |
| 10 | +# Cubics and discriminants |
| 11 | +
|
| 12 | +This file defines cubic polynomials over a semiring and their discriminants over a splitting field. |
| 13 | +
|
| 14 | +## Main definitions |
| 15 | +
|
| 16 | +* `cubic`: the structure representing a cubic polynomial. |
| 17 | +* `disc`: the discriminant of a cubic polynomial. |
| 18 | +
|
| 19 | +## Main statements |
| 20 | +
|
| 21 | +* `disc_ne_zero_iff_roots_nodup`: the cubic discriminant is not equal to zero if and only if |
| 22 | + the cubic has no duplicate roots. |
| 23 | +
|
| 24 | +## References |
| 25 | +
|
| 26 | +* https://en.wikipedia.org/wiki/Cubic_equation |
| 27 | +* https://en.wikipedia.org/wiki/Discriminant |
| 28 | +
|
| 29 | +## Tags |
| 30 | +
|
| 31 | +cubic, discriminant, polynomial, root |
| 32 | +-/ |
| 33 | + |
| 34 | +noncomputable theory |
| 35 | + |
| 36 | +/-- The structure representing a cubic polynomial. -/ |
| 37 | +@[ext] structure cubic (R : Type*) := (a b c d : R) |
| 38 | + |
| 39 | +namespace cubic |
| 40 | + |
| 41 | +open cubic polynomial |
| 42 | + |
| 43 | +variables {R S F K : Type*} |
| 44 | + |
| 45 | +instance [inhabited R] : inhabited (cubic R) := ⟨⟨default, default, default, default⟩⟩ |
| 46 | + |
| 47 | +instance [has_zero R] : has_zero (cubic R) := ⟨⟨0, 0, 0, 0⟩⟩ |
| 48 | + |
| 49 | +section basic |
| 50 | + |
| 51 | +variables {P : cubic R} [semiring R] |
| 52 | + |
| 53 | +/-- Convert a cubic polynomial to a polynomial. -/ |
| 54 | +def to_poly (P : cubic R) : polynomial R := C P.a * X ^ 3 + C P.b * X ^ 2 + C P.c * X + C P.d |
| 55 | + |
| 56 | +/-! ### Coefficients -/ |
| 57 | + |
| 58 | +section coeff |
| 59 | + |
| 60 | +private lemma coeffs : |
| 61 | + (∀ n > 3, P.to_poly.coeff n = 0) ∧ P.to_poly.coeff 3 = P.a ∧ P.to_poly.coeff 2 = P.b |
| 62 | + ∧ P.to_poly.coeff 1 = P.c ∧ P.to_poly.coeff 0 = P.d := |
| 63 | +begin |
| 64 | + simp only [to_poly, coeff_add, coeff_C, coeff_C_mul_X, coeff_C_mul_X_pow], |
| 65 | + norm_num, |
| 66 | + intros n hn, |
| 67 | + repeat { rw [if_neg] }, |
| 68 | + any_goals { linarith only [hn] }, |
| 69 | + repeat { rw [zero_add] } |
| 70 | +end |
| 71 | + |
| 72 | +@[simp] lemma coeff_gt_three (n : ℕ) (hn : 3 < n) : P.to_poly.coeff n = 0 := coeffs.1 n hn |
| 73 | + |
| 74 | +@[simp] lemma coeff_three : P.to_poly.coeff 3 = P.a := coeffs.2.1 |
| 75 | + |
| 76 | +@[simp] lemma coeff_two : P.to_poly.coeff 2 = P.b := coeffs.2.2.1 |
| 77 | + |
| 78 | +@[simp] lemma coeff_one : P.to_poly.coeff 1 = P.c := coeffs.2.2.2.1 |
| 79 | + |
| 80 | +@[simp] lemma coeff_zero : P.to_poly.coeff 0 = P.d := coeffs.2.2.2.2 |
| 81 | + |
| 82 | +lemma a_of_eq {Q : cubic R} (h : P.to_poly = Q.to_poly) : P.a = Q.a := |
| 83 | +by rw [← coeff_three, h, coeff_three] |
| 84 | + |
| 85 | +lemma b_of_eq {Q : cubic R} (h : P.to_poly = Q.to_poly) : P.b = Q.b := |
| 86 | +by rw [← coeff_two, h, coeff_two] |
| 87 | + |
| 88 | +lemma c_of_eq {Q : cubic R} (h : P.to_poly = Q.to_poly) : P.c = Q.c := |
| 89 | +by rw [← coeff_one, h, coeff_one] |
| 90 | + |
| 91 | +lemma d_of_eq {Q : cubic R} (h : P.to_poly = Q.to_poly) : P.d = Q.d := |
| 92 | +by rw [← coeff_zero, h, coeff_zero] |
| 93 | + |
| 94 | +@[simp] lemma to_poly_injective (P Q : cubic R) : P.to_poly = Q.to_poly ↔ P = Q := |
| 95 | +⟨λ h, cubic.ext _ _ (a_of_eq h) (b_of_eq h) (c_of_eq h) (d_of_eq h), congr_arg _⟩ |
| 96 | + |
| 97 | +@[simp] lemma of_a_eq_zero (ha : P.a = 0) : P.to_poly = C P.b * X ^ 2 + C P.c * X + C P.d := |
| 98 | +by rw [to_poly, C_eq_zero.mpr ha, zero_mul, zero_add] |
| 99 | + |
| 100 | +@[simp] lemma of_a_b_eq_zero (ha : P.a = 0) (hb : P.b = 0) : P.to_poly = C P.c * X + C P.d := |
| 101 | +by rw [of_a_eq_zero ha, C_eq_zero.mpr hb, zero_mul, zero_add] |
| 102 | + |
| 103 | +@[simp] lemma of_a_b_c_eq_zero (ha : P.a = 0) (hb : P.b = 0) (hc : P.c = 0) : P.to_poly = C P.d := |
| 104 | +by rw [of_a_b_eq_zero ha hb, C_eq_zero.mpr hc, zero_mul, zero_add] |
| 105 | + |
| 106 | +@[simp] lemma of_zero (ha : P.a = 0) (hb : P.b = 0) (hc : P.c = 0) (hd : P.d = 0) : P.to_poly = 0 := |
| 107 | +by rw [of_a_b_c_eq_zero ha hb hc, C_eq_zero.mpr hd] |
| 108 | + |
| 109 | +@[simp] lemma zero : (0 : cubic R).to_poly = 0 := of_zero rfl rfl rfl rfl |
| 110 | + |
| 111 | +@[simp] lemma eq_zero_iff : P.to_poly = 0 ↔ P = 0 := by rw [← zero, to_poly_injective] |
| 112 | + |
| 113 | +lemma ne_zero (h0 : ¬P.a = 0 ∨ ¬P.b = 0 ∨ ¬P.c = 0 ∨ ¬P.d = 0) : P.to_poly ≠ 0 := |
| 114 | +by { contrapose! h0, rw [eq_zero_iff.mp h0], exact ⟨rfl, rfl, rfl, rfl⟩ } |
| 115 | + |
| 116 | +lemma ne_zero_of_a_ne_zero (ha : P.a ≠ 0) : P.to_poly ≠ 0 := (or_imp_distrib.mp ne_zero).1 ha |
| 117 | + |
| 118 | +lemma ne_zero_of_b_ne_zero (hb : P.b ≠ 0) : P.to_poly ≠ 0 := |
| 119 | +(or_imp_distrib.mp (or_imp_distrib.mp ne_zero).2).1 hb |
| 120 | + |
| 121 | +lemma ne_zero_of_c_ne_zero (hc : P.c ≠ 0) : P.to_poly ≠ 0 := |
| 122 | +(or_imp_distrib.mp (or_imp_distrib.mp (or_imp_distrib.mp ne_zero).2).2).1 hc |
| 123 | + |
| 124 | +lemma ne_zero_of_d_ne_zero (hd : P.d ≠ 0) : P.to_poly ≠ 0 := |
| 125 | +(or_imp_distrib.mp (or_imp_distrib.mp (or_imp_distrib.mp ne_zero).2).2).2 hd |
| 126 | + |
| 127 | +end coeff |
| 128 | + |
| 129 | +/-! ### Degrees -/ |
| 130 | + |
| 131 | +section degree |
| 132 | + |
| 133 | +/-- The equivalence between cubic polynomials and polynomials of degree at most three. -/ |
| 134 | +@[simps] def equiv : cubic R ≃ {p : polynomial R // p.degree ≤ 3} := |
| 135 | +{ to_fun := λ P, ⟨P.to_poly, degree_cubic_le⟩, |
| 136 | + inv_fun := λ f, ⟨coeff f 3, coeff f 2, coeff f 1, coeff f 0⟩, |
| 137 | + left_inv := λ P, by ext; simp only [subtype.coe_mk, coeffs], |
| 138 | + right_inv := λ f, |
| 139 | + begin |
| 140 | + ext (_ | _ | _ | _ | n); simp only [subtype.coe_mk, coeffs], |
| 141 | + have h3 : 3 < n + 4 := by linarith only, |
| 142 | + rw [coeff_gt_three _ h3, |
| 143 | + (degree_le_iff_coeff_zero (f : polynomial R) 3).mp f.2 _ $ with_bot.coe_lt_coe.mpr h3] |
| 144 | + end } |
| 145 | + |
| 146 | +lemma degree (ha : P.a ≠ 0) : P.to_poly.degree = 3 := degree_cubic ha |
| 147 | + |
| 148 | +lemma degree_of_a_eq_zero (ha : P.a = 0) (hb : P.b ≠ 0) : P.to_poly.degree = 2 := |
| 149 | +by rw [of_a_eq_zero ha, degree_quadratic hb] |
| 150 | + |
| 151 | +lemma degree_of_a_b_eq_zero (ha : P.a = 0) (hb : P.b = 0) (hc : P.c ≠ 0) : P.to_poly.degree = 1 := |
| 152 | +by rw [of_a_b_eq_zero ha hb, degree_linear hc] |
| 153 | + |
| 154 | +lemma degree_of_a_b_c_eq_zero (ha : P.a = 0) (hb : P.b = 0) (hc : P.c = 0) (hd : P.d ≠ 0) : |
| 155 | + P.to_poly.degree = 0 := |
| 156 | +by rw [of_a_b_c_eq_zero ha hb hc, degree_C hd] |
| 157 | + |
| 158 | +lemma degree_of_zero (ha : P.a = 0) (hb : P.b = 0) (hc : P.c = 0) (hd : P.d = 0) : |
| 159 | + P.to_poly.degree = ⊥ := |
| 160 | +by rw [of_zero ha hb hc hd, degree_zero] |
| 161 | + |
| 162 | +lemma leading_coeff (ha : P.a ≠ 0) : P.to_poly.leading_coeff = P.a := leading_coeff_cubic ha |
| 163 | + |
| 164 | +lemma leading_coeff_of_a_eq_zero (ha : P.a = 0) (hb : P.b ≠ 0) : P.to_poly.leading_coeff = P.b := |
| 165 | +by rw [of_a_eq_zero ha, leading_coeff_quadratic hb] |
| 166 | + |
| 167 | +lemma leading_coeff_of_a_b_eq_zero (ha : P.a = 0) (hb : P.b = 0) (hc : P.c ≠ 0) : |
| 168 | + P.to_poly.leading_coeff = P.c := |
| 169 | +by rw [of_a_b_eq_zero ha hb, leading_coeff_linear hc] |
| 170 | + |
| 171 | +lemma leading_coeff_of_a_b_c_eq_zero (ha : P.a = 0) (hb : P.b = 0) (hc : P.c = 0) : |
| 172 | + P.to_poly.leading_coeff = P.d := |
| 173 | +by rw [of_a_b_c_eq_zero ha hb hc, leading_coeff_C] |
| 174 | + |
| 175 | +end degree |
| 176 | + |
| 177 | +/-! ### Map across a homomorphism -/ |
| 178 | + |
| 179 | +section map |
| 180 | + |
| 181 | +variables [semiring S] {φ : R →+* S} |
| 182 | + |
| 183 | +/-- Map a cubic polynomial across a semiring homomorphism. -/ |
| 184 | +def map (φ : R →+* S) (P : cubic R) : cubic S := ⟨φ P.a, φ P.b, φ P.c, φ P.d⟩ |
| 185 | + |
| 186 | +lemma map_to_poly : (map φ P).to_poly = polynomial.map φ P.to_poly := |
| 187 | +by simp only [map, to_poly, map_C, map_X, polynomial.map_add, polynomial.map_mul, |
| 188 | + polynomial.map_pow] |
| 189 | + |
| 190 | +end map |
| 191 | + |
| 192 | +end basic |
| 193 | + |
| 194 | +section roots |
| 195 | + |
| 196 | +open multiset |
| 197 | + |
| 198 | +/-! ### Roots over an extension -/ |
| 199 | + |
| 200 | +section extension |
| 201 | + |
| 202 | +variables {P : cubic R} [comm_ring R] [comm_ring S] {φ : R →+* S} |
| 203 | + |
| 204 | +/-- The roots of a cubic polynomial. -/ |
| 205 | +def roots [is_domain R] (P : cubic R) : multiset R := P.to_poly.roots |
| 206 | + |
| 207 | +lemma map_roots [is_domain S] : (map φ P).roots = (polynomial.map φ P.to_poly).roots := |
| 208 | +by rw [roots, map_to_poly] |
| 209 | + |
| 210 | +theorem mem_roots_iff [is_domain R] (h0 : P.to_poly ≠ 0) (x : R) : |
| 211 | + x ∈ P.roots ↔ P.a * x ^ 3 + P.b * x ^ 2 + P.c * x + P.d = 0 := |
| 212 | +begin |
| 213 | + rw [roots, mem_roots h0, is_root, to_poly], |
| 214 | + simp only [eval_C, eval_X, eval_add, eval_mul, eval_pow] |
| 215 | +end |
| 216 | + |
| 217 | +theorem card_roots_le [is_domain R] [decidable_eq R] : P.roots.to_finset.card ≤ 3 := |
| 218 | +begin |
| 219 | + apply (to_finset_card_le P.to_poly.roots).trans, |
| 220 | + by_cases hP : P.to_poly = 0, |
| 221 | + { exact (card_roots' P.to_poly).trans (by { rw [hP, nat_degree_zero], exact zero_le 3 }) }, |
| 222 | + { simpa only [← @with_bot.coe_le_coe _ _ _ 3] using (card_roots hP).trans degree_cubic_le } |
| 223 | +end |
| 224 | + |
| 225 | +end extension |
| 226 | + |
| 227 | +variables {P : cubic F} [field F] [field K] {φ : F →+* K} {x y z : K} |
| 228 | + |
| 229 | +/-! ### Roots over a splitting field -/ |
| 230 | + |
| 231 | +section split |
| 232 | + |
| 233 | +theorem splits_iff_card_roots (ha : P.a ≠ 0) : splits φ P.to_poly ↔ (map φ P).roots.card = 3 := |
| 234 | +begin |
| 235 | + replace ha : (map φ P).a ≠ 0 := (ring_hom.map_ne_zero φ).mpr ha, |
| 236 | + nth_rewrite_lhs 0 [← ring_hom.id_comp φ], |
| 237 | + rw [roots, ← splits_map_iff, ← map_to_poly, splits_iff_card_roots, |
| 238 | + ← ((degree_eq_iff_nat_degree_eq $ ne_zero_of_a_ne_zero ha).mp $ degree ha : _ = 3)] |
| 239 | +end |
| 240 | + |
| 241 | +theorem splits_iff_roots_eq_three (ha : P.a ≠ 0) : |
| 242 | + splits φ P.to_poly ↔ ∃ x y z : K, (map φ P).roots = {x, y, z} := |
| 243 | +by rw [splits_iff_card_roots ha, card_eq_three] |
| 244 | + |
| 245 | +theorem eq_prod_three_roots (ha : P.a ≠ 0) (h3 : (map φ P).roots = {x, y, z}) : |
| 246 | + (map φ P).to_poly = C (φ P.a) * (X - C x) * (X - C y) * (X - C z) := |
| 247 | +begin |
| 248 | + rw [map_to_poly, eq_prod_roots_of_splits $ (splits_iff_roots_eq_three ha).mpr $ exists.intro x $ |
| 249 | + exists.intro y $ exists.intro z h3, leading_coeff ha, ← map_roots, h3], |
| 250 | + change C (φ P.a) * ((X - C x) ::ₘ (X - C y) ::ₘ {X - C z}).prod = _, |
| 251 | + rw [prod_cons, prod_cons, prod_singleton, mul_assoc, mul_assoc] |
| 252 | +end |
| 253 | + |
| 254 | +theorem eq_sum_three_roots (ha : P.a ≠ 0) (h3 : (map φ P).roots = {x, y, z}) : |
| 255 | + map φ P = ⟨φ P.a, φ P.a * -(x + y + z), φ P.a * (x * y + x * z + y * z), φ P.a * -(x * y * z)⟩ := |
| 256 | +begin |
| 257 | + apply_fun to_poly, |
| 258 | + any_goals { exact λ P Q, (to_poly_injective P Q).mp }, |
| 259 | + rw [eq_prod_three_roots ha h3, to_poly], |
| 260 | + simp only [C_neg, C_add, C_mul], |
| 261 | + ring1 |
| 262 | +end |
| 263 | + |
| 264 | +theorem b_eq_three_roots (ha : P.a ≠ 0) (h3 : (map φ P).roots = {x, y, z}) : |
| 265 | + φ P.b = φ P.a * -(x + y + z) := |
| 266 | +by injection eq_sum_three_roots ha h3 |
| 267 | + |
| 268 | +theorem c_eq_three_roots (ha : P.a ≠ 0) (h3 : (map φ P).roots = {x, y, z}) : |
| 269 | + φ P.c = φ P.a * (x * y + x * z + y * z) := |
| 270 | +by injection eq_sum_three_roots ha h3 |
| 271 | + |
| 272 | +theorem d_eq_three_roots (ha : P.a ≠ 0) (h3 : (map φ P).roots = {x, y, z}) : |
| 273 | + φ P.d = φ P.a * -(x * y * z) := |
| 274 | +by injection eq_sum_three_roots ha h3 |
| 275 | + |
| 276 | +end split |
| 277 | + |
| 278 | +/-! ### Discriminant over a splitting field -/ |
| 279 | + |
| 280 | +section discriminant |
| 281 | + |
| 282 | +/-- The discriminant of a cubic polynomial. -/ |
| 283 | +def disc {R : Type*} [ring R] (P : cubic R) : R := |
| 284 | +P.b ^ 2 * P.c ^ 2 - 4 * P.a * P.c ^ 3 - 4 * P.b ^ 3 * P.d - 27 * P.a ^ 2 * P.d ^ 2 |
| 285 | + + 18 * P.a * P.b * P.c * P.d |
| 286 | + |
| 287 | +theorem disc_eq_prod_three_roots (ha : P.a ≠ 0) (h3 : (map φ P).roots = {x, y, z}) : |
| 288 | + φ P.disc = (φ P.a * φ P.a * (x - y) * (x - z) * (y - z)) ^ 2 := |
| 289 | +begin |
| 290 | + simp only [disc, ring_hom.map_add, ring_hom.map_sub, ring_hom.map_mul, map_pow], |
| 291 | + simp only [ring_hom.map_one, map_bit0, map_bit1], |
| 292 | + rw [b_eq_three_roots ha h3, c_eq_three_roots ha h3, d_eq_three_roots ha h3], |
| 293 | + ring1 |
| 294 | +end |
| 295 | + |
| 296 | +theorem disc_ne_zero_iff_roots_ne (ha : P.a ≠ 0) (h3 : (map φ P).roots = {x, y, z}) : |
| 297 | + P.disc ≠ 0 ↔ x ≠ y ∧ x ≠ z ∧ y ≠ z := |
| 298 | +begin |
| 299 | + rw [← ring_hom.map_ne_zero φ, disc_eq_prod_three_roots ha h3, pow_two], |
| 300 | + simp only [mul_ne_zero_iff, sub_ne_zero], |
| 301 | + rw [ring_hom.map_ne_zero], |
| 302 | + tautology |
| 303 | +end |
| 304 | + |
| 305 | +theorem disc_ne_zero_iff_roots_nodup (ha : P.a ≠ 0) (h3 : (map φ P).roots = {x, y, z}) : |
| 306 | + P.disc ≠ 0 ↔ (map φ P).roots.nodup := |
| 307 | +begin |
| 308 | + rw [disc_ne_zero_iff_roots_ne ha h3, h3], |
| 309 | + change _ ↔ (x ::ₘ y ::ₘ {z}).nodup, |
| 310 | + rw [nodup_cons, nodup_cons, mem_cons, mem_singleton, mem_singleton], |
| 311 | + simp only [nodup_singleton], |
| 312 | + tautology |
| 313 | +end |
| 314 | + |
| 315 | +theorem card_roots_of_disc_ne_zero [decidable_eq K] (ha : P.a ≠ 0) |
| 316 | + (h3 : (map φ P).roots = {x, y, z}) (hd : P.disc ≠ 0) : (map φ P).roots.to_finset.card = 3 := |
| 317 | +begin |
| 318 | + rw [to_finset_card_of_nodup $ (disc_ne_zero_iff_roots_nodup ha h3).mp hd, |
| 319 | + ← splits_iff_card_roots ha, splits_iff_roots_eq_three ha], |
| 320 | + exact ⟨x, ⟨y, ⟨z, h3⟩⟩⟩ |
| 321 | +end |
| 322 | + |
| 323 | +end discriminant |
| 324 | + |
| 325 | +end roots |
| 326 | + |
| 327 | +end cubic |
0 commit comments