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

Commit fa256f0

Browse files
committed
feat(data/polynomial): irreducibility criteria for (quadratic) monic polynomials (#17664)
+ To show a monic polynomial `p` over a commutative semiring without zero divisors is irreducible, it suffices to show that `p ≠ 1` and that there doesn't exist a factorization into the product of two monic polynomials of positive degrees: `monic.irreducible_iff_nat_degree`. + If such a factorization exists, one of the polynomial must have degree less than or equal to `p.nat_degree / 2`: `monic.irreducible_iff_nat_degree'`. + To show a quadratic monic polynomial `p` is reducible, it suffices to it doesn't factor as `(X+c)(X+c')`, i.e. there don't exist `c` and `c'` that add up to the 1st coefficient and multiply up to the 0th coefficient: `not_irreducible_iff_exists_add_mul_eq_coeff`. + Define the ring homomorphism `constant_coeff` in *coeff.lean* which is analogous to [mv_polynomial.constant_coeff](https://leanprover-community.github.io/mathlib_docs/data/mv_polynomial/basic.html#mv_polynomial.constant_coeff); use it to golf and generalize `is_unit_C` and `eq_one_of_is_unit_of_monic` in *monic.lean* and various lemmas in *ring_division.lean*. + Add `monic.is_unit_iff`. + Golf some lemmas in *erase_lead.lean*. Co-authored-by: Thomas Browning <thomas.l.browning@gmail.com> Co-authored-by: Anne Baanen <t.baanen@vu.nl> Inspired by #17631
1 parent 7679be2 commit fa256f0

6 files changed

Lines changed: 82 additions & 33 deletions

File tree

src/data/polynomial/coeff.lean

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,17 @@ end
9696
@[simp] lemma mul_coeff_zero (p q : R[X]) : coeff (p * q) 0 = coeff p 0 * coeff q 0 :=
9797
by simp [coeff_mul]
9898

99-
-- TODO: golf using `constant_coeff` once #17664 is merged
99+
/-- `constant_coeff p` returns the constant term of the polynomial `p`,
100+
defined as `coeff p 0`. This is a ring homomorphism. -/
101+
@[simps] def constant_coeff : R[X] →+* R :=
102+
{ to_fun := λ p, coeff p 0,
103+
map_one' := coeff_one_zero,
104+
map_mul' := mul_coeff_zero,
105+
map_zero' := coeff_zero 0,
106+
map_add' := λ p q, coeff_add p q 0 }
107+
100108
lemma is_unit_C {x : R} : is_unit (C x) ↔ is_unit x :=
101-
by { rintros ⟨⟨q, p, hqp, hpq⟩, rfl : q = C x⟩,
102-
exact ⟨⟨(C x).coeff 0, p.coeff 0, by rw [←mul_coeff_zero, hqp, coeff_one_zero],
103-
by rw [←mul_coeff_zero, hpq, coeff_one_zero]⟩, coeff_C_zero⟩ }, is_unit.map C⟩
109+
⟨λ h, (congr_arg is_unit coeff_C_zero).mp (h.map $ @constant_coeff R _), λ h, h.map C⟩
104110

105111
lemma coeff_mul_X_zero (p : R[X]) : coeff (p * X) 0 = 0 := by simp
106112

src/data/polynomial/degree/definitions.lean

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,12 +347,15 @@ ext (λ n, nat.cases_on n (by simp)
347347
lemma eq_X_add_C_of_degree_eq_one (h : degree p = 1) :
348348
p = C (p.leading_coeff) * X + C (p.coeff 0) :=
349349
(eq_X_add_C_of_degree_le_one (show degree p ≤ 1, from h ▸ le_rfl)).trans
350-
(by simp [leading_coeff, nat_degree_eq_of_degree_eq_some h])
350+
(by simp only [leading_coeff, nat_degree_eq_of_degree_eq_some h])
351351

352352
lemma eq_X_add_C_of_nat_degree_le_one (h : nat_degree p ≤ 1) :
353353
p = C (p.coeff 1) * X + C (p.coeff 0) :=
354354
eq_X_add_C_of_degree_le_one $ degree_le_of_nat_degree_le h
355355

356+
lemma monic.eq_X_add_C (hm : p.monic) (hnd : p.nat_degree = 1) : p = X + C (p.coeff 0) :=
357+
by rw [←one_mul X, ←C_1, ←hm.coeff_nat_degree, hnd, ←eq_X_add_C_of_nat_degree_le_one hnd.le]
358+
356359
lemma exists_eq_X_add_C_of_nat_degree_le_one (h : nat_degree p ≤ 1) :
357360
∃ a b, p = C a * X + C b :=
358361
⟨p.coeff 1, p.coeff 0, eq_X_add_C_of_nat_degree_le_one h⟩
@@ -1116,6 +1119,12 @@ begin
11161119
{ exact nat_degree_eq_of_degree_eq_some (degree_X_pow_add_C (pos_iff_ne_zero.mpr hn) r) },
11171120
end
11181121

1122+
lemma X_pow_add_C_ne_one {n : ℕ} (hn : 0 < n) (a : R) : (X : R[X]) ^ n + C a ≠ 1 :=
1123+
λ h, hn.ne' $ by simpa only [nat_degree_X_pow_add_C, nat_degree_one] using congr_arg nat_degree h
1124+
1125+
theorem X_add_C_ne_one (r : R) : X + C r ≠ 1 :=
1126+
pow_one (X : R[X]) ▸ X_pow_add_C_ne_one zero_lt_one r
1127+
11191128
end semiring
11201129
end nonzero_ring
11211130

src/data/polynomial/erase_lead.lean

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,7 @@ by simp only [erase_lead, erase_zero]
5454

5555
@[simp] lemma erase_lead_add_monomial_nat_degree_leading_coeff (f : R[X]) :
5656
f.erase_lead + monomial f.nat_degree f.leading_coeff = f :=
57-
begin
58-
ext i,
59-
simp only [erase_lead_coeff, coeff_monomial, coeff_add, @eq_comm _ _ i],
60-
split_ifs with h,
61-
{ subst i, simp only [leading_coeff, zero_add] },
62-
{ exact add_zero _ }
63-
end
57+
(add_comm _ _).trans (f.monomial_add_erase _)
6458

6559
@[simp] lemma erase_lead_add_C_mul_X_pow (f : R[X]) :
6660
f.erase_lead + (C f.leading_coeff) * X ^ f.nat_degree = f :=
@@ -76,7 +70,7 @@ by rw [C_mul_X_pow_eq_monomial, self_sub_monomial_nat_degree_leading_coeff]
7670

7771
lemma erase_lead_ne_zero (f0 : 2 ≤ f.support.card) : erase_lead f ≠ 0 :=
7872
begin
79-
rw [ne.def, ← card_support_eq_zero, erase_lead_support],
73+
rw [ne, ← card_support_eq_zero, erase_lead_support],
8074
exact (zero_lt_one.trans_le $ (tsub_le_tsub_right f0 1).trans
8175
finset.pred_card_le_card_erase).ne.symm
8276
end
@@ -85,7 +79,7 @@ lemma lt_nat_degree_of_mem_erase_lead_support {a : ℕ} (h : a ∈ (erase_lead f
8579
a < f.nat_degree :=
8680
begin
8781
rw [erase_lead_support, mem_erase] at h,
88-
exact lt_of_le_of_ne (le_nat_degree_of_mem_supp a h.2) h.1,
82+
exact (le_nat_degree_of_mem_supp a h.2).lt_of_ne h.1,
8983
end
9084

9185
lemma ne_nat_degree_of_mem_erase_lead_support {a : ℕ} (h : a ∈ (erase_lead f).support) :
@@ -157,14 +151,7 @@ begin
157151
exact nd (nat_degree_add_eq_right_of_nat_degree_lt pq) }
158152
end
159153

160-
lemma erase_lead_degree_le : (erase_lead f).degree ≤ f.degree :=
161-
begin
162-
rw degree_le_iff_coeff_zero,
163-
intros i hi,
164-
rw erase_lead_coeff,
165-
split_ifs with h, { refl },
166-
apply coeff_eq_zero_of_degree_lt hi
167-
end
154+
lemma erase_lead_degree_le : (erase_lead f).degree ≤ f.degree := f.degree_erase_le _
168155

169156
lemma erase_lead_nat_degree_le_aux : (erase_lead f).nat_degree ≤ f.nat_degree :=
170157
nat_degree_le_nat_degree erase_lead_degree_le

src/data/polynomial/eval.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,9 @@ def eval_ring_hom : R → R[X] →+* R := eval₂_ring_hom (ring_hom.id _)
786786

787787
@[simp] lemma coe_eval_ring_hom (r : R) : ((eval_ring_hom r) : R[X] → R) = eval r := rfl
788788

789+
lemma eval_ring_hom_zero : eval_ring_hom 0 = constant_coeff :=
790+
fun_like.ext _ _ $ λ p, p.coeff_zero_eq_eval_zero.symm
791+
789792
@[simp] lemma eval_pow (n : ℕ) : (p ^ n).eval x = p.eval x ^ n := eval₂_pow _ _ _
790793

791794
@[simp]

src/data/polynomial/monic.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,9 @@ begin
222222
exact hm.nat_degree_eq_zero_iff_eq_one.mp this.1,
223223
end
224224

225+
lemma monic.is_unit_iff (hm : p.monic) : is_unit p ↔ p = 1 :=
226+
⟨hm.eq_one_of_is_unit, λ h, h.symm ▸ is_unit_one⟩
227+
225228
end semiring
226229

227230
section comm_semiring

src/data/polynomial/ring_division.lean

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,12 @@ begin
183183
end
184184

185185
lemma degree_eq_zero_of_is_unit [nontrivial R] (h : is_unit p) : degree p = 0 :=
186-
le_antisymm (nat_degree_eq_zero_iff_degree_le_zero.mp (nat_degree_eq_zero_of_is_unit h))
186+
(nat_degree_eq_zero_iff_degree_le_zero.mp $ nat_degree_eq_zero_of_is_unit h).antisymm
187187
(zero_le_degree_iff.mpr h.ne_zero)
188188

189+
@[simp] lemma degree_coe_units [nontrivial R] (u : R[X]ˣ) : degree (u : R[X]) = 0 :=
190+
degree_eq_zero_of_is_unit ⟨u, rfl⟩
191+
189192
theorem is_unit_iff : is_unit p ↔ ∃ r : R, is_unit r ∧ C r = p :=
190193
⟨λ hp, ⟨p.coeff 0, let h := eq_C_of_nat_degree_eq_zero (nat_degree_eq_zero_of_is_unit hp) in
191194
⟨is_unit_C.1 (h ▸ hp), h.symm⟩⟩, λ ⟨r, hr, hrp⟩, hrp ▸ is_unit_C.2 hr⟩
@@ -228,16 +231,58 @@ variables [comm_semiring R] [no_zero_divisors R] {p q : R[X]}
228231
lemma irreducible_of_monic (hp : p.monic) (hp1 : p ≠ 1) :
229232
irreducible p ↔ ∀ f g : R[X], f.monic → g.monic → f * g = p → f = 1 ∨ g = 1 :=
230233
begin
231-
refine ⟨λ h f g hf hg hp, (h.2 f g hp.symm).elim (or.inl ∘ hf.eq_one_of_is_unit)
232-
(or.inr ∘ hg.eq_one_of_is_unit), λ h, ⟨hp1 ∘ hp.eq_one_of_is_unit, λ f g hfg,
233-
(h (g * C f.leading_coeff) (f * C g.leading_coeff) _ _ _).elim
234-
(or.inr ∘ is_unit_of_mul_eq_one g _) (or.inl ∘ is_unit_of_mul_eq_one f _)⟩⟩,
234+
refine ⟨λ h f g hf hg hp, (h.2 f g hp.symm).imp hf.eq_one_of_is_unit hg.eq_one_of_is_unit,
235+
λ h, ⟨hp1 ∘ hp.eq_one_of_is_unit, λ f g hfg, (h (g * C f.leading_coeff) (f * C g.leading_coeff)
236+
_ _ _).symm.imp (is_unit_of_mul_eq_one f _) (is_unit_of_mul_eq_one g _)⟩⟩,
235237
{ rwa [monic, leading_coeff_mul, leading_coeff_C, ←leading_coeff_mul, mul_comm, ←hfg, ←monic] },
236238
{ rwa [monic, leading_coeff_mul, leading_coeff_C, ←leading_coeff_mul, ←hfg, ←monic] },
237239
{ rw [mul_mul_mul_comm, ←C_mul, ←leading_coeff_mul, ←hfg, hp.leading_coeff, C_1, mul_one,
238240
mul_comm, ←hfg] },
239241
end
240242

243+
lemma monic.irreducible_iff_nat_degree (hp : p.monic) : irreducible p ↔
244+
p ≠ 1 ∧ ∀ f g : R[X], f.monic → g.monic → f * g = p → f.nat_degree = 0 ∨ g.nat_degree = 0 :=
245+
begin
246+
by_cases hp1 : p = 1, { simp [hp1] },
247+
rw [irreducible_of_monic hp hp1, and_iff_right hp1],
248+
refine forall₄_congr (λ a b ha hb, _),
249+
rw [ha.nat_degree_eq_zero_iff_eq_one, hb.nat_degree_eq_zero_iff_eq_one],
250+
end
251+
252+
lemma monic.irreducible_iff_nat_degree' (hp : p.monic) : irreducible p ↔ p ≠ 1
253+
∀ f g : R[X], f.monic → g.monic → f * g = p → g.nat_degree ∉ Ioc 0 (p.nat_degree / 2) :=
254+
begin
255+
simp_rw [hp.irreducible_iff_nat_degree, mem_Ioc, nat.le_div_iff_mul_le zero_lt_two, mul_two],
256+
apply and_congr_right',
257+
split; intros h f g hf hg he; subst he,
258+
{ rw [hf.nat_degree_mul hg, add_le_add_iff_right],
259+
exact λ ha, (h f g hf hg rfl).elim (ha.1.trans_le ha.2).ne' ha.1.ne' },
260+
{ simp_rw [hf.nat_degree_mul hg, pos_iff_ne_zero] at h,
261+
contrapose! h,
262+
obtain hl|hl := le_total f.nat_degree g.nat_degree,
263+
{ exact ⟨g, f, hg, hf, mul_comm g f, h.1, add_le_add_left hl _⟩ },
264+
{ exact ⟨f, g, hf, hg, rfl, h.2, add_le_add_right hl _⟩ } },
265+
end
266+
267+
lemma monic.not_irreducible_iff_exists_add_mul_eq_coeff (hm : p.monic) (hnd : p.nat_degree = 2) :
268+
¬ irreducible p ↔ ∃ c₁ c₂, p.coeff 0 = c₁ * c₂ ∧ p.coeff 1 = c₁ + c₂ :=
269+
begin
270+
casesI subsingleton_or_nontrivial R,
271+
{ simpa only [nat_degree_of_subsingleton] using hnd },
272+
rw [hm.irreducible_iff_nat_degree', and_iff_right, hnd],
273+
push_neg, split,
274+
{ rintros ⟨a, b, ha, hb, rfl, hdb|⟨⟨⟩⟩⟩,
275+
have hda := hnd, rw [ha.nat_degree_mul hb, hdb] at hda,
276+
use [a.coeff 0, b.coeff 0, mul_coeff_zero a b],
277+
simpa only [next_coeff, hnd, add_right_cancel hda, hdb] using ha.next_coeff_mul hb },
278+
{ rintros ⟨c₁, c₂, hmul, hadd⟩,
279+
refine ⟨X + C c₁, X + C c₂, monic_X_add_C _, monic_X_add_C _, _, or.inl $ nat_degree_X_add_C _⟩,
280+
rw [p.as_sum_range_C_mul_X_pow, hnd, finset.sum_range_succ, finset.sum_range_succ,
281+
finset.sum_range_one, ← hnd, hm.coeff_nat_degree, hnd, hmul, hadd, C_mul, C_add, C_1],
282+
ring },
283+
{ rintro rfl, simpa only [nat_degree_one] using hnd },
284+
end
285+
241286
lemma root_mul : is_root (p * q) a ↔ is_root p a ∨ is_root q a :=
242287
by simp_rw [is_root, eval_mul, mul_eq_zero]
243288

@@ -291,10 +336,6 @@ section roots
291336

292337
open multiset
293338

294-
@[simp] lemma degree_coe_units (u : R[X]ˣ) :
295-
degree (u : R[X]) = 0 :=
296-
degree_eq_zero_of_is_unit ⟨u, rfl⟩
297-
298339
theorem prime_X_sub_C (r : R) : prime (X - C r) :=
299340
⟨X_sub_C_ne_zero r, not_is_unit_X_sub_C r,
300341
λ _ _, by { simp_rw [dvd_iff_is_root, is_root.def, eval_mul, mul_eq_zero], exact id }⟩
@@ -322,10 +363,10 @@ theorem eq_of_monic_of_associated (hp : p.monic) (hq : q.monic) (hpq : associate
322363
begin
323364
obtain ⟨u, hu⟩ := hpq,
324365
unfold monic at hp hq,
325-
rw eq_C_of_degree_le_zero (le_of_eq $ degree_coe_units _) at hu,
366+
rw eq_C_of_degree_le_zero (degree_coe_units _).le at hu,
326367
rw [← hu, leading_coeff_mul, hp, one_mul, leading_coeff_C] at hq,
327368
rwa [hq, C_1, mul_one] at hu,
328-
apply_instance,
369+
all_goals { apply_instance },
329370
end
330371

331372
lemma root_multiplicity_mul {p q : R[X]} {x : R} (hpq : p * q ≠ 0) :

0 commit comments

Comments
 (0)