# HG changeset patch # User paulson # Date 1556553034 -3600 # Node ID ff8386fc191d026863a78ad85b22fa6286ce48bd # Parent 2388e0d2827b44d5753fefb161485e480f369dcc# Parent e886b58bf6982a7d7276bcbb5e0a454c2df30f35 merged diff -r 2388e0d2827b -r ff8386fc191d src/HOL/Algebra/Algebraic_Closure.thy --- a/src/HOL/Algebra/Algebraic_Closure.thy Mon Apr 29 00:36:54 2019 +0100 +++ b/src/HOL/Algebra/Algebraic_Closure.thy Mon Apr 29 16:50:34 2019 +0100 @@ -5,7 +5,7 @@ *) theory Algebraic_Closure - imports Indexed_Polynomials Polynomial_Divisibility Pred_Zorn Finite_Extensions + imports Indexed_Polynomials Polynomial_Divisibility Finite_Extensions begin @@ -21,18 +21,19 @@ \ mult := (\a \ carrier R. \b \ carrier R. a \\<^bsub>R\<^esub> b), add := (\a \ carrier R. \b \ carrier R. a \\<^bsub>R\<^esub> b) \" -definition (in ring) \ :: "'a list \ (('a list multiset) \ 'a) list" +definition (in ring) \ :: "'a list \ ((('a list \ nat) multiset) \ 'a) list" where "\ P = map indexed_const P" -definition (in ring) extensions :: "(('a list multiset) \ 'a) ring set" +definition (in ring) extensions :: "((('a list \ nat) multiset) \ 'a) ring set" where "extensions \ { L \ \such that\. \ \i\ (field L) \ \ \ii\ (indexed_const \ ring_hom R L) \ \ \iii\ (\\

\ carrier L. carrier_coeff \

) \ - \ \iv\ (\\

\ carrier L. \P \ carrier (poly_ring R). - \ index_free \

P \ \\<^bsub>P\<^esub> \ carrier L \ (ring.eval L) (\ P) \\<^bsub>P\<^esub> = \\<^bsub>L\<^esub>) }" + \ \iv\ (\\

\ carrier L. \P \ carrier (poly_ring R). \i. + \ index_free \

(P, i) \ + \\<^bsub>(P, i)\<^esub> \ carrier L \ (ring.eval L) (\ P) \\<^bsub>(P, i)\<^esub> = \\<^bsub>L\<^esub>) }" -abbreviation (in ring) restrict_extensions :: "(('a list multiset) \ 'a) ring set" ("\") +abbreviation (in ring) restrict_extensions :: "((('a list \ nat) multiset) \ 'a) ring set" ("\") where "\ \ law_restrict ` extensions" @@ -65,7 +66,7 @@ lemma (in field) law_restrict_is_field: "field (law_restrict R)" proof - have "comm_monoid_axioms (law_restrict R)" - using m_comm unfolding comm_monoid_axioms_def law_restrict_carrier law_restrict_mult by auto + using m_comm unfolding comm_monoid_axioms_def law_restrict_carrier law_restrict_mult by auto then interpret L: cring "law_restrict R" using cring.intro law_restrict_is_ring comm_monoid.intro ring.is_monoid by auto have "Units R = Units (law_restrict R)" @@ -73,7 +74,7 @@ thus ?thesis using L.cring_fieldI unfolding field_Units law_restrict_carrier law_restrict_zero by simp qed - + lemma law_restrict_iso_imp_eq: assumes "id \ ring_iso (law_restrict A) (law_restrict B)" and "ring A" and "ring B" shows "law_restrict A = law_restrict B" @@ -112,38 +113,38 @@ subsection \Partial Order\ -lemma iso_incl_backwards: +lemma iso_incl_backwards: assumes "A \ B" shows "id \ ring_hom A B" using assms by cases -lemma iso_incl_antisym_aux: +lemma iso_incl_antisym_aux: assumes "A \ B" and "B \ A" shows "id \ ring_iso A B" -proof - - have hom: "id \ ring_hom A B" "id \ ring_hom B A" +proof - + have hom: "id \ ring_hom A B" "id \ ring_hom B A" using assms(1-2)[THEN iso_incl_backwards] by auto - thus ?thesis + thus ?thesis using hom[THEN ring_hom_memE(1)] by (auto simp add: ring_iso_def bij_betw_def inj_on_def) qed -lemma iso_incl_refl: "A \ A" +lemma iso_incl_refl: "A \ A" by (rule iso_inclI[OF ring_hom_memI], auto) -lemma iso_incl_trans: +lemma iso_incl_trans: assumes "A \ B" and "B \ C" shows "A \ C" using ring_hom_trans[OF assms[THEN iso_incl_backwards]] by auto lemma (in ring) iso_incl_antisym: assumes "A \ \" "B \ \" and "A \ B" "B \ A" shows "A = B" -proof - - obtain A' B' :: "('a list multiset \ 'a) ring" +proof - + obtain A' B' :: "(('a list \ nat) multiset \ 'a) ring" where A: "A = law_restrict A'" "ring A'" and B: "B = law_restrict B'" "ring B'" using assms(1-2) field.is_ring by (auto simp add: extensions_def) - thus ?thesis + thus ?thesis using law_restrict_iso_imp_eq iso_incl_antisym_aux[OF assms(3-4)] by simp qed -lemma (in ring) iso_incl_partial_order: "partial_order_on \ (rel_of (\) \)" - using iso_incl_refl iso_incl_trans iso_incl_antisym by (rule partial_order_on_rel_ofI) +lemma (in ring) iso_incl_partial_order: "partial_order_on \ (relation_of (\) \)" + using iso_incl_refl iso_incl_trans iso_incl_antisym by (rule partial_order_on_relation_ofI) lemma iso_inclE: assumes "ring A" and "ring B" and "A \ B" shows "ring_hom_ring A B id" @@ -174,14 +175,14 @@ show "indexed_const \ ring_hom R (image_ring indexed_const R)" using inj_imp_image_ring_iso[OF indexed_const_inj_on] unfolding ring_iso_def by auto next - fix \

:: "('a list multiset) \ 'a" and P + fix \

:: "(('a list \ nat) multiset) \ 'a" and P and i assume "\

\ carrier (image_ring indexed_const R)" then obtain k where "k \ carrier R" and "\

= indexed_const k" unfolding image_ring_carrier by blast - hence "index_free \

P" for P + hence "index_free \

(P, i)" for P i unfolding index_free_def indexed_const_def by auto - thus "\ index_free \

P \ \\<^bsub>P\<^esub> \ carrier (image_ring indexed_const R)" - and "\ index_free \

P \ ring.eval (image_ring indexed_const R) (\ P) \\<^bsub>P\<^esub> = \\<^bsub>image_ring indexed_const R\<^esub>" + thus "\ index_free \

(P, i) \ \\<^bsub>(P, i)\<^esub> \ carrier (image_ring indexed_const R)" + and "\ index_free \

(P, i) \ ring.eval (image_ring indexed_const R) (\ P) \\<^bsub>(P, i)\<^esub> = \\<^bsub>image_ring indexed_const R\<^esub>" by auto from \k \ carrier R\ and \\

= indexed_const k\ show "carrier_coeff \

" unfolding indexed_const_def carrier_coeff_def by auto @@ -194,7 +195,7 @@ subsection \Chains\ definition union_ring :: "(('a, 'c) ring_scheme) set \ 'a ring" - where "union_ring C = + where "union_ring C = \ carrier = (\(carrier ` C)), monoid.mult = (\a b. (monoid.mult (SOME R. R \ C \ a \ carrier R \ b \ carrier R) a b)), one = one (SOME R. R \ C), @@ -281,7 +282,7 @@ using field_chain by simp show "a \\<^bsub>union_ring C\<^esub> b \ carrier (union_ring C)" - using R(1-3) unfolding same_laws(1)[OF R(1-3)] unfolding union_ring_def by auto + using R(1-3) unfolding same_laws(1)[OF R(1-3)] unfolding union_ring_def by auto show "(a \\<^bsub>union_ring C\<^esub> b) \\<^bsub>union_ring C\<^esub> c = a \\<^bsub>union_ring C\<^esub> (b \\<^bsub>union_ring C\<^esub> c)" and "a \\<^bsub>union_ring C\<^esub> b = b \\<^bsub>union_ring C\<^esub> a" and "\\<^bsub>union_ring C\<^esub> \\<^bsub>union_ring C\<^esub> a = a" @@ -290,7 +291,7 @@ next show "\\<^bsub>union_ring C\<^esub> \ carrier (union_ring C)" using ring.ring_simprules(6)[OF ring_chain] assms same_one_same_zero(1) - unfolding union_ring_carrier by auto + unfolding union_ring_carrier by auto qed lemma union_ring_is_abelian_group: @@ -308,7 +309,7 @@ show "(a \\<^bsub>union_ring C\<^esub> b) \\<^bsub>union_ring C\<^esub> c = (a \\<^bsub>union_ring C\<^esub> c) \\<^bsub>union_ring C\<^esub> (b \\<^bsub>union_ring C\<^esub> c)" and "(a \\<^bsub>union_ring C\<^esub> b) \\<^bsub>union_ring C\<^esub> c = a \\<^bsub>union_ring C\<^esub> (b \\<^bsub>union_ring C\<^esub> c)" and "a \\<^bsub>union_ring C\<^esub> b = b \\<^bsub>union_ring C\<^esub> a" - and "\\<^bsub>union_ring C\<^esub> \\<^bsub>union_ring C\<^esub> a = a" + and "\\<^bsub>union_ring C\<^esub> \\<^bsub>union_ring C\<^esub> a = a" using same_one_same_zero[OF R(1)] same_laws[OF R(1)] R(2-4) l_distr a_assoc a_comm by auto have "\a' \ carrier R. a' \\<^bsub>union_ring C\<^esub> a = \\<^bsub>union_ring C\<^esub>" using same_laws(2)[OF R(1)] R(2) same_one_same_zero[OF R(1)] by simp @@ -334,7 +335,7 @@ using field_chain by simp from \a \ carrier R\ and \a \ \\<^bsub>union_ring C\<^esub>\ have "a \ Units R" - unfolding same_one_same_zero[OF R(1)] field_Units by auto + unfolding same_one_same_zero[OF R(1)] field_Units by auto hence "\a' \ carrier R. a' \\<^bsub>union_ring C\<^esub> a = \\<^bsub>union_ring C\<^esub> \ a \\<^bsub>union_ring C\<^esub> a' = \\<^bsub>union_ring C\<^esub>" using same_laws[OF R(1)] same_one_same_zero[OF R(1)] R(2) unfolding Units_def by auto with \R \ C\ and \a \ carrier (union_ring C)\ show "a \ Units (union_ring C)" @@ -370,78 +371,84 @@ subsection \Zorn\ +(* ========== *) +lemma Chains_relation_of: + assumes "C \ Chains (relation_of P A)" shows "C \ A" + using assms unfolding Chains_def relation_of_def by auto +(* ========== *) + lemma (in ring) exists_core_chain: - assumes "C \ Chains (rel_of (\) \)" obtains C' where "C' \ extensions" and "C = law_restrict ` C'" - using Chains_rel_of[OF assms] by (meson subset_image_iff) + assumes "C \ Chains (relation_of (\) \)" obtains C' where "C' \ extensions" and "C = law_restrict ` C'" + using Chains_relation_of[OF assms] by (meson subset_image_iff) lemma (in ring) core_chain_is_chain: - assumes "law_restrict ` C \ Chains (rel_of (\) \)" shows "\R S. \ R \ C; S \ C \ \ R \ S \ S \ R" + assumes "law_restrict ` C \ Chains (relation_of (\) \)" shows "\R S. \ R \ C; S \ C \ \ R \ S \ S \ R" proof - fix R S assume "R \ C" and "S \ C" thus "R \ S \ S \ R" - using assms(1) unfolding iso_incl_hom[of R] iso_incl_hom[of S] Chains_def by auto + using assms(1) unfolding iso_incl_hom[of R] iso_incl_hom[of S] Chains_def relation_of_def + by auto qed lemma (in field) exists_maximal_extension: shows "\M \ \. \L \ \. M \ L \ L = M" proof (rule predicate_Zorn[OF iso_incl_partial_order]) - show "\C \ Chains (rel_of (\) \). \L \ \. \R \ C. R \ L" - proof - fix C assume C: "C \ Chains (rel_of (\) \)" - show "\L \ \. \R \ C. R \ L" - proof (cases) - assume "C = {}" thus ?thesis - using extensions_non_empty by auto - next - assume "C \ {}" - from \C \ Chains (rel_of (\) \)\ - obtain C' where C': "C' \ extensions" "C = law_restrict ` C'" - using exists_core_chain by auto - with \C \ {}\ obtain S where S: "S \ C'" and "C' \ {}" - by auto + fix C assume C: "C \ Chains (relation_of (\) \)" + show "\L \ \. \R \ C. R \ L" + proof (cases) + assume "C = {}" thus ?thesis + using extensions_non_empty by auto + next + assume "C \ {}" + from \C \ Chains (relation_of (\) \)\ + obtain C' where C': "C' \ extensions" "C = law_restrict ` C'" + using exists_core_chain by auto + with \C \ {}\ obtain S where S: "S \ C'" and "C' \ {}" + by auto - have core_chain: "\R. R \ C' \ field R" "\R S. \ R \ C'; S \ C' \ \ R \ S \ S \ R" - using core_chain_is_chain[of C'] C' C unfolding extensions_def by auto - from \C' \ {}\ interpret Union: field "union_ring C'" - using union_ring_is_field[OF core_chain] C'(1) by blast + have core_chain: "\R. R \ C' \ field R" "\R S. \ R \ C'; S \ C' \ \ R \ S \ S \ R" + using core_chain_is_chain[of C'] C' C unfolding extensions_def by auto + from \C' \ {}\ interpret Union: field "union_ring C'" + using union_ring_is_field[OF core_chain] C'(1) by blast - have "union_ring C' \ extensions" - proof (auto simp add: extensions_def) - show "field (union_ring C')" - using Union.field_axioms . - next - from \S \ C'\ have "indexed_const \ ring_hom R S" - using C'(1) unfolding extensions_def by auto - thus "indexed_const \ ring_hom R (union_ring C')" - using ring_hom_trans[of _ R S id] union_ring_is_upper_bound[OF core_chain S] - unfolding iso_incl.simps by auto - next - show "a \ carrier (union_ring C') \ carrier_coeff a" for a - using C'(1) unfolding union_ring_carrier extensions_def by auto - next - fix \

P - assume "\

\ carrier (union_ring C')" and P: "P \ carrier (poly_ring R)" "\ index_free \

P" - from \\

\ carrier (union_ring C')\ obtain T where T: "T \ C'" "\

\ carrier T" - using exists_superset_carrier[of C' "{ \

}"] core_chain by auto - hence "\\<^bsub>P\<^esub> \ carrier T" and "(ring.eval T) (\ P) \\<^bsub>P\<^esub> = \\<^bsub>T\<^esub>" - and field: "field T" and hom: "indexed_const \ ring_hom R T" - using P C'(1) unfolding extensions_def by auto - with \T \ C'\ show "\\<^bsub>P\<^esub> \ carrier (union_ring C')" - unfolding union_ring_carrier by auto - have "set P \ carrier R" - using P(1) unfolding sym[OF univ_poly_carrier] polynomial_def by auto - hence "set (\ P) \ carrier T" - using ring_hom_memE(1)[OF hom] unfolding \_def by (induct P) (auto) - with \\\<^bsub>P\<^esub> \ carrier T\ and \(ring.eval T) (\ P) \\<^bsub>P\<^esub> = \\<^bsub>T\<^esub>\ - show "(ring.eval (union_ring C')) (\ P) \\<^bsub>P\<^esub> = \\<^bsub>union_ring C'\<^esub>" - using iso_incl_imp_same_eval[OF field.is_ring[OF field] Union.is_ring - union_ring_is_upper_bound[OF core_chain T(1)]] same_one_same_zero(2)[OF core_chain T(1)] - by auto - qed - moreover have "R \ law_restrict (union_ring C')" if "R \ C" for R - using that union_ring_is_upper_bound[OF core_chain] iso_incl_hom unfolding C' by auto - ultimately show ?thesis - by blast + have "union_ring C' \ extensions" + proof (auto simp add: extensions_def) + show "field (union_ring C')" + using Union.field_axioms . + next + from \S \ C'\ have "indexed_const \ ring_hom R S" + using C'(1) unfolding extensions_def by auto + thus "indexed_const \ ring_hom R (union_ring C')" + using ring_hom_trans[of _ R S id] union_ring_is_upper_bound[OF core_chain S] + unfolding iso_incl.simps by auto + next + show "a \ carrier (union_ring C') \ carrier_coeff a" for a + using C'(1) unfolding union_ring_carrier extensions_def by auto + next + fix \

P i + assume "\

\ carrier (union_ring C')" + and P: "P \ carrier (poly_ring R)" + and not_index_free: "\ index_free \

(P, i)" + from \\

\ carrier (union_ring C')\ obtain T where T: "T \ C'" "\

\ carrier T" + using exists_superset_carrier[of C' "{ \

}"] core_chain by auto + hence "\\<^bsub>(P, i)\<^esub> \ carrier T" and "(ring.eval T) (\ P) \\<^bsub>(P, i)\<^esub> = \\<^bsub>T\<^esub>" + and field: "field T" and hom: "indexed_const \ ring_hom R T" + using P not_index_free C'(1) unfolding extensions_def by auto + with \T \ C'\ show "\\<^bsub>(P, i)\<^esub> \ carrier (union_ring C')" + unfolding union_ring_carrier by auto + have "set P \ carrier R" + using P unfolding sym[OF univ_poly_carrier] polynomial_def by auto + hence "set (\ P) \ carrier T" + using ring_hom_memE(1)[OF hom] unfolding \_def by (induct P) (auto) + with \\\<^bsub>(P, i)\<^esub> \ carrier T\ and \(ring.eval T) (\ P) \\<^bsub>(P, i)\<^esub> = \\<^bsub>T\<^esub>\ + show "(ring.eval (union_ring C')) (\ P) \\<^bsub>(P, i)\<^esub> = \\<^bsub>union_ring C'\<^esub>" + using iso_incl_imp_same_eval[OF field.is_ring[OF field] Union.is_ring + union_ring_is_upper_bound[OF core_chain T(1)]] same_one_same_zero(2)[OF core_chain T(1)] + by auto qed + moreover have "R \ law_restrict (union_ring C')" if "R \ C" for R + using that union_ring_is_upper_bound[OF core_chain] iso_incl_hom unfolding C' by auto + ultimately show ?thesis + by blast qed qed @@ -461,11 +468,11 @@ hence "set (map h p) \ carrier S" by (induct p) (auto) moreover have "h a = \\<^bsub>S\<^esub> \ a = \\<^bsub>R\<^esub>" if "a \ carrier R" for a - using non_trivial_field_hom_is_inj[OF assms(1-3)] that unfolding inj_on_def by simp + using non_trivial_field_hom_is_inj[OF assms(1-3)] that unfolding inj_on_def by simp with \set p \ carrier R\ have "lead_coeff (map h p) \ \\<^bsub>S\<^esub>" if "p \ []" using lc[OF that] that by (cases p) (auto) ultimately show ?thesis - unfolding sym[OF univ_poly_carrier] polynomial_def by auto + unfolding sym[OF univ_poly_carrier] polynomial_def by auto qed lemma (in ring_hom_ring) subfield_polynomial_hom: @@ -485,44 +492,1252 @@ using S.univ_poly_consistent[OF subfieldE(1)[OF img_is_subfield(2)[OF assms]]] by simp qed + +(* MOVE ========== *) +subsection \Roots and Multiplicity\ + +definition (in ring) is_root :: "'a list \ 'a \ bool" + where "is_root p x \ (x \ carrier R \ eval p x = \ \ p \ [])" + +definition (in ring) alg_mult :: "'a list \ 'a \ nat" + where "alg_mult p x = + (if p = [] then 0 else + (if x \ carrier R then Greatest (\ n. ([ \, \ x ] [^]\<^bsub>poly_ring R\<^esub> n) pdivides p) else 0))" + +definition (in ring) roots :: "'a list \ 'a multiset" + where "roots p = Abs_multiset (alg_mult p)" + +definition (in ring) roots_on :: "'a set \ 'a list \ 'a multiset" + where "roots_on K p = roots p \# mset_set K" + +definition (in ring) splitted :: "'a list \ bool" + where "splitted p \ size (roots p) = degree p" + +definition (in ring) splitted_on :: "'a set \ 'a list \ bool" + where "splitted_on K p \ size (roots_on K p) = degree p" + +lemma (in domain) polynomial_pow_not_zero: + assumes "p \ carrier (poly_ring R)" and "p \ []" + shows "p [^]\<^bsub>poly_ring R\<^esub> (n::nat) \ []" +proof - + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + from assms UP.integral show ?thesis + unfolding sym[OF univ_poly_zero[of R "carrier R"]] + by (induction n, auto) +qed + +lemma (in domain) subring_polynomial_pow_not_zero: + assumes "subring K R" and "p \ carrier (K[X])" and "p \ []" + shows "p [^]\<^bsub>K[X]\<^esub> (n::nat) \ []" + using domain.polynomial_pow_not_zero[OF subring_is_domain, of K p n] assms + unfolding univ_poly_consistent[OF assms(1)] by simp + +lemma (in domain) polynomial_pow_degree: + assumes "p \ carrier (poly_ring R)" + shows "degree (p [^]\<^bsub>poly_ring R\<^esub> n) = n * degree p" +proof - + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + show ?thesis + proof (induction n) + case 0 thus ?case + using UP.nat_pow_0 unfolding univ_poly_one by auto + next + let ?ppow = "\n. p [^]\<^bsub>poly_ring R\<^esub> n" + case (Suc n) thus ?case + proof (cases "p = []") + case True thus ?thesis + using univ_poly_zero[of R "carrier R"] UP.r_null assms by auto + next + case False + hence "?ppow n \ carrier (poly_ring R)" and "?ppow n \ []" and "p \ []" + using polynomial_pow_not_zero[of p n] assms by (auto simp add: univ_poly_one) + thus ?thesis + using poly_mult_degree_eq[OF carrier_is_subring, of "?ppow n" p] Suc assms + unfolding univ_poly_carrier univ_poly_zero + by (auto simp add: add.commute univ_poly_mult) + qed + qed +qed + +lemma (in domain) polynomial_pow_division: + assumes "p \ carrier (poly_ring R)" and "(n::nat) \ m" + shows "(p [^]\<^bsub>poly_ring R\<^esub> n) pdivides (p [^]\<^bsub>poly_ring R\<^esub> m)" +proof - + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + let ?ppow = "\n. p [^]\<^bsub>poly_ring R\<^esub> n" + + have "?ppow n \\<^bsub>poly_ring R\<^esub> ?ppow k = ?ppow (n + k)" for k + using assms(1) by (simp add: UP.nat_pow_mult) + thus ?thesis + using dividesI[of "?ppow (m - n)" "poly_ring R" "?ppow m" "?ppow n"] assms + unfolding pdivides_def by auto +qed + +lemma (in domain) degree_zero_imp_not_is_root: + assumes "p \ carrier (poly_ring R)" and "degree p = 0" shows "\ is_root p x" +proof (cases "p = []", simp add: is_root_def) + case False with \degree p = 0\ have "length p = Suc 0" + using le_SucE by fastforce + then obtain a where "p = [ a ]" and "a \ carrier R" and "a \ \" + using assms unfolding sym[OF univ_poly_carrier] polynomial_def + by (metis False length_0_conv length_Suc_conv list.sel(1) list.set_sel(1) subset_code(1)) + thus ?thesis + unfolding is_root_def by auto +qed + +lemma (in domain) is_root_imp_pdivides: + assumes "p \ carrier (poly_ring R)" + shows "is_root p x \ [ \, \ x ] pdivides p" +proof - + let ?b = "[ \ , \ x ]" + + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + assume "is_root p x" hence x: "x \ carrier R" and is_root: "eval p x = \" + unfolding is_root_def by auto + hence b: "?b \ carrier (poly_ring R)" + unfolding sym[OF univ_poly_carrier] polynomial_def by auto + then obtain q r where q: "q \ carrier (poly_ring R)" and r: "r \ carrier (poly_ring R)" + and long_divides: "p = (?b \\<^bsub>poly_ring R\<^esub> q) \\<^bsub>poly_ring R\<^esub> r" "r = [] \ degree r < degree ?b" + using long_division_theorem[OF carrier_is_subring, of p ?b] assms by (auto simp add: univ_poly_carrier) + + show ?thesis + proof (cases "r = []") + case True then have "r = \\<^bsub>poly_ring R\<^esub>" + unfolding univ_poly_zero[of R "carrier R"] . + thus ?thesis + using long_divides(1) q r b dividesI[OF q, of p ?b] by (simp add: pdivides_def) + next + case False then have "length r = Suc 0" + using long_divides(2) le_SucE by fastforce + then obtain a where "r = [ a ]" and a: "a \ carrier R" and "a \ \" + using r unfolding sym[OF univ_poly_carrier] polynomial_def + by (metis False length_0_conv length_Suc_conv list.sel(1) list.set_sel(1) subset_code(1)) + + have "eval p x = ((eval ?b x) \ (eval q x)) \ (eval r x)" + using long_divides(1) ring_hom_memE[OF eval_is_hom[OF carrier_is_subring x]] by (simp add: b q r) + also have " ... = eval r x" + using ring_hom_memE[OF eval_is_hom[OF carrier_is_subring x]] x b q r by (auto, algebra) + finally have "a = \" + using a unfolding \r = [ a ]\ is_root by simp + with \a \ \\ have False .. thus ?thesis .. + qed +qed + +lemma (in domain) pdivides_imp_is_root: + assumes "p \ []" and "x \ carrier R" + shows "[ \, \ x ] pdivides p \ is_root p x" +proof - + assume "[ \, \ x ] pdivides p" + then obtain q where q: "q \ carrier (poly_ring R)" and pdiv: "p = [ \, \ x ] \\<^bsub>poly_ring R\<^esub> q" + unfolding pdivides_def by auto + moreover have "[ \, \ x ] \ carrier (poly_ring R)" + using assms(2) unfolding sym[OF univ_poly_carrier] polynomial_def by simp + ultimately have "eval p x = \" + using ring_hom_memE[OF eval_is_hom[OF carrier_is_subring, of x]] assms(2) by (auto, algebra) + with \p \ []\ and \x \ carrier R\ show "is_root p x" + unfolding is_root_def by simp +qed + +(* MOVE TO Polynomial_Dvisibility.thy ================== *) +lemma (in domain) associated_polynomials_imp_same_length: (* stronger than "imp_same_degree" *) + assumes "subring K R" and "p \ carrier (K[X])" and "q \ carrier (K[X])" + shows "p \\<^bsub>K[X]\<^esub> q \ length p = length q" +proof - + { fix p q + assume p: "p \ carrier (K[X])" and q: "q \ carrier (K[X])" and "p \\<^bsub>K[X]\<^esub> q" + have "length p \ length q" + proof (cases "q = []") + case True with \p \\<^bsub>K[X]\<^esub> q\ have "p = []" + unfolding associated_def True factor_def univ_poly_def by auto + thus ?thesis + using True by simp + next + case False + from \p \\<^bsub>K[X]\<^esub> q\ have "p divides\<^bsub>K [X]\<^esub> q" + unfolding associated_def by simp + hence "p divides\<^bsub>poly_ring R\<^esub> q" + using carrier_polynomial[OF assms(1)] + unfolding factor_def univ_poly_carrier univ_poly_mult by auto + with \q \ []\ have "degree p \ degree q" + using pdivides_imp_degree_le[OF assms(1) p q] unfolding pdivides_def by simp + with \q \ []\ show ?thesis + by (cases "p = []", auto simp add: Suc_leI le_diff_iff) + qed + } note aux_lemma = this + + interpret UP: domain "K[X]" + using univ_poly_is_domain[OF assms(1)] . + + assume "p \\<^bsub>K[X]\<^esub> q" thus ?thesis + using aux_lemma[OF assms(2-3)] aux_lemma[OF assms(3,2) UP.associated_sym] by simp +qed +(* ================================================= *) + +lemma (in domain) associated_polynomials_imp_same_is_root: + assumes "p \ carrier (poly_ring R)" and "q \ carrier (poly_ring R)" and "p \\<^bsub>poly_ring R\<^esub> q" + shows "is_root p x \ is_root q x" +proof (cases "p = []") + case True with \p \\<^bsub>poly_ring R\<^esub> q\ have "q = []" + unfolding associated_def True factor_def univ_poly_def by auto + thus ?thesis + using True unfolding is_root_def by simp +next + case False + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + { fix p q + assume p: "p \ carrier (poly_ring R)" and q: "q \ carrier (poly_ring R)" and pq: "p \\<^bsub>poly_ring R\<^esub> q" + have "is_root p x \ is_root q x" + proof - + assume is_root: "is_root p x" + then have "[ \, \ x ] pdivides p" and "p \ []" and "x \ carrier R" + using is_root_imp_pdivides[OF p] unfolding is_root_def by auto + moreover have "[ \, \ x ] \ carrier (poly_ring R)" + using is_root unfolding is_root_def sym[OF univ_poly_carrier] polynomial_def by simp + ultimately have "[ \, \ x ] pdivides q" + using UP.divides_cong_r[OF _ pq ] unfolding pdivides_def by simp + with \p \ []\ and \x \ carrier R\ show ?thesis + using associated_polynomials_imp_same_length[OF carrier_is_subring p q pq] + pdivides_imp_is_root[of q x] + by fastforce + qed + } + + then show ?thesis + using assms UP.associated_sym[OF assms(3)] by blast +qed + +lemma (in ring) monic_degree_one_root_condition: + assumes "a \ carrier R" shows "is_root [ \, \ a ] b \ a = b" + using assms minus_equality r_neg[OF assms] unfolding is_root_def by (auto, fastforce) + +lemma (in field) degree_one_root_condition: + assumes "p \ carrier (poly_ring R)" and "degree p = 1" + shows "is_root p x \ x = \ (inv (lead_coeff p) \ (const_term p))" +proof - + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + from \degree p = 1\ have "length p = Suc (Suc 0)" + by simp + then obtain a b where p: "p = [ a, b ]" + by (metis length_0_conv length_Cons list.exhaust nat.inject) + hence a: "a \ carrier R" "a \ \" and b: "b \ carrier R" + using assms(1) unfolding sym[OF univ_poly_carrier] polynomial_def by auto + hence inv_a: "inv a \ carrier R" "(inv a) \ a = \" + using subfield_m_inv[OF carrier_is_subfield, of a] by auto + hence in_carrier: "[ \, (inv a) \ b ] \ carrier (poly_ring R)" + using b unfolding sym[OF univ_poly_carrier] polynomial_def by auto + + have "p \\<^bsub>poly_ring R\<^esub> [ \, (inv a) \ b ]" + proof (rule UP.associatedI2'[OF _ _ in_carrier, of _ "[ a ]"]) + have "p = [ a ] \\<^bsub>poly_ring R\<^esub> [ \, inv a \ b ]" + using a inv_a b m_assoc[of a "inv a" b] unfolding p univ_poly_mult by (auto, algebra) + also have " ... = [ \, inv a \ b ] \\<^bsub>poly_ring R\<^esub> [ a ]" + using UP.m_comm[OF in_carrier, of "[ a ]"] a + by (auto simp add: sym[OF univ_poly_carrier] polynomial_def) + finally show "p = [ \, inv a \ b ] \\<^bsub>poly_ring R\<^esub> [ a ]" . + next + from \a \ carrier R\ and \a \ \\ show "[ a ] \ Units (poly_ring R)" + unfolding univ_poly_units[OF carrier_is_subfield] by simp + qed + + moreover have "(inv a) \ b = \ (\ (inv (lead_coeff p) \ (const_term p)))" + and "inv (lead_coeff p) \ (const_term p) \ carrier R" + using inv_a a b unfolding p const_term_def by auto + + ultimately show ?thesis + using associated_polynomials_imp_same_is_root[OF assms(1) in_carrier] + monic_degree_one_root_condition + by (metis add.inv_closed) +qed + +lemma (in domain) is_root_imp_is_root_poly_mult: + assumes "p \ carrier (poly_ring R)" and "q \ carrier (poly_ring R)" and "q \ []" + shows "is_root p x \ is_root (p \\<^bsub>poly_ring R\<^esub> q) x" +proof - + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + assume "is_root p x" then have x: "x \ carrier R" and eval: "eval p x = \" and not_zero: "p \ []" + unfolding is_root_def by simp+ + hence "p \\<^bsub>poly_ring R\<^esub> q \ []" + using assms UP.integral unfolding sym[OF univ_poly_zero[of R "carrier R"]] by blast + moreover have "eval (p \\<^bsub>poly_ring R\<^esub> q) x = \" + using assms eval ring_hom_memE[OF eval_is_hom[OF carrier_is_subring x]] by auto + ultimately show ?thesis + using x unfolding is_root_def by simp +qed + +lemma (in domain) is_root_poly_mult_imp_is_root: + assumes "p \ carrier (poly_ring R)" and "q \ carrier (poly_ring R)" + shows "is_root (p \\<^bsub>poly_ring R\<^esub> q) x \ (is_root p x) \ (is_root q x)" +proof - + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + assume is_root: "is_root (p \\<^bsub>poly_ring R\<^esub> q) x" + hence "p \ []" and "q \ []" + unfolding is_root_def sym[OF univ_poly_zero[of R "carrier R"]] + using UP.l_null[OF assms(2)] UP.r_null[OF assms(1)] by blast+ + moreover have x: "x \ carrier R" and "eval (p \\<^bsub>poly_ring R\<^esub> q) x = \" + using is_root unfolding is_root_def by simp+ + hence "eval p x = \ \ eval q x = \" + using ring_hom_memE[OF eval_is_hom[OF carrier_is_subring], of x] assms integral by auto + ultimately show "(is_root p x) \ (is_root q x)" + using x unfolding is_root_def by auto +qed + +(* +lemma (in domain) + assumes "subfield K R" and "p \ carrier (K[X])" and "degree p = 1" + shows "pprime K p" +proof (rule pprimeI[OF assms(1-2)]) + from \degree p = 1\ show "p \ []" and "p \ Units (K [X])" + unfolding univ_poly_units[OF assms(1)] by auto +next + fix q r + assume "q \ carrier (K[X])" and "r \ carrier (K[X])" + and pdiv: "p pdivides q \\<^bsub>K [X]\<^esub> r" + hence "q \ carrier (poly_ring R)" and "r \ carrier (poly_ring R)" + using carrier_polynomial_shell[OF subfieldE(1)[OF assms(1)]] by auto + moreover obtain b where b: "b \" +qed +*) + +lemma (in domain) finite_number_of_roots: + assumes "p \ carrier (poly_ring R)" shows "finite { x. is_root p x }" + using assms +proof (induction "degree p" arbitrary: p) + case 0 thus ?case + by (simp add: degree_zero_imp_not_is_root) +next + case (Suc n) show ?case + proof (cases "{ x. is_root p x } = {}") + case True thus ?thesis + by (simp add: True) + next + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + case False + then obtain a where is_root: "is_root p a" + by blast + hence a: "a \ carrier R" and eval: "eval p a = \" and p_not_zero: "p \ []" + unfolding is_root_def by auto + hence in_carrier: "[ \, \ a ] \ carrier (poly_ring R)" + unfolding sym[OF univ_poly_carrier] polynomial_def by auto + + obtain q where q: "q \ carrier (poly_ring R)" and p: "p = [ \, \ a ] \\<^bsub>poly_ring R\<^esub> q" + using is_root_imp_pdivides[OF Suc(3) is_root] unfolding pdivides_def by auto + with \p \ []\ have q_not_zero: "q \ []" + using UP.r_null UP.integral in_carrier unfolding sym[OF univ_poly_zero[of R "carrier R"]] + by metis + hence "degree q = n" + using poly_mult_degree_eq[OF carrier_is_subring, of "[ \, \ a ]" q] + in_carrier q p_not_zero p Suc(2) + unfolding univ_poly_carrier + by (metis One_nat_def Suc_eq_plus1 diff_Suc_1 list.distinct(1) + list.size(3-4) plus_1_eq_Suc univ_poly_mult) + hence "finite { x. is_root q x }" + using Suc(1)[OF _ q] by simp + + moreover have "{ x. is_root p x } \ insert a { x. is_root q x }" + using is_root_poly_mult_imp_is_root[OF in_carrier q] + monic_degree_one_root_condition[OF a] + unfolding p by auto + + ultimately show ?thesis + using finite_subset by auto + qed +qed + +lemma (in domain) alg_multE: + assumes "x \ carrier R" and "p \ carrier (poly_ring R)" and "p \ []" + shows "([ \, \ x ] [^]\<^bsub>poly_ring R\<^esub> (alg_mult p x)) pdivides p" + and "\n. ([ \, \ x ] [^]\<^bsub>poly_ring R\<^esub> n) pdivides p \ n \ alg_mult p x" +proof - + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + let ?ppow = "\n :: nat. ([ \, \ x ] [^]\<^bsub>poly_ring R\<^esub> n)" + + define S :: "nat set" where "S = { n. ?ppow n pdivides p }" + have "?ppow 0 = \\<^bsub>poly_ring R\<^esub>" + using UP.nat_pow_0 by simp + hence "0 \ S" + using UP.one_divides[OF assms(2)] unfolding S_def pdivides_def by simp + hence "S \ {}" + by auto + + moreover have "n \ degree p" if "n \ S" for n :: nat + proof - + have "[ \, \ x ] \ carrier (poly_ring R)" + using assms unfolding sym[OF univ_poly_carrier] polynomial_def by auto + hence "?ppow n \ carrier (poly_ring R)" + using assms unfolding univ_poly_zero by auto + with \n \ S\ have "degree (?ppow n) \ degree p" + using pdivides_imp_degree_le[OF carrier_is_subring _ assms(2-3), of "?ppow n"] by (simp add: S_def) + with \[ \, \ x ] \ carrier (poly_ring R)\ show ?thesis + using polynomial_pow_degree by simp + qed + hence "finite S" + using finite_nat_set_iff_bounded_le by blast + + ultimately have MaxS: "\n. n \ S \ n \ Max S" "Max S \ S" + using Max_ge[of S] Max_in[of S] by auto + with \x \ carrier R\ have "alg_mult p x = Max S" + using Greatest_equality[of "\n. ?ppow n pdivides p" "Max S"] assms(3) + unfolding S_def alg_mult_def by auto + thus "([ \, \ x ] [^]\<^bsub>poly_ring R\<^esub> (alg_mult p x)) pdivides p" + and "\n. ([ \, \ x ] [^]\<^bsub>poly_ring R\<^esub> n) pdivides p \ n \ alg_mult p x" + using MaxS unfolding S_def by auto +qed + +lemma (in domain) le_alg_mult_imp_pdivides: + assumes "x \ carrier R" and "p \ carrier (poly_ring R)" + shows "n \ alg_mult p x \ ([ \, \ x ] [^]\<^bsub>poly_ring R\<^esub> n) pdivides p" +proof - + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + assume le_alg_mult: "n \ alg_mult p x" + have in_carrier: "[ \, \ x ] \ carrier (poly_ring R)" + using assms(1) unfolding sym[OF univ_poly_carrier] polynomial_def by auto + hence ppow_pdivides: + "([ \, \ x ] [^]\<^bsub>poly_ring R\<^esub> n) pdivides + ([ \, \ x ] [^]\<^bsub>poly_ring R\<^esub> (alg_mult p x))" + using polynomial_pow_division[OF _ le_alg_mult] by simp + + show ?thesis + proof (cases "p = []") + case True thus ?thesis + using in_carrier pdivides_zero[OF carrier_is_subring] by auto + next + case False thus ?thesis + using ppow_pdivides UP.divides_trans UP.nat_pow_closed alg_multE(1)[OF assms] in_carrier + unfolding pdivides_def by meson + qed +qed + +lemma (in domain) alg_mult_gt_zero_iff_is_root: + assumes "p \ carrier (poly_ring R)" shows "alg_mult p x > 0 \ is_root p x" +proof - + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + show ?thesis + proof + assume is_root: "is_root p x" hence x: "x \ carrier R" and not_zero: "p \ []" + unfolding is_root_def by auto + have "[\, \ x] [^]\<^bsub>poly_ring R\<^esub> (Suc 0) = [\, \ x]" + using x unfolding univ_poly_def by auto + thus "alg_mult p x > 0" + using is_root_imp_pdivides[OF _ is_root] alg_multE(2)[OF x, of p "Suc 0"] not_zero assms by auto + next + assume gt_zero: "alg_mult p x > 0" + hence x: "x \ carrier R" and not_zero: "p \ []" + unfolding alg_mult_def by (cases "p = []", auto, cases "x \ carrier R", auto) + hence in_carrier: "[ \, \ x ] \ carrier (poly_ring R)" + unfolding sym[OF univ_poly_carrier] polynomial_def by auto + with \x \ carrier R\ have "[ \, \ x ] pdivides p" and "eval [ \, \ x ] x = \" + using le_alg_mult_imp_pdivides[of x p "1::nat"] gt_zero assms by (auto, algebra) + thus "is_root p x" + using pdivides_imp_root_sharing[OF in_carrier] not_zero x by (simp add: is_root_def) + qed +qed + +lemma (in domain) alg_mult_in_multiset: + assumes "p \ carrier (poly_ring R)" shows "alg_mult p \ multiset" + using assms alg_mult_gt_zero_iff_is_root finite_number_of_roots unfolding multiset_def by auto + +lemma (in domain) alg_mult_eq_count_roots: + assumes "p \ carrier (poly_ring R)" shows "alg_mult p = count (roots p)" + using alg_mult_in_multiset[OF assms] by (simp add: roots_def) + +lemma (in domain) roots_mem_iff_is_root: + assumes "p \ carrier (poly_ring R)" shows "x \# roots p \ is_root p x" + using alg_mult_eq_count_roots[OF assms] count_greater_zero_iff + unfolding roots_def sym[OF alg_mult_gt_zero_iff_is_root[OF assms]] by metis + +lemma (in domain) degree_zero_imp_empty_roots: + assumes "p \ carrier (poly_ring R)" and "degree p = 0" shows "roots p = {#}" +proof - + have "alg_mult p = (\x. 0)" + proof (cases "p = []") + case True thus ?thesis + using assms unfolding alg_mult_def by auto + next + case False hence "length p = Suc 0" + using assms(2) by (simp add: le_Suc_eq) + then obtain a where "a \ carrier R" and "a \ \" and p: "p = [ a ]" + using assms(1) unfolding sym[OF univ_poly_carrier] polynomial_def + by (metis Suc_length_conv hd_in_set length_0_conv list.sel(1) subset_code(1)) + show ?thesis + proof (rule ccontr) + assume "alg_mult p \ (\x. 0)" + then obtain x where "alg_mult p x > 0" + by auto + with \p \ []\ have "eval p x = \" + using alg_mult_gt_zero_iff_is_root[OF assms(1), of x] unfolding is_root_def by simp + with \a \ carrier R\ have "a = \" + unfolding p by auto + with \a \ \\ show False .. + qed + qed + thus ?thesis + by (simp add: roots_def zero_multiset.abs_eq) +qed + +lemma (in domain) degree_zero_imp_splitted: + assumes "p \ carrier (poly_ring R)" and "degree p = 0" shows "splitted p" + unfolding splitted_def degree_zero_imp_empty_roots[OF assms] assms(2) by simp + +lemma (in domain) roots_inclI': + assumes "p \ carrier (poly_ring R)" and "\a. \ a \ carrier R; p \ [] \ \ alg_mult p a \ count m a" + shows "roots p \# m" +proof (intro mset_subset_eqI) + fix a show "count (roots p) a \ count m a" + using assms unfolding sym[OF alg_mult_eq_count_roots[OF assms(1)]] alg_mult_def + by (cases "p = []", simp, cases "a \ carrier R", auto) +qed + +lemma (in domain) roots_inclI: + assumes "p \ carrier (poly_ring R)" and "q \ carrier (poly_ring R)" "q \ []" + and "\a. \ a \ carrier R; p \ [] \ \ ([ \, \ a ] [^]\<^bsub>poly_ring R\<^esub> (alg_mult p a)) pdivides q" + shows "roots p \# roots q" + using roots_inclI'[OF assms(1), of "roots q"] assms alg_multE(2)[OF _ assms(2-3)] + unfolding sym[OF alg_mult_eq_count_roots[OF assms(2)]] by auto + +lemma (in domain) pdivides_imp_roots_incl: + assumes "p \ carrier (poly_ring R)" and "q \ carrier (poly_ring R)" "q \ []" + shows "p pdivides q \ roots p \# roots q" +proof (rule roots_inclI[OF assms]) + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + fix a assume "p pdivides q" and a: "a \ carrier R" + hence "[ \ , \ a ] \ carrier (poly_ring R)" + unfolding sym[OF univ_poly_carrier] polynomial_def by simp + with \p pdivides q\ show "([\, \ a] [^]\<^bsub>poly_ring R\<^esub> (alg_mult p a)) pdivides q" + using UP.divides_trans[of _p q] le_alg_mult_imp_pdivides[OF a assms(1)] + by (auto simp add: pdivides_def) +qed + +lemma (in domain) associated_polynomials_imp_same_roots: + assumes "p \ carrier (poly_ring R)" and "q \ carrier (poly_ring R)" and "p \\<^bsub>poly_ring R\<^esub> q" + shows "roots p = roots q" + using assms pdivides_imp_roots_incl zero_pdivides + unfolding pdivides_def associated_def + by (metis subset_mset.eq_iff) + +(* MOVE to Polynomial_Divisibility.thy *) +lemma (in comm_monoid_cancel) prime_pow_divides_iff: + assumes "p \ carrier G" "a \ carrier G" "b \ carrier G" and "prime G p" and "\ (p divides a)" + shows "(p [^] (n :: nat)) divides (a \ b) \ (p [^] n) divides b" +proof + assume "(p [^] n) divides b" thus "(p [^] n) divides (a \ b)" + using divides_prod_l[of "p [^] n" b a] assms by simp +next + assume "(p [^] n) divides (a \ b)" thus "(p [^] n) divides b" + proof (induction n) + case 0 with \b \ carrier G\ show ?case + by (simp add: unit_divides) + next + case (Suc n) + hence "(p [^] n) divides (a \ b)" and "(p [^] n) divides b" + using assms(1) divides_prod_r by auto + with \(p [^] (Suc n)) divides (a \ b)\ obtain c d + where c: "c \ carrier G" and "b = (p [^] n) \ c" + and d: "d \ carrier G" and "a \ b = (p [^] (Suc n)) \ d" + using assms by blast + hence "(p [^] n) \ (a \ c) = (p [^] n) \ (p \ d)" + using assms by (simp add: m_assoc m_lcomm) + hence "a \ c = p \ d" + using c d assms(1) assms(2) l_cancel by blast + with \\ (p divides a)\ and \prime G p\ have "p divides c" + by (metis assms(2) c d dividesI' prime_divides) + with \b = (p [^] n) \ c\ show ?case + using assms(1) c by simp + qed +qed + +(* MOVE to Polynomial_Divisibility.thy *) +lemma (in domain) pirreducible_pow_pdivides_iff: + assumes "subfield K R" "p \ carrier (K[X])" "q \ carrier (K[X])" "r \ carrier (K[X])" + and "pirreducible K p" and "\ (p pdivides q)" + shows "(p [^]\<^bsub>K[X]\<^esub> (n :: nat)) pdivides (q \\<^bsub>K[X]\<^esub> r) \ (p [^]\<^bsub>K[X]\<^esub> n) pdivides r" +proof - + interpret UP: principal_domain "K[X]" + using univ_poly_is_principal[OF assms(1)] . + show ?thesis + proof (cases "r = []") + case True with \q \ carrier (K[X])\ have "q \\<^bsub>K[X]\<^esub> r = []" and "r = []" + unfolding sym[OF univ_poly_zero[of R K]] by auto + thus ?thesis + using pdivides_zero[OF subfieldE(1),of K] assms by auto + next + case False then have not_zero: "p \ []" "q \ []" "r \ []" "q \\<^bsub>K[X]\<^esub> r \ []" + using subfieldE(1) pdivides_zero[OF _ assms(2)] assms(1-2,5-6) pirreducibleE(1) + UP.integral_iff[OF assms(3-4)] univ_poly_zero[of R K] by auto + from \p \ []\ + have ppow: "p [^]\<^bsub>K[X]\<^esub> (n :: nat) \ []" "p [^]\<^bsub>K[X]\<^esub> (n :: nat) \ carrier (K[X])" + using subring_polynomial_pow_not_zero[OF subfieldE(1)] assms(1-2) by auto + have not_pdiv: "\ (p divides\<^bsub>mult_of (K[X])\<^esub> q)" + using assms(6) pdivides_iff_shell[OF assms(1-3)] unfolding pdivides_def by auto + have prime: "prime (mult_of (K[X])) p" + using assms(5) pprime_iff_pirreducible[OF assms(1-2)] + unfolding sym[OF UP.prime_eq_prime_mult[OF assms(2)]] ring_prime_def by simp + have "a pdivides b \ a divides\<^bsub>mult_of (K[X])\<^esub> b" + if "a \ carrier (K[X])" "a \ \\<^bsub>K[X]\<^esub>" "b \ carrier (K[X])" "b \ \\<^bsub>K[X]\<^esub>" for a b + using that UP.divides_imp_divides_mult[of a b] divides_mult_imp_divides[of "K[X]" a b] + unfolding pdivides_iff_shell[OF assms(1) that(1,3)] by blast + thus ?thesis + using UP.mult_of.prime_pow_divides_iff[OF _ _ _ prime not_pdiv, of r] ppow not_zero assms(2-4) + unfolding nat_pow_mult_of carrier_mult_of mult_mult_of sym[OF univ_poly_zero[of R K]] + by (metis DiffI UP.m_closed singletonD) + qed +qed + +(* MOVE to Polynomial_Divisibility.thy *) +lemma (in domain) univ_poly_units': + assumes "subfield K R" shows "p \ Units (K[X]) \ p \ carrier (K[X]) \ p \ [] \ degree p = 0" + unfolding univ_poly_units[OF assms] sym[OF univ_poly_carrier] polynomial_def + by (auto, metis hd_in_set le_0_eq le_Suc_eq length_0_conv length_Suc_conv list.sel(1) subsetD) + +(* MOVE to Polynomial_Divisibility.thy *) +lemma (in domain) subring_degree_one_imp_pirreducible: + assumes "subring K R" and "a \ Units (R \ carrier := K \)" and "b \ K" + shows "pirreducible K [ a, b ]" +proof (rule pirreducibleI[OF assms(1)]) + have "a \ K" and "a \ \" + using assms(2) subringE(1)[OF assms(1)] unfolding Units_def by auto + thus "[ a, b ] \ carrier (K[X])" and "[ a, b ] \ []" and "[ a, b ] \ Units (K [X])" + using univ_poly_units_incl[OF assms(1)] assms(2-3) + unfolding sym[OF univ_poly_carrier] polynomial_def by auto +next + interpret UP: domain "K[X]" + using univ_poly_is_domain[OF assms(1)] . + + { fix q r + assume q: "q \ carrier (K[X])" and r: "r \ carrier (K[X])" and "[ a, b ] = q \\<^bsub>K[X]\<^esub> r" + hence not_zero: "q \ []" "r \ []" + by (metis UP.integral_iff list.distinct(1) univ_poly_zero)+ + have "degree (q \\<^bsub>K[X]\<^esub> r) = degree q + degree r" + using not_zero poly_mult_degree_eq[OF assms(1)] q r + by (simp add: univ_poly_carrier univ_poly_mult) + with sym[OF \[ a, b ] = q \\<^bsub>K[X]\<^esub> r\] have "degree q + degree r = 1" and "q \ []" "r \ []" + using not_zero by auto + } note aux_lemma1 = this + + { fix q r + assume q: "q \ carrier (K[X])" "q \ []" and r: "r \ carrier (K[X])" "r \ []" + and "[ a, b ] = q \\<^bsub>K[X]\<^esub> r" and "degree q = 1" and "degree r = 0" + hence "length q = Suc (Suc 0)" and "length r = Suc 0" + by (linarith, metis add.right_neutral add_eq_if length_0_conv) + from \length q = Suc (Suc 0)\ obtain c d where q_def: "q = [ c, d ]" + by (metis length_0_conv length_Cons list.exhaust nat.inject) + from \length r = Suc 0\ obtain e where r_def: "r = [ e ]" + by (metis length_0_conv length_Suc_conv) + from \r = [ e ]\ and \q = [ c, d ]\ + have c: "c \ K" "c \ \" and d: "d \ K" and e: "e \ K" "e \ \" + using r q subringE(1)[OF assms(1)] unfolding sym[OF univ_poly_carrier] polynomial_def by auto + with sym[OF \[ a, b ] = q \\<^bsub>K[X]\<^esub> r\] have "a = c \ e" + using poly_mult_lead_coeff[OF assms(1), of q r] + unfolding polynomial_def sym[OF univ_poly_mult[of R K]] r_def q_def by auto + obtain inv_a where a: "a \ K" and inv_a: "inv_a \ K" "a \ inv_a = \" "inv_a \ a = \" + using assms(2) unfolding Units_def by auto + hence "a \ \" and "inv_a \ \" + using subringE(1)[OF assms(1)] integral_iff by auto + with \c \ K\ and \c \ \\ have in_carrier: "[ c \ inv_a ] \ carrier (K[X])" + using subringE(1,6)[OF assms(1)] inv_a integral + unfolding sym[OF univ_poly_carrier] polynomial_def + by (auto, meson subsetD) + moreover have "[ c \ inv_a ] \\<^bsub>K[X]\<^esub> r = [ \ ]" + using \a = c \ e\ a inv_a c e subsetD[OF subringE(1)[OF assms(1)]] + unfolding r_def univ_poly_mult by (auto) (simp add: m_assoc m_lcomm integral_iff)+ + ultimately have "r \ Units (K[X])" + using r(1) UP.m_comm[OF in_carrier r(1)] unfolding sym[OF univ_poly_one[of R K]] Units_def by auto + } note aux_lemma2 = this + + fix q r + assume q: "q \ carrier (K[X])" and r: "r \ carrier (K[X])" and qr: "[ a, b ] = q \\<^bsub>K[X]\<^esub> r" + thus "q \ Units (K[X]) \ r \ Units (K[X])" + using aux_lemma1[OF q r qr] aux_lemma2[of q r] aux_lemma2[of r q] UP.m_comm add_is_1 by auto +qed + +(* MOVE to Polynomial_Divisibility.thy *) +lemma (in domain) degree_one_imp_pirreducible: + assumes "subfield K R" and "p \ carrier (K[X])" and "degree p = 1" + shows "pirreducible K p" +proof - + from \degree p = 1\ have "length p = Suc (Suc 0)" + by simp + then obtain a b where p: "p = [ a, b ]" + by (metis length_0_conv length_Suc_conv) + with \p \ carrier (K[X])\ show ?thesis + using subring_degree_one_imp_pirreducible[OF subfieldE(1)[OF assms(1)], of a b] + subfield.subfield_Units[OF assms(1)] + unfolding sym[OF univ_poly_carrier] polynomial_def by auto +qed + +(* MOVE to Polynomial_Divisibility.thy *) +lemma (in ring) degree_oneE[elim]: + assumes "p \ carrier (K[X])" and "degree p = 1" + and "\a b. \ a \ K; a \ \; b \ K; p = [ a, b ] \ \ P" + shows P +proof - + from \degree p = 1\ have "length p = Suc (Suc 0)" + by simp + then obtain a b where "p = [ a, b ]" + by (metis length_0_conv length_Cons nat.inject neq_Nil_conv) + with \p \ carrier (K[X])\ have "a \ K" and "a \ \" and "b \ K" + unfolding sym[OF univ_poly_carrier] polynomial_def by auto + with \p = [ a, b ]\ show ?thesis + using assms(3) by simp +qed + +(* MOVE to Polynomial_Divisibility.thy *) +lemma (in domain) subring_degree_one_associatedI: + assumes "subring K R" and "a \ K" "a' \ K" and "b \ K" and "a \ a' = \" + shows "[ a , b ] \\<^bsub>K[X]\<^esub> [ \, a' \ b ]" +proof - + from \a \ a' = \\ have not_zero: "a \ \" "a' \ \" + using subringE(1)[OF assms(1)] assms(2-3) by auto + hence "[ a, b ] = [ a ] \\<^bsub>K[X]\<^esub> [ \, a' \ b ]" + using assms(2-4)[THEN subsetD[OF subringE(1)[OF assms(1)]]] assms(5) m_assoc + unfolding univ_poly_mult by fastforce + moreover have "[ a, b ] \ carrier (K[X])" and "[ \, a' \ b ] \ carrier (K[X])" + using subringE(1,3,6)[OF assms(1)] not_zero one_not_zero assms + unfolding sym[OF univ_poly_carrier] polynomial_def by auto + moreover have "[ a ] \ Units (K[X])" + proof - + from \a \ \\ and \a' \ \\ have "[ a ] \ carrier (K[X])" and "[ a' ] \ carrier (K[X])" + using assms(2-3) unfolding sym[OF univ_poly_carrier] polynomial_def by auto + moreover have "a' \ a = \" + using subsetD[OF subringE(1)[OF assms(1)]] assms m_comm by simp + hence "[ a ] \\<^bsub>K[X]\<^esub> [ a' ] = [ \ ]" and "[ a' ] \\<^bsub>K[X]\<^esub> [ a ] = [ \ ]" + using assms unfolding univ_poly_mult by auto + ultimately show ?thesis + unfolding sym[OF univ_poly_one[of R K]] Units_def by blast + qed + ultimately show ?thesis + using domain.ring_associated_iff[OF univ_poly_is_domain[OF assms(1)]] by blast +qed + +(* MOVE to Polynomial_Divisibility.thy *) +lemma (in domain) degree_one_associatedI: + assumes "subfield K R" and "p \ carrier (K[X])" and "degree p = 1" + shows "p \\<^bsub>K[X]\<^esub> [ \, inv (lead_coeff p) \ (const_term p) ]" +proof - + from \p \ carrier (K[X])\ and \degree p = 1\ + obtain a b where "p = [ a, b ]" and "a \ K" "a \ \" and "b \ K" + by auto + thus ?thesis + using subring_degree_one_associatedI[OF subfieldE(1)[OF assms(1)]] + subfield_m_inv[OF assms(1)] subsetD[OF subfieldE(3)[OF assms(1)]] + unfolding const_term_def + by auto +qed + +lemma (in domain) monic_degree_one_roots: + assumes "a \ carrier R" shows "roots [ \ , \ a ] = {# a #}" +proof - + let ?p = "[ \ , \ a ]" + + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + from \a \ carrier R\ have in_carrier: "?p \ carrier (poly_ring R)" + unfolding sym[OF univ_poly_carrier] polynomial_def by simp + show ?thesis + proof (rule subset_mset.antisym) + show "{# a #} \# roots ?p" + using roots_mem_iff_is_root[OF in_carrier] + monic_degree_one_root_condition[OF assms] + by simp + next + show "roots ?p \# {# a #}" + proof (rule mset_subset_eqI, auto) + fix b assume "a \ b" thus "count (roots ?p) b = 0" + using alg_mult_gt_zero_iff_is_root[OF in_carrier] + monic_degree_one_root_condition[OF assms] + unfolding sym[OF alg_mult_eq_count_roots[OF in_carrier]] + by fastforce + next + have "(?p [^]\<^bsub>poly_ring R\<^esub> (alg_mult ?p a)) pdivides ?p" + using le_alg_mult_imp_pdivides[OF assms in_carrier] by simp + hence "degree (?p [^]\<^bsub>poly_ring R\<^esub> (alg_mult ?p a)) \ degree ?p" + using pdivides_imp_degree_le[OF carrier_is_subring, of _ ?p] in_carrier by auto + thus "count (roots ?p) a \ Suc 0" + using polynomial_pow_degree[OF in_carrier] + unfolding sym[OF alg_mult_eq_count_roots[OF in_carrier]] + by auto + qed + qed +qed + +lemma (in domain) degree_one_roots: + assumes "a \ carrier R" "a' \ carrier R" and "b \ carrier R" and "a \ a' = \" + shows "roots [ a , b ] = {# \ (a' \ b) #}" +proof - + have "[ a, b ] \ carrier (poly_ring R)" and "[ \, a' \ b ] \ carrier (poly_ring R)" + using assms unfolding sym[OF univ_poly_carrier] polynomial_def by auto + thus ?thesis + using subring_degree_one_associatedI[OF carrier_is_subring assms] assms + monic_degree_one_roots associated_polynomials_imp_same_roots + by (metis add.inv_closed local.minus_minus m_closed) +qed + +lemma (in field) degree_one_imp_singleton_roots: + assumes "p \ carrier (poly_ring R)" and "degree p = 1" + shows "roots p = {# \ (inv (lead_coeff p) \ (const_term p)) #}" +proof - + from \p \ carrier (poly_ring R)\ and \degree p = 1\ + obtain a b where "p = [ a, b ]" and "a \ carrier R" "a \ \" and "b \ carrier R" + by auto + thus ?thesis + using degree_one_roots[of a "inv a" b] + by (auto simp add: const_term_def field_Units) +qed + +lemma (in field) degree_one_imp_splitted: + assumes "p \ carrier (poly_ring R)" and "degree p = 1" shows "splitted p" + using degree_one_imp_singleton_roots[OF assms] assms(2) unfolding splitted_def by simp + +lemma (in field) no_roots_imp_same_roots: + assumes "p \ carrier (poly_ring R)" "p \ []" and "q \ carrier (poly_ring R)" + shows "roots p = {#} \ roots (p \\<^bsub>poly_ring R\<^esub> q) = roots q" +proof - + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + assume no_roots: "roots p = {#}" show "roots (p \\<^bsub>poly_ring R\<^esub> q) = roots q" + proof (intro subset_mset.antisym) + have pdiv: "q pdivides (p \\<^bsub>poly_ring R\<^esub> q)" + using UP.divides_prod_l assms unfolding pdivides_def by blast + show "roots q \# roots (p \\<^bsub>poly_ring R\<^esub> q)" + using pdivides_imp_roots_incl[OF _ _ _ pdiv] assms + degree_zero_imp_empty_roots[OF assms(3)] + by (cases "q = []", auto, metis UP.l_null UP.m_rcancel UP.zero_closed univ_poly_zero) + next + show "roots (p \\<^bsub>poly_ring R\<^esub> q) \# roots q" + proof (cases "p \\<^bsub>poly_ring R\<^esub> q = []") + case True thus ?thesis + using degree_zero_imp_empty_roots[OF UP.m_closed[OF assms(1,3)]] by simp + next + case False with \p \ []\ have q_not_zero: "q \ []" + by (metis UP.r_null assms(1) univ_poly_zero) + show ?thesis + proof (rule roots_inclI[OF UP.m_closed[OF assms(1,3)] assms(3) q_not_zero]) + fix a assume a: "a \ carrier R" + hence "\ ([ \, \ a ] pdivides p)" + using assms(1-2) no_roots pdivides_imp_is_root roots_mem_iff_is_root[of p] by auto + moreover have in_carrier: "[ \, \ a ] \ carrier (poly_ring R)" + using a unfolding sym[OF univ_poly_carrier] polynomial_def by auto + hence "pirreducible (carrier R) [ \, \ a ]" + using degree_one_imp_pirreducible[OF carrier_is_subfield] by simp + moreover + have "([ \, \ a ] [^]\<^bsub>poly_ring R\<^esub> (alg_mult (p \\<^bsub>poly_ring R\<^esub> q) a)) pdivides (p \\<^bsub>poly_ring R\<^esub> q)" + using le_alg_mult_imp_pdivides[OF a UP.m_closed, of p q] assms by simp + ultimately show "([ \, \ a ] [^]\<^bsub>poly_ring R\<^esub> (alg_mult (p \\<^bsub>poly_ring R\<^esub> q) a)) pdivides q" + using pirreducible_pow_pdivides_iff[OF carrier_is_subfield in_carrier] assms by auto + qed + qed + qed +qed + +lemma (in field) poly_mult_degree_one_monic_imp_same_roots: + assumes "a \ carrier R" and "p \ carrier (poly_ring R)" "p \ []" + shows "roots ([ \, \ a ] \\<^bsub>poly_ring R\<^esub> p) = add_mset a (roots p)" +proof - + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + from \a \ carrier R\ have in_carrier: "[ \, \ a ] \ carrier (poly_ring R)" + unfolding sym[OF univ_poly_carrier] polynomial_def by simp + + show ?thesis + proof (intro subset_mset.antisym[OF roots_inclI' mset_subset_eqI]) + show "([ \, \ a ] \\<^bsub>poly_ring R\<^esub> p) \ carrier (poly_ring R)" + using in_carrier assms(2) by simp + next + fix b assume b: "b \ carrier R" and "[ \, \ a ] \\<^bsub>poly_ring R\<^esub> p \ []" + hence not_zero: "p \ []" + unfolding univ_poly_def by auto + from \b \ carrier R\ have in_carrier': "[ \, \ b ] \ carrier (poly_ring R)" + unfolding sym[OF univ_poly_carrier] polynomial_def by simp + show "alg_mult ([ \, \ a ] \\<^bsub>poly_ring R\<^esub> p) b \ count (add_mset a (roots p)) b" + proof (cases "a = b") + case False + hence "\ [ \, \ b ] pdivides [ \, \ a ]" + using assms(1) b monic_degree_one_root_condition pdivides_imp_is_root by blast + moreover have "pirreducible (carrier R) [ \, \ b ]" + using degree_one_imp_pirreducible[OF carrier_is_subfield in_carrier'] by simp + ultimately + have "[ \, \ b ] [^]\<^bsub>poly_ring R\<^esub> (alg_mult ([ \, \ a ] \\<^bsub>poly_ring R\<^esub> p) b) pdivides p" + using le_alg_mult_imp_pdivides[OF b UP.m_closed, of _ p] assms(2) in_carrier + pirreducible_pow_pdivides_iff[OF carrier_is_subfield in_carrier' in_carrier, of p] + by auto + with \a \ b\ show ?thesis + using alg_mult_eq_count_roots[OF assms(2)] alg_multE(2)[OF b assms(2) not_zero] by auto + next + case True + have "[ \, \ a ] pdivides ([ \, \ a ] \\<^bsub>poly_ring R\<^esub> p)" + using dividesI[OF assms(2)] unfolding pdivides_def by auto + with \[ \, \ a ] \\<^bsub>poly_ring R\<^esub> p \ []\ + have "alg_mult ([ \, \ a ] \\<^bsub>poly_ring R\<^esub> p) a \ Suc 0" + using alg_multE(2)[of a _ "Suc 0"] in_carrier assms by auto + then obtain m where m: "alg_mult ([ \, \ a ] \\<^bsub>poly_ring R\<^esub> p) a = Suc m" + using Suc_le_D by blast + hence "([ \, \ a ] \\<^bsub>poly_ring R\<^esub> ([ \, \ a ] [^]\<^bsub>poly_ring R\<^esub> m)) pdivides + ([ \, \ a ] \\<^bsub>poly_ring R\<^esub> p)" + using le_alg_mult_imp_pdivides[OF _ UP.m_closed, of a _ p] + in_carrier assms UP.nat_pow_Suc2 by force + hence "([ \, \ a ] [^]\<^bsub>poly_ring R\<^esub> m) pdivides p" + using UP.mult_divides in_carrier assms(2) + unfolding univ_poly_zero pdivides_def factor_def + by (simp add: UP.m_assoc UP.m_lcancel univ_poly_zero) + with \a = b\ show ?thesis + using alg_mult_eq_count_roots assms in_carrier UP.nat_pow_Suc2 + alg_multE(2)[OF assms(1) _ not_zero] m + by auto + qed + next + fix b + have not_zero: "[ \, \ a ] \\<^bsub>poly_ring R\<^esub> p \ []" + using assms in_carrier univ_poly_zero[of R] UP.integral by auto + + show "count (add_mset a (roots p)) b \ count (roots ([\, \ a] \\<^bsub>poly_ring R\<^esub> p)) b" + proof (cases "a = b") + case True + have "([ \, \ a ] \\<^bsub>poly_ring R\<^esub> ([ \, \ a ] [^]\<^bsub>poly_ring R\<^esub> (alg_mult p a))) pdivides + ([ \, \ a ] \\<^bsub>poly_ring R\<^esub> p)" + using UP.divides_mult[OF _ in_carrier] le_alg_mult_imp_pdivides[OF assms(1,2)] in_carrier assms + by (auto simp add: pdivides_def) + with \a = b\ show ?thesis + using alg_mult_eq_count_roots assms in_carrier UP.nat_pow_Suc2 + alg_multE(2)[OF assms(1) _ not_zero] + by auto + next + case False + have "p pdivides ([ \, \ a ] \\<^bsub>poly_ring R\<^esub> p)" + using dividesI[OF in_carrier] UP.m_comm in_carrier assms unfolding pdivides_def by auto + thus ?thesis + using False pdivides_imp_roots_incl assms in_carrier not_zero + by (simp add: subseteq_mset_def) + qed + qed +qed + +lemma (in domain) not_empty_rootsE[elim]: + assumes "p \ carrier (poly_ring R)" and "roots p \ {#}" + and "\a. \ a \ carrier R; a \# roots p; + [ \, \ a ] \ carrier (poly_ring R); [ \, \ a ] pdivides p \ \ P" + shows P +proof - + from \roots p \ {#}\ obtain a where "a \# roots p" + by blast + with \p \ carrier (poly_ring R)\ have "[ \, \ a ] pdivides p" + and "[ \, \ a ] \ carrier (poly_ring R)" and "a \ carrier R" + using is_root_imp_pdivides[of p] roots_mem_iff_is_root[of p] is_root_def[of p a] + unfolding sym[OF univ_poly_carrier] polynomial_def by auto + with \a \# roots p\ show ?thesis + using assms(3)[of a] by auto +qed + +(* REPLACE th following lemmas on Divisibility.thy ============= *) +(* the only difference is the locale *) +lemma (in monoid) mult_cong_r: + assumes "b \ b'" "a \ carrier G" "b \ carrier G" "b' \ carrier G" + shows "a \ b \ a \ b'" + by (meson assms associated_def divides_mult_lI) + +lemma (in comm_monoid) mult_cong_l: + assumes "a \ a'" "a \ carrier G" "a' \ carrier G" "b \ carrier G" + shows "a \ b \ a' \ b" + using assms m_comm mult_cong_r by auto +(* ============================================================= *) + +lemma (in field) associated_polynomials_imp_same_roots: + assumes "p \ carrier (poly_ring R)" "p \ []" and "q \ carrier (poly_ring R)" "q \ []" + shows "roots (p \\<^bsub>poly_ring R\<^esub> q) = roots p + roots q" +proof - + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + from assms show ?thesis + proof (induction "degree p" arbitrary: p rule: less_induct) + case less show ?case + proof (cases "roots p = {#}") + case True thus ?thesis + using no_roots_imp_same_roots[of p q] less by simp + next + case False with \p \ carrier (poly_ring R)\ + obtain a where a: "a \ carrier R" and "a \# roots p" and pdiv: "[ \, \ a ] pdivides p" + and in_carrier: "[ \, \ a ] \ carrier (poly_ring R)" + by blast + show ?thesis + proof (cases "degree p = 1") + case True with \p \ carrier (poly_ring R)\ + obtain b c where p: "p = [ b, c ]" and b: "b \ carrier R" "b \ \" and c: "c \ carrier R" + by auto + with \a \# roots p\ have roots: "roots p = {# a #}" and a: "\ a = inv b \ c" "a \ carrier R" + and lead: "lead_coeff p = b" and const: "const_term p = c" + using degree_one_imp_singleton_roots[of p] less(2) field_Units + unfolding const_term_def by auto + hence "(p \\<^bsub>poly_ring R\<^esub> q) \\<^bsub>poly_ring R\<^esub> ([ \, \ a ] \\<^bsub>poly_ring R\<^esub> q)" + using UP.mult_cong_l[OF degree_one_associatedI[OF carrier_is_subfield _ True]] less(2,4) + by (auto simp add: a lead const) + hence "roots (p \\<^bsub>poly_ring R\<^esub> q) = roots ([ \, \ a ] \\<^bsub>poly_ring R\<^esub> q)" + using associated_polynomials_imp_same_roots in_carrier less(2,4) unfolding a by simp + thus ?thesis + unfolding poly_mult_degree_one_monic_imp_same_roots[OF a(2) less(4,5)] roots by simp + next + case False + from \[ \, \ a ] pdivides p\ + obtain r where p: "p = [ \, \ a ] \\<^bsub>poly_ring R\<^esub> r" and r: "r \ carrier (poly_ring R)" + unfolding pdivides_def by auto + with \p \ []\ have not_zero: "r \ []" + using in_carrier univ_poly_zero[of R "carrier R"] UP.integral_iff by auto + with \p = [ \, \ a ] \\<^bsub>poly_ring R\<^esub> r\ have deg: "degree p = Suc (degree r)" + using poly_mult_degree_eq[OF carrier_is_subring, of _ r] in_carrier r + unfolding univ_poly_carrier sym[OF univ_poly_mult[of R "carrier R"]] by auto + with \r \ []\ and \q \ []\ have "r \\<^bsub>poly_ring R\<^esub> q \ []" + using in_carrier univ_poly_zero[of R "carrier R"] UP.integral less(4) r by auto + hence "roots (p \\<^bsub>poly_ring R\<^esub> q) = add_mset a (roots (r \\<^bsub>poly_ring R\<^esub> q))" + using poly_mult_degree_one_monic_imp_same_roots[OF a UP.m_closed[OF r less(4)]] + UP.m_assoc[OF in_carrier r less(4)] p by auto + also have " ... = add_mset a (roots r + roots q)" + using less(1)[OF _ r not_zero less(4-5)] deg by simp + also have " ... = (add_mset a (roots r)) + roots q" + by simp + also have " ... = roots p + roots q" + using poly_mult_degree_one_monic_imp_same_roots[OF a r not_zero] p by simp + finally show ?thesis . + qed + qed + qed +qed + +lemma (in field) size_roots_le_degree: + assumes "p \ carrier (poly_ring R)" shows "size (roots p) \ degree p" + using assms +proof (induction "degree p" arbitrary: p rule: less_induct) + case less show ?case + proof (cases "roots p = {#}", simp) + interpret UP: domain "poly_ring R" + using univ_poly_is_domain[OF carrier_is_subring] . + + case False with \p \ carrier (poly_ring R)\ + obtain a where a: "a \ carrier R" and "a \# roots p" and "[ \, \ a ] pdivides p" + and in_carrier: "[ \, \ a ] \ carrier (poly_ring R)" + by blast + then obtain q where p: "p = [ \, \ a ] \\<^bsub>poly_ring R\<^esub> q" and q: "q \ carrier (poly_ring R)" + unfolding pdivides_def by auto + with \a \# roots p\ have "p \ []" + using degree_zero_imp_empty_roots[OF less(2)] by auto + hence not_zero: "q \ []" + using in_carrier univ_poly_zero[of R "carrier R"] UP.integral_iff p by auto + hence "degree p = Suc (degree q)" + using poly_mult_degree_eq[OF carrier_is_subring, of _ q] in_carrier p q + unfolding univ_poly_carrier sym[OF univ_poly_mult[of R "carrier R"]] by auto + with \q \ []\ show ?thesis + using poly_mult_degree_one_monic_imp_same_roots[OF a q] p less(1)[OF _ q] + by (metis Suc_le_mono lessI size_add_mset) + qed +qed + +(* MOVE to Divisibility.thy ======== *) +lemma divides_irreducible_condition: + assumes "irreducible G r" and "a \ carrier G" + shows "a divides\<^bsub>G\<^esub> r \ a \ Units G \ a \\<^bsub>G\<^esub> r" + using assms unfolding irreducible_def properfactor_def associated_def + by (cases "r divides\<^bsub>G\<^esub> a", auto) + +(* MOVE to Polynomial_Divisibility.thy ======== *) +lemma (in ring) divides_pirreducible_condition: + assumes "pirreducible K q" and "p \ carrier (K[X])" + shows "p divides\<^bsub>K[X]\<^esub> q \ p \ Units (K[X]) \ p \\<^bsub>K[X]\<^esub> q" + using divides_irreducible_condition[of "K[X]" q p] assms + unfolding ring_irreducible_def by auto + +lemma (in domain) pirreducible_roots: + assumes "p \ carrier (poly_ring R)" and "pirreducible (carrier R) p" and "degree p \ 1" + shows "roots p = {#}" +proof (rule ccontr) + assume "roots p \ {#}" with \p \ carrier (poly_ring R)\ + obtain a where a: "a \ carrier R" and "a \# roots p" and "[ \, \ a ] pdivides p" + and in_carrier: "[ \, \ a ] \ carrier (poly_ring R)" + by blast + hence "[ \, \ a ] \\<^bsub>poly_ring R\<^esub> p" + using divides_pirreducible_condition[OF assms(2) in_carrier] + univ_poly_units_incl[OF carrier_is_subring] + unfolding pdivides_def by auto + hence "degree p = 1" + using associated_polynomials_imp_same_length[OF carrier_is_subring in_carrier assms(1)] by auto + with \degree p \ 1\ show False .. +qed + +lemma (in field) pirreducible_imp_not_splitted: + assumes "p \ carrier (poly_ring R)" and "pirreducible (carrier R) p" and "degree p \ 1" + shows "\ splitted p" + using pirreducible_roots[of p] pirreducible_degree[OF carrier_is_subfield, of p] assms + by (simp add: splitted_def) + +lemma (in field) + assumes "p \ carrier (poly_ring R)" and "q \ carrier (poly_ring R)" + and "pirreducible (carrier R) p" and "degree p \ 1" + shows "roots (p \\<^bsub>poly_ring R\<^esub> q) = roots q" + using no_roots_imp_same_roots[of p q] pirreducible_roots[of p] assms + unfolding ring_irreducible_def univ_poly_zero by auto + +lemma (in field) trivial_factors_imp_splitted: + assumes "p \ carrier (poly_ring R)" + and "\q. \ q \ carrier (poly_ring R); pirreducible (carrier R) q; q pdivides p \ \ degree q \ 1" + shows "splitted p" + using assms +proof (induction "degree p" arbitrary: p rule: less_induct) + interpret UP: principal_domain "poly_ring R" + using univ_poly_is_principal[OF carrier_is_subfield] . + case less show ?case + proof (cases "degree p = 0", simp add: degree_zero_imp_splitted[OF less(2)]) + case False show ?thesis + proof (cases "roots p = {#}") + case True + from \degree p \ 0\ have "p \ Units (poly_ring R)" and "p \ carrier (poly_ring R) - { [] }" + using univ_poly_units'[OF carrier_is_subfield, of p] less(2) by auto + then obtain q where "q \ carrier (poly_ring R)" "pirreducible (carrier R) q" and "q pdivides p" + using UP.exists_irreducible_divisor[of p] unfolding univ_poly_zero pdivides_def by auto + with \degree p \ 0\ have "roots p \ {#}" + using degree_one_imp_singleton_roots[OF _ , of q] less(3)[of q] + pdivides_imp_roots_incl[OF _ less(2), of q] + pirreducible_degree[OF carrier_is_subfield, of q] + by force + from \roots p = {#}\ and \roots p \ {#}\ have False + by simp + thus ?thesis .. + next + case False with \p \ carrier (poly_ring R)\ + obtain a where a: "a \ carrier R" and "a \# roots p" and "[ \, \ a ] pdivides p" + and in_carrier: "[ \, \ a ] \ carrier (poly_ring R)" + by blast + then obtain q where p: "p = [ \, \ a ] \\<^bsub>poly_ring R\<^esub> q" and q: "q \ carrier (poly_ring R)" + unfolding pdivides_def by blast + with \degree p \ 0\ have "p \ []" + by auto + with \p = [ \, \ a ] \\<^bsub>poly_ring R\<^esub> q\ have "q \ []" + using in_carrier q unfolding sym[OF univ_poly_zero[of R "carrier R"]] by auto + with \p = [ \, \ a ] \\<^bsub>poly_ring R\<^esub> q\ and \p \ []\ have "degree p = Suc (degree q)" + using poly_mult_degree_eq[OF carrier_is_subring] in_carrier q + unfolding univ_poly_carrier sym[OF univ_poly_mult[of R "carrier R"]] by auto + moreover have "q pdivides p" + using p dividesI[OF in_carrier] UP.m_comm[OF in_carrier q] by (auto simp add: pdivides_def) + hence "degree r = 1" if "r \ carrier (poly_ring R)" and "pirreducible (carrier R) r" + and "r pdivides q" for r + using less(3)[OF that(1-2)] UP.divides_trans[OF _ _ that(1), of q p] that(3) + pirreducible_degree[OF carrier_is_subfield that(1-2)] + by (auto simp add: pdivides_def) + ultimately have "splitted q" + using less(1)[OF _ q] by auto + with \degree p = Suc (degree q)\ and \q \ []\ show ?thesis + using poly_mult_degree_one_monic_imp_same_roots[OF a q] + unfolding sym[OF p] splitted_def + by simp + qed + qed +qed + +lemma (in field) pdivides_imp_splitted: + assumes "p \ carrier (poly_ring R)" and "q \ carrier (poly_ring R)" "q \ []" and "splitted q" + shows "p pdivides q \ splitted p" +proof (cases "p = []") + case True thus ?thesis + using degree_zero_imp_splitted[OF assms(1)] by simp +next + interpret UP: principal_domain "poly_ring R" + using univ_poly_is_principal[OF carrier_is_subfield] . + + case False + assume "p pdivides q" + then obtain b where b: "b \ carrier (poly_ring R)" and q: "q = p \\<^bsub>poly_ring R\<^esub> b" + unfolding pdivides_def by auto + with \q \ []\ have "p \ []" and "b \ []" + using assms UP.integral_iff[of p b] unfolding sym[OF univ_poly_zero[of R "carrier R"]] by auto + hence "degree p + degree b = size (roots p) + size (roots b)" + using associated_polynomials_imp_same_roots[of p b] assms b q splitted_def + poly_mult_degree_eq[OF carrier_is_subring,of p b] + unfolding univ_poly_carrier sym[OF univ_poly_mult[of R "carrier R"]] + by auto + moreover have "size (roots p) \ degree p" and "size (roots b) \ degree b" + using size_roots_le_degree assms(1) b by auto + ultimately show ?thesis + unfolding splitted_def by linarith +qed + +lemma (in field) splitted_imp_trivial_factors: + assumes "p \ carrier (poly_ring R)" "p \ []" and "splitted p" + shows "\q. \ q \ carrier (poly_ring R); pirreducible (carrier R) q; q pdivides p \ \ degree q = 1" + using pdivides_imp_splitted[OF _ assms] pirreducible_imp_not_splitted + by auto + lemma (in field) exists_root: assumes "M \ extensions" and "\L. \ L \ extensions; M \ L \ \ law_restrict L = law_restrict M" - and "P \ carrier (poly_ring R)" and "degree P > 0" - shows "\x \ carrier M. (ring.eval M) (\ P) x = \\<^bsub>M\<^esub>" + and "P \ carrier (poly_ring R)" + shows "(ring.splitted M) (\ P)" proof (rule ccontr) from \M \ extensions\ interpret M: field M + Hom: ring_hom_ring R M "indexed_const" using ring_hom_ringI2[OF ring_axioms field.is_ring] unfolding extensions_def by auto interpret UP: principal_domain "poly_ring M" using M.univ_poly_is_principal[OF M.carrier_is_subfield] . - assume no_roots: "\ (\x \ carrier M. M.eval (\ P) x = \\<^bsub>M\<^esub>)" + assume not_splitted: "\ (ring.splitted M) (\ P)" have "(\ P) \ carrier (poly_ring M)" using polynomial_hom[OF Hom.homh field_axioms M.field_axioms assms(3)] unfolding \_def by simp - moreover have "(\ P) \ Units (poly_ring M)" and "(\ P) \ \\<^bsub>poly_ring M\<^esub>" - using assms(4) unfolding M.univ_poly_carrier_units \_def univ_poly_zero by auto - ultimately obtain Q + then obtain Q where Q: "Q \ carrier (poly_ring M)" "pirreducible\<^bsub>M\<^esub> (carrier M) Q" "Q pdivides\<^bsub>M\<^esub> (\ P)" - using UP.exists_irreducible_divisor[of "\ P"] unfolding pdivides_def by blast + and degree_gt: "degree Q > 1" + using M.trivial_factors_imp_splitted[of "\ P"] not_splitted by force + + from \(\ P) \ carrier (poly_ring M)\ have "(\ P) \ []" + using M.degree_zero_imp_splitted[of "\ P"] not_splitted unfolding \_def by auto - have hyps: + have "\i. \\

\ carrier M. index_free \

(P, i)" + proof (rule ccontr) + assume "\i. \\

\ carrier M. index_free \

(P, i)" + then have "\\<^bsub>(P, i)\<^esub> \ carrier M" and "(ring.eval M) (\ P) \\<^bsub>(P, i)\<^esub> = \\<^bsub>M\<^esub>" for i + using assms(1,3) unfolding extensions_def by blast+ + with \(\ P) \ []\ have "((\i :: nat. \\<^bsub>(P, i)\<^esub>) ` UNIV) \ { a. (ring.is_root M) (\ P) a }" + unfolding M.is_root_def by auto + moreover have "inj (\i :: nat. \\<^bsub>(P, i)\<^esub>)" + unfolding indexed_var_def indexed_const_def indexed_pmult_def inj_def + by (metis (no_types, lifting) add_mset_eq_singleton_iff diff_single_eq_union + multi_member_last prod.inject zero_not_one) + hence "infinite ((\i :: nat. \\<^bsub>(P, i)\<^esub>) ` UNIV)" + unfolding infinite_iff_countable_subset by auto + ultimately have "infinite { a. (ring.is_root M) (\ P) a }" + using finite_subset by auto + with \(\ P) \ carrier (poly_ring M)\ show False + using M.finite_number_of_roots by simp + qed + then obtain i :: nat where "\\

\ carrier M. index_free \

(P, i)" + by blast + + then have hyps: \ \i\ "field M" \ \ii\ "\\

. \

\ carrier M \ carrier_coeff \

" - \ \iii\ "\\

. \

\ carrier M \ index_free \

P" + \ \iii\ "\\

. \

\ carrier M \ index_free \

(P, i)" \ \iv\ "\\<^bsub>M\<^esub> = indexed_const \" - using assms(1,3) no_roots unfolding extensions_def by auto - have degree_gt: "degree Q > 1" - proof (rule ccontr) - assume "\ degree Q > 1" hence "degree Q = 1" - using M.pirreducible_degree[OF M.carrier_is_subfield Q(1-2)] by simp - then obtain x where "x \ carrier M" and "M.eval Q x = \\<^bsub>M\<^esub>" - using M.degree_one_root[OF M.carrier_is_subfield Q(1)] M.add.inv_closed by blast - hence "M.eval (\ P) x = \\<^bsub>M\<^esub>" - using M.pdivides_imp_root_sharing[OF Q(1,3)] by simp - with \x \ carrier M\ show False - using no_roots by simp - qed + using assms(1,3) unfolding extensions_def by auto - define image_poly where "image_poly = image_ring (eval_pmod M P Q) (poly_ring M)" + define image_poly where "image_poly = image_ring (eval_pmod M (P, i) Q) (poly_ring M)" with \degree Q > 1\ have "M \ image_poly" using image_poly_iso_incl[OF hyps Q(1)] by auto moreover have is_field: "field image_poly" @@ -530,7 +1745,7 @@ moreover have "image_poly \ extensions" proof (auto simp add: extensions_def is_field) fix \

assume "\

\ carrier image_poly" - then obtain R where \

: "\

= eval_pmod M P Q R" and "R \ carrier (poly_ring M)" + then obtain R where \

: "\

= eval_pmod M (P, i) Q R" and "R \ carrier (poly_ring M)" unfolding image_poly_def image_ring_carrier by auto hence "M.pmod R Q \ carrier (poly_ring M)" using M.long_division_closed(2)[OF M.carrier_is_subfield _ Q(1)] by simp @@ -545,32 +1760,32 @@ from \M \ image_poly\ interpret Id: ring_hom_ring M image_poly id using iso_inclE[OF M.ring_axioms field.is_ring[OF is_field]] by simp - fix \

S - assume A: "\

\ carrier image_poly" "\ index_free \

S" "S \ carrier (poly_ring R)" - have "\\<^bsub>S\<^esub> \ carrier image_poly \ Id.eval (\ S) \\<^bsub>S\<^esub> = \\<^bsub>image_poly\<^esub>" + fix \

S j + assume A: "\

\ carrier image_poly" "\ index_free \

(S, j)" "S \ carrier (poly_ring R)" + have "\\<^bsub>(S, j)\<^esub> \ carrier image_poly \ Id.eval (\ S) \\<^bsub>(S, j)\<^esub> = \\<^bsub>image_poly\<^esub>" proof (cases) - assume "P \ S" - then obtain Q' where "Q' \ carrier M" and "\ index_free Q' S" + assume "(P, i) \ (S, j)" + then obtain Q' where "Q' \ carrier M" and "\ index_free Q' (S, j)" using A(1) image_poly_index_free[OF hyps Q(1) _ A(2)] unfolding image_poly_def by auto - hence "\\<^bsub>S\<^esub> \ carrier M" and "M.eval (\ S) \\<^bsub>S\<^esub> = \\<^bsub>M\<^esub>" + hence "\\<^bsub>(S, j)\<^esub> \ carrier M" and "M.eval (\ S) \\<^bsub>(S, j)\<^esub> = \\<^bsub>M\<^esub>" using assms(1) A(3) unfolding extensions_def by auto moreover have "\ S \ carrier (poly_ring M)" using polynomial_hom[OF Hom.homh field_axioms M.field_axioms A(3)] unfolding \_def . ultimately show ?thesis using Id.eval_hom[OF M.carrier_is_subring] Id.hom_closed Id.hom_zero by auto next - assume "\ P \ S" hence S: "P = S" + assume "\ (P, i) \ (S, j)" hence S: "(P, i) = (S, j)" by simp have poly_hom: "R \ carrier (poly_ring image_poly)" if "R \ carrier (poly_ring M)" for R using polynomial_hom[OF Id.homh M.field_axioms is_field that] by simp - have "\\<^bsub>S\<^esub> \ carrier image_poly" + have "\\<^bsub>(S, j)\<^esub> \ carrier image_poly" using eval_pmod_var(2)[OF hyps Hom.homh Q(1) degree_gt] unfolding image_poly_def S by simp - moreover have "Id.eval Q \\<^bsub>S\<^esub> = \\<^bsub>image_poly\<^esub>" + moreover have "Id.eval Q \\<^bsub>(S, j)\<^esub> = \\<^bsub>image_poly\<^esub>" using image_poly_eval_indexed_var[OF hyps Hom.homh Q(1) degree_gt Q(2)] unfolding image_poly_def S by simp moreover have "Q pdivides\<^bsub>image_poly\<^esub> (\ S)" proof - obtain R where R: "R \ carrier (poly_ring M)" "\ S = Q \\<^bsub>poly_ring M\<^esub> R" - using Q(3) unfolding S pdivides_def by auto + using Q(3) S unfolding pdivides_def by auto moreover have "set Q \ carrier M" and "set R \ carrier M" using Q(1) R(1) unfolding sym[OF univ_poly_carrier] polynomial_def by auto ultimately have "Id.normalize (\ S) = Q \\<^bsub>poly_ring image_poly\<^esub> R" @@ -590,23 +1805,22 @@ ultimately show ?thesis using domain.pdivides_imp_root_sharing[OF field.axioms(1)[OF is_field], of Q] by auto qed - thus "\\<^bsub>S\<^esub> \ carrier image_poly" and "Id.eval (\ S) \\<^bsub>S\<^esub> = \\<^bsub>image_poly\<^esub>" + thus "\\<^bsub>(S, j)\<^esub> \ carrier image_poly" and "Id.eval (\ S) \\<^bsub>(S, j)\<^esub> = \\<^bsub>image_poly\<^esub>" by auto qed ultimately have "law_restrict M = law_restrict image_poly" using assms(2) by simp hence "carrier M = carrier image_poly" unfolding law_restrict_def by (simp add:ring.defs) - moreover have "\\<^bsub>P\<^esub> \ carrier image_poly" + moreover have "\\<^bsub>(P, i)\<^esub> \ carrier image_poly" using eval_pmod_var(2)[OF hyps Hom.homh Q(1) degree_gt] unfolding image_poly_def by simp - moreover have "\\<^bsub>P\<^esub> \ carrier M" - using indexed_var_not_index_free[of P] hyps(3) by blast + moreover have "\\<^bsub>(P, i)\<^esub> \ carrier M" + using indexed_var_not_index_free[of "(P, i)"] hyps(3) by blast ultimately show False by simp qed lemma (in field) exists_extension_with_roots: - shows "\L \ extensions. \P \ carrier (poly_ring R). - degree P > 0 \ (\x \ carrier L. (ring.eval L) (\ P) x = \\<^bsub>L\<^esub>)" + shows "\L \ extensions. \P \ carrier (poly_ring R). (ring.splitted L) (\ P)" proof - obtain M where "M \ extensions" and "\L \ extensions. M \ L \ law_restrict L = law_restrict M" using exists_maximal_extension iso_incl_hom by blast @@ -619,17 +1833,16 @@ locale algebraic_closure = field L + subfield K L for L (structure) and K + assumes algebraic_extension: "x \ carrier L \ (algebraic over K) x" - and roots_over_subfield: "\ P \ carrier (K[X]); degree P > 0 \ \ \x \ carrier L. eval P x = \\<^bsub>L\<^esub>" + and roots_over_subfield: "P \ carrier (K[X]) \ splitted P" locale algebraically_closed = field L for L (structure) + - assumes roots_over_carrier: "\ P \ carrier (poly_ring L); degree P > 0 \ \ \x \ carrier L. eval P x = \\<^bsub>L\<^esub>" + assumes roots_over_carrier: "P \ carrier (poly_ring L) \ splitted P" -definition (in field) closure :: "(('a list) multiset \ 'a) ring" ("\") +definition (in field) closure :: "(('a list \ nat) multiset \ 'a) ring" ("\") where "closure = (SOME L \ \such that\. - \ \i\ algebraic_closure L (indexed_const ` (carrier R)) \ + \ \i\ algebraic_closure L (indexed_const ` (carrier R)) \ \ \ii\ indexed_const \ ring_hom R L)" - lemma algebraic_hom: assumes "h \ ring_hom R S" and "field R" and "field S" and "subfield K R" and "x \ carrier R" shows "((ring.algebraic R) over K) x \ ((ring.algebraic S) over (h ` K)) (h x)" @@ -648,12 +1861,11 @@ qed lemma (in field) exists_closure: - obtains L :: "(('a list multiset) \ 'a) ring" + obtains L :: "((('a list \ nat) multiset) \ 'a) ring" where "algebraic_closure L (indexed_const ` (carrier R))" and "indexed_const \ ring_hom R L" proof - obtain L where "L \ extensions" - and roots: "\P. \ P \ carrier (poly_ring R); degree P > 0 \ \ - \x \ carrier L. (ring.eval L) (\ P) x = \\<^bsub>L\<^esub>" + and roots: "\P. P \ carrier (poly_ring R) \ (ring.splitted L) (\ P)" using exists_extension_with_roots by auto let ?K = "indexed_const ` (carrier R)" @@ -685,7 +1897,7 @@ next show "?K \ carrier ?M" proof - fix x :: "('a list multiset) \ 'a" + fix x :: "(('a list \ nat) multiset) \ 'a" assume "x \ ?K" hence "x \ carrier L" using ring_hom_memE(1)[OF ring_hom_ring.homh[OF hom]] by auto @@ -700,54 +1912,126 @@ proof (intro algebraic_closure.intro[OF M is_subfield]) have "(Id.R.algebraic over ?K) x" if "x \ carrier ?M" for x using that Id.S.algebraic_consistent[OF subfieldE(1)[OF set_of_algs]] by simp - moreover have "\x \ carrier ?M. Id.R.eval P x = \\<^bsub>?M\<^esub>" - if "P \ carrier (?K[X]\<^bsub>?M\<^esub>)" and "degree P > 0" for P + moreover have "Id.R.splitted P" if "P \ carrier (?K[X]\<^bsub>?M\<^esub>)" for P proof - - from \P \ carrier (?K[X]\<^bsub>?M\<^esub>)\ have "P \ carrier (?K[X]\<^bsub>L\<^esub>)" - unfolding Id.S.univ_poly_consistent[OF subfieldE(1)[OF set_of_algs]] . - hence "set P \ ?K" - unfolding sym[OF univ_poly_carrier] polynomial_def by auto - hence "\Q. set Q \ carrier R \ P = \ Q" - proof (induct P, simp add: \_def) - case (Cons p P) - then obtain q Q where "q \ carrier R" "set Q \ carrier R" and "\ Q = P""indexed_const q = p" - unfolding \_def by auto - hence "set (q # Q) \ carrier R" and "\ (q # Q) = (p # P)" - unfolding \_def by auto - thus ?case - by metis - qed - then obtain Q where "set Q \ carrier R" and "\ Q = P" - by auto - moreover have "lead_coeff Q \ \" - proof (rule ccontr) - assume "\ lead_coeff Q \ \" then have "lead_coeff Q = \" + from \P \ carrier (?K[X]\<^bsub>?M\<^esub>)\ have "P \ carrier (poly_ring ?M)" + using Id.R.carrier_polynomial_shell[OF subfieldE(1)[OF is_subfield]] by simp + show ?thesis + proof (cases "degree P = 0") + case True with \P \ carrier (poly_ring ?M)\ show ?thesis + using domain.degree_zero_imp_splitted[OF field.axioms(1)[OF M]] + by fastforce + next + case False then have "degree P > 0" by simp - with \\ Q = P\ and \degree P > 0\ have "lead_coeff P = indexed_const \" - unfolding \_def by (metis diff_0_eq_0 length_map less_irrefl_nat list.map_sel(1) list.size(3)) - hence "lead_coeff P = \\<^bsub>L\<^esub>" - using ring_hom_zero[OF ring_hom_ring.homh ring_hom_ring.axioms(1-2)] hom by auto - with \degree P > 0\ have "\ P \ carrier (?K[X]\<^bsub>?M\<^esub>)" + from \P \ carrier (?K[X]\<^bsub>?M\<^esub>)\ have "P \ carrier (?K[X]\<^bsub>L\<^esub>)" + unfolding Id.S.univ_poly_consistent[OF subfieldE(1)[OF set_of_algs]] . + hence "set P \ ?K" + unfolding sym[OF univ_poly_carrier] polynomial_def by auto + hence "\Q. set Q \ carrier R \ P = \ Q" + proof (induct P, simp add: \_def) + case (Cons p P) + then obtain q Q where "q \ carrier R" "set Q \ carrier R" + and "\ Q = P" "indexed_const q = p" + unfolding \_def by auto + hence "set (q # Q) \ carrier R" and "\ (q # Q) = (p # P)" + unfolding \_def by auto + thus ?case + by metis + qed + then obtain Q where "set Q \ carrier R" and "\ Q = P" + by auto + moreover have "lead_coeff Q \ \" + proof (rule ccontr) + assume "\ lead_coeff Q \ \" then have "lead_coeff Q = \" + by simp + with \\ Q = P\ and \degree P > 0\ have "lead_coeff P = indexed_const \" + unfolding \_def by (metis diff_0_eq_0 length_map less_irrefl_nat list.map_sel(1) list.size(3)) + hence "lead_coeff P = \\<^bsub>L\<^esub>" + using ring_hom_zero[OF ring_hom_ring.homh ring_hom_ring.axioms(1-2)] hom by auto + with \degree P > 0\ have "\ P \ carrier (?K[X]\<^bsub>?M\<^esub>)" + unfolding sym[OF univ_poly_carrier] polynomial_def by auto + with \P \ carrier (?K[X]\<^bsub>?M\<^esub>)\ show False + by simp + qed + ultimately have "Q \ carrier (poly_ring R)" unfolding sym[OF univ_poly_carrier] polynomial_def by auto - with \P \ carrier (?K[X]\<^bsub>?M\<^esub>)\ show False - by simp + with \\ Q = P\ have "Id.S.splitted P" + using roots[of Q] by simp + + from \P \ carrier (poly_ring ?M)\ show ?thesis + proof (rule field.trivial_factors_imp_splitted[OF M]) + fix R + assume R: "R \ carrier (poly_ring ?M)" "pirreducible\<^bsub>?M\<^esub> (carrier ?M) R" and "R pdivides\<^bsub>?M\<^esub> P" + + from \P \ carrier (poly_ring ?M)\ and \R \ carrier (poly_ring ?M)\ + have "P \ carrier ((?set_of_algs)[X]\<^bsub>L\<^esub>)" and "R \ carrier ((?set_of_algs)[X]\<^bsub>L\<^esub>)" + unfolding Id.S.univ_poly_consistent[OF subfieldE(1)[OF set_of_algs]] by auto + hence in_carrier: "P \ carrier (poly_ring L)" "R \ carrier (poly_ring L)" + using Id.S.carrier_polynomial_shell[OF subfieldE(1)[OF set_of_algs]] by auto + + from \R pdivides\<^bsub>?M\<^esub> P\ have "R divides\<^bsub>((?set_of_algs)[X]\<^bsub>L\<^esub>)\<^esub> P" + unfolding pdivides_def Id.S.univ_poly_consistent[OF subfieldE(1)[OF set_of_algs]] + by simp + with \P \ carrier ((?set_of_algs)[X]\<^bsub>L\<^esub>)\ and \R \ carrier ((?set_of_algs)[X]\<^bsub>L\<^esub>)\ + have "R pdivides\<^bsub>L\<^esub> P" + using domain.pdivides_iff_shell[OF field.axioms(1)[OF L] set_of_algs, of R P] by simp + with \Id.S.splitted P\ and \degree P \ 0\ have "Id.S.splitted R" + using field.pdivides_imp_splitted[OF L in_carrier(2,1)] by fastforce + show "degree R \ 1" + proof (cases "Id.S.roots R = {#}") + case True with \Id.S.splitted R\ show ?thesis + unfolding Id.S.splitted_def by simp + next + case False with \R \ carrier (poly_ring L)\ + obtain a where "a \ carrier L" and "a \# Id.S.roots R" + and "[ \\<^bsub>L\<^esub>, \\<^bsub>L\<^esub> a ] \ carrier (poly_ring L)" and pdiv: "[ \\<^bsub>L\<^esub>, \\<^bsub>L\<^esub> a ] pdivides\<^bsub>L\<^esub> R" + using domain.not_empty_rootsE[OF field.axioms(1)[OF L], of R] by blast + + from \P \ carrier (?K[X]\<^bsub>L\<^esub>)\ + have "(Id.S.algebraic over ?K) a" + proof (rule Id.S.algebraicI) + from \degree P \ 0\ show "P \ []" + by auto + next + from \a \# Id.S.roots R\ and \R \ carrier (poly_ring L)\ + have "Id.S.eval R a = \\<^bsub>L\<^esub>" + using domain.roots_mem_iff_is_root[OF field.axioms(1)[OF L]] + unfolding Id.S.is_root_def by auto + with \R pdivides\<^bsub>L\<^esub> P\ and \a \ carrier L\ show "Id.S.eval P a = \\<^bsub>L\<^esub>" + using domain.pdivides_imp_root_sharing[OF field.axioms(1)[OF L] in_carrier(2)] by simp + qed + with \a \ carrier L\ have "a \ ?set_of_algs" + by simp + hence "[ \\<^bsub>L\<^esub>, \\<^bsub>L\<^esub> a ] \ carrier ((?set_of_algs)[X]\<^bsub>L\<^esub>)" + using subringE(3,5)[of ?set_of_algs L] subfieldE(1,6)[OF set_of_algs] + unfolding sym[OF univ_poly_carrier] polynomial_def by simp + hence "[ \\<^bsub>L\<^esub>, \\<^bsub>L\<^esub> a ] \ carrier (poly_ring ?M)" + unfolding Id.S.univ_poly_consistent[OF subfieldE(1)[OF set_of_algs]] by simp + + from \[ \\<^bsub>L\<^esub>, \\<^bsub>L\<^esub> a ] \ carrier ((?set_of_algs)[X]\<^bsub>L\<^esub>)\ + and \R \ carrier ((?set_of_algs)[X]\<^bsub>L\<^esub>)\ + have "[ \\<^bsub>L\<^esub>, \\<^bsub>L\<^esub> a ] divides\<^bsub>(?set_of_algs)[X]\<^bsub>L\<^esub>\<^esub> R" + using pdiv domain.pdivides_iff_shell[OF field.axioms(1)[OF L] set_of_algs] by simp + hence "[ \\<^bsub>L\<^esub>, \\<^bsub>L\<^esub> a ] divides\<^bsub>poly_ring ?M\<^esub> R" + unfolding pdivides_def Id.S.univ_poly_consistent[OF subfieldE(1)[OF set_of_algs]] + by simp + + have "[ \\<^bsub>L\<^esub>, \\<^bsub>L\<^esub> a ] \ Units (poly_ring ?M)" + using Id.R.univ_poly_units[OF field.carrier_is_subfield[OF M]] by force + with \[ \\<^bsub>L\<^esub>, \\<^bsub>L\<^esub> a ] \ carrier (poly_ring ?M)\ and \R \ carrier (poly_ring ?M)\ + and \[ \\<^bsub>L\<^esub>, \\<^bsub>L\<^esub> a ] divides\<^bsub>poly_ring ?M\<^esub> R\ + have "[ \\<^bsub>L\<^esub>, \\<^bsub>L\<^esub> a ] \\<^bsub>poly_ring ?M\<^esub> R" + using Id.R.divides_pirreducible_condition[OF R(2)] by auto + with \[ \\<^bsub>L\<^esub>, \\<^bsub>L\<^esub> a ] \ carrier (poly_ring ?M)\ and \R \ carrier (poly_ring ?M)\ + have "degree R = 1" + using domain.associated_polynomials_imp_same_length[OF field.axioms(1)[OF M] + Id.R.carrier_is_subring, of "[ \\<^bsub>L\<^esub>, \\<^bsub>L\<^esub> a ]" R] by force + thus ?thesis + by simp + qed + qed qed - ultimately have "Q \ carrier (poly_ring R)" - unfolding sym[OF univ_poly_carrier] polynomial_def by auto - moreover from \degree P > 0\ and \\ Q = P\ have "degree Q > 0" - unfolding \_def by auto - ultimately obtain x where "x \ carrier L" and "Id.S.eval P x = \\<^bsub>L\<^esub>" - using roots[of Q] unfolding \\ Q = P\ by auto - hence "Id.R.eval P x = \\<^bsub>?M\<^esub>" - unfolding Id.S.eval_consistent[OF subfieldE(1)[OF set_of_algs]] by simp - moreover from \degree P > 0\ have "P \ []" - by auto - with \P \ carrier (?K[X]\<^bsub>L\<^esub>)\ and \Id.S.eval P x = \\<^bsub>L\<^esub>\ have "(Id.S.algebraic over ?K) x" - using Id.S.non_trivial_ker_imp_algebraic[of ?K x] unfolding a_kernel_def' by auto - with \x \ carrier L\ have "x \ carrier ?M" - by auto - ultimately show ?thesis - by auto qed ultimately show "algebraic_closure_axioms ?M ?K" unfolding algebraic_closure_axioms_def by auto @@ -764,5 +2048,161 @@ using exists_closure unfolding closure_def by (metis (mono_tags, lifting) someI2)+ +lemma (in field) algebraically_closedI: + assumes "\p. \ p \ carrier (poly_ring R); degree p > 1 \ \ \x \ carrier R. eval p x = \" + shows "algebraically_closed R" +proof + fix p assume "p \ carrier (poly_ring R)" thus "splitted p" + proof (induction "degree p" arbitrary: p rule: less_induct) + case less show ?case + proof (cases "degree p \ 1") + case True with \p \ carrier (poly_ring R)\ show ?thesis + using degree_zero_imp_splitted degree_one_imp_splitted by fastforce + next + case False then have "degree p > 1" + by simp + with \p \ carrier (poly_ring R)\ have "roots p \ {#}" + using assms[of p] roots_mem_iff_is_root[of p] unfolding is_root_def by force + then obtain a where a: "a \ carrier R" "a \# roots p" + and pdiv: "[ \, \ a ] pdivides p" and in_carrier: "[ \, \ a ] \ carrier (poly_ring R)" + using less(2) by blast + then obtain q where q: "q \ carrier (poly_ring R)" and p: "p = [ \, \ a ] \\<^bsub>poly_ring R\<^esub> q" + unfolding pdivides_def by blast + with \degree p > 1\ have not_zero: "q \ []" and "p \ []" + using domain.integral_iff[OF univ_poly_is_domain[OF carrier_is_subring] in_carrier, of q] + by (auto simp add: univ_poly_zero[of R "carrier R"]) + hence deg: "degree p = Suc (degree q)" + using poly_mult_degree_eq[OF carrier_is_subring] in_carrier q p + unfolding univ_poly_carrier sym[OF univ_poly_mult[of R "carrier R"]] by auto + hence "splitted q" + using less(1)[OF _ q] by simp + moreover have "roots p = add_mset a (roots q)" + using poly_mult_degree_one_monic_imp_same_roots[OF a(1) q not_zero] p by simp + ultimately show ?thesis + unfolding splitted_def deg by simp + qed + qed +qed + +sublocale algebraic_closure \ algebraically_closed +proof (rule algebraically_closedI) + fix P assume in_carrier: "P \ carrier (poly_ring L)" and gt_one: "degree P > 1" + then have gt_zero: "degree P > 0" + by simp + + define A where "A = finite_extension K P" + + from \P \ carrier (poly_ring L)\ have "set P \ carrier L" + by (simp add: polynomial_incl univ_poly_carrier) + hence A: "subfield A L" and P: "P \ carrier (A[X])" + using finite_extension_mem[OF subfieldE(1)[OF subfield_axioms], of P] in_carrier + algebraic_extension finite_extension_is_subfield[OF subfield_axioms, of P] + unfolding sym[OF A_def] sym[OF univ_poly_carrier] polynomial_def by auto + from \set P \ carrier L\ have incl: "K \ A" + using finite_extension_incl[OF subfieldE(3)[OF subfield_axioms]] unfolding A_def by simp + + interpret UP_K: domain "K[X]" + using univ_poly_is_domain[OF subfieldE(1)[OF subfield_axioms]] . + interpret UP_A: domain "A[X]" + using univ_poly_is_domain[OF subfieldE(1)[OF A]] . + interpret Rupt: ring "Rupt A P" + unfolding rupture_def using ideal.quotient_is_ring[OF UP_A.cgenideal_ideal[OF P]] . + interpret Hom: ring_hom_ring "L \ carrier := A \" "Rupt A P" "rupture_surj A P \ poly_of_const" + using ring_hom_ringI2[OF subring_is_ring[OF subfieldE(1)] Rupt.ring_axioms + rupture_surj_norm_is_hom[OF subfieldE(1) P]] A by simp + let ?h = "rupture_surj A P \ poly_of_const" + + have h_simp: "rupture_surj A P ` poly_of_const ` E = ?h ` E" for E + by auto + hence aux_lemmas: + "subfield (rupture_surj A P ` poly_of_const ` K) (Rupt A P)" + "subfield (rupture_surj A P ` poly_of_const ` A) (Rupt A P)" + using Hom.img_is_subfield(2)[OF _ rupture_one_not_zero[OF A P gt_zero]] + ring.subfield_iff(1)[OF subring_is_ring[OF subfieldE(1)[OF A]]] + subfield_iff(2)[OF subfield_axioms] subfield_iff(2)[OF A] incl + by auto + + have "carrier (K[X]) \ carrier (A[X])" + using subsetI[of "carrier (K[X])" "carrier (A[X])"] incl + unfolding sym[OF univ_poly_carrier] polynomial_def by auto + hence "id \ ring_hom (K[X]) (A[X])" + unfolding ring_hom_def unfolding univ_poly_mult univ_poly_add univ_poly_one by (simp add: subsetD) + hence "rupture_surj A P \ ring_hom (K[X]) (Rupt A P)" + using ring_hom_trans[OF _ rupture_surj_hom(1)[OF subfieldE(1)[OF A] P], of id] by simp + then interpret Hom': ring_hom_ring "K[X]" "Rupt A P" "rupture_surj A P" + using ring_hom_ringI2[OF UP_K.ring_axioms Rupt.ring_axioms] by simp + + from \id \ ring_hom (K[X]) (A[X])\ have Id: "ring_hom_ring (K[X]) (A[X]) id" + using ring_hom_ringI2[OF UP_K.ring_axioms UP_A.ring_axioms] by simp + hence "subalgebra (poly_of_const ` K) (carrier (K[X])) (A[X])" + using ring_hom_ring.img_is_subalgebra[OF Id _ UP_K.carrier_is_subalgebra[OF subfieldE(3)]] + univ_poly_subfield_of_consts[OF subfield_axioms] by auto + + moreover from \carrier (K[X]) \ carrier (A[X])\ have "poly_of_const ` K \ carrier (A[X])" + using subfieldE(3)[OF univ_poly_subfield_of_consts[OF subfield_axioms]] by simp + + ultimately + have "subalgebra (rupture_surj A P ` poly_of_const ` K) (rupture_surj A P ` carrier (K[X])) (Rupt A P)" + using ring_hom_ring.img_is_subalgebra[OF rupture_surj_hom(2)[OF subfieldE(1)[OF A] P]] by simp + + moreover have "Rupt.finite_dimension (rupture_surj A P ` poly_of_const ` K) (carrier (Rupt A P))" + proof (intro Rupt.telescopic_base_dim(1)[where + ?K = "rupture_surj A P ` poly_of_const ` K" and + ?F = "rupture_surj A P ` poly_of_const ` A" and + ?E = "carrier (Rupt A P)", OF aux_lemmas]) + show "Rupt.finite_dimension (rupture_surj A P ` poly_of_const ` A) (carrier (Rupt A P))" + using Rupt.finite_dimensionI[OF rupture_dimension[OF A P gt_zero]] . + next + let ?h = "rupture_surj A P \ poly_of_const" + + from \set P \ carrier L\ have "finite_dimension K A" + using finite_extension_finite_dimension(1)[OF subfield_axioms, of P] algebraic_extension + unfolding A_def by auto + then obtain Us where Us: "set Us \ carrier L" "A = Span K Us" + using exists_base subfield_axioms by blast + hence "?h ` A = Rupt.Span (?h ` K) (map ?h Us)" + using Hom.Span_hom[of K Us] incl Span_base_incl[OF subfield_axioms, of Us] + unfolding Span_consistent[OF subfieldE(1)[OF A]] by simp + moreover have "set (map ?h Us) \ carrier (Rupt A P)" + using Span_base_incl[OF subfield_axioms Us(1)] ring_hom_memE(1)[OF Hom.homh] + unfolding sym[OF Us(2)] by auto + ultimately + show "Rupt.finite_dimension (rupture_surj A P ` poly_of_const ` K) (rupture_surj A P ` poly_of_const ` A)" + using Rupt.Span_finite_dimension[OF aux_lemmas(1)] unfolding h_simp by simp + qed + + moreover have "rupture_surj A P ` carrier (A[X]) = carrier (Rupt A P)" + unfolding rupture_def FactRing_def A_RCOSETS_def' by auto + with \carrier (K[X]) \ carrier (A[X])\ have "rupture_surj A P ` carrier (K[X]) \ carrier (Rupt A P)" + by auto + + ultimately + have "Rupt.finite_dimension (rupture_surj A P ` poly_of_const ` K) (rupture_surj A P ` carrier (K[X]))" + using Rupt.subalbegra_incl_imp_finite_dimension[OF aux_lemmas(1)] by simp + + hence "\ inj_on (rupture_surj A P) (carrier (K[X]))" + using Hom'.infinite_dimension_hom[OF _ rupture_one_not_zero[OF A P gt_zero] _ + UP_K.carrier_is_subalgebra[OF subfieldE(3)] univ_poly_infinite_dimension[OF subfield_axioms]] + univ_poly_subfield_of_consts[OF subfield_axioms] + by auto + then obtain Q where Q: "Q \ carrier (K[X])" "Q \ []" and "rupture_surj A P Q = \\<^bsub>Rupt A P\<^esub>" + using Hom'.trivial_ker_imp_inj Hom'.hom_zero unfolding a_kernel_def' univ_poly_zero by blast + with \carrier (K[X]) \ carrier (A[X])\ have "Q \ PIdl\<^bsub>A[X]\<^esub> P" + using ideal.rcos_const_imp_mem[OF UP_A.cgenideal_ideal[OF P]] + unfolding rupture_def FactRing_def by auto + then obtain R where "R \ carrier (A[X])" and "Q = R \\<^bsub>A[X]\<^esub> P" + unfolding cgenideal_def by blast + with \P \ carrier (A[X])\ have "P pdivides Q" + using dividesI[of _ "A[X]"] UP_A.m_comm pdivides_iff_shell[OF A] by simp + hence "splitted P" + using pdivides_imp_splitted[OF in_carrier + carrier_polynomial_shell[OF subfieldE(1)[OF subfield_axioms] Q(1)] Q(2) + roots_over_subfield[OF Q(1)]] Q by simp + with \degree P > 1\ obtain a where "a \# roots P" + unfolding splitted_def by force + thus "\x\carrier L. eval P x = \" + unfolding roots_mem_iff_is_root[OF in_carrier] is_root_def by blast +qed + end - +