Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit cc7f06b

Browse files
feat(data/polynomial/lifts): polynomials that lift (#4796)
Given semirings `R` and `S` with a morphism `f : R →+* S`, a polynomial with coefficients in `S` lifts if there exist `q : polynomial R` such that `map f p = q`. I proved some basic results about polynomials that lifts, for example concerning the sum etc. Almost all the proof are trivial (and essentially identical), fell free to comment just the first ones, I will do the changes in all the relevant lemmas. The proofs of `lifts_iff_lifts_deg` (a polynomial that lifts can be lifted to a polynomial of the same degree) and of `lifts_iff_lifts_deg_monic` (the same for monic polynomials) are quite painful, but this are the shortest proofs I found... I think that at least these two results deserve to be in mathlib (I'm using them to prove that the cyclotomic polynomial lift to `\Z`).
1 parent bfadf05 commit cc7f06b

File tree

1 file changed

+264
-0
lines changed

1 file changed

+264
-0
lines changed

src/data/polynomial/lifts.lean

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
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

Comments
 (0)