Skip to content

Commit 1799b8c

Browse files
committed
feat(Data/Polynomial): irreducibility of degree-{2,3} polynomials (#9697)
The goal is to show that a degree 2 or 3 polynomial is irreducible iff it doesn't have roots. We already have `Polynomial.Monic.irreducible_iff_natDegree'` and some existing results in Lean 3: https://github.com/lean-forward/class-group-and-mordell-equation/blob/main/src/number_theory/assorted_lemmas.lean#L254 and the main work is to connect these bits together. I added a few helper lemmas about the "monicization" of a polynomial `p`, `p * C (leadingCoeff p)⁻¹`. Then I used these to show the `Polynomial.Monic.irreducible_iff ...` statements could be translated to (not necessarily monic) polynomials over a field, then I specialized these results to the degree-{2,3} case. I created a new file because I couldn't find an obvious place that imported both `Polynomial.FieldDivision` and `Tactic.IntervalCases`. Zulip discussion: https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/Polynomial.20irreducible Co-authored-by: Anne Baanen <Vierkantor@users.noreply.github.com>
1 parent 625e2ac commit 1799b8c

File tree

7 files changed

+237
-11
lines changed

7 files changed

+237
-11
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1933,6 +1933,7 @@ import Mathlib.Data.Polynomial.PartialFractions
19331933
import Mathlib.Data.Polynomial.Reverse
19341934
import Mathlib.Data.Polynomial.RingDivision
19351935
import Mathlib.Data.Polynomial.Smeval
1936+
import Mathlib.Data.Polynomial.SpecificDegree
19361937
import Mathlib.Data.Polynomial.Splits
19371938
import Mathlib.Data.Polynomial.Taylor
19381939
import Mathlib.Data.Polynomial.UnitTrinomial

Mathlib/Data/Polynomial/Degree/Definitions.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,6 +1685,10 @@ theorem leadingCoeff_pow (p : R[X]) (n : ℕ) : leadingCoeff (p ^ n) = leadingCo
16851685
(leadingCoeffHom : R[X] →* R).map_pow p n
16861686
#align polynomial.leading_coeff_pow Polynomial.leadingCoeff_pow
16871687

1688+
theorem leadingCoeff_dvd_leadingCoeff {a p : R[X]} (hap : a ∣ p) :
1689+
a.leadingCoeff ∣ p.leadingCoeff :=
1690+
map_dvd leadingCoeffHom hap
1691+
16881692
end NoZeroDivisors
16891693

16901694
end Polynomial

Mathlib/Data/Polynomial/Degree/Lemmas.lean

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,4 +421,59 @@ theorem leadingCoeff_comp (hq : natDegree q ≠ 0) :
421421

422422
end NoZeroDivisors
423423

424+
section DivisionRing
425+
426+
variable {K : Type*} [DivisionRing K]
427+
428+
/-! Useful lemmas for the "monicization" of a nonzero polynomial `p`. -/
429+
@[simp]
430+
theorem irreducible_mul_leadingCoeff_inv {p : K[X]} :
431+
Irreducible (p * C (leadingCoeff p)⁻¹) ↔ Irreducible p := by
432+
by_cases hp0 : p = 0
433+
· simp [hp0]
434+
exact irreducible_mul_isUnit
435+
(isUnit_C.mpr (IsUnit.mk0 _ (inv_ne_zero (leadingCoeff_ne_zero.mpr hp0))))
436+
437+
@[simp] lemma dvd_mul_leadingCoeff_inv {p q : K[X]} (hp0 : p ≠ 0) :
438+
q ∣ p * C (leadingCoeff p)⁻¹ ↔ q ∣ p :=
439+
IsUnit.dvd_mul_right <| isUnit_C.mpr <| IsUnit.mk0 _ <|
440+
inv_ne_zero <| leadingCoeff_ne_zero.mpr hp0
441+
442+
theorem monic_mul_leadingCoeff_inv {p : K[X]} (h : p ≠ 0) : Monic (p * C (leadingCoeff p)⁻¹) := by
443+
rw [Monic, leadingCoeff_mul, leadingCoeff_C,
444+
mul_inv_cancel (show leadingCoeff p ≠ 0 from mt leadingCoeff_eq_zero.1 h)]
445+
#align polynomial.monic_mul_leading_coeff_inv Polynomial.monic_mul_leadingCoeff_inv
446+
447+
-- `simp` normal form of `degree_mul_leadingCoeff_inv`
448+
@[simp] lemma degree_leadingCoeff_inv {p : K[X]} (hp0 : p ≠ 0) :
449+
degree (C (leadingCoeff p)⁻¹) = 0 :=
450+
degree_C (inv_ne_zero <| leadingCoeff_ne_zero.mpr hp0)
451+
452+
theorem degree_mul_leadingCoeff_inv (p : K[X]) {q : K[X]} (h : q ≠ 0) :
453+
degree (p * C (leadingCoeff q)⁻¹) = degree p := by
454+
have h₁ : (leadingCoeff q)⁻¹ ≠ 0 := inv_ne_zero (mt leadingCoeff_eq_zero.1 h)
455+
rw [degree_mul_C h₁]
456+
#align polynomial.degree_mul_leading_coeff_inv Polynomial.degree_mul_leadingCoeff_inv
457+
458+
theorem natDegree_mul_leadingCoeff_inv (p : K[X]) {q : K[X]} (h : q ≠ 0) :
459+
natDegree (p * C (leadingCoeff q)⁻¹) = natDegree p :=
460+
natDegree_eq_of_degree_eq (degree_mul_leadingCoeff_inv _ h)
461+
462+
theorem degree_mul_leadingCoeff_self_inv (p : K[X]) :
463+
degree (p * C (leadingCoeff p)⁻¹) = degree p := by
464+
by_cases hp : p = 0
465+
· simp [hp]
466+
exact degree_mul_leadingCoeff_inv _ hp
467+
468+
theorem natDegree_mul_leadingCoeff_self_inv (p : K[X]) :
469+
natDegree (p * C (leadingCoeff p)⁻¹) = natDegree p :=
470+
natDegree_eq_of_degree_eq (degree_mul_leadingCoeff_self_inv _)
471+
472+
-- `simp` normal form of `degree_mul_leadingCoeff_self_inv`
473+
@[simp] lemma degree_add_degree_leadingCoeff_inv (p : K[X]) :
474+
degree p + degree (C (leadingCoeff p)⁻¹) = degree p := by
475+
rw [← degree_mul, degree_mul_leadingCoeff_self_inv]
476+
477+
end DivisionRing
478+
424479
end Polynomial

Mathlib/Data/Polynomial/FieldDivision.lean

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -225,17 +225,6 @@ theorem degree_pos_of_ne_zero_of_nonunit (hp0 : p ≠ 0) (hp : ¬IsUnit p) : 0 <
225225
exact hp (IsUnit.map C (IsUnit.mk0 (coeff p 0) (mt C_inj.2 (by simpa using hp0))))
226226
#align polynomial.degree_pos_of_ne_zero_of_nonunit Polynomial.degree_pos_of_ne_zero_of_nonunit
227227

228-
theorem monic_mul_leadingCoeff_inv (h : p ≠ 0) : Monic (p * C (leadingCoeff p)⁻¹) := by
229-
rw [Monic, leadingCoeff_mul, leadingCoeff_C,
230-
mul_inv_cancel (show leadingCoeff p ≠ 0 from mt leadingCoeff_eq_zero.1 h)]
231-
#align polynomial.monic_mul_leading_coeff_inv Polynomial.monic_mul_leadingCoeff_inv
232-
233-
theorem degree_mul_leadingCoeff_inv (p : R[X]) (h : q ≠ 0) :
234-
degree (p * C (leadingCoeff q)⁻¹) = degree p := by
235-
have h₁ : (leadingCoeff q)⁻¹ ≠ 0 := inv_ne_zero (mt leadingCoeff_eq_zero.1 h)
236-
rw [degree_mul, degree_C h₁, add_zero]
237-
#align polynomial.degree_mul_leading_coeff_inv Polynomial.degree_mul_leadingCoeff_inv
238-
239228
@[simp]
240229
theorem map_eq_zero [Semiring S] [Nontrivial S] (f : R →+* S) : p.map f = 0 ↔ p = 0 := by
241230
simp only [Polynomial.ext_iff]
@@ -655,6 +644,35 @@ theorem isCoprime_of_is_root_of_eval_derivative_ne_zero {K : Type*} [Field K] (f
655644
rwa [← C_inj, C_0]
656645
#align polynomial.is_coprime_of_is_root_of_eval_derivative_ne_zero Polynomial.isCoprime_of_is_root_of_eval_derivative_ne_zero
657646

647+
/-- To check a polynomial over a field is irreducible, it suffices to check only for
648+
divisors that have smaller degree.
649+
650+
See also: `Polynomial.Monic.irreducible_iff_natDegree`.
651+
-/
652+
theorem irreducible_iff_degree_lt (p : R[X]) (hp0 : p ≠ 0) (hpu : ¬ IsUnit p) :
653+
Irreducible p ↔ ∀ q, q.degree ≤ ↑(natDegree p / 2) → q ∣ p → IsUnit q := by
654+
rw [← irreducible_mul_leadingCoeff_inv,
655+
(monic_mul_leadingCoeff_inv hp0).irreducible_iff_degree_lt]
656+
simp [hp0, natDegree_mul_leadingCoeff_inv]
657+
· contrapose! hpu
658+
exact isUnit_of_mul_eq_one _ _ hpu
659+
660+
/-- To check a polynomial `p` over a field is irreducible, it suffices to check there are no
661+
divisors of degree `0 < d ≤ degree p / 2`.
662+
663+
See also: `Polynomial.Monic.irreducible_iff_natDegree'`.
664+
-/
665+
theorem irreducible_iff_lt_natDegree_lt {p : R[X]} (hp0 : p ≠ 0) (hpu : ¬ IsUnit p) :
666+
Irreducible p ↔ ∀ q, Monic q → natDegree q ∈ Finset.Ioc 0 (natDegree p / 2) → ¬ q ∣ p := by
667+
have : p * C (leadingCoeff p)⁻¹ ≠ 1
668+
· contrapose! hpu
669+
exact isUnit_of_mul_eq_one _ _ hpu
670+
rw [← irreducible_mul_leadingCoeff_inv,
671+
(monic_mul_leadingCoeff_inv hp0).irreducible_iff_lt_natDegree_lt this,
672+
natDegree_mul_leadingCoeff_inv _ hp0]
673+
simp only [IsUnit.dvd_mul_right
674+
(isUnit_C.mpr (IsUnit.mk0 (leadingCoeff p)⁻¹ (inv_ne_zero (leadingCoeff_ne_zero.mpr hp0))))]
675+
658676
end Field
659677

660678
end Polynomial

Mathlib/Data/Polynomial/RingDivision.lean

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,17 @@ theorem isUnit_iff : IsUnit p ↔ ∃ r : R, IsUnit r ∧ C r = p :=
239239
fun ⟨_, hr, hrp⟩ => hrp ▸ isUnit_C.2 hr⟩
240240
#align polynomial.is_unit_iff Polynomial.isUnit_iff
241241

242+
theorem not_isUnit_of_degree_pos (p : R[X])
243+
(hpl : 0 < p.degree) : ¬ IsUnit p := by
244+
cases subsingleton_or_nontrivial R
245+
· simp [Subsingleton.elim p 0] at hpl
246+
intro h
247+
simp [degree_eq_zero_of_isUnit h] at hpl
248+
249+
theorem not_isUnit_of_natDegree_pos (p : R[X])
250+
(hpl : 0 < p.natDegree) : ¬ IsUnit p :=
251+
not_isUnit_of_degree_pos _ (natDegree_pos_iff_degree_pos.mp hpl)
252+
242253
variable [CharZero R]
243254

244255
-- Porting note: bit0/bit1 are deprecated
@@ -314,6 +325,17 @@ theorem Monic.irreducible_iff_natDegree' (hp : p.Monic) : Irreducible p ↔ p
314325
· exact ⟨f, g, hf, hg, rfl, h.2, add_le_add_right hl _⟩
315326
#align polynomial.monic.irreducible_iff_nat_degree' Polynomial.Monic.irreducible_iff_natDegree'
316327

328+
/-- Alternate phrasing of `Polynomial.Monic.irreducible_iff_natDegree'` where we only have to check
329+
one divisor at a time. -/
330+
theorem Monic.irreducible_iff_lt_natDegree_lt {p : R[X]} (hp : p.Monic) (hp1 : p ≠ 1) :
331+
Irreducible p ↔ ∀ q, Monic q → natDegree q ∈ Finset.Ioc 0 (natDegree p / 2) → ¬ q ∣ p := by
332+
rw [hp.irreducible_iff_natDegree', and_iff_right hp1]
333+
constructor
334+
· rintro h g hg hdg ⟨f, rfl⟩
335+
exact h f g (hg.of_mul_monic_left hp) hg (mul_comm f g) hdg
336+
· rintro h f g - hg rfl hdg
337+
exact h g hg hdg (dvd_mul_left g f)
338+
317339
theorem Monic.not_irreducible_iff_exists_add_mul_eq_coeff (hm : p.Monic) (hnd : p.natDegree = 2) :
318340
¬Irreducible p ↔ ∃ c₁ c₂, p.coeff 0 = c₁ * c₂ ∧ p.coeff 1 = c₁ + c₂ := by
319341
cases subsingleton_or_nontrivial R
@@ -358,6 +380,38 @@ instance : IsDomain R[X] :=
358380

359381
end Ring
360382

383+
section CommSemiring
384+
385+
variable [CommSemiring R]
386+
387+
theorem Monic.C_dvd_iff_isUnit {p : R[X]} (hp : Monic p) {a : R} :
388+
C a ∣ p ↔ IsUnit a :=
389+
fun h => isUnit_iff_dvd_one.mpr <|
390+
hp.coeff_natDegree ▸ (C_dvd_iff_dvd_coeff _ _).mp h p.natDegree,
391+
fun ha => (ha.map C).dvd⟩
392+
393+
theorem degree_pos_of_not_isUnit_of_dvd_monic {a p : R[X]} (ha : ¬ IsUnit a)
394+
(hap : a ∣ p) (hp : Monic p) :
395+
0 < degree a :=
396+
lt_of_not_ge <| fun h => ha <| by
397+
rw [Polynomial.eq_C_of_degree_le_zero h] at hap ⊢
398+
simpa [hp.C_dvd_iff_isUnit, isUnit_C] using hap
399+
400+
theorem natDegree_pos_of_not_isUnit_of_dvd_monic {a p : R[X]} (ha : ¬ IsUnit a)
401+
(hap : a ∣ p) (hp : Monic p) :
402+
0 < natDegree a :=
403+
natDegree_pos_iff_degree_pos.mpr <| degree_pos_of_not_isUnit_of_dvd_monic ha hap hp
404+
405+
theorem degree_pos_of_monic_of_not_isUnit {a : R[X]} (hu : ¬ IsUnit a) (ha : Monic a) :
406+
0 < degree a :=
407+
degree_pos_of_not_isUnit_of_dvd_monic hu dvd_rfl ha
408+
409+
theorem natDegree_pos_of_monic_of_not_isUnit {a : R[X]} (hu : ¬ IsUnit a) (ha : Monic a) :
410+
0 < natDegree a :=
411+
natDegree_pos_iff_degree_pos.mpr <| degree_pos_of_monic_of_not_isUnit hu ha
412+
413+
end CommSemiring
414+
361415
section CommRing
362416

363417
variable [CommRing R]
@@ -1440,6 +1494,31 @@ theorem prod_multiset_X_sub_C_of_monic_of_roots_card_eq (hp : p.Monic)
14401494
set_option linter.uppercaseLean3 false in
14411495
#align polynomial.prod_multiset_X_sub_C_of_monic_of_roots_card_eq Polynomial.prod_multiset_X_sub_C_of_monic_of_roots_card_eq
14421496

1497+
theorem Monic.isUnit_leadingCoeff_of_dvd {a p : R[X]} (hp : Monic p) (hap : a ∣ p) :
1498+
IsUnit a.leadingCoeff :=
1499+
isUnit_of_dvd_one (by simpa only [hp.leadingCoeff] using leadingCoeff_dvd_leadingCoeff hap)
1500+
1501+
/-- To check a monic polynomial is irreducible, it suffices to check only for
1502+
divisors that have smaller degree.
1503+
1504+
See also: `Polynomial.Monic.irreducible_iff_natDegree`.
1505+
-/
1506+
theorem Monic.irreducible_iff_degree_lt {p : R[X]} (p_monic : Monic p) (p_1 : p ≠ 1) :
1507+
Irreducible p ↔ ∀ q, degree q ≤ ↑(p.natDegree / 2) → q ∣ p → IsUnit q := by
1508+
simp only [p_monic.irreducible_iff_lt_natDegree_lt p_1, mem_Ioc, and_imp,
1509+
natDegree_pos_iff_degree_pos, natDegree_le_iff_degree_le]
1510+
constructor
1511+
· rintro h q deg_le dvd
1512+
by_contra q_unit
1513+
have := degree_pos_of_not_isUnit_of_dvd_monic q_unit dvd p_monic
1514+
have hu := p_monic.isUnit_leadingCoeff_of_dvd dvd
1515+
refine (h _ (monic_of_isUnit_leadingCoeff_inv_smul hu) ?_ ?_ (dvd_trans ?_ dvd)).elim
1516+
· rwa [degree_smul_of_smul_regular _ (isSMulRegular_of_group _)]
1517+
· rwa [degree_smul_of_smul_regular _ (isSMulRegular_of_group _)]
1518+
· rw [Units.smul_def, Polynomial.smul_eq_C_mul, (isUnit_C.mpr (Units.isUnit _)).mul_left_dvd]
1519+
· rintro h q _ deg_pos deg_le dvd
1520+
exact deg_pos.ne' <| degree_eq_zero_of_isUnit (h q deg_le dvd)
1521+
14431522
end CommRing
14441523

14451524
section
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/-
2+
Copyright (c) 2024 Anne Baanen. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Anne Baanen, Alex J. Best
5+
-/
6+
import Mathlib.Data.Polynomial.RingDivision
7+
import Mathlib.Tactic.IntervalCases
8+
9+
/-!
10+
# Polynomials of specific degree
11+
12+
Facts about polynomials that have a specific integer degree.
13+
-/
14+
15+
namespace Polynomial
16+
17+
section IsDomain
18+
19+
variable {R : Type*} [CommRing R] [IsDomain R]
20+
21+
/-- A polynomial of degree 2 or 3 is irreducible iff it doesn't have roots. -/
22+
theorem Monic.irreducible_iff_roots_eq_zero_of_degree_le_three {p : R[X]} (hp : p.Monic)
23+
(hp2 : 2 ≤ p.natDegree) (hp3 : p.natDegree ≤ 3) : Irreducible p ↔ p.roots = 0 := by
24+
have hp0 : p ≠ 0 := hp.ne_zero
25+
have hp1 : p ≠ 1 := by rintro rfl; rw [natDegree_one] at hp2; cases hp2
26+
rw [hp.irreducible_iff_lt_natDegree_lt hp1]
27+
simp_rw [show p.natDegree / 2 = 1 from
28+
(Nat.div_le_div_right hp3).antisymm
29+
(by apply Nat.div_le_div_right (c := 2) hp2),
30+
show Finset.Ioc 0 1 = {1} from rfl,
31+
Finset.mem_singleton, Multiset.eq_zero_iff_forall_not_mem, mem_roots hp0, ← dvd_iff_isRoot]
32+
refine ⟨fun h r ↦ h _ (monic_X_sub_C r) (natDegree_X_sub_C r), fun h q hq hq1 ↦ ?_⟩
33+
rw [hq.eq_X_add_C hq1, ← sub_neg_eq_add, ← C_neg]
34+
apply h
35+
36+
end IsDomain
37+
38+
section Field
39+
40+
variable {K : Type*} [Field K]
41+
42+
/-- A polynomial of degree 2 or 3 is irreducible iff it doesn't have roots. -/
43+
theorem irreducible_iff_roots_eq_zero_of_degree_le_three
44+
{p : K[X]} (hp2 : 2 ≤ p.natDegree) (hp3 : p.natDegree ≤ 3) : Irreducible p ↔ p.roots = 0 := by
45+
have hp0 : p ≠ 0 := by rintro rfl; rw [natDegree_zero] at hp2; cases hp2
46+
rw [← irreducible_mul_leadingCoeff_inv,
47+
(monic_mul_leadingCoeff_inv hp0).irreducible_iff_roots_eq_zero_of_degree_le_three,
48+
mul_comm, roots_C_mul]
49+
· exact inv_ne_zero (leadingCoeff_ne_zero.mpr hp0)
50+
· rwa [natDegree_mul_leadingCoeff_inv _ hp0]
51+
· rwa [natDegree_mul_leadingCoeff_inv _ hp0]
52+
53+
end Field
54+
55+
end Polynomial

Mathlib/RingTheory/Polynomial/Nilpotent.lean

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,20 @@ lemma isUnit_iff' :
169169
conv_lhs => rw [← modByMonic_add_div P monic_X]
170170
simp [modByMonic_X]
171171

172+
theorem not_isUnit_of_natDegree_pos_of_isReduced [IsReduced R] (p : R[X])
173+
(hpl : 0 < p.natDegree) : ¬ IsUnit p := by
174+
simp only [ne_eq, isNilpotent_iff_eq_zero, not_and, not_forall, exists_prop,
175+
Polynomial.isUnit_iff_coeff_isUnit_isNilpotent]
176+
intro _
177+
refine ⟨p.natDegree, hpl.ne', ?_⟩
178+
contrapose! hpl
179+
simp only [coeff_natDegree, leadingCoeff_eq_zero] at hpl
180+
simp [hpl]
181+
182+
theorem not_isUnit_of_degree_pos_of_isReduced [IsReduced R] (p : R[X])
183+
(hpl : 0 < p.degree) : ¬ IsUnit p :=
184+
not_isUnit_of_natDegree_pos_of_isReduced _ (natDegree_pos_iff_degree_pos.mpr hpl)
185+
172186
end CommRing
173187

174188
section CommAlgebra

0 commit comments

Comments
 (0)