|
| 1 | +/- |
| 2 | +Copyright (c) 2020 Riccardo Brasca. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Author: Riccardo Brasca |
| 5 | +-/ |
| 6 | + |
| 7 | +import data.polynomial.algebra_map |
| 8 | +import algebra.algebra.subalgebra |
| 9 | +import algebra.polynomial.big_operators |
| 10 | +import data.polynomial.erase_lead |
| 11 | +import data.polynomial.degree.basic |
| 12 | + |
| 13 | +/-! |
| 14 | +# Polynomials that lift |
| 15 | +
|
| 16 | +Given semirings `R` and `S` with a morphism `f : R →+* S`, we define a subsemiring `lifts` of |
| 17 | +`polynomial S` by the image of `ring_hom.of (map f)`. |
| 18 | +Then, we prove that a polynomial that lifts can always be lifted to a polynomial of the same degree |
| 19 | +and that a monic polynomial that lifts can be lifted to a monic polynomial (of the same degree). |
| 20 | +
|
| 21 | +## Main definition |
| 22 | +
|
| 23 | +* `lifts (f : R →+* S)` : the subsemiring of polynomials that lift. |
| 24 | +
|
| 25 | +## Main results |
| 26 | +
|
| 27 | +* `lifts_and_degree_eq` : A polynomial lifts if and only if it can be lifted to a polynomial |
| 28 | +of the same degree. |
| 29 | +* `lifts_and_degree_eq_and_monic` : A monic polynomial lifts if and only if it can be lifted to a |
| 30 | +monic polynomial of the same degree. |
| 31 | +* `lifts_iff_alg` : if `R` is commutative, a polynomial lifts if and only if it is in the image of |
| 32 | +`map_alg`, where `map_alg : polynomial R →ₐ[R] polynomial S` is the only `R`-algebra map |
| 33 | +that sends `X` to `X`. |
| 34 | +
|
| 35 | +## Implementation details |
| 36 | +
|
| 37 | +In general `R` and `S` are semiring, so `lifts` is a semiring. In the case of rings, see |
| 38 | +`lifts_iff_lifts_ring`. |
| 39 | +
|
| 40 | +Since we do not assume `R` to be commutative, we cannot say in general that the set of polynomials |
| 41 | +that lift is a subalgebra. (By `lift_iff` this is true if `R` is commutative.) |
| 42 | +
|
| 43 | +-/ |
| 44 | + |
| 45 | +open_locale classical big_operators |
| 46 | +noncomputable theory |
| 47 | + |
| 48 | +namespace polynomial |
| 49 | +universes u v w |
| 50 | + |
| 51 | +section semiring |
| 52 | + |
| 53 | +variables {R : Type u} [semiring R] {S : Type v} [semiring S] {f : R →+* S} |
| 54 | + |
| 55 | +/-- We define the subsemiring of polynomials that lifts as the image of `ring_hom.of (map f)`. -/ |
| 56 | +def lifts (f : R →+* S) : subsemiring (polynomial S) := ring_hom.srange (ring_hom.of (map f)) |
| 57 | + |
| 58 | +lemma mem_lifts (p : polynomial S) : p ∈ lifts f ↔ ∃ (q : polynomial R), map f q = p := |
| 59 | +by simp only [lifts, ring_hom.coe_of, ring_hom.mem_srange] |
| 60 | + |
| 61 | +lemma lifts_iff_set_range (p : polynomial S) : p ∈ lifts f ↔ p ∈ set.range (map f) := |
| 62 | +by simp only [lifts, set.mem_range, ring_hom.coe_of, ring_hom.mem_srange] |
| 63 | + |
| 64 | +lemma lifts_iff_coeff_lifts (p : polynomial S) : p ∈ lifts f ↔ ∀ (n : ℕ), p.coeff n ∈ set.range f := |
| 65 | +by rw [lifts_iff_set_range, mem_map_range] |
| 66 | + |
| 67 | +/--If `(r : R)`, then `C (f r)` lifts. -/ |
| 68 | +lemma C_mem_lifts (f : R →+* S) (r : R) : (C (f r)) ∈ lifts f := |
| 69 | +⟨C r, by simp only [map_C, set.mem_univ, subsemiring.coe_top, eq_self_iff_true, |
| 70 | + ring_hom.coe_of, and_self]⟩ |
| 71 | + |
| 72 | +/-- If `(s : S)` is in the image of `f`, then `C s` lifts. -/ |
| 73 | +lemma C'_mem_lifts {f : R →+* S} {s : S} (h : s ∈ set.range f) : (C s) ∈ lifts f := |
| 74 | +begin |
| 75 | + obtain ⟨r, rfl⟩ := set.mem_range.1 h, |
| 76 | + use C r, |
| 77 | + simp only [map_C, set.mem_univ, subsemiring.coe_top, eq_self_iff_true, ring_hom.coe_of, and_self] |
| 78 | +end |
| 79 | + |
| 80 | +/-- The polynomial `X` lifts. -/ |
| 81 | +lemma X_mem_lifts (f : R →+* S) : (X : polynomial S) ∈ lifts f := |
| 82 | +⟨X, by simp only [set.mem_univ, subsemiring.coe_top, eq_self_iff_true, map_X, |
| 83 | + ring_hom.coe_of, and_self]⟩ |
| 84 | + |
| 85 | +/-- The polynomial `X ^ n` lifts. -/ |
| 86 | +lemma X_pow_mem_lifts (f : R →+* S) (n : ℕ) : (X ^ n : polynomial S) ∈ lifts f := |
| 87 | +⟨X ^ n, by simp only [map_pow, set.mem_univ, subsemiring.coe_top, eq_self_iff_true, map_X, |
| 88 | + ring_hom.coe_of, and_self]⟩ |
| 89 | + |
| 90 | +/-- If `p` lifts and `(r : R)` then `r * p` lifts. -/ |
| 91 | +lemma base_mul_mem_lifts {p : polynomial S} (r : R) (hp : p ∈ lifts f) : C (f r) * p ∈ lifts f := |
| 92 | +begin |
| 93 | + simp only [lifts, ring_hom.coe_of, ring_hom.mem_srange] at hp ⊢, |
| 94 | + obtain ⟨p₁, rfl⟩ := hp, |
| 95 | + use C r * p₁, |
| 96 | + simp only [map_C, map_mul] |
| 97 | +end |
| 98 | + |
| 99 | +/-- If `(s : S)` is in the image of `f`, then `monomial n s` lifts. -/ |
| 100 | +lemma monomial_mem_lifts {s : S} (n : ℕ) (h : s ∈ set.range f) : (monomial n s) ∈ lifts f := |
| 101 | +begin |
| 102 | + obtain ⟨r, rfl⟩ := set.mem_range.1 h, |
| 103 | + use monomial n r, |
| 104 | + simp only [set.mem_univ, map_monomial, subsemiring.coe_top, eq_self_iff_true, ring_hom.coe_of, |
| 105 | + and_self], |
| 106 | +end |
| 107 | + |
| 108 | +/-- If `p` lifts then `p.erase n` lifts. -/ |
| 109 | +lemma erase_mem_lifts {p : polynomial S} (n : ℕ) (h : p ∈ lifts f) : p.erase n ∈ lifts f := |
| 110 | +begin |
| 111 | + rw [lifts_iff_set_range, mem_map_range, coeff] at h ⊢, |
| 112 | + intros k, |
| 113 | + by_cases hk : k = n, |
| 114 | + { use 0, |
| 115 | + simp only [hk, ring_hom.map_zero, finsupp.erase_same] }, |
| 116 | + obtain ⟨i, hi⟩ := h k, |
| 117 | + use i, |
| 118 | + simp only [hi, hk, finsupp.erase_ne, ne.def, not_false_iff], |
| 119 | +end |
| 120 | + |
| 121 | +section lift_deg |
| 122 | + |
| 123 | +lemma monomial_mem_lifts_and_degree_eq {s : S} {n : ℕ} (hl : monomial n s ∈ lifts f) : |
| 124 | + ∃ (q : polynomial R), map f q = (monomial n s) ∧ q.degree = (monomial n s).degree := |
| 125 | +begin |
| 126 | + by_cases hzero : s = 0, |
| 127 | + { use 0, |
| 128 | + simp only [hzero, degree_zero, eq_self_iff_true, and_self, monomial_zero_right, map_zero] }, |
| 129 | + rw lifts_iff_set_range at hl, |
| 130 | + obtain ⟨q, hq⟩ := hl, |
| 131 | + replace hq := (ext_iff.1 hq) n, |
| 132 | + have hcoeff : f (q.coeff n) = s, |
| 133 | + { simp [coeff_monomial] at hq, |
| 134 | + exact hq }, |
| 135 | + use (monomial n (q.coeff n)), |
| 136 | + split, |
| 137 | + { simp only [hcoeff, map_monomial] }, |
| 138 | + have hqzero : q.coeff n ≠ 0, |
| 139 | + { intro habs, |
| 140 | + simp only [habs, ring_hom.map_zero] at hcoeff, |
| 141 | + exact hzero hcoeff.symm }, |
| 142 | + repeat {rw single_eq_C_mul_X}, |
| 143 | + simp only [hzero, hqzero, ne.def, not_false_iff, degree_C_mul_X_pow], |
| 144 | +end |
| 145 | + |
| 146 | +/-- A polynomial lifts if and only if it can be lifted to a polynomial of the same degree. -/ |
| 147 | +lemma mem_lifts_and_degree_eq {p : polynomial S} (hlifts : p ∈ lifts f) : |
| 148 | + ∃ (q : polynomial R), map f q = p ∧ q.degree = p.degree := |
| 149 | +begin |
| 150 | + generalize' hd : p.nat_degree = d, |
| 151 | + revert hd p, |
| 152 | + apply nat.strong_induction_on d, |
| 153 | + intros n hn p hlifts hdeg, |
| 154 | + by_cases erase_zero : p.erase_lead = 0, |
| 155 | + { rw [← erase_lead_add_monomial_nat_degree_leading_coeff p, erase_zero, zero_add, leading_coeff], |
| 156 | + exact monomial_mem_lifts_and_degree_eq (monomial_mem_lifts p.nat_degree |
| 157 | + ((lifts_iff_coeff_lifts p).1 hlifts p.nat_degree)) }, |
| 158 | + have deg_erase := or.resolve_right (erase_lead_nat_degree_lt_or_erase_lead_eq_zero p) erase_zero, |
| 159 | + have pzero : p ≠ 0, |
| 160 | + { intro habs, |
| 161 | + exfalso, |
| 162 | + rw [habs, erase_lead_zero, eq_self_iff_true, not_true] at erase_zero, |
| 163 | + exact erase_zero }, |
| 164 | + have lead_zero : p.coeff p.nat_degree ≠ 0, |
| 165 | + { rw [← leading_coeff, ne.def, leading_coeff_eq_zero]; exact pzero }, |
| 166 | + obtain ⟨lead, hlead⟩ := monomial_mem_lifts_and_degree_eq (monomial_mem_lifts p.nat_degree |
| 167 | + ((lifts_iff_coeff_lifts p).1 hlifts p.nat_degree)), |
| 168 | + have deg_lead : lead.degree = p.nat_degree, |
| 169 | + { rw [hlead.2, single_eq_C_mul_X, degree_C_mul_X_pow p.nat_degree lead_zero] }, |
| 170 | + rw hdeg at deg_erase, |
| 171 | + obtain ⟨erase, herase⟩ := hn p.erase_lead.nat_degree deg_erase |
| 172 | + (erase_mem_lifts p.nat_degree hlifts) (refl p.erase_lead.nat_degree), |
| 173 | + use erase + lead, |
| 174 | + split, |
| 175 | + { simp only [hlead, herase, map_add], |
| 176 | + nth_rewrite 0 erase_lead_add_monomial_nat_degree_leading_coeff p }, |
| 177 | + rw [←hdeg, erase_lead] at deg_erase, |
| 178 | + replace deg_erase := lt_of_le_of_lt degree_le_nat_degree (with_bot.coe_lt_coe.2 deg_erase), |
| 179 | + rw [← deg_lead, ← herase.2] at deg_erase, |
| 180 | + rw [degree_add_eq_of_degree_lt deg_erase, deg_lead, degree_eq_nat_degree pzero] |
| 181 | +end |
| 182 | + |
| 183 | +end lift_deg |
| 184 | + |
| 185 | +section monic |
| 186 | + |
| 187 | +/-- A monic polynomial lifts if and only if it can be lifted to a monic polynomial |
| 188 | +of the same degree. -/ |
| 189 | +lemma lifts_and_degree_eq_and_monic [nontrivial S] {p : polynomial S} (hlifts :p ∈ lifts f) |
| 190 | + (hmonic : p.monic) : ∃ (q : polynomial R), map f q = p ∧ q.degree = p.degree ∧ q.monic := |
| 191 | +begin |
| 192 | + by_cases Rtrivial : nontrivial R, |
| 193 | + swap, |
| 194 | + { rw not_nontrivial_iff_subsingleton at Rtrivial, |
| 195 | + obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq hlifts, |
| 196 | + use q, |
| 197 | + exact ⟨hq.1, hq.2, @monic_of_subsingleton _ _ Rtrivial q⟩ }, |
| 198 | + by_cases er_zero : p.erase_lead = 0, |
| 199 | + { rw [← erase_lead_add_C_mul_X_pow p, er_zero, zero_add, monic.def.1 hmonic, C_1, one_mul], |
| 200 | + use X ^ p.nat_degree, |
| 201 | + repeat {split}, |
| 202 | + { simp only [map_pow, map_X] }, |
| 203 | + { rw [@degree_X_pow R _ Rtrivial, degree_X_pow] }, |
| 204 | + {exact monic_pow monic_X p.nat_degree } }, |
| 205 | + obtain ⟨q, hq⟩ := mem_lifts_and_degree_eq (erase_mem_lifts p.nat_degree hlifts), |
| 206 | + have deg_er : p.erase_lead.nat_degree < p.nat_degree := |
| 207 | + or.resolve_right (erase_lead_nat_degree_lt_or_erase_lead_eq_zero p) er_zero, |
| 208 | + replace deg_er := with_bot.coe_lt_coe.2 deg_er, |
| 209 | + rw [← degree_eq_nat_degree er_zero, erase_lead, ← hq.2, |
| 210 | + ← @degree_X_pow R _ Rtrivial p.nat_degree] at deg_er, |
| 211 | + use q + X ^ p.nat_degree, |
| 212 | + repeat {split}, |
| 213 | + { simp only [hq, map_add, map_pow, map_X], |
| 214 | + nth_rewrite 3 [← erase_lead_add_C_mul_X_pow p], |
| 215 | + rw [erase_lead, monic.leading_coeff hmonic, C_1, one_mul] }, |
| 216 | + { rw [degree_add_eq_of_degree_lt deg_er, @degree_X_pow R _ Rtrivial p.nat_degree, |
| 217 | + degree_eq_nat_degree (monic.ne_zero hmonic)] }, |
| 218 | + { rw [monic.def, leading_coeff_add_of_degree_lt deg_er], |
| 219 | + exact monic_pow monic_X p.nat_degree } |
| 220 | +end |
| 221 | + |
| 222 | +end monic |
| 223 | + |
| 224 | +end semiring |
| 225 | + |
| 226 | +section ring |
| 227 | + |
| 228 | +variables {R : Type u} [ring R] {S : Type v} [ring S] (f : R →+* S) |
| 229 | + |
| 230 | +/-- The subring of polynomials that lift. -/ |
| 231 | +def lifts_ring (f : R →+* S) : subring (polynomial S) := ring_hom.range (ring_hom.of (map f)) |
| 232 | + |
| 233 | +/-- If `R` and `S` are rings, `p` is in the subring of polynomials that lift if and only if it is in |
| 234 | +the subsemiring of polynomials that lift. -/ |
| 235 | +lemma lifts_iff_lifts_ring (p : polynomial S) : p ∈ lifts f ↔ p ∈ lifts_ring f := |
| 236 | +by simp only [lifts, lifts_ring, ring_hom.mem_range, ring_hom.mem_srange] |
| 237 | + |
| 238 | +end ring |
| 239 | + |
| 240 | +section algebra |
| 241 | + |
| 242 | +variables {R : Type u} [comm_semiring R] {S : Type v} [semiring S] [algebra R S] |
| 243 | + |
| 244 | +/-- The map `polynomial R → polynomial S` as an algebra homomorphism. -/ |
| 245 | +def map_alg (R : Type u) [comm_semiring R] (S : Type v) [semiring S] [algebra R S] : |
| 246 | + polynomial R →ₐ[R] polynomial S := @aeval _ (polynomial S) _ _ _ (X : polynomial S) |
| 247 | + |
| 248 | +/-- `map_alg` is the morphism induced by `R → S`. -/ |
| 249 | +lemma map_alg_eq_map (p : polynomial R) : map_alg R S p = map (algebra_map R S) p := |
| 250 | +by simp only [map_alg, aeval_def, eval₂, map, algebra_map_apply, ring_hom.coe_comp] |
| 251 | + |
| 252 | +/-- A polynomial `p` lifts if and only if it is in the image of `map_alg`. -/ |
| 253 | +lemma mem_lifts_iff_mem_alg (R : Type u) [comm_semiring R] {S : Type v} [semiring S] [algebra R S] |
| 254 | + (p : polynomial S) :p ∈ lifts (algebra_map R S) ↔ p ∈ (alg_hom.range (@map_alg R _ S _ _)) := |
| 255 | +by simp only [lifts, map_alg_eq_map, alg_hom.mem_range, ring_hom.coe_of, ring_hom.mem_srange] |
| 256 | + |
| 257 | +/-- If `p` lifts and `(r : R)` then `r • p` lifts. -/ |
| 258 | +lemma smul_mem_lifts {p : polynomial S} (r : R) (hp : p ∈ lifts (algebra_map R S)) : |
| 259 | + r • p ∈ lifts (algebra_map R S) := |
| 260 | +by { rw mem_lifts_iff_mem_alg at hp ⊢, exact subalgebra.smul_mem (map_alg R S).range hp r } |
| 261 | + |
| 262 | +end algebra |
| 263 | + |
| 264 | +end polynomial |
0 commit comments