|
| 1 | +/- |
| 2 | +Copyright (c) 2020 Thomas Browning. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Thomas Browning |
| 5 | +
|
| 6 | +! This file was ported from Lean 3 source module data.polynomial.mirror |
| 7 | +! leanprover-community/mathlib commit 2196ab363eb097c008d4497125e0dde23fb36db2 |
| 8 | +! Please do not edit these lines, except to modify the commit id |
| 9 | +! if you have ported upstream changes. |
| 10 | +-/ |
| 11 | +import Mathlib.Algebra.BigOperators.NatAntidiagonal |
| 12 | +import Mathlib.Data.Polynomial.RingDivision |
| 13 | + |
| 14 | +/-! |
| 15 | +# "Mirror" of a univariate polynomial |
| 16 | +
|
| 17 | +In this file we define `Polynomial.mirror`, a variant of `Polynomial.reverse`. The difference |
| 18 | +between `reverse` and `mirror` is that `reverse` will decrease the degree if the polynomial is |
| 19 | +divisible by `X`. |
| 20 | +
|
| 21 | +## Main definitions |
| 22 | +
|
| 23 | +- `Polynomial.mirror` |
| 24 | +
|
| 25 | +## Main results |
| 26 | +
|
| 27 | +- `Polynomial.mirror_mul_of_domain`: `mirror` preserves multiplication. |
| 28 | +- `Polynomial.irreducible_of_mirror`: an irreducibility criterion involving `mirror` |
| 29 | +
|
| 30 | +-/ |
| 31 | + |
| 32 | + |
| 33 | +namespace Polynomial |
| 34 | + |
| 35 | +open Polynomial |
| 36 | + |
| 37 | +section Semiring |
| 38 | + |
| 39 | +variable {R : Type _} [Semiring R] (p q : R[X]) |
| 40 | + |
| 41 | +/-- mirror of a polynomial: reverses the coefficients while preserving `Polynomial.natDegree` -/ |
| 42 | +noncomputable def mirror := |
| 43 | + p.reverse * X ^ p.natTrailingDegree |
| 44 | +#align polynomial.mirror Polynomial.mirror |
| 45 | + |
| 46 | +@[simp] |
| 47 | +theorem mirror_zero : (0 : R[X]).mirror = 0 := by simp [mirror] |
| 48 | +#align polynomial.mirror_zero Polynomial.mirror_zero |
| 49 | + |
| 50 | +theorem mirror_monomial (n : ℕ) (a : R) : (monomial n a).mirror = monomial n a := by |
| 51 | + classical |
| 52 | + by_cases ha : a = 0 |
| 53 | + · rw [ha, monomial_zero_right, mirror_zero] |
| 54 | + · rw [mirror, reverse, natDegree_monomial n a, if_neg ha, natTrailingDegree_monomial ha, ← |
| 55 | + C_mul_X_pow_eq_monomial, reflect_C_mul_X_pow, revAt_le (le_refl n), tsub_self, pow_zero, |
| 56 | + mul_one] |
| 57 | +#align polynomial.mirror_monomial Polynomial.mirror_monomial |
| 58 | + |
| 59 | +theorem mirror_C (a : R) : (C a).mirror = C a := |
| 60 | + mirror_monomial 0 a |
| 61 | +set_option linter.uppercaseLean3 false in |
| 62 | +#align polynomial.mirror_C Polynomial.mirror_C |
| 63 | + |
| 64 | +theorem mirror_X : X.mirror = (X : R[X]) := |
| 65 | + mirror_monomial 1 (1 : R) |
| 66 | +set_option linter.uppercaseLean3 false in |
| 67 | +#align polynomial.mirror_X Polynomial.mirror_X |
| 68 | + |
| 69 | +theorem mirror_natDegree : p.mirror.natDegree = p.natDegree := by |
| 70 | + by_cases hp : p = 0 |
| 71 | + · rw [hp, mirror_zero] |
| 72 | + --Porting note: below two lines were `nontriviality R` in Lean3 |
| 73 | + have : p.leadingCoeff ≠ 0 := by simpa |
| 74 | + let _ : Nontrivial R := nontrivial_of_ne _ _ this |
| 75 | + rw [mirror, natDegree_mul', reverse_natDegree, natDegree_X_pow, |
| 76 | + tsub_add_cancel_of_le p.natTrailingDegree_le_natDegree] |
| 77 | + rwa [leadingCoeff_X_pow, mul_one, reverse_leadingCoeff, Ne, trailingCoeff_eq_zero] |
| 78 | +#align polynomial.mirror_nat_degree Polynomial.mirror_natDegree |
| 79 | + |
| 80 | +theorem mirror_natTrailingDegree : p.mirror.natTrailingDegree = p.natTrailingDegree := by |
| 81 | + by_cases hp : p = 0 |
| 82 | + · rw [hp, mirror_zero] |
| 83 | + · |
| 84 | + rw [mirror, natTrailingDegree_mul_X_pow ((mt reverse_eq_zero.mp) hp), |
| 85 | + reverse_natTrailingDegree, zero_add] |
| 86 | +#align polynomial.mirror_nat_trailing_degree Polynomial.mirror_natTrailingDegree |
| 87 | + |
| 88 | +theorem coeff_mirror (n : ℕ) : |
| 89 | + p.mirror.coeff n = p.coeff (revAt (p.natDegree + p.natTrailingDegree) n) := by |
| 90 | + by_cases h2 : p.natDegree < n |
| 91 | + · rw [coeff_eq_zero_of_natDegree_lt (by rwa [mirror_natDegree])] |
| 92 | + by_cases h1 : n ≤ p.natDegree + p.natTrailingDegree |
| 93 | + · rw [revAt_le h1, coeff_eq_zero_of_lt_natTrailingDegree] |
| 94 | + exact (tsub_lt_iff_left h1).mpr (Nat.add_lt_add_right h2 _) |
| 95 | + · rw [← revAtFun_eq, revAtFun, if_neg h1, coeff_eq_zero_of_natDegree_lt h2] |
| 96 | + rw [not_lt] at h2 |
| 97 | + rw [revAt_le (h2.trans (Nat.le_add_right _ _))] |
| 98 | + by_cases h3 : p.natTrailingDegree ≤ n |
| 99 | + · rw [← tsub_add_eq_add_tsub h2, ← tsub_tsub_assoc h2 h3, mirror, coeff_mul_X_pow', if_pos h3, |
| 100 | + coeff_reverse, revAt_le (tsub_le_self.trans h2)] |
| 101 | + rw [not_le] at h3 |
| 102 | + rw [coeff_eq_zero_of_natDegree_lt (lt_tsub_iff_right.mpr (Nat.add_lt_add_left h3 _))] |
| 103 | + exact coeff_eq_zero_of_lt_natTrailingDegree (by rwa [mirror_natTrailingDegree]) |
| 104 | +#align polynomial.coeff_mirror Polynomial.coeff_mirror |
| 105 | + |
| 106 | +--TODO: Extract `finset.sum_range_rev_at` lemma. |
| 107 | +theorem mirror_eval_one : p.mirror.eval 1 = p.eval 1 := by |
| 108 | + simp_rw [eval_eq_sum_range, one_pow, mul_one, mirror_natDegree] |
| 109 | + refine' Finset.sum_bij_ne_zero _ _ _ _ _ |
| 110 | + · exact fun n _ _ => revAt (p.natDegree + p.natTrailingDegree) n |
| 111 | + · intro n hn hp |
| 112 | + rw [Finset.mem_range_succ_iff] at * |
| 113 | + rw [revAt_le (hn.trans (Nat.le_add_right _ _))] |
| 114 | + rw [tsub_le_iff_tsub_le, add_comm, add_tsub_cancel_right, ← mirror_natTrailingDegree] |
| 115 | + exact natTrailingDegree_le_of_ne_zero hp |
| 116 | + · exact fun n₁ n₂ _ _ _ _ h => by rw [← @revAt_invol _ n₁, h, revAt_invol] |
| 117 | + · intro n hn hp |
| 118 | + use revAt (p.natDegree + p.natTrailingDegree) n |
| 119 | + refine' ⟨_, _, revAt_invol.symm⟩ |
| 120 | + · rw [Finset.mem_range_succ_iff] at * |
| 121 | + rw [revAt_le (hn.trans (Nat.le_add_right _ _))] |
| 122 | + rw [tsub_le_iff_tsub_le, add_comm, add_tsub_cancel_right] |
| 123 | + exact natTrailingDegree_le_of_ne_zero hp |
| 124 | + · change p.mirror.coeff _ ≠ 0 |
| 125 | + rwa [coeff_mirror, revAt_invol] |
| 126 | + · exact fun n _ _ => p.coeff_mirror n |
| 127 | +#align polynomial.mirror_eval_one Polynomial.mirror_eval_one |
| 128 | + |
| 129 | +theorem mirror_mirror : p.mirror.mirror = p := |
| 130 | + Polynomial.ext fun n => by |
| 131 | + rw [coeff_mirror, coeff_mirror, mirror_natDegree, mirror_natTrailingDegree, revAt_invol] |
| 132 | +#align polynomial.mirror_mirror Polynomial.mirror_mirror |
| 133 | + |
| 134 | +variable {p q} |
| 135 | + |
| 136 | +theorem mirror_involutive : Function.Involutive (mirror : R[X] → R[X]) := |
| 137 | + mirror_mirror |
| 138 | +#align polynomial.mirror_involutive Polynomial.mirror_involutive |
| 139 | + |
| 140 | +theorem mirror_eq_iff : p.mirror = q ↔ p = q.mirror := |
| 141 | + mirror_involutive.eq_iff |
| 142 | +#align polynomial.mirror_eq_iff Polynomial.mirror_eq_iff |
| 143 | + |
| 144 | +@[simp] |
| 145 | +theorem mirror_inj : p.mirror = q.mirror ↔ p = q := |
| 146 | + mirror_involutive.injective.eq_iff |
| 147 | +#align polynomial.mirror_inj Polynomial.mirror_inj |
| 148 | + |
| 149 | +@[simp] |
| 150 | +theorem mirror_eq_zero : p.mirror = 0 ↔ p = 0 := |
| 151 | + ⟨fun h => by rw [← p.mirror_mirror, h, mirror_zero], fun h => by rw [h, mirror_zero]⟩ |
| 152 | +#align polynomial.mirror_eq_zero Polynomial.mirror_eq_zero |
| 153 | + |
| 154 | +variable (p q) |
| 155 | + |
| 156 | +@[simp] |
| 157 | +theorem mirror_trailingCoeff : p.mirror.trailingCoeff = p.leadingCoeff := by |
| 158 | + rw [leadingCoeff, trailingCoeff, mirror_natTrailingDegree, coeff_mirror, |
| 159 | + revAt_le (Nat.le_add_left _ _), add_tsub_cancel_right] |
| 160 | +#align polynomial.mirror_trailing_coeff Polynomial.mirror_trailingCoeff |
| 161 | + |
| 162 | +@[simp] |
| 163 | +theorem mirror_leadingCoeff : p.mirror.leadingCoeff = p.trailingCoeff := by |
| 164 | + rw [← p.mirror_mirror, mirror_trailingCoeff, p.mirror_mirror] |
| 165 | +#align polynomial.mirror_leading_coeff Polynomial.mirror_leadingCoeff |
| 166 | + |
| 167 | +theorem coeff_mul_mirror : |
| 168 | + (p * p.mirror).coeff (p.natDegree + p.natTrailingDegree) = p.sum fun n => (· ^ 2) := by |
| 169 | + rw [coeff_mul, Finset.Nat.sum_antidiagonal_eq_sum_range_succ_mk] |
| 170 | + refine' |
| 171 | + (Finset.sum_congr rfl fun n hn => _).trans |
| 172 | + (p.sum_eq_of_subset (fun _ => (· ^ 2)) (fun _ => zero_pow zero_lt_two) _ fun n hn => |
| 173 | + Finset.mem_range_succ_iff.mpr |
| 174 | + ((le_natDegree_of_mem_supp n hn).trans (Nat.le_add_right _ _))).symm |
| 175 | + rw [coeff_mirror, ← revAt_le (Finset.mem_range_succ_iff.mp hn), revAt_invol, ← sq] |
| 176 | +#align polynomial.coeff_mul_mirror Polynomial.coeff_mul_mirror |
| 177 | + |
| 178 | +variable [NoZeroDivisors R] |
| 179 | + |
| 180 | +theorem natDegree_mul_mirror : (p * p.mirror).natDegree = 2 * p.natDegree := by |
| 181 | + by_cases hp : p = 0 |
| 182 | + · rw [hp, MulZeroClass.zero_mul, natDegree_zero, MulZeroClass.mul_zero] |
| 183 | + rw [natDegree_mul hp (mt mirror_eq_zero.mp hp), mirror_natDegree, two_mul] |
| 184 | +#align polynomial.nat_degree_mul_mirror Polynomial.natDegree_mul_mirror |
| 185 | + |
| 186 | +theorem natTrailingDegree_mul_mirror : (p * p.mirror).natTrailingDegree = 2 * p.natTrailingDegree := |
| 187 | + by |
| 188 | + by_cases hp : p = 0 |
| 189 | + · rw [hp, MulZeroClass.zero_mul, natTrailingDegree_zero, MulZeroClass.mul_zero] |
| 190 | + rw [natTrailingDegree_mul hp (mt mirror_eq_zero.mp hp), mirror_natTrailingDegree, two_mul] |
| 191 | +#align polynomial.nat_trailing_degree_mul_mirror Polynomial.natTrailingDegree_mul_mirror |
| 192 | + |
| 193 | +end Semiring |
| 194 | + |
| 195 | +section Ring |
| 196 | + |
| 197 | +variable {R : Type _} [Ring R] (p q : R[X]) |
| 198 | + |
| 199 | +theorem mirror_neg : (-p).mirror = -p.mirror := by |
| 200 | + rw [mirror, mirror, reverse_neg, natTrailingDegree_neg, neg_mul_eq_neg_mul] |
| 201 | +#align polynomial.mirror_neg Polynomial.mirror_neg |
| 202 | + |
| 203 | +variable [NoZeroDivisors R] |
| 204 | + |
| 205 | +theorem mirror_mul_of_domain : (p * q).mirror = p.mirror * q.mirror := by |
| 206 | + by_cases hp : p = 0 |
| 207 | + · rw [hp, MulZeroClass.zero_mul, mirror_zero, MulZeroClass.zero_mul] |
| 208 | + by_cases hq : q = 0 |
| 209 | + · rw [hq, MulZeroClass.mul_zero, mirror_zero, MulZeroClass.mul_zero] |
| 210 | + rw [mirror, mirror, mirror, reverse_mul_of_domain, natTrailingDegree_mul hp hq, pow_add] |
| 211 | + rw [mul_assoc, ← mul_assoc q.reverse, ← X_pow_mul (p := reverse q)] |
| 212 | + repeat' rw [mul_assoc] |
| 213 | +#align polynomial.mirror_mul_of_domain Polynomial.mirror_mul_of_domain |
| 214 | + |
| 215 | +theorem mirror_smul (a : R) : (a • p).mirror = a • p.mirror := by |
| 216 | + rw [← C_mul', ← C_mul', mirror_mul_of_domain, mirror_C] |
| 217 | +#align polynomial.mirror_smul Polynomial.mirror_smul |
| 218 | + |
| 219 | +end Ring |
| 220 | + |
| 221 | +section CommRing |
| 222 | + |
| 223 | +variable {R : Type _} [CommRing R] [NoZeroDivisors R] {f : R[X]} |
| 224 | + |
| 225 | +theorem irreducible_of_mirror (h1 : ¬IsUnit f) |
| 226 | + (h2 : ∀ k, f * f.mirror = k * k.mirror → k = f ∨ k = -f ∨ k = f.mirror ∨ k = -f.mirror) |
| 227 | + (h3 : ∀ g, g ∣ f → g ∣ f.mirror → IsUnit g) : Irreducible f := by |
| 228 | + constructor |
| 229 | + · exact h1 |
| 230 | + · intro g h fgh |
| 231 | + let k := g * h.mirror |
| 232 | + have key : f * f.mirror = k * k.mirror := by |
| 233 | + rw [fgh, mirror_mul_of_domain, mirror_mul_of_domain, mirror_mirror, mul_assoc, mul_comm h, |
| 234 | + mul_comm g.mirror, mul_assoc, ← mul_assoc] |
| 235 | + have g_dvd_f : g ∣ f := by |
| 236 | + rw [fgh] |
| 237 | + exact dvd_mul_right g h |
| 238 | + have h_dvd_f : h ∣ f := by |
| 239 | + rw [fgh] |
| 240 | + exact dvd_mul_left h g |
| 241 | + have g_dvd_k : g ∣ k := dvd_mul_right g h.mirror |
| 242 | + have h_dvd_k_rev : h ∣ k.mirror := by |
| 243 | + rw [mirror_mul_of_domain, mirror_mirror] |
| 244 | + exact dvd_mul_left h g.mirror |
| 245 | + have hk := h2 k key |
| 246 | + rcases hk with (hk | hk | hk | hk) |
| 247 | + · exact Or.inr (h3 h h_dvd_f (by rwa [← hk])) |
| 248 | + · exact Or.inr (h3 h h_dvd_f (by rwa [← neg_eq_iff_eq_neg.mpr hk, mirror_neg, dvd_neg])) |
| 249 | + · exact Or.inl (h3 g g_dvd_f (by rwa [← hk])) |
| 250 | + · exact Or.inl (h3 g g_dvd_f (by rwa [← neg_eq_iff_eq_neg.mpr hk, dvd_neg])) |
| 251 | +#align polynomial.irreducible_of_mirror Polynomial.irreducible_of_mirror |
| 252 | + |
| 253 | +end CommRing |
| 254 | + |
| 255 | +end Polynomial |
0 commit comments