|
| 1 | +/- |
| 2 | +Copyright (c) 2025 Thomas Browning. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Thomas Browning |
| 5 | +-/ |
| 6 | +import Mathlib.Algebra.Polynomial.FieldDivision |
| 7 | + |
| 8 | +/-! |
| 9 | +# Split polynomials |
| 10 | +
|
| 11 | +A polynomial `f : R[X]` factors if it is a product of constant and monic linear polynomials. |
| 12 | +
|
| 13 | +## Main definitions |
| 14 | +
|
| 15 | +* `Polynomial.Factors f`: A predicate on a polynomial `f` saying that `f` is a product of |
| 16 | + constant and monic linear polynomials. |
| 17 | +
|
| 18 | +## TODO |
| 19 | +
|
| 20 | +- Redefine `Splits` in terms of `Factors` and then deprecate `Splits`. |
| 21 | +
|
| 22 | +-/ |
| 23 | + |
| 24 | +variable {R : Type*} |
| 25 | + |
| 26 | +namespace Polynomial |
| 27 | + |
| 28 | +section Semiring |
| 29 | + |
| 30 | +variable [Semiring R] |
| 31 | + |
| 32 | +/-- A polynomial `Factors` if it is a product of constant and monic linear polynomials. |
| 33 | +This will eventually replace `Polynomial.Splits`. -/ |
| 34 | +def Factors (f : R[X]) : Prop := f ∈ Submonoid.closure ({C a | a : R} ∪ {X + C a | a : R}) |
| 35 | + |
| 36 | +@[simp, aesop safe apply] |
| 37 | +protected theorem Factors.C (a : R) : Factors (C a) := |
| 38 | + Submonoid.mem_closure_of_mem (Set.mem_union_left _ ⟨a, rfl⟩) |
| 39 | + |
| 40 | +@[simp, aesop safe apply] |
| 41 | +protected theorem Factors.zero : Factors (0 : R[X]) := by |
| 42 | + simpa using Factors.C (0 : R) |
| 43 | + |
| 44 | +@[simp, aesop safe apply] |
| 45 | +protected theorem Factors.one : Factors (1 : R[X]) := |
| 46 | + Factors.C (1 : R) |
| 47 | + |
| 48 | +@[simp, aesop safe apply] |
| 49 | +theorem Factors.X_add_C (a : R) : Factors (X + C a) := |
| 50 | + Submonoid.mem_closure_of_mem (Set.mem_union_right _ ⟨a, rfl⟩) |
| 51 | + |
| 52 | +@[simp, aesop safe apply] |
| 53 | +protected theorem Factors.X : Factors (X : R[X]) := by |
| 54 | + simpa using Factors.X_add_C (0 : R) |
| 55 | + |
| 56 | +@[simp, aesop safe apply] |
| 57 | +protected theorem Factors.mul {f g : R[X]} (hf : Factors f) (hg : Factors g) : |
| 58 | + Factors (f * g) := |
| 59 | + mul_mem hf hg |
| 60 | + |
| 61 | +protected theorem Factors.C_mul {f : R[X]} (hf : Factors f) (a : R) : Factors (C a * f) := |
| 62 | + (Factors.C a).mul hf |
| 63 | + |
| 64 | +@[simp, aesop safe apply] |
| 65 | +theorem Factors.listProd {l : List R[X]} (h : ∀ f ∈ l, Factors f) : Factors l.prod := |
| 66 | + list_prod_mem h |
| 67 | + |
| 68 | +@[simp, aesop safe apply] |
| 69 | +protected theorem Factors.pow {f : R[X]} (hf : Factors f) (n : ℕ) : Factors (f ^ n) := |
| 70 | + pow_mem hf n |
| 71 | + |
| 72 | +theorem Factors.X_pow (n : ℕ) : Factors (X ^ n : R[X]) := |
| 73 | + Factors.X.pow n |
| 74 | + |
| 75 | +theorem Factors.C_mul_X_pow (a : R) (n : ℕ) : Factors (C a * X ^ n) := |
| 76 | + (Factors.X_pow n).C_mul a |
| 77 | + |
| 78 | +@[simp, aesop safe apply] |
| 79 | +theorem Factors.monomial (n : ℕ) (a : R) : Factors (monomial n a) := by |
| 80 | + simp [← C_mul_X_pow_eq_monomial] |
| 81 | + |
| 82 | +protected theorem Factors.map {f : R[X]} (hf : Factors f) {S : Type*} [Semiring S] (i : R →+* S) : |
| 83 | + Factors (map i f) := by |
| 84 | + induction hf using Submonoid.closure_induction <;> aesop |
| 85 | + |
| 86 | +theorem factors_of_natDegree_eq_zero {f : R[X]} (hf : natDegree f = 0) : |
| 87 | + Factors f := |
| 88 | + (natDegree_eq_zero.mp hf).choose_spec ▸ by aesop |
| 89 | + |
| 90 | +theorem factors_of_degree_le_zero {f : R[X]} (hf : degree f ≤ 0) : |
| 91 | + Factors f := |
| 92 | + factors_of_natDegree_eq_zero (natDegree_eq_zero_iff_degree_le_zero.mpr hf) |
| 93 | + |
| 94 | +end Semiring |
| 95 | + |
| 96 | +section CommSemiring |
| 97 | + |
| 98 | +variable [CommSemiring R] |
| 99 | + |
| 100 | +@[simp, aesop safe apply] |
| 101 | +theorem Factors.multisetProd {m : Multiset R[X]} (hm : ∀ f ∈ m, Factors f) : Factors m.prod := |
| 102 | + multiset_prod_mem _ hm |
| 103 | + |
| 104 | +@[simp, aesop safe apply] |
| 105 | +protected theorem Factors.prod {ι : Type*} {f : ι → R[X]} {s : Finset ι} |
| 106 | + (h : ∀ i ∈ s, Factors (f i)) : Factors (∏ i ∈ s, f i) := |
| 107 | + prod_mem h |
| 108 | + |
| 109 | +/-- See `factors_iff_exists_multiset` for the version with subtraction. -/ |
| 110 | +theorem factors_iff_exists_multiset' {f : R[X]} : |
| 111 | + Factors f ↔ ∃ m : Multiset R, f = C f.leadingCoeff * (m.map (X + C ·)).prod := by |
| 112 | + refine ⟨fun hf ↦ ?_, ?_⟩ |
| 113 | + · let S : Submonoid R[X] := MonoidHom.mrange C |
| 114 | + have hS : S = {C a | a : R} := MonoidHom.coe_mrange C |
| 115 | + rw [Factors, Submonoid.closure_union, ← hS, Submonoid.closure_eq, Submonoid.mem_sup] at hf |
| 116 | + obtain ⟨-, ⟨a, rfl⟩, g, hg, rfl⟩ := hf |
| 117 | + obtain ⟨mg, hmg, rfl⟩ := Submonoid.exists_multiset_of_mem_closure hg |
| 118 | + choose! j hj using hmg |
| 119 | + have hmg : mg = (mg.map j).map (X + C ·) := by simp [Multiset.map_congr rfl hj] |
| 120 | + rw [hmg, leadingCoeff_mul_monic, leadingCoeff_C] |
| 121 | + · use mg.map j |
| 122 | + · rw [hmg] |
| 123 | + apply monic_multiset_prod_of_monic |
| 124 | + simp [monic_X_add_C] |
| 125 | + · rintro ⟨m, hm⟩ |
| 126 | + exact hm ▸ (Factors.C _).mul (.multisetProd (by simp [Factors.X_add_C])) |
| 127 | + |
| 128 | +theorem Factors.natDegree_le_one_of_irreducible {f : R[X]} (hf : Factors f) |
| 129 | + (h : Irreducible f) : natDegree f ≤ 1 := by |
| 130 | + nontriviality R |
| 131 | + obtain ⟨m, hm⟩ := factors_iff_exists_multiset'.mp hf |
| 132 | + rcases m.empty_or_exists_mem with rfl | ⟨a, ha⟩ |
| 133 | + · rw [hm] |
| 134 | + simp |
| 135 | + · obtain ⟨m, rfl⟩ := Multiset.exists_cons_of_mem ha |
| 136 | + rw [Multiset.map_cons, Multiset.prod_cons] at hm |
| 137 | + rw [hm] at h |
| 138 | + simp only [irreducible_mul_iff, IsUnit.mul_iff, not_isUnit_X_add_C, false_and, and_false, |
| 139 | + or_false, false_or, ← Multiset.prod_toList, List.prod_isUnit_iff] at h |
| 140 | + have : m = 0 := by simpa [not_isUnit_X_add_C, ← Multiset.eq_zero_iff_forall_notMem] using h.1.2 |
| 141 | + grw [hm, this, natDegree_mul_le] |
| 142 | + simp |
| 143 | + |
| 144 | +end CommSemiring |
| 145 | + |
| 146 | +section Ring |
| 147 | + |
| 148 | +variable [Ring R] |
| 149 | + |
| 150 | +@[simp, aesop safe apply] |
| 151 | +theorem Factors.X_sub_C (a : R) : Factors (X - C a) := by |
| 152 | + simpa using Factors.X_add_C (-a) |
| 153 | + |
| 154 | +@[aesop safe apply] |
| 155 | +protected theorem Factors.neg {f : R[X]} (hf : Factors f) : Factors (-f) := by |
| 156 | + rw [← neg_one_mul, ← C_1, ← C_neg] |
| 157 | + exact hf.C_mul (-1) |
| 158 | + |
| 159 | +@[simp] |
| 160 | +theorem factors_neg_iff {f : R[X]} : Factors (-f) ↔ Factors f := |
| 161 | + ⟨fun hf ↦ neg_neg f ▸ hf.neg, .neg⟩ |
| 162 | + |
| 163 | +end Ring |
| 164 | + |
| 165 | +section CommRing |
| 166 | + |
| 167 | +variable [CommRing R] {f g : R[X]} |
| 168 | + |
| 169 | +theorem factors_iff_exists_multiset : |
| 170 | + Factors f ↔ ∃ m : Multiset R, f = C f.leadingCoeff * (m.map (X - C ·)).prod := by |
| 171 | + refine factors_iff_exists_multiset'.trans ⟨?_, ?_⟩ <;> |
| 172 | + rintro ⟨m, hm⟩ <;> exact ⟨m.map (- ·), by simpa⟩ |
| 173 | + |
| 174 | +theorem Factors.exists_eval_eq_zero (hf : Factors f) (hf0 : degree f ≠ 0) : |
| 175 | + ∃ a, eval a f = 0 := by |
| 176 | + obtain ⟨m, hm⟩ := factors_iff_exists_multiset.mp hf |
| 177 | + by_cases hf₀ : f.leadingCoeff = 0 |
| 178 | + · simp [leadingCoeff_eq_zero.mp hf₀] |
| 179 | + obtain rfl | ⟨a, ha⟩ := m.empty_or_exists_mem |
| 180 | + · rw [hm, Multiset.map_zero, Multiset.prod_zero, mul_one, degree_C hf₀] at hf0 |
| 181 | + contradiction |
| 182 | + obtain ⟨m, rfl⟩ := Multiset.exists_cons_of_mem ha |
| 183 | + exact ⟨a, hm ▸ by simp⟩ |
| 184 | + |
| 185 | +variable [IsDomain R] |
| 186 | + |
| 187 | +theorem Factors.eq_prod_roots (hf : Factors f) : |
| 188 | + f = C f.leadingCoeff * (f.roots.map (X - C ·)).prod := by |
| 189 | + by_cases hf0 : f.leadingCoeff = 0 |
| 190 | + · simp [leadingCoeff_eq_zero.mp hf0] |
| 191 | + · obtain ⟨m, hm⟩ := factors_iff_exists_multiset.mp hf |
| 192 | + suffices hf : f.roots = m by rwa [hf] |
| 193 | + rw [hm, roots_C_mul _ hf0, roots_multiset_prod_X_sub_C] |
| 194 | + |
| 195 | +theorem Factors.natDegree_eq_card_roots (hf : Factors f) : |
| 196 | + f.natDegree = f.roots.card := by |
| 197 | + by_cases hf0 : f.leadingCoeff = 0 |
| 198 | + · simp [leadingCoeff_eq_zero.mp hf0] |
| 199 | + · conv_lhs => rw [hf.eq_prod_roots, natDegree_C_mul hf0, natDegree_multiset_prod_X_sub_C_eq_card] |
| 200 | + |
| 201 | +theorem Factors.roots_ne_zero (hf : Factors f) (hf0 : natDegree f ≠ 0) : |
| 202 | + f.roots ≠ 0 := by |
| 203 | + obtain ⟨a, ha⟩ := hf.exists_eval_eq_zero (degree_ne_of_natDegree_ne hf0) |
| 204 | + exact mt (· ▸ (mem_roots (by aesop)).mpr ha) (Multiset.notMem_zero a) |
| 205 | + |
| 206 | +theorem factors_X_sub_C_mul_iff {a : R} : Factors ((X - C a) * f) ↔ Factors f := by |
| 207 | + refine ⟨fun hf ↦ ?_, ((Factors.X_sub_C _).mul ·)⟩ |
| 208 | + by_cases hf₀ : f = 0 |
| 209 | + · aesop |
| 210 | + have := hf.eq_prod_roots |
| 211 | + rw [leadingCoeff_mul, leadingCoeff_X_sub_C, one_mul, |
| 212 | + roots_mul (mul_ne_zero (X_sub_C_ne_zero _) hf₀), roots_X_sub_C, |
| 213 | + Multiset.singleton_add, Multiset.map_cons, Multiset.prod_cons, mul_left_comm] at this |
| 214 | + rw [mul_left_cancel₀ (X_sub_C_ne_zero _) this] |
| 215 | + aesop |
| 216 | + |
| 217 | +theorem factors_mul_iff (hf₀ : f ≠ 0) (hg₀ : g ≠ 0) : |
| 218 | + Factors (f * g) ↔ Factors f ∧ Factors g := by |
| 219 | + refine ⟨fun h ↦ ?_, and_imp.mpr .mul⟩ |
| 220 | + generalize hp : f * g = p at * |
| 221 | + generalize hn : p.natDegree = n |
| 222 | + induction n generalizing p f g with |
| 223 | + | zero => |
| 224 | + rw [← hp, natDegree_mul hf₀ hg₀, Nat.add_eq_zero] at hn |
| 225 | + exact ⟨factors_of_natDegree_eq_zero hn.1, factors_of_natDegree_eq_zero hn.2⟩ |
| 226 | + | succ n ih => |
| 227 | + obtain ⟨a, ha⟩ := Factors.exists_eval_eq_zero h (degree_ne_of_natDegree_ne <| hn ▸ by aesop) |
| 228 | + have := dvd_iff_isRoot.mpr ha |
| 229 | + rw [← hp, (prime_X_sub_C a).dvd_mul] at this |
| 230 | + wlog hf : X - C a ∣ f with hf2 |
| 231 | + · exact .symm <| hf2 n ih hg₀ hf₀ p ((mul_comm g f).trans hp) h hn a ha this.symm <| |
| 232 | + this.resolve_left hf |
| 233 | + obtain ⟨f, rfl⟩ := hf |
| 234 | + rw [mul_assoc] at hp; subst hp |
| 235 | + rw [natDegree_mul (by aesop) (by aesop), natDegree_X_sub_C, add_comm, Nat.succ_inj] at hn |
| 236 | + have := ih (by aesop) hg₀ (f * g) rfl (factors_X_sub_C_mul_iff.mp h) hn |
| 237 | + aesop |
| 238 | + |
| 239 | +theorem Factors.of_dvd (hg : Factors g) (hg₀ : g ≠ 0) (hfg : f ∣ g) : Factors f := by |
| 240 | + obtain ⟨g, rfl⟩ := hfg |
| 241 | + exact ((factors_mul_iff (by aesop) (by aesop)).mp hg).1 |
| 242 | + |
| 243 | +-- Todo: Remove or fix name once `Splits` is gone. |
| 244 | +theorem Factors.splits (hf : Factors f) : |
| 245 | + f = 0 ∨ ∀ {g : R[X]}, Irreducible g → g ∣ f → degree g ≤ 1 := |
| 246 | + or_iff_not_imp_left.mpr fun hf0 _ hg hgf ↦ degree_le_of_natDegree_le <| |
| 247 | + (hf.of_dvd hf0 hgf).natDegree_le_one_of_irreducible hg |
| 248 | + |
| 249 | +end CommRing |
| 250 | + |
| 251 | +section DivisionSemiring |
| 252 | + |
| 253 | +variable [DivisionSemiring R] |
| 254 | + |
| 255 | +theorem Factors.of_natDegree_le_one {f : R[X]} (hf : natDegree f ≤ 1) : Factors f := by |
| 256 | + obtain ⟨a, b, rfl⟩ := exists_eq_X_add_C_of_natDegree_le_one hf |
| 257 | + by_cases ha : a = 0 |
| 258 | + · aesop |
| 259 | + · rw [← mul_inv_cancel_left₀ ha b, C_mul, ← mul_add] |
| 260 | + exact (X_add_C (a⁻¹ * b)).C_mul a |
| 261 | + |
| 262 | +theorem Factors.of_natDegree_eq_one {f : R[X]} (hf : natDegree f = 1) : Factors f := |
| 263 | + of_natDegree_le_one hf.le |
| 264 | + |
| 265 | +theorem Factors.of_degree_le_one {f : R[X]} (hf : degree f ≤ 1) : Factors f := |
| 266 | + of_natDegree_le_one (natDegree_le_of_degree_le hf) |
| 267 | + |
| 268 | +theorem Factors.of_degree_eq_one {f : R[X]} (hf : degree f = 1) : Factors f := |
| 269 | + of_degree_le_one hf.le |
| 270 | + |
| 271 | +end DivisionSemiring |
| 272 | + |
| 273 | +section Field |
| 274 | + |
| 275 | +variable [Field R] |
| 276 | + |
| 277 | +open UniqueFactorizationMonoid in |
| 278 | +-- Todo: Remove or fix name once `Splits` is gone. |
| 279 | +theorem factors_iff_splits {f : R[X]} : |
| 280 | + Factors f ↔ f = 0 ∨ ∀ {g : R[X]}, Irreducible g → g ∣ f → degree g = 1 := by |
| 281 | + refine ⟨fun hf ↦ hf.splits.imp_right (forall₃_imp fun g hg hgf ↦ |
| 282 | + (le_antisymm · (Nat.WithBot.one_le_iff_zero_lt.mpr hg.degree_pos))), ?_⟩ |
| 283 | + rintro (rfl | hf) |
| 284 | + · aesop |
| 285 | + classical |
| 286 | + by_cases hf0 : f = 0 |
| 287 | + · simp [hf0] |
| 288 | + obtain ⟨u, hu⟩ := factors_prod hf0 |
| 289 | + rw [← hu] |
| 290 | + refine (Factors.multisetProd fun g hg ↦ ?_).mul |
| 291 | + (factors_of_natDegree_eq_zero (natDegree_eq_zero_of_isUnit u.isUnit)) |
| 292 | + exact Factors.of_degree_eq_one (hf (irreducible_of_factor g hg) (dvd_of_mem_factors hg)) |
| 293 | + |
| 294 | +end Field |
| 295 | + |
| 296 | +end Polynomial |
0 commit comments