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

Commit f4210e9

Browse files
feat(data/polynomial/ring_division): move lemmas, add lemmas (#16432)
Rename `count_map_roots` to `count_map_roots_of_injective`. Add 8 lemmas: ``` le_root_multiplicity_iff root_multiplicity_le_iff pow_root_multiplicity_not_dvd _root_.multiset.prod_X_sub_C_dvd_iff_le_roots count_map_roots map_roots_le map_roots_le_of_injective card_roots_le_map ``` Remove `root_multiplicity_of_dvd`, it's just the left direction of `le_root_multiplicity_iff`. Move and golf 3 lemmas: ``` le_root_multiplicity_map (8 -> 5) eq_root_multiplicity_map (10 -> 7) roots_map_of_injective_card_eq_total_degree (7 -> 4) ``` - [x] depends on: #16440 Co-authored-by: alreadydone <junyanxumath@gmail.com> Co-authored-by: Junyan Xu <junyanxumath@gmail.com>
1 parent ec5f9ad commit f4210e9

File tree

2 files changed

+112
-81
lines changed

2 files changed

+112
-81
lines changed

src/data/polynomial/ring_division.lean

Lines changed: 111 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,37 @@ instance : is_domain R[X] :=
225225
end ring
226226

227227
section comm_ring
228-
variables [comm_ring R] [is_domain R] {p q : R[X]}
228+
variable [comm_ring R]
229+
230+
/-- The multiplicity of `a` as root of a nonzero polynomial `p` is at least `n` iff
231+
`(X - a) ^ n` divides `p`. -/
232+
lemma le_root_multiplicity_iff {p : R[X]} (p0 : p ≠ 0) {a : R} {n : ℕ} :
233+
n ≤ root_multiplicity a p ↔ (X - C a) ^ n ∣ p :=
234+
begin
235+
simp_rw [root_multiplicity, dif_neg p0, nat.le_find_iff, not_not],
236+
refine ⟨λ h, _, λ h m hm, (pow_dvd_pow _ hm).trans h⟩,
237+
cases n, { rw pow_zero, apply one_dvd }, { exact h n n.lt_succ_self },
238+
end
239+
240+
lemma root_multiplicity_le_iff {p : R[X]} (p0 : p ≠ 0) (a : R) (n : ℕ) :
241+
root_multiplicity a p ≤ n ↔ ¬ (X - C a) ^ (n + 1) ∣ p :=
242+
by rw [← (le_root_multiplicity_iff p0).not, not_le, nat.lt_add_one_iff]
243+
244+
lemma pow_root_multiplicity_not_dvd {p : R[X]} (p0 : p ≠ 0) (a : R) :
245+
¬ (X - C a) ^ (root_multiplicity a p + 1) ∣ p :=
246+
by rw [← root_multiplicity_le_iff p0]
247+
248+
/-- The multiplicity of `p + q` is at least the minimum of the multiplicities. -/
249+
lemma root_multiplicity_add {p q : R[X]} (a : R) (hzero : p + q ≠ 0) :
250+
min (root_multiplicity a p) (root_multiplicity a q) ≤ root_multiplicity a (p + q) :=
251+
begin
252+
rw le_root_multiplicity_iff hzero,
253+
have hdivp : (X - C a) ^ root_multiplicity a p ∣ p := pow_root_multiplicity_dvd p a,
254+
have hdivq : (X - C a) ^ root_multiplicity a q ∣ q := pow_root_multiplicity_dvd q a,
255+
exact min_pow_dvd_add hdivp hdivq
256+
end
257+
258+
variables [is_domain R] {p q : R[X]}
229259

230260
section roots
231261

@@ -315,27 +345,6 @@ begin
315345
simp only [root_multiplicity_mul hzero, root_multiplicity_X_sub_C_self, hn, nat.one_add]
316346
end
317347

318-
/-- If `(X - a) ^ n` divides a polynomial `p` then the multiplicity of `a` as root of `p` is at
319-
least `n`. -/
320-
lemma root_multiplicity_of_dvd {p : R[X]} {a : R} {n : ℕ}
321-
(hzero : p ≠ 0) (h : (X - C a) ^ n ∣ p) : n ≤ root_multiplicity a p :=
322-
begin
323-
obtain ⟨q, hq⟩ := exists_eq_mul_right_of_dvd h,
324-
rw hq at hzero,
325-
simp only [hq, root_multiplicity_mul hzero, root_multiplicity_X_sub_C_pow,
326-
ge_iff_le, _root_.zero_le, le_add_iff_nonneg_right],
327-
end
328-
329-
/-- The multiplicity of `p + q` is at least the minimum of the multiplicities. -/
330-
lemma root_multiplicity_add {p q : R[X]} (a : R) (hzero : p + q ≠ 0) :
331-
min (root_multiplicity a p) (root_multiplicity a q) ≤ root_multiplicity a (p + q) :=
332-
begin
333-
refine root_multiplicity_of_dvd hzero _,
334-
have hdivp : (X - C a) ^ root_multiplicity a p ∣ p := pow_root_multiplicity_dvd p a,
335-
have hdivq : (X - C a) ^ root_multiplicity a q ∣ q := pow_root_multiplicity_dvd q a,
336-
exact min_pow_dvd_add hdivp hdivq
337-
end
338-
339348
lemma exists_multiset_roots : ∀ {p : R[X]} (hp : p ≠ 0),
340349
∃ s : multiset R, (s.card : with_bot ℕ) ≤ degree p ∧ ∀ a, s.count a = root_multiplicity a p
341350
| p := λ hp, by haveI := classical.prop_decidable (∃ x, is_root p x); exact
@@ -541,61 +550,6 @@ calc ((roots ((X : R[X]) ^ n - C a)).card : with_bot ℕ)
541550
≤ degree ((X : R[X]) ^ n - C a) : card_roots (X_pow_sub_C_ne_zero hn a)
542551
... = n : degree_X_pow_sub_C hn a
543552

544-
section
545-
546-
variables {A B : Type*} [comm_ring A] [comm_ring B]
547-
548-
lemma le_root_multiplicity_map {p : A[X]} {f : A →+* B} (hmap : map f p ≠ 0) (a : A) :
549-
root_multiplicity a p ≤ root_multiplicity (f a) (map f p) :=
550-
begin
551-
have hp0 : p ≠ 0 := λ h, hmap (h.symm ▸ polynomial.map_zero f),
552-
rw [root_multiplicity, root_multiplicity, dif_neg hp0, dif_neg hmap],
553-
simp only [not_not, nat.lt_find_iff, nat.le_find_iff],
554-
intros m hm,
555-
have := (map_ring_hom f).map_dvd (hm m le_rfl),
556-
simpa only [coe_map_ring_hom, map_pow, map_sub, map_X, map_C],
557-
end
558-
559-
lemma eq_root_multiplicity_map {p : A[X]} {f : A →+* B} (hf : function.injective f)
560-
(a : A) : root_multiplicity a p = root_multiplicity (f a) (map f p) :=
561-
begin
562-
by_cases hp0 : p = 0, { simp only [hp0, root_multiplicity_zero, polynomial.map_zero], },
563-
have hmap : map f p ≠ 0, { simpa only [polynomial.map_zero] using (map_injective f hf).ne hp0, },
564-
apply le_antisymm (le_root_multiplicity_map hmap a),
565-
rw [root_multiplicity, root_multiplicity, dif_neg hp0, dif_neg hmap],
566-
simp only [not_not, nat.lt_find_iff, nat.le_find_iff],
567-
intros m hm, rw ← map_dvd_map f hf ((monic_X_sub_C a).pow _),
568-
convert hm m le_rfl,
569-
simp only [polynomial.map_pow, polynomial.map_sub, map_pow, map_sub, map_X, map_C],
570-
end
571-
572-
lemma count_map_roots [is_domain A] (p : A[X]) {f : A →+* B} (hf : function.injective f)
573-
(a : B) : count a (p.roots.map f) ≤ root_multiplicity a (map f p) :=
574-
begin
575-
by_cases h : ∃ t, f t = a,
576-
{ rcases h with ⟨h_w, rfl⟩,
577-
rw [multiset.count_map_eq_count' f _ hf, count_roots],
578-
exact (eq_root_multiplicity_map hf h_w).le },
579-
{ suffices : (multiset.map f p.roots).count a = 0,
580-
{ rw this, exact zero_le _, },
581-
rw [multiset.count_map, multiset.card_eq_zero, multiset.filter_eq_nil],
582-
rintro k hk rfl,
583-
exact h ⟨k, rfl⟩, },
584-
end
585-
586-
lemma roots_map_of_injective_card_eq_total_degree [is_domain A] [is_domain B] {p : A[X]}
587-
{f : A →+* B} (hf : function.injective f) (hroots : p.roots.card = p.nat_degree) :
588-
p.roots.map f = (map f p).roots :=
589-
begin
590-
by_cases hp0 : p = 0, { simp only [hp0, roots_zero, multiset.map_zero, polynomial.map_zero], },
591-
have hmap : map f p ≠ 0, { simpa only [polynomial.map_zero] using (map_injective f hf).ne hp0, },
592-
apply multiset.eq_of_le_of_card_le,
593-
{ simpa only [multiset.le_iff_count, count_roots] using count_map_roots p hf },
594-
{ simpa only [multiset.card_map, hroots] using (card_roots' _).trans (nat_degree_map_le f p) },
595-
end
596-
597-
end
598-
599553
section nth_roots
600554

601555
/-- `nth_roots n a` noncomputably returns the solutions to `x ^ n = a`-/
@@ -847,12 +801,21 @@ begin
847801
{ exact polynomial.map_dvd _ (pow_root_multiplicity_dvd p a) },
848802
end
849803

804+
/-- A Galois connection. -/
805+
lemma _root_.multiset.prod_X_sub_C_dvd_iff_le_roots {p : R[X]} (hp : p ≠ 0) (s : multiset R) :
806+
(s.map (λ a, X - C a)).prod ∣ p ↔ s ≤ p.roots :=
807+
⟨λ h, multiset.le_iff_count.2 $ λ r, begin
808+
rw [count_roots, le_root_multiplicity_iff hp, ← multiset.prod_repeat,
809+
← multiset.map_repeat (λ a, X - C a), ← multiset.filter_eq],
810+
exact (multiset.prod_dvd_prod_of_le $ multiset.map_le_map $ s.filter_le _).trans h,
811+
end, λ h, (multiset.prod_dvd_prod_of_le $ multiset.map_le_map h).trans p.prod_multiset_X_sub_C_dvd⟩
812+
850813
lemma exists_prod_multiset_X_sub_C_mul (p : R[X]) : ∃ q,
851814
(p.roots.map (λ a, X - C a)).prod * q = p ∧
852815
p.roots.card + q.nat_degree = p.nat_degree ∧
853816
q.roots = 0 :=
854817
begin
855-
obtain ⟨q, he⟩ := prod_multiset_X_sub_C_dvd p,
818+
obtain ⟨q, he⟩ := p.prod_multiset_X_sub_C_dvd,
856819
use [q, he.symm],
857820
obtain (rfl|hq) := eq_or_ne q 0,
858821
{ rw mul_zero at he, subst he, simp },
@@ -869,8 +832,7 @@ can be written `p = p.leading_coeff * ∏(X - a)`, for `a` in `p.roots`. -/
869832
lemma C_leading_coeff_mul_prod_multiset_X_sub_C (hroots : p.roots.card = p.nat_degree) :
870833
C p.leading_coeff * (p.roots.map (λ a, X - C a)).prod = p :=
871834
(eq_leading_coeff_mul_of_monic_of_dvd_of_nat_degree_le monic_prod_multiset_X_sub_C
872-
(prod_multiset_X_sub_C_dvd p) $
873-
((nat_degree_multiset_prod_X_sub_C_eq_card _).trans hroots).ge).symm
835+
p.prod_multiset_X_sub_C_dvd ((nat_degree_multiset_prod_X_sub_C_eq_card _).trans hroots).ge).symm
874836

875837
/-- A monic polynomial `p` that has as many roots as its degree
876838
can be written `p = ∏(X - a)`, for `a` in `p.roots`. -/
@@ -881,6 +843,75 @@ by { convert C_leading_coeff_mul_prod_multiset_X_sub_C hroots, rw [hp.leading_co
881843

882844
end comm_ring
883845

846+
section
847+
variables {A B : Type*} [comm_ring A] [comm_ring B]
848+
849+
lemma le_root_multiplicity_map {p : A[X]} {f : A →+* B} (hmap : map f p ≠ 0) (a : A) :
850+
root_multiplicity a p ≤ root_multiplicity (f a) (p.map f) :=
851+
begin
852+
rw [le_root_multiplicity_iff hmap],
853+
refine trans _ ((map_ring_hom f).map_dvd (pow_root_multiplicity_dvd p a)),
854+
rw [map_pow, map_sub, coe_map_ring_hom, map_X, map_C],
855+
end
856+
857+
lemma eq_root_multiplicity_map {p : A[X]} {f : A →+* B} (hf : function.injective f)
858+
(a : A) : root_multiplicity a p = root_multiplicity (f a) (p.map f) :=
859+
begin
860+
by_cases hp0 : p = 0, { simp only [hp0, root_multiplicity_zero, polynomial.map_zero], },
861+
apply le_antisymm (le_root_multiplicity_map ((polynomial.map_ne_zero_iff hf).mpr hp0) a),
862+
rw [le_root_multiplicity_iff hp0, ← map_dvd_map f hf ((monic_X_sub_C a).pow _),
863+
polynomial.map_pow, polynomial.map_sub, map_X, map_C],
864+
apply pow_root_multiplicity_dvd,
865+
end
866+
867+
lemma count_map_roots [is_domain A] {p : A[X]} {f : A →+* B} (hmap : map f p ≠ 0) (b : B) :
868+
(p.roots.map f).count b ≤ root_multiplicity b (p.map f) :=
869+
begin
870+
rw [le_root_multiplicity_iff hmap, ← multiset.prod_repeat, ← multiset.map_repeat (λ a, X - C a)],
871+
rw ← multiset.filter_eq,
872+
refine (multiset.prod_dvd_prod_of_le $ multiset.map_le_map $ multiset.filter_le _ _).trans _,
873+
convert polynomial.map_dvd _ p.prod_multiset_X_sub_C_dvd,
874+
simp only [polynomial.map_multiset_prod, multiset.map_map],
875+
congr, ext1,
876+
simp only [function.comp_app, polynomial.map_sub, map_X, map_C],
877+
end
878+
879+
lemma count_map_roots_of_injective [is_domain A] (p : A[X]) {f : A →+* B}
880+
(hf : function.injective f) (b : B) :
881+
(p.roots.map f).count b ≤ root_multiplicity b (p.map f) :=
882+
begin
883+
by_cases hp0 : p = 0,
884+
{ simp only [hp0, roots_zero, multiset.map_zero,
885+
multiset.count_zero, polynomial.map_zero, root_multiplicity_zero] },
886+
{ exact count_map_roots ((polynomial.map_ne_zero_iff hf).mpr hp0) b },
887+
end
888+
889+
lemma map_roots_le [is_domain A] [is_domain B] {p : A[X]} {f : A →+* B} (h : p.map f ≠ 0) :
890+
p.roots.map f ≤ (p.map f).roots :=
891+
multiset.le_iff_count.2 $ λ b, by { rw count_roots, apply count_map_roots h }
892+
893+
lemma map_roots_le_of_injective [is_domain A] [is_domain B] (p : A[X])
894+
{f : A →+* B} (hf : function.injective f) :
895+
p.roots.map f ≤ (p.map f).roots :=
896+
begin
897+
by_cases hp0 : p = 0, { simp only [hp0, roots_zero, multiset.map_zero, polynomial.map_zero], },
898+
exact map_roots_le ((polynomial.map_ne_zero_iff hf).mpr hp0),
899+
end
900+
901+
lemma card_roots_le_map [is_domain A] [is_domain B] {p : A[X]} {f : A →+* B} (h : p.map f ≠ 0) :
902+
p.roots.card ≤ (p.map f).roots.card :=
903+
by { rw ← p.roots.card_map f, exact multiset.card_le_of_le (map_roots_le h) }
904+
905+
lemma roots_map_of_injective_of_card_eq_nat_degree [is_domain A] [is_domain B] {p : A[X]}
906+
{f : A →+* B} (hf : function.injective f) (hroots : p.roots.card = p.nat_degree) :
907+
p.roots.map f = (p.map f).roots :=
908+
begin
909+
apply multiset.eq_of_le_of_card_le (map_roots_le_of_injective p hf),
910+
simpa only [multiset.card_map, hroots] using (card_roots' _).trans (nat_degree_map_le f p),
911+
end
912+
913+
end
914+
884915
section
885916

886917
variables [semiring R] [comm_ring S] [is_domain S] (φ : R →+* S)

src/field_theory/splitting_field.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ by rw [degree_eq_nat_degree p_ne_zero, nat_degree_eq_card_roots hsplit]
273273

274274
theorem roots_map {f : K[X]} (hf : f.splits $ ring_hom.id K) :
275275
(f.map i).roots = f.roots.map i :=
276-
(roots_map_of_injective_card_eq_total_degree i.injective $
276+
(roots_map_of_injective_of_card_eq_nat_degree i.injective $
277277
by { convert (nat_degree_eq_card_roots hf).symm, rw map_id }).symm
278278

279279
lemma image_root_set [algebra F K] [algebra F L] {p : F[X]} (h : p.splits (algebra_map F K))

0 commit comments

Comments
 (0)