Skip to content

Commit 5771d64

Browse files
feat: port RingTheory.Polynomial.Eisenstein.Basic (#3382)
1 parent da5ce5a commit 5771d64

File tree

2 files changed

+253
-0
lines changed

2 files changed

+253
-0
lines changed

β€ŽMathlib.leanβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,6 +1501,7 @@ import Mathlib.RingTheory.OreLocalization.OreSet
15011501
import Mathlib.RingTheory.Polynomial.Basic
15021502
import Mathlib.RingTheory.Polynomial.Chebyshev
15031503
import Mathlib.RingTheory.Polynomial.Content
1504+
import Mathlib.RingTheory.Polynomial.Eisenstein.Basic
15041505
import Mathlib.RingTheory.Polynomial.Opposites
15051506
import Mathlib.RingTheory.Polynomial.Pochhammer
15061507
import Mathlib.RingTheory.Polynomial.ScaleRoots
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
/-
2+
Copyright (c) 2022 Riccardo Brasca. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Riccardo Brasca
5+
6+
! This file was ported from Lean 3 source module ring_theory.polynomial.eisenstein.basic
7+
! leanprover-community/mathlib commit 2032a878972d5672e7c27c957e7a6e297b044973
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.EisensteinCriterion
12+
import Mathlib.RingTheory.Polynomial.ScaleRoots
13+
14+
/-!
15+
# Eisenstein polynomials
16+
Given an ideal `π“Ÿ` of a commutative semiring `R`, we say that a polynomial `f : R[X]` is
17+
*Eisenstein at `π“Ÿ`* if `f.leadingCoeff βˆ‰ π“Ÿ`, `βˆ€ n, n < f.natDegree β†’ f.coeff n ∈ π“Ÿ` and
18+
`f.coeff 0 βˆ‰ π“Ÿ ^ 2`. In this file we gather miscellaneous results about Eisenstein polynomials.
19+
20+
## Main definitions
21+
* `Polynomial.IsEisensteinAt f π“Ÿ`: the property of being Eisenstein at `π“Ÿ`.
22+
23+
## Main results
24+
* `Polynomial.IsEisensteinAt.irreducible`: if a primitive `f` satisfies `f.IsEisensteinAt π“Ÿ`,
25+
where `π“Ÿ.IsPrime`, then `f` is irreducible.
26+
27+
## Implementation details
28+
We also define a notion `IsWeaklyEisensteinAt` requiring only that
29+
`βˆ€ n < f.natDegree β†’ f.coeff n ∈ π“Ÿ`. This makes certain results slightly more general and it is
30+
useful since it is sometimes better behaved (for example it is stable under `Polynomial.map`).
31+
32+
-/
33+
34+
35+
universe u v w z
36+
37+
variable {R : Type u}
38+
39+
open Ideal Algebra Finset
40+
41+
open BigOperators Polynomial
42+
43+
namespace Polynomial
44+
45+
/-- Given an ideal `π“Ÿ` of a commutative semiring `R`, we say that a polynomial `f : R[X]`
46+
is *weakly Eisenstein at `π“Ÿ`* if `βˆ€ n, n < f.natDegree β†’ f.coeff n ∈ π“Ÿ`. -/
47+
@[mk_iff]
48+
structure IsWeaklyEisensteinAt [CommSemiring R] (f : R[X]) (π“Ÿ : Ideal R) : Prop where
49+
mem : βˆ€ {n}, n < f.natDegree β†’ f.coeff n ∈ π“Ÿ
50+
#align polynomial.is_weakly_eisenstein_at Polynomial.IsWeaklyEisensteinAt
51+
52+
/-- Given an ideal `π“Ÿ` of a commutative semiring `R`, we say that a polynomial `f : R[X]`
53+
is *Eisenstein at `π“Ÿ`* if `f.leadingCoeff βˆ‰ π“Ÿ`, `βˆ€ n, n < f.natDegree β†’ f.coeff n ∈ π“Ÿ` and
54+
`f.coeff 0 βˆ‰ π“Ÿ ^ 2`. -/
55+
@[mk_iff]
56+
structure IsEisensteinAt [CommSemiring R] (f : R[X]) (π“Ÿ : Ideal R) : Prop where
57+
leading : f.leadingCoeff βˆ‰ π“Ÿ
58+
mem : βˆ€ {n}, n < f.natDegree β†’ f.coeff n ∈ π“Ÿ
59+
not_mem : f.coeff 0 βˆ‰ π“Ÿ ^ 2
60+
#align polynomial.is_eisenstein_at Polynomial.IsEisensteinAt
61+
62+
namespace IsWeaklyEisensteinAt
63+
64+
section CommSemiring
65+
66+
variable [CommSemiring R] {π“Ÿ : Ideal R} {f : R[X]} (hf : f.IsWeaklyEisensteinAt π“Ÿ)
67+
68+
set_option synthInstance.etaExperiment true
69+
70+
theorem map {A : Type v} [CommRing A] (Ο† : R β†’+* A) : (f.map Ο†).IsWeaklyEisensteinAt (π“Ÿ.map Ο†) :=
71+
by
72+
refine' (IsWeaklyEisensteinAt_iff _ _).2 fun hn => _
73+
rw [coeff_map]
74+
exact mem_map_of_mem _ (hf.mem (lt_of_lt_of_le hn (natDegree_map_le _ _)))
75+
#align polynomial.is_weakly_eisenstein_at.map Polynomial.IsWeaklyEisensteinAt.map
76+
77+
end CommSemiring
78+
79+
section CommRing
80+
81+
variable [CommRing R] {π“Ÿ : Ideal R} {f : R[X]} (hf : f.IsWeaklyEisensteinAt π“Ÿ)
82+
83+
variable {S : Type v} [CommRing S] [Algebra R S]
84+
85+
section Principal
86+
87+
variable {p : R}
88+
89+
theorem exists_mem_adjoin_mul_eq_pow_natDegree {x : S} (hx : aeval x f = 0) (hmo : f.Monic)
90+
(hf : f.IsWeaklyEisensteinAt (Submodule.span R {p})) :
91+
βˆƒ y ∈ adjoin R ({x} : Set S), (algebraMap R S) p * y = x ^ (f.map (algebraMap R S)).natDegree :=
92+
by
93+
rw [aeval_def, Polynomial.evalβ‚‚_eq_eval_map, eval_eq_sum_range, range_add_one,
94+
sum_insert not_mem_range_self, sum_range, (hmo.map (algebraMap R S)).coeff_natDegree,
95+
one_mul] at hx
96+
replace hx := eq_neg_of_add_eq_zero_left hx
97+
have : βˆ€ n < f.natDegree, p ∣ f.coeff n := by
98+
intro n hn
99+
refine' mem_span_singleton.1 (by simpa using hf.mem hn)
100+
choose! φ hφ using this
101+
conv_rhs at hx =>
102+
congr
103+
congr
104+
Β· skip
105+
ext i
106+
rw [coeff_map, hφ i.1 (lt_of_lt_of_le i.2 (natDegree_map_le _ _)),
107+
RingHom.map_mul, mul_assoc]
108+
rw [hx, ← mul_sum, neg_eq_neg_one_mul, ← mul_assoc (-1 : S), mul_comm (-1 : S), mul_assoc]
109+
refine'
110+
⟨-1 * βˆ‘ i : Fin (f.map (algebraMap R S)).natDegree, (algebraMap R S) (Ο† i.1) * x ^ i.1, _, rfl⟩
111+
exact
112+
Subalgebra.mul_mem _ (Subalgebra.neg_mem _ (Subalgebra.one_mem _))
113+
(Subalgebra.sum_mem _ fun i _ =>
114+
Subalgebra.mul_mem _ (Subalgebra.algebraMap_mem _ _)
115+
(Subalgebra.pow_mem _ (subset_adjoin (Set.mem_singleton x)) _))
116+
#align polynomial.is_weakly_eisenstein_at.exists_mem_adjoin_mul_eq_pow_nat_degree
117+
Polynomial.IsWeaklyEisensteinAt.exists_mem_adjoin_mul_eq_pow_natDegree
118+
119+
theorem exists_mem_adjoin_mul_eq_pow_natDegree_le {x : S} (hx : aeval x f = 0) (hmo : f.Monic)
120+
(hf : f.IsWeaklyEisensteinAt (Submodule.span R {p})) :
121+
βˆ€ i, (f.map (algebraMap R S)).natDegree ≀ i β†’
122+
βˆƒ y ∈ adjoin R ({x} : Set S), (algebraMap R S) p * y = x ^ i := by
123+
intro i hi
124+
obtain ⟨k, hk⟩ := exists_add_of_le hi
125+
rw [hk, pow_add]
126+
obtain ⟨y, hy, H⟩ := exists_mem_adjoin_mul_eq_pow_natDegree hx hmo hf
127+
refine' ⟨y * x ^ k, _, _⟩
128+
Β· exact Subalgebra.mul_mem _ hy (Subalgebra.pow_mem _ (subset_adjoin (Set.mem_singleton x)) _)
129+
Β· rw [← mul_assoc _ y, H]
130+
#align polynomial.is_weakly_eisenstein_at.exists_mem_adjoin_mul_eq_pow_nat_degree_le
131+
Polynomial.IsWeaklyEisensteinAt.exists_mem_adjoin_mul_eq_pow_natDegree_le
132+
133+
end Principal
134+
135+
-- Porting note: `Ideal.neg_mem_iff` was `neg_mem_iff` on line 142 but Lean was not able to find
136+
-- NegMemClass
137+
theorem pow_natDegree_le_of_root_of_monic_mem {x : R} (hroot : IsRoot f x) (hmo : f.Monic) :
138+
βˆ€ i, f.natDegree ≀ i β†’ x ^ i ∈ π“Ÿ := by
139+
intro i hi
140+
obtain ⟨k, hk⟩ := exists_add_of_le hi
141+
rw [hk, pow_add]
142+
suffices x ^ f.natDegree ∈ π“Ÿ by exact mul_mem_right (x ^ k) π“Ÿ this
143+
rw [IsRoot.def, eval_eq_sum_range, Finset.range_add_one,
144+
Finset.sum_insert Finset.not_mem_range_self, Finset.sum_range, hmo.coeff_natDegree, one_mul] at
145+
*
146+
rw [eq_neg_of_add_eq_zero_left hroot, Ideal.neg_mem_iff]
147+
refine' Submodule.sum_mem _ fun i _ => mul_mem_right _ _ (hf.mem (Fin.is_lt i))
148+
#align polynomial.is_weakly_eisenstein_at.pow_nat_degree_le_of_root_of_monic_mem
149+
Polynomial.IsWeaklyEisensteinAt.pow_natDegree_le_of_root_of_monic_mem
150+
151+
theorem pow_natDegree_le_of_aeval_zero_of_monic_mem_map {x : S} (hx : aeval x f = 0)
152+
(hmo : f.Monic) :
153+
βˆ€ i, (f.map (algebraMap R S)).natDegree ≀ i β†’ x ^ i ∈ π“Ÿ.map (algebraMap R S) := by
154+
suffices x ^ (f.map (algebraMap R S)).natDegree ∈ π“Ÿ.map (algebraMap R S) by
155+
intro i hi
156+
obtain ⟨k, hk⟩ := exists_add_of_le hi
157+
rw [hk, pow_add]
158+
refine' mul_mem_right _ _ this
159+
rw [aeval_def, evalβ‚‚_eq_eval_map, ← IsRoot.def] at hx
160+
refine' pow_natDegree_le_of_root_of_monic_mem (hf.map _) hx (hmo.map _) _ rfl.le
161+
#align polynomial.is_weakly_eisenstein_at.pow_nat_degree_le_of_aeval_zero_of_monic_mem_map
162+
Polynomial.IsWeaklyEisensteinAt.pow_natDegree_le_of_aeval_zero_of_monic_mem_map
163+
164+
end CommRing
165+
166+
end IsWeaklyEisensteinAt
167+
168+
section ScaleRoots
169+
170+
variable {A : Type _} [CommRing R] [CommRing A]
171+
172+
theorem scaleRoots.isWeaklyEisensteinAt (p : R[X]) {x : R} {P : Ideal R} (hP : x ∈ P) :
173+
(scaleRoots p x).IsWeaklyEisensteinAt P := by
174+
refine' ⟨fun i => _⟩
175+
rw [coeff_scaleRoots]
176+
rw [natDegree_scaleRoots, ← tsub_pos_iff_lt] at i
177+
exact Ideal.mul_mem_left _ _ (Ideal.pow_mem_of_mem P hP _ i)
178+
#align polynomial.scale_roots.is_weakly_eisenstein_at Polynomial.scaleRoots.isWeaklyEisensteinAt
179+
180+
theorem dvd_pow_natDegree_of_evalβ‚‚_eq_zero {f : R β†’+* A} (hf : Function.Injective f) {p : R[X]}
181+
(hp : p.Monic) (x y : R) (z : A) (h : p.evalβ‚‚ f z = 0) (hz : f x * z = f y) :
182+
x ∣ y ^ p.natDegree := by
183+
rw [← natDegree_scaleRoots p x, ← Ideal.mem_span_singleton]
184+
refine'
185+
(scaleRoots.isWeaklyEisensteinAt _
186+
(Ideal.mem_span_singleton.mpr <| dvd_refl x)).pow_natDegree_le_of_root_of_monic_mem
187+
_ ((monic_scaleRoots_iff x).mpr hp) _ le_rfl
188+
rw [injective_iff_map_eq_zero'] at hf
189+
have : evalβ‚‚ _ _ (p.scaleRoots x) = 0 := scaleRoots_evalβ‚‚_eq_zero f h
190+
rwa [hz, Polynomial.evalβ‚‚_at_apply, hf] at this
191+
#align polynomial.dvd_pow_nat_degree_of_evalβ‚‚_eq_zero Polynomial.dvd_pow_natDegree_of_evalβ‚‚_eq_zero
192+
193+
theorem dvd_pow_natDegree_of_aeval_eq_zero [Algebra R A] [Nontrivial A] [NoZeroSMulDivisors R A]
194+
{p : R[X]} (hp : p.Monic) (x y : R) (z : A) (h : Polynomial.aeval z p = 0)
195+
(hz : z * algebraMap R A x = algebraMap R A y) : x ∣ y ^ p.natDegree :=
196+
dvd_pow_natDegree_of_evalβ‚‚_eq_zero (NoZeroSMulDivisors.algebraMap_injective R A) hp x y z h
197+
((mul_comm _ _).trans hz)
198+
#align polynomial.dvd_pow_nat_degree_of_aeval_eq_zero Polynomial.dvd_pow_natDegree_of_aeval_eq_zero
199+
200+
end ScaleRoots
201+
202+
namespace IsEisensteinAt
203+
204+
section CommSemiring
205+
206+
variable [CommSemiring R] {π“Ÿ : Ideal R} {f : R[X]} (hf : f.IsEisensteinAt π“Ÿ)
207+
208+
theorem Polynomial.Monic.leadingCoeff_not_mem (hf : f.Monic) (h : π“Ÿ β‰  ⊀) : Β¬f.leadingCoeff ∈ π“Ÿ :=
209+
hf.leadingCoeff.symm β–Έ (Ideal.ne_top_iff_one _).1 h
210+
#align polynomial.monic.leading_coeff_not_mem
211+
Polynomial.IsEisensteinAt.Polynomial.Monic.leadingCoeff_not_mem
212+
213+
theorem Polynomial.Monic.isEisensteinAt_of_mem_of_not_mem (hf : f.Monic) (h : π“Ÿ β‰  ⊀)
214+
(hmem : βˆ€ {n}, n < f.natDegree β†’ f.coeff n ∈ π“Ÿ) (hnot_mem : f.coeff 0 βˆ‰ π“Ÿ ^ 2) :
215+
f.IsEisensteinAt π“Ÿ :=
216+
{ leading := leadingCoeff_not_mem hf h
217+
mem := fun hn => hmem hn
218+
not_mem := hnot_mem }
219+
#align polynomial.monic.is_eisenstein_at_of_mem_of_not_mem
220+
Polynomial.IsEisensteinAt.Polynomial.Monic.isEisensteinAt_of_mem_of_not_mem
221+
222+
theorem isWeaklyEisensteinAt : IsWeaklyEisensteinAt f π“Ÿ :=
223+
⟨fun h => hf.mem h⟩
224+
#align polynomial.is_eisenstein_at.is_weakly_eisenstein_at
225+
Polynomial.IsEisensteinAt.isWeaklyEisensteinAt
226+
227+
theorem coeff_mem {n : β„•} (hn : n β‰  f.natDegree) : f.coeff n ∈ π“Ÿ := by
228+
cases' ne_iff_lt_or_gt.1 hn with h₁ hβ‚‚
229+
Β· exact hf.mem h₁
230+
Β· rw [coeff_eq_zero_of_natDegree_lt hβ‚‚]
231+
exact Ideal.zero_mem _
232+
#align polynomial.is_eisenstein_at.coeff_mem Polynomial.IsEisensteinAt.coeff_mem
233+
234+
end CommSemiring
235+
236+
section IsDomain
237+
238+
variable [CommRing R] [IsDomain R] {π“Ÿ : Ideal R} {f : R[X]} (hf : f.IsEisensteinAt π“Ÿ)
239+
240+
/-- If a primitive `f` satisfies `f.IsEisensteinAt π“Ÿ`, where `π“Ÿ.IsPrime`,
241+
then `f` is irreducible. -/
242+
theorem irreducible (hprime : π“Ÿ.IsPrime) (hu : f.IsPrimitive) (hfd0 : 0 < f.natDegree) :
243+
Irreducible f :=
244+
irreducible_of_eisenstein_criterion hprime hf.leading (fun _ hn => hf.mem (coe_lt_degree.1 hn))
245+
(natDegree_pos_iff_degree_pos.1 hfd0) hf.not_mem hu
246+
#align polynomial.is_eisenstein_at.irreducible Polynomial.IsEisensteinAt.irreducible
247+
248+
end IsDomain
249+
250+
end IsEisensteinAt
251+
252+
end Polynomial

0 commit comments

Comments
Β (0)