Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
Try doing some basic maths questions in the Lean Theorem Prover. Functions, real numbers, equivalence relations and groups. Click on README.md and then on "Open in CoCalc with one click".
Project: Xena
Views: 18542License: APACHE
/- Copyright (c) 2018 Chris Hughes. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Chris Hughes Definition of splitting fields, and definition of homomorphism into any field that splits -/ import ring_theory.unique_factorization_domain import data.polynomial ring_theory.principal_ideal_domain algebra.euclidean_domain local attribute [instance, priority 100000] is_ring_hom.id universes u v w variables {α : Type u} {β : Type v} {γ : Type w} namespace polynomial noncomputable theory open_locale classical variables [discrete_field α] [discrete_field β] [discrete_field γ] open polynomial section splits variables (i : α → β) [is_ring_hom i] /-- a polynomial `splits` iff it is zero or all of its irreducible factors have `degree` 1 -/ def splits (f : polynomial α) : Prop := f = 0 ∨ ∀ {g : polynomial β}, irreducible g → g ∣ f.map i → degree g = 1 @[simp] lemma splits_zero : splits i (0 : polynomial α) := or.inl rfl @[simp] lemma splits_C (a : α) : splits i (C a) := if ha : a = 0 then ha.symm ▸ (@C_0 α _).symm ▸ splits_zero i else have hia : i a ≠ 0, from mt ((is_add_group_hom.injective_iff i).1 (is_ring_hom.injective i) _) ha, or.inr $ λ g hg ⟨p, hp⟩, absurd hg.1 (classical.not_not.2 (is_unit_iff_degree_eq_zero.2 $ by have := congr_arg degree hp; simp [degree_C hia, @eq_comm (with_bot ℕ) 0, nat.with_bot.add_eq_zero_iff] at this; clear _fun_match; tautology)) lemma splits_of_degree_eq_one {f : polynomial α} (hf : degree f = 1) : splits i f := or.inr $ λ g hg ⟨p, hp⟩, by have := congr_arg degree hp; simp [nat.with_bot.add_eq_one_iff, hf, @eq_comm (with_bot ℕ) 1, mt is_unit_iff_degree_eq_zero.2 hg.1] at this; clear _fun_match; tauto lemma splits_of_degree_le_one {f : polynomial α} (hf : degree f ≤ 1) : splits i f := begin cases h : degree f with n, { rw [degree_eq_bot.1 h]; exact splits_zero i }, { cases n with n, { rw [eq_C_of_degree_le_zero (trans_rel_right (≤) h (le_refl _))]; exact splits_C _ _ }, { have hn : n = 0, { rw h at hf, cases n, { refl }, { exact absurd hf dec_trivial } }, exact splits_of_degree_eq_one _ (by rw [h, hn]; refl) } } end lemma splits_mul {f g : polynomial α} (hf : splits i f) (hg : splits i g) : splits i (f * g) := if h : f * g = 0 then by simp [h] else or.inr $ λ p hp hpf, ((principal_ideal_domain.irreducible_iff_prime.1 hp).2.2 _ _ (show p ∣ map i f * map i g, by convert hpf; rw polynomial.map_mul)).elim (hf.resolve_left (λ hf, by simpa [hf] using h) hp) (hg.resolve_left (λ hg, by simpa [hg] using h) hp) lemma splits_of_splits_mul {f g : polynomial α} (hfg : f * g ≠ 0) (h : splits i (f * g)) : splits i f ∧ splits i g := ⟨or.inr $ λ g hgi hg, or.resolve_left h hfg hgi (by rw map_mul; exact dvd.trans hg (dvd_mul_right _ _)), or.inr $ λ g hgi hg, or.resolve_left h hfg hgi (by rw map_mul; exact dvd.trans hg (dvd_mul_left _ _))⟩ lemma splits_map_iff (j : β → γ) [is_ring_hom j] {f : polynomial α} : splits j (f.map i) ↔ splits (λ x, j (i x)) f := by simp [splits, polynomial.map_map] lemma exists_root_of_splits {f : polynomial α} (hs : splits i f) (hf0 : degree f ≠ 0) : ∃ x, eval₂ i x f = 0 := if hf0 : f = 0 then ⟨37, by simp [hf0]⟩ else let ⟨g, hg⟩ := is_noetherian_ring.exists_irreducible_factor (show ¬ is_unit (f.map i), from mt is_unit_iff_degree_eq_zero.1 (by rwa degree_map)) (by rw [ne.def, map_eq_zero]; exact hf0) in let ⟨x, hx⟩ := exists_root_of_degree_eq_one (hs.resolve_left hf0 hg.1 hg.2) in let ⟨i, hi⟩ := hg.2 in ⟨x, by rw [← eval_map, hi, eval_mul, show _ = _, from hx, zero_mul]⟩ lemma exists_multiset_of_splits {f : polynomial α} : splits i f → ∃ (s : multiset β), f.map i = C (i f.leading_coeff) * (s.map (λ a : β, (X : polynomial β) - C a)).prod := suffices splits id (f.map i) → ∃ s : multiset β, f.map i = (C (f.map i).leading_coeff) * (s.map (λ a : β, (X : polynomial β) - C a)).prod, by rwa [splits_map_iff, leading_coeff_map i] at this, is_noetherian_ring.irreducible_induction_on (f.map i) (λ _, ⟨{37}, by simp [is_ring_hom.map_zero i]⟩) (λ u hu _, ⟨0, by conv_lhs { rw eq_C_of_degree_eq_zero (is_unit_iff_degree_eq_zero.1 hu) }; simp [leading_coeff, nat_degree_eq_of_degree_eq_some (is_unit_iff_degree_eq_zero.1 hu)]⟩) (λ f p hf0 hp ih hfs, have hpf0 : p * f ≠ 0, from mul_ne_zero hp.ne_zero hf0, let ⟨s, hs⟩ := ih (splits_of_splits_mul _ hpf0 hfs).2 in ⟨-(p * norm_unit p).coeff 0 :: s, have hp1 : degree p = 1, from hfs.resolve_left hpf0 hp (by simp), begin rw [multiset.map_cons, multiset.prod_cons, leading_coeff_mul, C_mul, mul_assoc, mul_left_comm (C f.leading_coeff), ← hs, ← mul_assoc, domain.mul_right_inj hf0], conv_lhs {rw eq_X_add_C_of_degree_eq_one hp1}, simp only [mul_add, coe_norm_unit hp.ne_zero, mul_comm p, coeff_neg, C_neg, sub_eq_add_neg, neg_neg, coeff_C_mul, (mul_assoc _ _ _).symm, C_mul.symm, mul_inv_cancel (show p.leading_coeff ≠ 0, from mt leading_coeff_eq_zero.1 hp.ne_zero), one_mul], end⟩) section UFD local attribute [instance, priority 10] principal_ideal_domain.to_unique_factorization_domain local infix ` ~ᵤ ` : 50 := associated open unique_factorization_domain associates lemma splits_of_exists_multiset {f : polynomial α} {s : multiset β} (hs : f.map i = C (i f.leading_coeff) * (s.map (λ a : β, (X : polynomial β) - C a)).prod) : splits i f := if hf0 : f = 0 then or.inl hf0 else or.inr $ λ p hp hdp, have ht : multiset.rel associated (factors (f.map i)) (s.map (λ a : β, (X : polynomial β) - C a)) := unique (λ p hp, irreducible_factors (mt (map_eq_zero i).1 hf0) _ hp) (λ p, by simp [@eq_comm _ _ p, -sub_eq_add_neg, irreducible_of_degree_eq_one (degree_X_sub_C _)] {contextual := tt}) (associated.symm $ calc _ ~ᵤ f.map i : ⟨(units.map' C : units β →* units (polynomial β)) (units.mk0 (f.map i).leading_coeff (mt leading_coeff_eq_zero.1 (mt (map_eq_zero i).1 hf0))), by conv_rhs {rw [hs, ← leading_coeff_map i, mul_comm]}; refl⟩ ... ~ᵤ _ : associated.symm (unique_factorization_domain.factors_prod (by simpa using hf0))), let ⟨q, hq, hpq⟩ := exists_mem_factors_of_dvd (by simpa) hp hdp in let ⟨q', hq', hqq'⟩ := multiset.exists_mem_of_rel_of_mem ht hq in let ⟨a, ha⟩ := multiset.mem_map.1 hq' in by rw [← degree_X_sub_C a, ha.2]; exact degree_eq_degree_of_associated (hpq.trans hqq') lemma splits_of_splits_id {f : polynomial α} : splits id f → splits i f := unique_factorization_domain.induction_on_prime f (λ _, splits_zero _) (λ _ hu _, splits_of_degree_le_one _ ((is_unit_iff_degree_eq_zero.1 hu).symm ▸ dec_trivial)) (λ a p ha0 hp ih hfi, splits_mul _ (splits_of_degree_eq_one _ ((splits_of_splits_mul _ (mul_ne_zero hp.1 ha0) hfi).1.resolve_left hp.1 (irreducible_of_prime hp) (by rw map_id))) (ih (splits_of_splits_mul _ (mul_ne_zero hp.1 ha0) hfi).2)) end UFD lemma splits_iff_exists_multiset {f : polynomial α} : splits i f ↔ ∃ (s : multiset β), f.map i = C (i f.leading_coeff) * (s.map (λ a : β, (X : polynomial β) - C a)).prod := ⟨exists_multiset_of_splits i, λ ⟨s, hs⟩, splits_of_exists_multiset i hs⟩ lemma splits_comp_of_splits (j : β → γ) [is_ring_hom j] {f : polynomial α} (h : splits i f) : splits (λ x, j (i x)) f := begin change i with (λ x, id (i x)) at h, rw [← splits_map_iff], rw [← splits_map_iff i id] at h, exact splits_of_splits_id _ h end end splits end polynomial