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

Commit 475cf37

Browse files
committed
refactor(data/polynomial): extract/add lemmas and golf (#14888)
+ Extract lemmas `roots_multiset_prod_X_sub_C`, `nat_degree_multiset_prod_X_sub_C_eq_card`, `monic_prod_multiset_X_sub_C` from the proof of `C_leading_coeff_mul_prod_multiset_X_sub_C` in *ring_division.lean*. + Add the lemma `exists_prod_multiset_X_sub_C_mul` in *ring_division.lean* and `roots_ne_zero_of_splits` in *splitting_field.lean* and use them to golf `nat_degree_eq_card_roots` The proof of the latter originally depends on `eq_prod_roots_of_splits`, but now the dependency reversed, with `nat_degree_eq_card_roots` now used to golf `eq_prod_roots_of_splits` (and `roots_map` as well). + Move `prod_multiset_root_eq_finset_root` and `prod_multiset_X_sub_C_dvd` from *field_division.lean* to *ring_division.lean* and golf the proof of the latter, generalizing `field` to `is_domain`. + Remove redundant imports and the lemma `exists_multiset_of_splits`, because it is just one direction of `splits_iff_exists_multiset`, and it follows trivially from `eq_prod_roots_of_splits`. It couldn't be removed before this PR because `roots_map` and `eq_prod_roots_of_splits` depended on it. + Golf `splits_of_exists_multiset` (independent of other changes).
1 parent dabb0c6 commit 475cf37

File tree

5 files changed

+120
-175
lines changed

5 files changed

+120
-175
lines changed

src/data/polynomial/field_division.lean

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@ Copyright (c) 2018 Chris Hughes. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker
55
-/
6-
import algebra.gcd_monoid.basic
76
import data.polynomial.derivative
87
import data.polynomial.ring_division
9-
import data.set.pairwise
10-
import ring_theory.coprime.lemmas
118
import ring_theory.euclidean_domain
129

1310
/-!
@@ -27,11 +24,6 @@ variables {R : Type u} {S : Type v} {k : Type y} {A : Type z} {a b : R} {n : ℕ
2724
section is_domain
2825
variables [comm_ring R] [is_domain R]
2926

30-
lemma prod_multiset_root_eq_finset_root {p : R[X]} :
31-
(multiset.map (λ (a : R), X - C a) p.roots).prod =
32-
∏ a in p.roots.to_finset, (X - C a) ^ root_multiplicity a p :=
33-
by simp only [count_roots, finset.prod_multiset_map_count]
34-
3527
lemma roots_C_mul (p : R[X]) {a : R} (hzero : a ≠ 0) : (C a * p).roots = p.roots :=
3628
begin
3729
by_cases hpzero : p = 0,
@@ -490,20 +482,5 @@ begin
490482
rw [← C_inj, this, C_0],
491483
end
492484

493-
/-- The product `∏ (X - a)` for `a` inside the multiset `p.roots` divides `p`. -/
494-
lemma prod_multiset_X_sub_C_dvd (p : R[X]) :
495-
(multiset.map (λ (a : R), X - C a) p.roots).prod ∣ p :=
496-
begin
497-
rw prod_multiset_root_eq_finset_root,
498-
have hcoprime : pairwise (is_coprime on λ (a : R), polynomial.X - C (id a)) :=
499-
pairwise_coprime_X_sub_C function.injective_id,
500-
have H : pairwise (is_coprime on λ (a : R), (polynomial.X - C (id a)) ^ (root_multiplicity a p)),
501-
{ intros a b hdiff, exact (hcoprime a b hdiff).pow },
502-
apply finset.prod_dvd_of_coprime (H.set_pairwise (↑(multiset.to_finset p.roots) : set R)),
503-
intros a h,
504-
rw multiset.mem_to_finset at h,
505-
exact pow_root_multiplicity_dvd p a
506-
end
507-
508485
end field
509486
end polynomial

src/data/polynomial/ring_division.lean

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,23 @@ lemma roots_prod_X_sub_C (s : finset R) :
463463
(roots_prod (λ a, X - C a) s (prod_ne_zero_iff.mpr (λ a _, X_sub_C_ne_zero a))).trans
464464
(by simp_rw [roots_X_sub_C, multiset.bind_singleton, multiset.map_id'])
465465

466+
@[simp] lemma roots_multiset_prod_X_sub_C (s : multiset R) :
467+
(s.map (λ a, X - C a)).prod.roots = s :=
468+
begin
469+
rw [roots_multiset_prod, multiset.bind_map],
470+
{ simp_rw [roots_X_sub_C, multiset.bind_singleton, multiset.map_id'] },
471+
{ rw [multiset.mem_map], rintro ⟨a, -, h⟩, exact X_sub_C_ne_zero a h },
472+
end
473+
474+
@[simp] lemma nat_degree_multiset_prod_X_sub_C_eq_card (s : multiset R):
475+
(s.map (λ a, X - C a)).prod.nat_degree = s.card :=
476+
begin
477+
rw [nat_degree_multiset_prod_of_monic, multiset.map_map],
478+
{ convert multiset.sum_repeat 1 _,
479+
{ convert multiset.map_const _ 1, ext, apply nat_degree_X_sub_C }, { simp } },
480+
{ intros f hf, obtain ⟨a, ha, rfl⟩ := multiset.mem_map.1 hf, exact monic_X_sub_C a },
481+
end
482+
466483
lemma card_roots_X_pow_sub_C {n : ℕ} (hn : 0 < n) (a : R) :
467484
(roots ((X : R[X]) ^ n - C a)).card ≤ n :=
468485
with_bot.coe_le_coe.1 $
@@ -498,8 +515,8 @@ begin
498515
simp only [polynomial.map_pow, polynomial.map_sub, map_pow, map_sub, map_X, map_C],
499516
end
500517

501-
lemma count_map_roots [is_domain A] {p : A[X]} {f : A →+* B} (hf : function.injective f)
502-
(a : B) : count a (multiset.map f p.roots) ≤ root_multiplicity a (map f p) :=
518+
lemma count_map_roots [is_domain A] (p : A[X]) {f : A →+* B} (hf : function.injective f)
519+
(a : B) : count a (p.roots.map f) ≤ root_multiplicity a (map f p) :=
503520
begin
504521
by_cases h : ∃ t, f t = a,
505522
{ rcases h with ⟨h_w, rfl⟩,
@@ -514,12 +531,12 @@ end
514531

515532
lemma roots_map_of_injective_card_eq_total_degree [is_domain A] [is_domain B] {p : A[X]}
516533
{f : A →+* B} (hf : function.injective f) (hroots : p.roots.card = p.nat_degree) :
517-
multiset.map f p.roots = (map f p).roots :=
534+
p.roots.map f = (map f p).roots :=
518535
begin
519536
by_cases hp0 : p = 0, { simp only [hp0, roots_zero, multiset.map_zero, polynomial.map_zero], },
520537
have hmap : map f p ≠ 0, { simpa only [polynomial.map_zero] using (map_injective f hf).ne hp0, },
521538
apply multiset.eq_of_le_of_card_le,
522-
{ simpa only [multiset.le_iff_count, count_roots] using count_map_roots hf },
539+
{ simpa only [multiset.le_iff_count, count_roots] using count_map_roots p hf },
523540
{ simpa only [multiset.card_map, hroots] using (card_roots' _).trans (nat_degree_map_le f p) },
524541
end
525542

@@ -719,8 +736,7 @@ begin
719736
rw [hr, nat_degree_mul'] at hdeg, swap,
720737
{ rw [hp.leading_coeff, one_mul, leading_coeff_ne_zero], exact rzero },
721738
rw [mul_comm, @eq_C_of_nat_degree_eq_zero _ _ r] at hr,
722-
{ convert hr, convert leading_coeff_C _ using 1,
723-
rw [hr, leading_coeff_mul_monic hp] },
739+
{ convert hr, convert leading_coeff_C _ using 1, rw [hr, leading_coeff_mul_monic hp] },
724740
{ exact (add_right_inj _).1 (le_antisymm hdeg $ nat.le.intro rfl) },
725741
end
726742

@@ -741,33 +757,56 @@ theorem pairwise_coprime_X_sub_C {K} [field K] {I : Type v} {s : I → K}
741757
(H : function.injective s) : pairwise (is_coprime on (λ i : I, X - C (s i))) :=
742758
λ i j hij, is_coprime_X_sub_C_of_is_unit_sub (sub_ne_zero_of_ne $ H.ne hij).is_unit
743759

760+
lemma monic_prod_multiset_X_sub_C : monic (p.roots.map (λ a, X - C a)).prod :=
761+
monic_multiset_prod_of_monic _ _ (λ a _, monic_X_sub_C a)
762+
763+
lemma prod_multiset_root_eq_finset_root :
764+
(p.roots.map (λ a, X - C a)).prod =
765+
p.roots.to_finset.prod (λ a, (X - C a) ^ root_multiplicity a p) :=
766+
by simp only [count_roots, finset.prod_multiset_map_count]
767+
768+
/-- The product `∏ (X - a)` for `a` inside the multiset `p.roots` divides `p`. -/
769+
lemma prod_multiset_X_sub_C_dvd (p : R[X]) : (p.roots.map (λ a, X - C a)).prod ∣ p :=
770+
begin
771+
rw ← map_dvd_map _ (is_fraction_ring.injective R $ fraction_ring R) monic_prod_multiset_X_sub_C,
772+
rw [prod_multiset_root_eq_finset_root, polynomial.map_prod],
773+
refine finset.prod_dvd_of_coprime (λ a _ b _ h, _) (λ a _, _),
774+
{ simp_rw [polynomial.map_pow, polynomial.map_sub, map_C, map_X],
775+
exact (pairwise_coprime_X_sub_C (is_fraction_ring.injective R $ fraction_ring R) _ _ h).pow },
776+
{ exact polynomial.map_dvd _ (pow_root_multiplicity_dvd p a) },
777+
end
778+
779+
lemma exists_prod_multiset_X_sub_C_mul (p : R[X]) : ∃ q,
780+
(p.roots.map (λ a, X - C a)).prod * q = p ∧
781+
p.roots.card + q.nat_degree = p.nat_degree ∧
782+
q.roots = 0 :=
783+
begin
784+
obtain ⟨q, he⟩ := prod_multiset_X_sub_C_dvd p,
785+
use [q, he.symm],
786+
obtain (rfl|hq) := eq_or_ne q 0,
787+
{ rw mul_zero at he, subst he, simp },
788+
split,
789+
{ conv_rhs { rw he },
790+
rw [monic_prod_multiset_X_sub_C.nat_degree_mul' hq, nat_degree_multiset_prod_X_sub_C_eq_card] },
791+
{ replace he := congr_arg roots he.symm,
792+
rw [roots_mul, roots_multiset_prod_X_sub_C] at he,
793+
exacts [add_right_eq_self.1 he, mul_ne_zero monic_prod_multiset_X_sub_C.ne_zero hq] },
794+
end
795+
744796
/-- A polynomial `p` that has as many roots as its degree
745797
can be written `p = p.leading_coeff * ∏(X - a)`, for `a` in `p.roots`. -/
746798
lemma C_leading_coeff_mul_prod_multiset_X_sub_C (hroots : p.roots.card = p.nat_degree) :
747-
C p.leading_coeff * (p.roots.map (λ (a : R), X - C a)).prod = p :=
748-
begin
749-
symmetry, classical,
750-
apply eq_leading_coeff_mul_of_monic_of_dvd_of_nat_degree_le,
751-
{ exact monic_multiset_prod_of_monic _ _ (λ a _, monic_X_sub_C a) },
752-
{ rw ← map_dvd_map _ (is_fraction_ring.injective R $ fraction_ring R),
753-
swap, { exact monic_multiset_prod_of_monic _ _ (λ a _, monic_X_sub_C a) },
754-
rw [finset.prod_multiset_map_count, polynomial.map_prod],
755-
refine finset.prod_dvd_of_coprime (λ a _ b _ h, _) (λ a _, _),
756-
{ simp_rw [polynomial.map_pow, polynomial.map_sub, map_C, map_X],
757-
exact (pairwise_coprime_X_sub_C (is_fraction_ring.injective R $ fraction_ring R) _ _ h).pow },
758-
{ rw count_roots, exact polynomial.map_dvd _ (pow_root_multiplicity_dvd p a) } },
759-
{ rw [nat_degree_multiset_prod_of_monic, multiset.map_map],
760-
{ convert hroots.symm.le, convert multiset.sum_repeat 1 _,
761-
{ convert multiset.map_const _ 1, ext, apply nat_degree_X_sub_C }, { simp } },
762-
{ intros f hf, obtain ⟨a, ha, rfl⟩ := multiset.mem_map.1 hf, exact monic_X_sub_C a } },
763-
end
799+
C p.leading_coeff * (p.roots.map (λ a, X - C a)).prod = p :=
800+
(eq_leading_coeff_mul_of_monic_of_dvd_of_nat_degree_le monic_prod_multiset_X_sub_C
801+
(prod_multiset_X_sub_C_dvd p) $
802+
((nat_degree_multiset_prod_X_sub_C_eq_card _).trans hroots).ge).symm
764803

765804
/-- A monic polynomial `p` that has as many roots as its degree
766805
can be written `p = ∏(X - a)`, for `a` in `p.roots`. -/
767806
lemma prod_multiset_X_sub_C_of_monic_of_roots_card_eq
768807
(hp : p.monic) (hroots : p.roots.card = p.nat_degree) :
769-
(p.roots.map (λ (a : R), X - C a)).prod = p :=
770-
by {convert C_leading_coeff_mul_prod_multiset_X_sub_C hroots, rw [hp.leading_coeff, C_1, one_mul] }
808+
(p.roots.map (λ a, X - C a)).prod = p :=
809+
by { convert C_leading_coeff_mul_prod_multiset_X_sub_C hroots, rw [hp.leading_coeff, C_1, one_mul] }
771810

772811
end comm_ring
773812

@@ -776,7 +815,7 @@ section
776815
variables [semiring R] [comm_ring S] [is_domain S] (φ : R →+* S)
777816

778817
lemma is_unit_of_is_unit_leading_coeff_of_is_unit_map
779-
(f : R[X]) (hf : is_unit (leading_coeff f)) (H : is_unit (map φ f)) :
818+
{f : R[X]} (hf : is_unit f.leading_coeff) (H : is_unit (map φ f)) :
780819
is_unit f :=
781820
begin
782821
have dz := degree_eq_zero_of_is_unit H,

src/field_theory/abel_ruffini.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ begin
311311
(minpoly.dvd F α (by rw [aeval_comp, aeval_X_pow, minpoly.aeval]))⟩ },
312312
{ refine gal_is_solvable_tower p (p.comp (X ^ n)) _ hα _,
313313
{ exact gal.splits_in_splitting_field_of_comp _ _ (by rwa [nat_degree_X_pow]) },
314-
{ obtain ⟨s, hs⟩ := exists_multiset_of_splits _ (splitting_field.splits p),
314+
{ obtain ⟨s, hs⟩ := (splits_iff_exists_multiset _).1 (splitting_field.splits p),
315315
rw [map_comp, polynomial.map_pow, map_X, hs, mul_comp, C_comp],
316316
apply gal_mul_is_solvable (gal_C_is_solvable _),
317317
rw multiset_prod_comp,

src/field_theory/separable.lean

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -404,11 +404,9 @@ end
404404

405405
lemma exists_finset_of_splits
406406
(i : F →+* K) {f : F[X]} (sep : separable f) (sp : splits i f) :
407-
∃ (s : finset K), f.map i =
408-
C (i f.leading_coeff) * (s.prod (λ a : K, (X : K[X]) - C a)) :=
407+
∃ (s : finset K), f.map i = C (i f.leading_coeff) * (s.prod (λ a : K, X - C a)) :=
409408
begin
410-
classical,
411-
obtain ⟨s, h⟩ := exists_multiset_of_splits i sp,
409+
obtain ⟨s, h⟩ := (splits_iff_exists_multiset _).1 sp,
412410
use s.to_finset,
413411
rw [h, finset.prod_eq_multiset_prod, ←multiset.to_finset_eq],
414412
apply nodup_of_separable_prod,

0 commit comments

Comments
 (0)