|
| 1 | +/- |
| 2 | +Copyright (c) 2020 Kenny Lau. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Kenny Lau |
| 5 | +
|
| 6 | +! This file was ported from Lean 3 source module data.polynomial.expand |
| 7 | +! leanprover-community/mathlib commit bbeb185db4ccee8ed07dc48449414ebfa39cb821 |
| 8 | +! Please do not edit these lines, except to modify the commit id |
| 9 | +! if you have ported upstream changes. |
| 10 | +-/ |
| 11 | +import Mathlib.RingTheory.Polynomial.Basic |
| 12 | +import Mathlib.RingTheory.Ideal.LocalRing |
| 13 | + |
| 14 | +/-! |
| 15 | +# Expand a polynomial by a factor of p, so `∑ aₙ xⁿ` becomes `∑ aₙ xⁿᵖ`. |
| 16 | +
|
| 17 | +## Main definitions |
| 18 | +
|
| 19 | +* `Polynomial.expand R p f`: expand the polynomial `f` with coefficients in a |
| 20 | + commutative semiring `R` by a factor of p, so `expand R p (∑ aₙ xⁿ)` is `∑ aₙ xⁿᵖ`. |
| 21 | +* `Polynomial.contract p f`: the opposite of `expand`, so it sends `∑ aₙ xⁿᵖ` to `∑ aₙ xⁿ`. |
| 22 | +
|
| 23 | +-/ |
| 24 | + |
| 25 | + |
| 26 | +universe u v w |
| 27 | + |
| 28 | +open Classical BigOperators Polynomial |
| 29 | + |
| 30 | +open Finset |
| 31 | + |
| 32 | +namespace Polynomial |
| 33 | + |
| 34 | +section CommSemiring |
| 35 | + |
| 36 | +variable (R : Type u) [CommSemiring R] {S : Type v} [CommSemiring S] (p q : ℕ) |
| 37 | + |
| 38 | +/-- Expand the polynomial by a factor of p, so `∑ aₙ xⁿ` becomes `∑ aₙ xⁿᵖ`. -/ |
| 39 | +noncomputable def expand : R[X] →ₐ[R] R[X] := |
| 40 | + { (eval₂RingHom C (X ^ p) : R[X] →+* R[X]) with commutes' := fun _ => eval₂_C _ _ } |
| 41 | +#align polynomial.expand Polynomial.expand |
| 42 | + |
| 43 | +theorem coe_expand : (expand R p : R[X] → R[X]) = eval₂ C (X ^ p) := |
| 44 | + rfl |
| 45 | +#align polynomial.coe_expand Polynomial.coe_expand |
| 46 | + |
| 47 | +variable {R} |
| 48 | + |
| 49 | +theorem expand_eq_sum {f : R[X]} : expand R p f = f.sum fun e a => C a * (X ^ p) ^ e := by |
| 50 | + simp [expand, eval₂] |
| 51 | +#align polynomial.expand_eq_sum Polynomial.expand_eq_sum |
| 52 | + |
| 53 | +@[simp] |
| 54 | +theorem expand_C (r : R) : expand R p (C r) = C r := |
| 55 | + eval₂_C _ _ |
| 56 | +set_option linter.uppercaseLean3 false in |
| 57 | +#align polynomial.expand_C Polynomial.expand_C |
| 58 | + |
| 59 | +@[simp] |
| 60 | +theorem expand_X : expand R p X = X ^ p := |
| 61 | + eval₂_X _ _ |
| 62 | +set_option linter.uppercaseLean3 false in |
| 63 | +#align polynomial.expand_X Polynomial.expand_X |
| 64 | + |
| 65 | +@[simp] |
| 66 | +theorem expand_monomial (r : R) : expand R p (monomial q r) = monomial (q * p) r := by |
| 67 | + simp_rw [← smul_X_eq_monomial, AlgHom.map_smul, AlgHom.map_pow, expand_X, mul_comm, pow_mul] |
| 68 | +#align polynomial.expand_monomial Polynomial.expand_monomial |
| 69 | + |
| 70 | +theorem expand_expand (f : R[X]) : expand R p (expand R q f) = expand R (p * q) f := |
| 71 | + Polynomial.induction_on f (fun r => by simp_rw [expand_C]) |
| 72 | + (fun f g ihf ihg => by simp_rw [AlgHom.map_add, ihf, ihg]) fun n r _ => by |
| 73 | + simp_rw [AlgHom.map_mul, expand_C, AlgHom.map_pow, expand_X, AlgHom.map_pow, expand_X, pow_mul] |
| 74 | +#align polynomial.expand_expand Polynomial.expand_expand |
| 75 | + |
| 76 | +theorem expand_mul (f : R[X]) : expand R (p * q) f = expand R p (expand R q f) := |
| 77 | + (expand_expand p q f).symm |
| 78 | +#align polynomial.expand_mul Polynomial.expand_mul |
| 79 | + |
| 80 | +@[simp] |
| 81 | +theorem expand_zero (f : R[X]) : expand R 0 f = C (eval 1 f) := by simp [expand] |
| 82 | +#align polynomial.expand_zero Polynomial.expand_zero |
| 83 | + |
| 84 | +@[simp] |
| 85 | +theorem expand_one (f : R[X]) : expand R 1 f = f := |
| 86 | + Polynomial.induction_on f (fun r => by rw [expand_C]) |
| 87 | + (fun f g ihf ihg => by rw [AlgHom.map_add, ihf, ihg]) fun n r _ => by |
| 88 | + rw [AlgHom.map_mul, expand_C, AlgHom.map_pow, expand_X, pow_one] |
| 89 | +#align polynomial.expand_one Polynomial.expand_one |
| 90 | + |
| 91 | +theorem expand_pow (f : R[X]) : expand R (p ^ q) f = (expand R p^[q]) f := |
| 92 | + Nat.recOn q (by rw [pow_zero, expand_one, Function.iterate_zero, id]) fun n ih => by |
| 93 | + rw [Function.iterate_succ_apply', pow_succ, expand_mul, ih] |
| 94 | +#align polynomial.expand_pow Polynomial.expand_pow |
| 95 | + |
| 96 | +theorem derivative_expand (f : R[X]) : Polynomial.derivative (expand R p f) = |
| 97 | + expand R p (Polynomial.derivative f) * (p * (X ^ (p - 1) : R[X])) := by |
| 98 | + rw [coe_expand, derivative_eval₂_C, derivative_pow, C_eq_nat_cast, derivative_X, mul_one] |
| 99 | +#align polynomial.derivative_expand Polynomial.derivative_expand |
| 100 | + |
| 101 | +theorem coeff_expand {p : ℕ} (hp : 0 < p) (f : R[X]) (n : ℕ) : |
| 102 | + (expand R p f).coeff n = if p ∣ n then f.coeff (n / p) else 0 := by |
| 103 | + simp only [expand_eq_sum] |
| 104 | + simp_rw [coeff_sum, ← pow_mul, C_mul_X_pow_eq_monomial, coeff_monomial, sum] |
| 105 | + split_ifs with h |
| 106 | + · rw [Finset.sum_eq_single (n / p), Nat.mul_div_cancel' h, if_pos rfl] |
| 107 | + · intro b _ hb2 |
| 108 | + rw [if_neg] |
| 109 | + intro hb3 |
| 110 | + apply hb2 |
| 111 | + rw [← hb3, Nat.mul_div_cancel_left b hp] |
| 112 | + · intro hn |
| 113 | + rw [not_mem_support_iff.1 hn] |
| 114 | + split_ifs <;> rfl |
| 115 | + · rw [Finset.sum_eq_zero] |
| 116 | + intro k _ |
| 117 | + rw [if_neg] |
| 118 | + exact fun hkn => h ⟨k, hkn.symm⟩ |
| 119 | +#align polynomial.coeff_expand Polynomial.coeff_expand |
| 120 | + |
| 121 | +@[simp] |
| 122 | +theorem coeff_expand_mul {p : ℕ} (hp : 0 < p) (f : R[X]) (n : ℕ) : |
| 123 | + (expand R p f).coeff (n * p) = f.coeff n := by |
| 124 | + rw [coeff_expand hp, if_pos (dvd_mul_left _ _), Nat.mul_div_cancel _ hp] |
| 125 | +#align polynomial.coeff_expand_mul Polynomial.coeff_expand_mul |
| 126 | + |
| 127 | +@[simp] |
| 128 | +theorem coeff_expand_mul' {p : ℕ} (hp : 0 < p) (f : R[X]) (n : ℕ) : |
| 129 | + (expand R p f).coeff (p * n) = f.coeff n := by rw [mul_comm, coeff_expand_mul hp] |
| 130 | +#align polynomial.coeff_expand_mul' Polynomial.coeff_expand_mul' |
| 131 | + |
| 132 | +/-- Expansion is injective. -/ |
| 133 | +theorem expand_injective {n : ℕ} (hn : 0 < n) : Function.Injective (expand R n) := fun g g' H => |
| 134 | + ext fun k => by rw [← coeff_expand_mul hn, H, coeff_expand_mul hn] |
| 135 | +#align polynomial.expand_injective Polynomial.expand_injective |
| 136 | + |
| 137 | +theorem expand_inj {p : ℕ} (hp : 0 < p) {f g : R[X]} : expand R p f = expand R p g ↔ f = g := |
| 138 | + (expand_injective hp).eq_iff |
| 139 | +#align polynomial.expand_inj Polynomial.expand_inj |
| 140 | + |
| 141 | +theorem expand_eq_zero {p : ℕ} (hp : 0 < p) {f : R[X]} : expand R p f = 0 ↔ f = 0 := |
| 142 | + (expand_injective hp).eq_iff' (map_zero _) |
| 143 | +#align polynomial.expand_eq_zero Polynomial.expand_eq_zero |
| 144 | + |
| 145 | +theorem expand_ne_zero {p : ℕ} (hp : 0 < p) {f : R[X]} : expand R p f ≠ 0 ↔ f ≠ 0 := |
| 146 | + (expand_eq_zero hp).not |
| 147 | +#align polynomial.expand_ne_zero Polynomial.expand_ne_zero |
| 148 | + |
| 149 | +theorem expand_eq_C {p : ℕ} (hp : 0 < p) {f : R[X]} {r : R} : expand R p f = C r ↔ f = C r := by |
| 150 | + rw [← expand_C, expand_inj hp, expand_C] |
| 151 | +set_option linter.uppercaseLean3 false in |
| 152 | +#align polynomial.expand_eq_C Polynomial.expand_eq_C |
| 153 | + |
| 154 | +theorem natDegree_expand (p : ℕ) (f : R[X]) : (expand R p f).natDegree = f.natDegree * p := by |
| 155 | + cases' p.eq_zero_or_pos with hp hp |
| 156 | + · rw [hp, coe_expand, pow_zero, MulZeroClass.mul_zero, ← C_1, eval₂_hom, natDegree_C] |
| 157 | + by_cases hf : f = 0 |
| 158 | + · rw [hf, AlgHom.map_zero, natDegree_zero, MulZeroClass.zero_mul] |
| 159 | + have hf1 : expand R p f ≠ 0 := mt (expand_eq_zero hp).1 hf |
| 160 | + rw [← WithBot.coe_eq_coe] |
| 161 | + convert (degree_eq_natDegree hf1).symm -- Porting note: was `rw [degree_eq_natDegree hf1]` |
| 162 | + symm |
| 163 | + refine' le_antisymm ((degree_le_iff_coeff_zero _ _).2 fun n hn => _) _ |
| 164 | + · rw [coeff_expand hp] |
| 165 | + split_ifs with hpn |
| 166 | + · rw [coeff_eq_zero_of_natDegree_lt] |
| 167 | + contrapose! hn |
| 168 | + erw [WithBot.coe_le_coe, ← Nat.div_mul_cancel hpn] |
| 169 | + exact Nat.mul_le_mul_right p hn |
| 170 | + · rfl |
| 171 | + · refine' le_degree_of_ne_zero _ |
| 172 | + erw [coeff_expand_mul hp, ← leadingCoeff] |
| 173 | + exact mt leadingCoeff_eq_zero.1 hf |
| 174 | +#align polynomial.nat_degree_expand Polynomial.natDegree_expand |
| 175 | + |
| 176 | +theorem Monic.expand {p : ℕ} {f : R[X]} (hp : 0 < p) (h : f.Monic) : (expand R p f).Monic := by |
| 177 | + rw [Monic.def, Polynomial.leadingCoeff, natDegree_expand, coeff_expand hp] |
| 178 | + simp [hp, h] |
| 179 | +#align polynomial.monic.expand Polynomial.Monic.expand |
| 180 | + |
| 181 | +theorem map_expand {p : ℕ} {f : R →+* S} {q : R[X]} : |
| 182 | + map f (expand R p q) = expand S p (map f q) := by |
| 183 | + by_cases hp : p = 0 |
| 184 | + · simp [hp] |
| 185 | + ext |
| 186 | + rw [coeff_map, coeff_expand (Nat.pos_of_ne_zero hp), coeff_expand (Nat.pos_of_ne_zero hp)] |
| 187 | + split_ifs <;> simp_all |
| 188 | +#align polynomial.map_expand Polynomial.map_expand |
| 189 | + |
| 190 | +@[simp] |
| 191 | +theorem expand_eval (p : ℕ) (P : R[X]) (r : R) : eval r (expand R p P) = eval (r ^ p) P := by |
| 192 | + refine' Polynomial.induction_on P (fun a => by simp) (fun f g hf hg => _) fun n a _ => by simp |
| 193 | + rw [AlgHom.map_add, eval_add, eval_add, hf, hg] |
| 194 | +#align polynomial.expand_eval Polynomial.expand_eval |
| 195 | + |
| 196 | +@[simp] |
| 197 | +theorem expand_aeval {A : Type _} [Semiring A] [Algebra R A] (p : ℕ) (P : R[X]) (r : A) : |
| 198 | + aeval r (expand R p P) = aeval (r ^ p) P := by |
| 199 | + refine' Polynomial.induction_on P (fun a => by simp) (fun f g hf hg => _) fun n a _ => by simp |
| 200 | + rw [AlgHom.map_add, aeval_add, aeval_add, hf, hg] |
| 201 | +#align polynomial.expand_aeval Polynomial.expand_aeval |
| 202 | + |
| 203 | +/-- The opposite of `expand`: sends `∑ aₙ xⁿᵖ` to `∑ aₙ xⁿ`. -/ |
| 204 | +noncomputable def contract (p : ℕ) (f : R[X]) : R[X] := |
| 205 | + ∑ n in range (f.natDegree + 1), monomial n (f.coeff (n * p)) |
| 206 | +#align polynomial.contract Polynomial.contract |
| 207 | + |
| 208 | +theorem coeff_contract {p : ℕ} (hp : p ≠ 0) (f : R[X]) (n : ℕ) : |
| 209 | + (contract p f).coeff n = f.coeff (n * p) := by |
| 210 | + simp only [contract, coeff_monomial, sum_ite_eq', finset_sum_coeff, mem_range, not_lt, |
| 211 | + ite_eq_left_iff] |
| 212 | + intro hn |
| 213 | + apply (coeff_eq_zero_of_natDegree_lt _).symm |
| 214 | + calc |
| 215 | + f.natDegree < f.natDegree + 1 := Nat.lt_succ_self _ |
| 216 | + _ ≤ n * 1 := by simpa only [mul_one] using hn |
| 217 | + _ ≤ n * p := mul_le_mul_of_nonneg_left (show 1 ≤ p from hp.bot_lt) (zero_le n) |
| 218 | +#align polynomial.coeff_contract Polynomial.coeff_contract |
| 219 | + |
| 220 | +theorem contract_expand {f : R[X]} (hp : p ≠ 0) : contract p (expand R p f) = f := by |
| 221 | + ext |
| 222 | + simp [coeff_contract hp, coeff_expand hp.bot_lt, Nat.mul_div_cancel _ hp.bot_lt] |
| 223 | +#align polynomial.contract_expand Polynomial.contract_expand |
| 224 | + |
| 225 | +section CharP |
| 226 | + |
| 227 | +variable [CharP R p] |
| 228 | + |
| 229 | +theorem expand_contract [NoZeroDivisors R] {f : R[X]} (hf : Polynomial.derivative f = 0) |
| 230 | + (hp : p ≠ 0) : expand R p (contract p f) = f := by |
| 231 | + ext n |
| 232 | + rw [coeff_expand hp.bot_lt, coeff_contract hp] |
| 233 | + split_ifs with h |
| 234 | + · rw [Nat.div_mul_cancel h] |
| 235 | + · cases' n with n |
| 236 | + · exact absurd (dvd_zero p) h |
| 237 | + have := coeff_derivative f n |
| 238 | + rw [hf, coeff_zero, zero_eq_mul] at this |
| 239 | + cases' this with h' |
| 240 | + · rw [h'] |
| 241 | + rename_i _ _ _ _ h' |
| 242 | + rw [← Nat.cast_succ, CharP.cast_eq_zero_iff R p] at h' |
| 243 | + exact absurd h' h |
| 244 | +#align polynomial.expand_contract Polynomial.expand_contract |
| 245 | + |
| 246 | +variable [hp : Fact p.Prime] |
| 247 | + |
| 248 | +theorem expand_char (f : R[X]) : map (frobenius R p) (expand R p f) = f ^ p := by |
| 249 | + refine' f.induction_on' (fun a b ha hb => _) fun n a => _ |
| 250 | + · rw [AlgHom.map_add, Polynomial.map_add, ha, hb, add_pow_char] |
| 251 | + · rw [expand_monomial, map_monomial, ← C_mul_X_pow_eq_monomial, ← C_mul_X_pow_eq_monomial, |
| 252 | + mul_pow, ← C.map_pow, frobenius_def] |
| 253 | + ring |
| 254 | +#align polynomial.expand_char Polynomial.expand_char |
| 255 | + |
| 256 | +theorem map_expand_pow_char (f : R[X]) (n : ℕ) : |
| 257 | + map (frobenius R p ^ n) (expand R (p ^ n) f) = f ^ p ^ n := by |
| 258 | + induction' n with _ n_ih |
| 259 | + · simp [RingHom.one_def] |
| 260 | + symm |
| 261 | + rw [pow_succ', pow_mul, ← n_ih, ← expand_char, pow_succ, RingHom.mul_def, ← map_map, mul_comm, |
| 262 | + expand_mul, ← map_expand] |
| 263 | +#align polynomial.map_expand_pow_char Polynomial.map_expand_pow_char |
| 264 | + |
| 265 | +end CharP |
| 266 | + |
| 267 | +end CommSemiring |
| 268 | + |
| 269 | +section IsDomain |
| 270 | + |
| 271 | +variable (R : Type u) [CommRing R] [IsDomain R] |
| 272 | + |
| 273 | +theorem isLocalRingHom_expand {p : ℕ} (hp : 0 < p) : |
| 274 | + IsLocalRingHom (↑(expand R p) : R[X] →+* R[X]) := by |
| 275 | + refine' ⟨fun f hf1 => _⟩; norm_cast at hf1 |
| 276 | + have hf2 := eq_C_of_degree_eq_zero (degree_eq_zero_of_isUnit hf1) |
| 277 | + rw [coeff_expand hp, if_pos (dvd_zero _), p.zero_div] at hf2 |
| 278 | + rw [hf2, isUnit_C] at hf1; rw [expand_eq_C hp] at hf2; rwa [hf2, isUnit_C] |
| 279 | +#align polynomial.is_local_ring_hom_expand Polynomial.isLocalRingHom_expand |
| 280 | + |
| 281 | +variable {R} |
| 282 | + |
| 283 | +theorem of_irreducible_expand {p : ℕ} (hp : p ≠ 0) {f : R[X]} (hf : Irreducible (expand R p f)) : |
| 284 | + Irreducible f := |
| 285 | + let _ := isLocalRingHom_expand R hp.bot_lt |
| 286 | + of_irreducible_map (↑(expand R p)) hf |
| 287 | +#align polynomial.of_irreducible_expand Polynomial.of_irreducible_expand |
| 288 | + |
| 289 | +theorem of_irreducible_expand_pow {p : ℕ} (hp : p ≠ 0) {f : R[X]} {n : ℕ} : |
| 290 | + Irreducible (expand R (p ^ n) f) → Irreducible f := |
| 291 | + Nat.recOn n (fun hf => by rwa [pow_zero, expand_one] at hf) fun n ih hf => |
| 292 | + ih <| of_irreducible_expand hp <| by |
| 293 | + rw [pow_succ] at hf |
| 294 | + rwa [expand_expand] |
| 295 | +#align polynomial.of_irreducible_expand_pow Polynomial.of_irreducible_expand_pow |
| 296 | + |
| 297 | +end IsDomain |
| 298 | + |
| 299 | +end Polynomial |
0 commit comments