diff --git a/metadata/entries/Finite_Fields.toml b/metadata/entries/Finite_Fields.toml --- a/metadata/entries/Finite_Fields.toml +++ b/metadata/entries/Finite_Fields.toml @@ -1,39 +1,39 @@ title = "Finite Fields" date = 2022-06-08 topics = [ "Mathematics/Algebra", ] abstract = """ This entry formalizes the classification of the finite fields (also called Galois fields): For each prime power $p^n$ there exists exactly one (up to isomorphisms) finite field of that size and there are no other finite fields. The derivation includes a formalization of the characteristic of rings, the Frobenius endomorphism, formal differentiation for polynomials in HOL-Algebra, Rabin's test for the irreducibility of polynomials and Gauss' formula for the number of monic irreducible polynomials over finite fields: \\[ \\frac{1}{n} \\sum_{d | n} \\mu(d) p^{n/d} \\textrm{.} \\] The proofs are based on the books and publications from Ireland and Rosen, Rabin, as well as, Lidl and Niederreiter.""" license = "bsd" note = "" [authors] [authors.karayel] homepage = "karayel_homepage" [contributors] [notify] karayel = "karayel_email" [history] -2023-01-17 = "Added Rabin's test for the irreducibility of polynomials in finite fields." +2024-01-17 = "Added Rabin's test for the irreducibility of polynomials in finite fields." [extra] [related] diff --git a/thys/Finite_Fields/Finite_Fields_Preliminary_Results.thy b/thys/Finite_Fields/Finite_Fields_Preliminary_Results.thy --- a/thys/Finite_Fields/Finite_Fields_Preliminary_Results.thy +++ b/thys/Finite_Fields/Finite_Fields_Preliminary_Results.thy @@ -1,1010 +1,1037 @@ section \Introduction\ text \The following section starts with preliminary results. Section~\ref{sec:ring_char} introduces the characteristic of rings with the Frobenius endomorphism. Whenever it makes sense, the definitions and facts do not assume the finiteness of the fields or rings. For example the characteristic is defined over arbitrary rings (and also fields). While formal derivatives do exist for type-class based structures in \verb|HOL-Computational_Algebra|, as far as I can tell, they do not exist for the structure based polynomials in \verb|HOL-Algebra|. These are introduced in Section~\ref{sec:pderiv}. A cornerstone of the proof is the derivation of Gauss' formula for the number of monic irreducible polynomials over a finite field $R$ in Section~\ref{sec:card_irred}. The proof follows the derivation by Ireland and Rosen~\<^cite>\\\textsection 7\ in "ireland1982"\ closely, with the caveat that it does not assume that $R$ is a simple prime field, but that it is just a finite field. This works by adjusting a proof step with the information that the order of a finite field must be of the form $p^n$, where $p$ is the characteristic of the field, derived in Section~\ref{sec:ring_char}. The final step relies on the M\"obius inversion theorem formalized by Eberl~\<^cite>\"Dirichlet_Series-AFP"\.\footnote{Thanks to Katharina Kreuzer for discovering that formalization.} With Gauss' formula it is possible to show the existence of the finite fields of order $p^n$ where $p$ is a prime and $n > 0$. During the proof the fact that the polynomial $X^n - X$ splits in a field of order $n$ is also derived, which is necessary for the uniqueness result as well. The uniqueness proof is inspired by the derivation of the same result in Lidl and Niederreiter~\<^cite>\"lidl1986"\, but because of the already derived existence proof for irreducible polynomials, it was possible to reduce its complexity. The classification consists of three theorems: \begin{itemize} \item \emph{Existence}: For each prime power $p^n$ there exists a finite field of that size. This is shown at the conclusion of Section~\ref{sec:card_irred}. \item \emph{Uniqueness}: Any two finite fields of the same size are isomorphic. This is shown at the conclusion of Section~\ref{sec:uniqueness}. \item \emph{Completeness}: Any finite fields' size must be a prime power. This is shown at the conclusion of Section~\ref{sec:ring_char}. \end{itemize} \ section \Preliminary Results\ theory Finite_Fields_Preliminary_Results imports "HOL-Algebra.Polynomial_Divisibility" begin subsection \Summation in the discrete topology\ text \The following lemmas transfer the corresponding result from the summation over finite sets to summation over functions which vanish outside of a finite set.\ lemma sum'_subtractf_nat: fixes f :: "'a \ nat" assumes "finite {i \ A. f i \ 0}" assumes "\i. i \ A \ g i \ f i" shows "sum' (\i. f i - g i) A = sum' f A - sum' g A" (is "?lhs = ?rhs") proof - have c:"finite {i \ A. g i \ 0}" using assms(2) by (intro finite_subset[OF _ assms(1)] subsetI, force) let ?B = "{i \ A. f i \ 0 \ g i \ 0}" have b:"?B = {i \ A. f i \ 0} \ {i \ A. g i \ 0}" by (auto simp add:set_eq_iff) have a:"finite ?B" using assms(1) c by (subst b, simp) have "?lhs = sum' (\i. f i - g i) ?B" by (intro sum.mono_neutral_cong_right', simp_all) also have "... = sum (\i. f i - g i) ?B" by (intro sum.eq_sum a) also have "... = sum f ?B - sum g ?B" using assms(2) by (subst sum_subtractf_nat, auto) also have "... = sum' f ?B - sum' g ?B" by (intro arg_cong2[where f="(-)"] sum.eq_sum[symmetric] a) also have "... = ?rhs" by (intro arg_cong2[where f="(-)"] sum.mono_neutral_cong_left') simp_all finally show ?thesis by simp qed lemma sum'_nat_eq_0_iff: fixes f :: "'a \ nat" assumes "finite {i \ A. f i \ 0}" assumes "sum' f A = 0" shows "\i. i \ A \ f i = 0" proof - let ?B = "{i \ A. f i \ 0}" have "sum f ?B = sum' f ?B" by (intro sum.eq_sum[symmetric] assms(1)) also have "... = sum' f A" by (intro sum.non_neutral') also have "... = 0" using assms(2) by simp finally have a:"sum f ?B = 0" by simp have "\i. i \ ?B \ f i = 0" using sum_nonneg_0[OF assms(1) _ a] by blast thus "\i. i \ A \ f i = 0" by blast qed lemma sum'_eq_iff: fixes f :: "'a \ nat" assumes "finite {i \ A. f i \ 0}" assumes "\i. i \ A \ f i \ g i" assumes "sum' f A \ sum' g A" shows "\i \ A. f i = g i" proof - have "{i \ A. g i \ 0} \ {i \ A. f i \ 0}" using assms(2) order_less_le_trans by (intro subsetI, auto) hence a:"finite {i \ A. g i \ 0}" by (rule finite_subset, intro assms(1)) have " {i \ A. f i - g i \ 0} \ {i \ A. f i \ 0}" by (intro subsetI, simp_all) hence b: "finite {i \ A. f i - g i \ 0}" by (rule finite_subset, intro assms(1)) have "sum' (\i. f i - g i) A = sum' f A - sum' g A" using assms(1,2) a by (subst sum'_subtractf_nat, auto) also have "... = 0" using assms(3) by simp finally have "sum' (\i. f i - g i) A = 0" by simp hence "\i. i \ A \ f i - g i = 0" using sum'_nat_eq_0_iff[OF b] by simp thus ?thesis using assms(2) diff_is_0_eq' diffs0_imp_equal by blast qed subsection \Polynomials\ text \The embedding of the constant polynomials into the polynomials is injective:\ lemma (in ring) poly_of_const_inj: "inj poly_of_const" proof - have "coeff (poly_of_const x) 0 = x" for x unfolding poly_of_const_def normalize_coeff[symmetric] by simp thus ?thesis by (metis injI) qed lemma (in domain) embed_hom: assumes "subring K R" shows "ring_hom_ring (K[X]) (poly_ring R) id" proof (rule ring_hom_ringI) show "ring (K[X])" using univ_poly_is_ring[OF assms(1)] by simp show "ring (poly_ring R)" using univ_poly_is_ring[OF carrier_is_subring] by simp have "K \ carrier R" using subringE(1)[OF assms(1)] by simp thus "\x. x \ carrier (K [X]) \ id x \ carrier (poly_ring R)" unfolding univ_poly_carrier[symmetric] polynomial_def by auto show "id (x \\<^bsub>K [X]\<^esub> y) = id x \\<^bsub>poly_ring R\<^esub> id y" if "x \ carrier (K [X])" "y \ carrier (K [X])" for x y unfolding univ_poly_mult by simp show "id (x \\<^bsub>K [X]\<^esub> y) = id x \\<^bsub>poly_ring R\<^esub> id y" if "x \ carrier (K [X])" "y \ carrier (K [X])" for x y unfolding univ_poly_add by simp show "id \\<^bsub>K [X]\<^esub> = \\<^bsub>poly_ring R\<^esub>" unfolding univ_poly_one by simp qed text \The following are versions of the properties of the degrees of polynomials, that abstract over the definition of the polynomial ring structure. In the theories @{theory "HOL-Algebra.Polynomials"} and also @{theory "HOL-Algebra.Polynomial_Divisibility"} these abstract version are usually indicated with the suffix ``shell'', consider for example: @{thm [source] "domain.pdivides_iff_shell"}.\ lemma (in ring) degree_add_distinct: assumes "subring K R" assumes "f \ carrier (K[X]) - {\\<^bsub>K[X]\<^esub>}" assumes "g \ carrier (K[X]) - {\\<^bsub>K[X]\<^esub>}" assumes "degree f \ degree g" shows "degree (f \\<^bsub>K[X]\<^esub> g) = max (degree f) (degree g)" unfolding univ_poly_add using assms(2,3,4) by (subst poly_add_degree_eq[OF assms(1)]) (auto simp:univ_poly_carrier univ_poly_zero) lemma (in domain) degree_mult: assumes "subring K R" assumes "f \ carrier (K[X]) - {\\<^bsub>K[X]\<^esub>}" assumes "g \ carrier (K[X]) - {\\<^bsub>K[X]\<^esub>}" shows "degree (f \\<^bsub>K[X]\<^esub> g) = degree f + degree g" unfolding univ_poly_mult using assms(2,3) by (subst poly_mult_degree_eq[OF assms(1)]) (auto simp:univ_poly_carrier univ_poly_zero) lemma (in ring) degree_one: "degree (\\<^bsub>K[X]\<^esub>) = 0" unfolding univ_poly_one by simp lemma (in domain) pow_non_zero: "x \ carrier R \ x \ \ \ x [^] (n :: nat) \ \" using integral by (induction n, auto) lemma (in domain) degree_pow: assumes "subring K R" assumes "f \ carrier (K[X]) - {\\<^bsub>K[X]\<^esub>}" shows "degree (f [^]\<^bsub>K[X]\<^esub> n) = degree f * n" proof - interpret p:domain "K[X]" using univ_poly_is_domain[OF assms(1)] by simp show ?thesis proof (induction n) case 0 then show ?case by (simp add:univ_poly_one) next case (Suc n) have "degree (f [^]\<^bsub>K [X]\<^esub> Suc n) = degree (f [^]\<^bsub>K [X]\<^esub> n \\<^bsub>K[X]\<^esub> f)" by simp also have "... = degree (f [^]\<^bsub>K [X]\<^esub> n) + degree f" using p.pow_non_zero assms(2) by (subst degree_mult[OF assms(1)], auto) also have "... = degree f * Suc n" by (subst Suc, simp) finally show ?case by simp qed qed lemma (in ring) degree_var: "degree (X\<^bsub>R\<^esub>) = 1" unfolding var_def by simp lemma (in domain) var_carr: fixes n :: nat assumes "subring K R" shows "X\<^bsub>R\<^esub> \ carrier (K[X]) - {\\<^bsub>K [X]\<^esub>}" proof - have "X\<^bsub>R\<^esub> \ carrier (K[X])" using var_closed[OF assms(1)] by simp moreover have "X \ \\<^bsub>K [X]\<^esub>" unfolding var_def univ_poly_zero by simp ultimately show ?thesis by simp qed lemma (in domain) var_pow_carr: fixes n :: nat assumes "subring K R" shows "X\<^bsub>R\<^esub> [^]\<^bsub>K [X]\<^esub> n \ carrier (K[X]) - {\\<^bsub>K [X]\<^esub>}" proof - interpret p:domain "K[X]" using univ_poly_is_domain[OF assms(1)] by simp have "X\<^bsub>R\<^esub> [^]\<^bsub>K [X]\<^esub> n \ carrier (K[X])" using var_pow_closed[OF assms(1)] by simp moreover have "X \ \\<^bsub>K [X]\<^esub>" unfolding var_def univ_poly_zero by simp hence "X\<^bsub>R\<^esub> [^]\<^bsub>K [X]\<^esub> n \ \\<^bsub>K [X]\<^esub>" using var_closed(1)[OF assms(1)] by (intro p.pow_non_zero, auto) ultimately show ?thesis by simp qed lemma (in domain) var_pow_degree: fixes n :: nat assumes "subring K R" shows "degree (X\<^bsub>R\<^esub> [^]\<^bsub>K [X]\<^esub> n) = n" using var_carr[OF assms(1)] degree_var by (subst degree_pow[OF assms(1)], auto) lemma (in domain) finprod_non_zero: assumes "finite A" assumes "f \ A \ carrier R - {\}" shows "(\i \ A. f i) \ carrier R - {\}" using assms proof (induction A rule:finite_induct) case empty then show ?case by simp next case (insert x F) have "finprod R f (insert x F) = f x \ finprod R f F" using insert by (subst finprod_insert, simp_all add:Pi_def) also have "... \ carrier R-{\}" using integral insert by auto finally show ?case by simp qed lemma (in domain) degree_prod: assumes "finite A" assumes "subring K R" assumes "f \ A \ carrier (K[X]) - {\\<^bsub>K[X]\<^esub>}" shows "degree (\\<^bsub>K[X]\<^esub>i \ A. f i) = (\i \ A. degree (f i))" using assms proof - interpret p:domain "K[X]" using univ_poly_is_domain[OF assms(2)] by simp show ?thesis using assms(1,3) proof (induction A rule: finite_induct) case empty then show ?case by (simp add:univ_poly_one) next case (insert x F) have "degree (finprod (K[X]) f (insert x F)) = degree (f x \\<^bsub>K[X]\<^esub> finprod (K[X]) f F)" using insert by (subst p.finprod_insert, auto) also have "... = degree (f x) + degree (finprod (K[X]) f F)" using insert p.finprod_non_zero[OF insert(1)] by (subst degree_mult[OF assms(2)], simp_all) also have "... = degree (f x) + (\i \ F. degree (f i))" using insert by (subst insert(3), auto) also have "... = (\i \ insert x F. degree (f i))" using insert by simp finally show ?case by simp qed qed lemma (in ring) coeff_add: assumes "subring K R" assumes "f \ carrier (K[X])" "g \ carrier (K[X])" shows "coeff (f \\<^bsub>K[X]\<^esub> g) i = coeff f i \\<^bsub>R\<^esub> coeff g i" proof - have a:"set f \ carrier R" using assms(1,2) univ_poly_carrier using subringE(1)[OF assms(1)] polynomial_incl by blast have b:"set g \ carrier R" using assms(1,3) univ_poly_carrier using subringE(1)[OF assms(1)] polynomial_incl by blast show ?thesis unfolding univ_poly_add poly_add_coeff[OF a b] by simp qed + +lemma (in domain) coeff_a_inv: + assumes "subring K R" + assumes "f \ carrier (K[X])" + shows "coeff (\\<^bsub>K[X]\<^esub> f) i = \ (coeff f i)" (is "?L = ?R") +proof - + have "?L = coeff (map (a_inv R) f) i" + unfolding univ_poly_a_inv_def'[OF assms(1,2)] by simp + also have "... = ?R" by (induction f) auto + finally show ?thesis by simp +qed + text \This is a version of geometric sums for commutative rings:\ lemma (in cring) geom: fixes q:: nat assumes [simp]: "a \ carrier R" shows "(a \ \) \ (\i\{.. \)" (is "?lhs = ?rhs") proof - have [simp]: "a [^] i \ carrier R" for i :: nat by (intro nat_pow_closed assms) have [simp]: "\ \ \ x = \ x" if "x \ carrier R" for x using l_minus l_one one_closed that by presburger let ?cterm = "(\i\{1.. (\i\{.. (\i\{..i\{.. a [^] i) \ (\i\{..i\{.. (\i\{..i\Suc ` {.. (\i\{..i\ insert q {1.. (\i\ insert 0 {1.. 0") case True moreover have "Suc ` {.. ?cterm) \ (\ \ ?cterm)" by simp also have "... = a [^] q \ ?cterm \ (\ \ \ \ ?cterm)" unfolding a_minus_def by (subst minus_add, simp_all) also have "... = a [^] q \ (?cterm \ (\ \ \ \ ?cterm))" by (subst a_assoc, simp_all) also have "... = a [^] q \ (?cterm \ (\ ?cterm \ \ \))" by (subst a_comm[where x="\ \"], simp_all) also have "... = a [^] q \ ((?cterm \ (\ ?cterm)) \ \ \)" by (subst a_assoc, simp_all) also have "... = a [^] q \ (\ \ \ \)" by (subst r_neg, simp_all) also have "... = a [^] q \ \" unfolding a_minus_def by simp finally show ?thesis by simp qed lemma (in domain) rupture_eq_0_iff: assumes "subfield K R" "p \ carrier (K[X])" "q \ carrier (K[X])" shows "rupture_surj K p q = \\<^bsub>Rupt K p\<^esub> \ p pdivides q" (is "?lhs \ ?rhs") proof - interpret h:ring_hom_ring "K[X]" "(Rupt K p)" "(rupture_surj K p)" using assms subfieldE by (intro rupture_surj_hom) auto have a: "q pmod p \ (\q. q pmod p) ` carrier (K [X])" using assms(3) by simp have "\\<^bsub>K[X]\<^esub> = \\<^bsub>K[X]\<^esub> pmod p" using assms(1,2) long_division_zero(2) by (simp add:univ_poly_zero) hence b: "\\<^bsub>K[X]\<^esub> \ (\q. q pmod p) ` carrier (K[X])" by (simp add:image_iff) auto have "?lhs \ rupture_surj K p (q pmod p) = rupture_surj K p (\\<^bsub>K[X]\<^esub>)" by (subst rupture_surj_composed_with_pmod[OF assms]) simp also have "... \ q pmod p = \\<^bsub>K[X]\<^esub>" using assms(3) by (intro inj_on_eq_iff[OF rupture_surj_inj_on[OF assms(1,2)]] a b) also have "... \ ?rhs" unfolding univ_poly_zero by (intro pmod_zero_iff_pdivides[OF assms(1)] assms(2,3)) finally show "?thesis" by simp qed subsection \Ring Isomorphisms\ text \The following lemma shows that an isomorphism between domains also induces an isomorphism between the corresponding polynomial rings.\ lemma lift_iso_to_poly_ring: assumes "h \ ring_iso R S" "domain R" "domain S" shows "map h \ ring_iso (poly_ring R) (poly_ring S)" proof (rule ring_iso_memI) interpret dr: domain "R" using assms(2) by blast interpret ds: domain "S" using assms(3) by blast interpret pdr: domain "poly_ring R" using dr.univ_poly_is_domain[OF dr.carrier_is_subring] by simp interpret pds: domain "poly_ring S" using ds.univ_poly_is_domain[OF ds.carrier_is_subring] by simp interpret h: ring_hom_ring "R" "S" h using dr.ring_axioms ds.ring_axioms assms(1) by (intro ring_hom_ringI2, simp_all add:ring_iso_def) let ?R = "poly_ring R" let ?S = "poly_ring S" have h_img: "h ` (carrier R) = carrier S" using assms(1) unfolding ring_iso_def bij_betw_def by auto have h_inj: "inj_on h (carrier R)" using assms(1) unfolding ring_iso_def bij_betw_def by auto hence h_non_zero_iff: "h x \ \\<^bsub>S\<^esub>" if "x \ \\<^bsub>R\<^esub>" "x \ carrier R" for x using h.hom_zero dr.zero_closed inj_onD that by metis have norm_elim: "ds.normalize (map h x) = map h x" if "x \ carrier (poly_ring R)" for x proof (cases "x") case Nil then show ?thesis by simp next case (Cons xh xt) have "xh \ carrier R" "xh \ \\<^bsub>R\<^esub>" using that unfolding Cons univ_poly_carrier[symmetric] unfolding polynomial_def by auto hence "h xh \ \\<^bsub>S\<^esub>" using h_non_zero_iff by simp then show ?thesis unfolding Cons by simp qed show t_1: "map h x \ carrier ?S" if "x \ carrier ?R" for x using that hd_in_set h_non_zero_iff hd_map unfolding univ_poly_carrier[symmetric] polynomial_def by (cases x, auto) show "map h (x \\<^bsub>?R\<^esub> y) = map h x \\<^bsub>?S\<^esub> map h y" if "x \ carrier ?R" "y \ carrier ?R" for x y proof - have "map h (x \\<^bsub>?R\<^esub> y) = ds.normalize (map h (x \\<^bsub>?R\<^esub> y))" using that by (intro norm_elim[symmetric],simp) also have "... = map h x \\<^bsub>?S\<^esub> map h y" using that unfolding univ_poly_mult univ_poly_carrier[symmetric] unfolding polynomial_def by (intro h.poly_mult_hom'[of x y] , auto) finally show ?thesis by simp qed show "map h (x \\<^bsub>?R\<^esub> y) = map h x \\<^bsub>?S\<^esub> map h y" if "x \ carrier ?R" "y \ carrier ?R" for x y proof - have "map h (x \\<^bsub>?R\<^esub> y) = ds.normalize (map h (x \\<^bsub>?R\<^esub> y))" using that by (intro norm_elim[symmetric],simp) also have "... = map h x \\<^bsub>?S\<^esub> map h y" using that unfolding univ_poly_add univ_poly_carrier[symmetric] unfolding polynomial_def by (intro h.poly_add_hom'[of x y], auto) finally show ?thesis by simp qed show "map h \\<^bsub>?R\<^esub> = \\<^bsub>?S\<^esub>" unfolding univ_poly_one by simp let ?hinv = "map (the_inv_into (carrier R) h)" have "map h \ carrier ?R \ carrier ?S" using t_1 by simp moreover have "?hinv x \ carrier ?R" if "x \ carrier ?S" for x proof (cases "x = []") case True then show ?thesis by (simp add:univ_poly_carrier[symmetric] polynomial_def) next case False have set_x: "set x \ h ` carrier R" using that h_img unfolding univ_poly_carrier[symmetric] unfolding polynomial_def by auto have "lead_coeff x \ \\<^bsub>S\<^esub>" "lead_coeff x \ carrier S" using that False unfolding univ_poly_carrier[symmetric] unfolding polynomial_def by auto hence "the_inv_into (carrier R) h (lead_coeff x) \ the_inv_into (carrier R) h \\<^bsub>S\<^esub>" using inj_on_the_inv_into[OF h_inj] inj_onD using ds.zero_closed h_img by metis hence "the_inv_into (carrier R) h (lead_coeff x) \ \\<^bsub>R\<^esub>" unfolding h.hom_zero[symmetric] unfolding the_inv_into_f_f[OF h_inj dr.zero_closed] by simp hence "lead_coeff (?hinv x) \ \\<^bsub>R\<^esub>" using False by (simp add:hd_map) moreover have "the_inv_into (carrier R) h ` set x \ carrier R" using the_inv_into_into[OF h_inj] set_x by (intro image_subsetI) auto hence "set (?hinv x) \ carrier R" by simp ultimately show ?thesis by (simp add:univ_poly_carrier[symmetric] polynomial_def) qed moreover have "?hinv (map h x) = x" if "x \ carrier ?R" for x proof - have set_x: "set x \ carrier R" using that unfolding univ_poly_carrier[symmetric] unfolding polynomial_def by auto have "?hinv (map h x) = map (\y. the_inv_into (carrier R) h (h y)) x" by simp also have "... = map id x" using set_x by (intro map_cong) (auto simp add:the_inv_into_f_f[OF h_inj]) also have "... = x" by simp finally show ?thesis by simp qed moreover have "map h (?hinv x) = x" if "x \ carrier ?S" for x proof - have set_x: "set x \ h ` carrier R" using that h_img unfolding univ_poly_carrier[symmetric] unfolding polynomial_def by auto have "map h (?hinv x) = map (\y. h (the_inv_into (carrier R) h y)) x" by simp also have "... = map id x" using set_x by (intro map_cong) (auto simp add:f_the_inv_into_f[OF h_inj]) also have "... = x" by simp finally show ?thesis by simp qed ultimately show "bij_betw (map h) (carrier ?R) (carrier ?S)" by (intro bij_betwI[where g="?hinv"], auto) qed lemma carrier_hom: assumes "f \ carrier (poly_ring R)" assumes "h \ ring_iso R S" "domain R" "domain S" shows "map h f \ carrier (poly_ring S)" proof - note poly_iso = lift_iso_to_poly_ring[OF assms(2,3,4)] show ?thesis using ring_iso_memE(1)[OF poly_iso assms(1)] by simp qed lemma carrier_hom': assumes "f \ carrier (poly_ring R)" assumes "h \ ring_hom R S" assumes "domain R" "domain S" assumes "inj_on h (carrier R)" shows "map h f \ carrier (poly_ring S)" proof - let ?S = "S \ carrier := h ` carrier R \" interpret dr: domain "R" using assms(3) by blast interpret ds: domain "S" using assms(4) by blast interpret h1: ring_hom_ring R S h using assms(2) ring_hom_ringI2 dr.ring_axioms using ds.ring_axioms by blast have subr: "subring (h ` carrier R) S" using h1.img_is_subring[OF dr.carrier_is_subring] by blast interpret h: ring_hom_ring "((h ` carrier R)[X]\<^bsub>S\<^esub>)" "poly_ring S" "id" using ds.embed_hom[OF subr] by simp let ?S = "S \ carrier := h ` carrier R \" have "h \ ring_hom R ?S" using assms(2) unfolding ring_hom_def by simp moreover have "bij_betw h (carrier R) (carrier ?S)" using assms(5) bij_betw_def by auto ultimately have h_iso: "h \ ring_iso R ?S" unfolding ring_iso_def by simp have dom_S: "domain ?S" using ds.subring_is_domain[OF subr] by simp note poly_iso = lift_iso_to_poly_ring[OF h_iso assms(3) dom_S] have "map h f \ carrier (poly_ring ?S)" using ring_iso_memE(1)[OF poly_iso assms(1)] by simp also have "carrier (poly_ring ?S) = carrier (univ_poly S (h ` carrier R))" using ds.univ_poly_consistent[OF subr] by simp also have "... \ carrier (poly_ring S)" using h.hom_closed by auto finally show ?thesis by simp qed text \The following lemmas transfer properties like divisibility, irreducibility etc. between ring isomorphisms.\ lemma divides_hom: assumes "h \ ring_iso R S" assumes "domain R" "domain S" assumes "x \ carrier R" "y \ carrier R" shows "x divides\<^bsub>R\<^esub> y \ (h x) divides\<^bsub>S\<^esub> (h y)" (is "?lhs \ ?rhs") proof - interpret dr: domain "R" using assms(2) by blast interpret ds: domain "S" using assms(3) by blast interpret pdr: domain "poly_ring R" using dr.univ_poly_is_domain[OF dr.carrier_is_subring] by simp interpret pds: domain "poly_ring S" using ds.univ_poly_is_domain[OF ds.carrier_is_subring] by simp interpret h: ring_hom_ring "R" "S" h using dr.ring_axioms ds.ring_axioms assms(1) by (intro ring_hom_ringI2, simp_all add:ring_iso_def) have h_inj_on: "inj_on h (carrier R)" using assms(1) unfolding ring_iso_def bij_betw_def by auto have h_img: "h ` (carrier R) = carrier S" using assms(1) unfolding ring_iso_def bij_betw_def by auto have "?lhs \ (\c \ carrier R. y = x \\<^bsub>R\<^esub> c)" unfolding factor_def by simp also have "... \ (\c \ carrier R. h y = h x \\<^bsub>S\<^esub> h c)" using assms(4,5) inj_onD[OF h_inj_on] by (intro bex_cong, auto simp flip:h.hom_mult) also have "... \ (\c \ carrier S. h y = h x \\<^bsub>S\<^esub> c)" unfolding h_img[symmetric] by simp also have "... \ ?rhs" unfolding factor_def by simp finally show ?thesis by simp qed lemma properfactor_hom: assumes "h \ ring_iso R S" assumes "domain R" "domain S" assumes "x \ carrier R" "b \ carrier R" shows "properfactor R b x \ properfactor S (h b) (h x)" using divides_hom[OF assms(1,2,3)] assms(4,5) unfolding properfactor_def by simp lemma Units_hom: assumes "h \ ring_iso R S" assumes "domain R" "domain S" assumes "x \ carrier R" shows "x \ Units R \ h x \ Units S" proof - interpret dr: domain "R" using assms(2) by blast interpret ds: domain "S" using assms(3) by blast interpret pdr: domain "poly_ring R" using dr.univ_poly_is_domain[OF dr.carrier_is_subring] by simp interpret pds: domain "poly_ring S" using ds.univ_poly_is_domain[OF ds.carrier_is_subring] by simp interpret h: ring_hom_ring "R" "S" h using dr.ring_axioms ds.ring_axioms assms(1) by (intro ring_hom_ringI2, simp_all add:ring_iso_def) have h_img: "h ` (carrier R) = carrier S" using assms(1) unfolding ring_iso_def bij_betw_def by auto have h_inj_on: "inj_on h (carrier R)" using assms(1) unfolding ring_iso_def bij_betw_def by auto hence h_one_iff: "h x = \\<^bsub>S\<^esub> \ x = \\<^bsub>R\<^esub>" if "x \ carrier R" for x using h.hom_one that by (metis dr.one_closed inj_onD) have "x \ Units R \ (\y\carrier R. x \\<^bsub>R\<^esub> y = \\<^bsub>R\<^esub> \ y \\<^bsub>R\<^esub> x = \\<^bsub>R\<^esub>)" using assms unfolding Units_def by auto also have "... \ (\y\carrier R. h x \\<^bsub>S\<^esub> h y = h \\<^bsub>R\<^esub> \ h y \\<^bsub>S\<^esub> h x = h \\<^bsub>R\<^esub>)" using h_one_iff assms by (intro bex_cong, simp_all flip:h.hom_mult) also have "... \ (\y\carrier S. h x \\<^bsub>S\<^esub> y = h \\<^bsub>R\<^esub> \ y \\<^bsub>S\<^esub> h x = \\<^bsub>S\<^esub>)" unfolding h_img[symmetric] by simp also have "... \ h x \ Units S" using assms h.hom_closed unfolding Units_def by auto finally show ?thesis by simp qed lemma irreducible_hom: assumes "h \ ring_iso R S" assumes "domain R" "domain S" assumes "x \ carrier R" shows "irreducible R x = irreducible S (h x)" proof - have h_img: "h ` (carrier R) = carrier S" using assms(1) unfolding ring_iso_def bij_betw_def by auto have "irreducible R x \ (x \ Units R \ (\b\carrier R. properfactor R b x \ b \ Units R))" unfolding Divisibility.irreducible_def by simp also have "... \ (x \ Units R \ (\b\carrier R. properfactor S (h b) (h x) \ b \ Units R))" using properfactor_hom[OF assms(1,2,3)] assms(4) by simp also have "... \ (h x \ Units S \ (\b\carrier R. properfactor S (h b) (h x) \ h b \ Units S))" using assms(4) Units_hom[OF assms(1,2,3)] by simp also have "...\ (h x \ Units S \ (\b\h ` carrier R. properfactor S b (h x) \ b \ Units S))" by simp also have "... \ irreducible S (h x)" unfolding h_img Divisibility.irreducible_def by simp finally show ?thesis by simp qed lemma pirreducible_hom: assumes "h \ ring_iso R S" assumes "domain R" "domain S" assumes "f \ carrier (poly_ring R)" shows "pirreducible\<^bsub>R\<^esub> (carrier R) f = pirreducible\<^bsub>S\<^esub> (carrier S) (map h f)" (is "?lhs = ?rhs") proof - note lift_iso = lift_iso_to_poly_ring[OF assms(1,2,3)] interpret dr: domain "R" using assms(2) by blast interpret ds: domain "S" using assms(3) by blast interpret pdr: domain "poly_ring R" using dr.univ_poly_is_domain[OF dr.carrier_is_subring] by simp interpret pds: domain "poly_ring S" using ds.univ_poly_is_domain[OF ds.carrier_is_subring] by simp have mh_inj_on: "inj_on (map h) (carrier (poly_ring R))" using lift_iso unfolding ring_iso_def bij_betw_def by auto moreover have "map h \\<^bsub>poly_ring R\<^esub> = \\<^bsub>poly_ring S\<^esub>" by (simp add:univ_poly_zero) ultimately have mh_zero_iff: "map h f = \\<^bsub>poly_ring S\<^esub> \ f = \\<^bsub>poly_ring R\<^esub>" using assms(4) by (metis pdr.zero_closed inj_onD) have "?lhs \ (f \ \\<^bsub>poly_ring R\<^esub> \ irreducible (poly_ring R) f)" unfolding ring_irreducible_def by simp also have "... \ (f \ \\<^bsub>poly_ring R\<^esub> \ irreducible (poly_ring S) (map h f))" using irreducible_hom[OF lift_iso] pdr.domain_axioms using assms(4) pds.domain_axioms by simp also have "... \ (map h f \ \\<^bsub>poly_ring S\<^esub> \ irreducible (poly_ring S) (map h f))" using mh_zero_iff by simp also have "... \ ?rhs" unfolding ring_irreducible_def by simp finally show ?thesis by simp qed - lemma ring_hom_cong: assumes "\x. x \ carrier R \ f' x = f x" assumes "ring R" assumes "f \ ring_hom R S" shows "f' \ ring_hom R S" proof - interpret ring "R" using assms(2) by simp show ?thesis using assms(1) ring_hom_memE[OF assms(3)] by (intro ring_hom_memI, auto) qed text \The natural homomorphism between factor rings, where one ideal is a subset of the other.\ lemma (in ring) quot_quot_hom: assumes "ideal I R" assumes "ideal J R" assumes "I \ J" shows "(\x. (J <+>\<^bsub>R\<^esub> x)) \ ring_hom (R Quot I) (R Quot J)" proof (rule ring_hom_memI) interpret ji: ideal J R using assms(2) by simp interpret ii: ideal I R using assms(1) by simp have a:"J <+>\<^bsub>R\<^esub> I = J" using assms(3) unfolding set_add_def set_mult_def by auto show "J <+>\<^bsub>R\<^esub> x \ carrier (R Quot J)" if "x \ carrier (R Quot I)" for x proof - have " \y\carrier R. x = I +> y" using that unfolding FactRing_def A_RCOSETS_def' by simp then obtain y where y_def: "y \ carrier R" "x = I +> y" by auto have "J <+>\<^bsub>R\<^esub> (I +> y) = (J <+>\<^bsub>R\<^esub> I) +> y" using y_def(1) by (subst a_setmult_rcos_assoc) auto also have "... = J +> y" using a by simp finally have "J <+>\<^bsub>R\<^esub> (I +> y) = J +> y" by simp thus ?thesis using y_def unfolding FactRing_def A_RCOSETS_def' by auto qed show "J <+>\<^bsub>R\<^esub> x \\<^bsub>R Quot I\<^esub> y = (J <+>\<^bsub>R\<^esub> x) \\<^bsub>R Quot J\<^esub> (J <+>\<^bsub>R\<^esub> y)" if "x \ carrier (R Quot I)" "y \ carrier (R Quot I)" for x y proof - have "\x1\carrier R. x = I +> x1" "\y1\carrier R. y = I +> y1" using that unfolding FactRing_def A_RCOSETS_def' by auto then obtain x1 y1 where x1_def: "x1 \ carrier R" "x = I +> x1" and y1_def: "y1 \ carrier R" "y = I +> y1" by auto have "J <+>\<^bsub>R\<^esub> x \\<^bsub>R Quot I\<^esub> y = J <+>\<^bsub>R\<^esub> (I +> x1 \ y1)" using x1_def y1_def by (simp add: FactRing_def ii.rcoset_mult_add) also have "... = (J <+>\<^bsub>R\<^esub> I) +> x1 \ y1" using x1_def(1) y1_def(1) by (subst a_setmult_rcos_assoc) auto also have "... = J +> x1 \ y1" using a by simp also have "... = [mod J:] (J +> x1) \ (J +> y1)" using x1_def(1) y1_def(1) by (subst ji.rcoset_mult_add, auto) also have "... = [mod J:] ((J <+>\<^bsub>R\<^esub> I) +> x1) \ ((J <+>\<^bsub>R\<^esub> I) +> y1)" using a by simp also have "... = [mod J:] (J <+>\<^bsub>R\<^esub> (I +> x1)) \ (J <+>\<^bsub>R\<^esub> (I +> y1))" using x1_def(1) y1_def(1) by (subst (1 2) a_setmult_rcos_assoc) auto also have "... = (J <+>\<^bsub>R\<^esub> x) \\<^bsub>R Quot J\<^esub> (J <+>\<^bsub>R\<^esub> y)" using x1_def y1_def by (simp add: FactRing_def) finally show ?thesis by simp qed show "J <+>\<^bsub>R\<^esub> x \\<^bsub>R Quot I\<^esub> y = (J <+>\<^bsub>R\<^esub> x) \\<^bsub>R Quot J\<^esub> (J <+>\<^bsub>R\<^esub> y)" if "x \ carrier (R Quot I)" "y \ carrier (R Quot I)" for x y proof - have "\x1\carrier R. x = I +> x1" "\y1\carrier R. y = I +> y1" using that unfolding FactRing_def A_RCOSETS_def' by auto then obtain x1 y1 where x1_def: "x1 \ carrier R" "x = I +> x1" and y1_def: "y1 \ carrier R" "y = I +> y1" by auto have "J <+>\<^bsub>R\<^esub> x \\<^bsub>R Quot I\<^esub> y = J <+>\<^bsub>R\<^esub> ((I +> x1) <+>\<^bsub>R\<^esub> (I +> y1))" using x1_def y1_def by (simp add:FactRing_def) also have "... = J <+>\<^bsub>R\<^esub> (I +> (x1 \ y1))" using x1_def y1_def ii.a_rcos_sum by simp also have "... = (J <+>\<^bsub>R\<^esub> I) +> (x1 \ y1)" using x1_def y1_def by (subst a_setmult_rcos_assoc) auto also have "... = J +> (x1 \ y1)" using a by simp also have "... = ((J <+>\<^bsub>R\<^esub> I) +> x1) <+>\<^bsub>R\<^esub> ((J <+>\<^bsub>R\<^esub> I) +> y1)" using x1_def y1_def ji.a_rcos_sum a by simp also have "... = J <+>\<^bsub>R\<^esub> (I +> x1) <+>\<^bsub>R\<^esub> (J <+>\<^bsub>R\<^esub> (I +> y1))" using x1_def y1_def by (subst (1 2) a_setmult_rcos_assoc) auto also have "... = (J <+>\<^bsub>R\<^esub> x) \\<^bsub>R Quot J\<^esub> (J <+>\<^bsub>R\<^esub> y)" using x1_def y1_def by (simp add:FactRing_def) finally show ?thesis by simp qed have "J <+>\<^bsub>R\<^esub> \\<^bsub>R Quot I\<^esub> = J <+>\<^bsub>R\<^esub> (I +> \)" unfolding FactRing_def by simp also have "... = (J <+>\<^bsub>R\<^esub> I) +> \" by (subst a_setmult_rcos_assoc) auto also have "... = J +> \" using a by simp also have "... = \\<^bsub>R Quot J\<^esub>" unfolding FactRing_def by simp finally show "J <+>\<^bsub>R\<^esub> \\<^bsub>R Quot I\<^esub> = \\<^bsub>R Quot J\<^esub>" by simp qed lemma (in ring) quot_carr: assumes "ideal I R" assumes "y \ carrier (R Quot I)" shows "y \ carrier R" proof - interpret ideal I R using assms(1) by simp have "y \ a_rcosets I" using assms(2) unfolding FactRing_def by simp then obtain v where y_def: "y = I +> v" "v \ carrier R" unfolding A_RCOSETS_def' by auto have "I +> v \ carrier R" using y_def(2) a_r_coset_subset_G a_subset by presburger thus "y \ carrier R" unfolding y_def by simp qed lemma (in ring) set_add_zero: assumes "A \ carrier R" shows "{\} <+>\<^bsub>R\<^esub> A = A" proof - have "{\} <+>\<^bsub>R\<^esub> A = (\x\A. {\ \ x})" using assms unfolding set_add_def set_mult_def by simp also have "... = (\x\A. {x})" using assms by (intro arg_cong[where f="Union"] image_cong, auto) also have "... = A" by simp finally show ?thesis by simp qed text \Adapted from the proof of @{thm [source] domain.polynomial_rupture}\ lemma (in domain) rupture_surj_as_eval: assumes "subring K R" assumes "p \ carrier (K[X])" "q \ carrier (K[X])" shows "rupture_surj K p q = ring.eval (Rupt K p) (map ((rupture_surj K p) \ poly_of_const) q) (rupture_surj K p X)" proof - let ?surj = "rupture_surj K p" interpret UP: domain "K[X]" using univ_poly_is_domain[OF assms(1)] . interpret h: ring_hom_ring "K[X]" "Rupt K p" ?surj using rupture_surj_hom(2)[OF assms(1,2)] . have "(h.S.eval) (map (?surj \ poly_of_const) q) (?surj X) = ?surj ((UP.eval) (map poly_of_const q) X)" using h.eval_hom[OF UP.carrier_is_subring var_closed(1)[OF assms(1)] map_norm_in_poly_ring_carrier[OF assms(1,3)]] by simp also have " ... = ?surj q" unfolding sym[OF eval_rewrite[OF assms(1,3)]] .. finally show ?thesis by simp qed subsection \Divisibility\ lemma (in field) f_comm_group_1: assumes "x \ carrier R" "y \ carrier R" assumes "x \ \" "y \ \" assumes "x \ y = \" shows "False" using integral assms by auto lemma (in field) f_comm_group_2: assumes "x \ carrier R" assumes "x \ \" shows " \y\carrier R - {\}. y \ x = \" proof - have x_unit: "x \ Units R" using field_Units assms by simp thus ?thesis unfolding Units_def by auto qed sublocale field < mult_of: comm_group "mult_of R" rewrites "mult (mult_of R) = mult R" and "one (mult_of R) = one R" using f_comm_group_1 f_comm_group_2 by (auto intro!:comm_groupI m_assoc m_comm) lemma (in domain) div_neg: assumes "a \ carrier R" "b \ carrier R" assumes "a divides b" shows "a divides (\ b)" proof - obtain r1 where r1_def: "r1 \ carrier R" "a \ r1 = b" using assms by (auto simp:factor_def) have "a \ (\ r1) = \ (a \ r1)" using assms(1) r1_def(1) by algebra also have "... = \ b" using r1_def(2) by simp finally have "\b = a \ (\ r1)" by simp moreover have "\r1 \ carrier R" using r1_def(1) by simp ultimately show ?thesis by (auto simp:factor_def) qed lemma (in domain) div_sum: assumes "a \ carrier R" "b \ carrier R" "c \ carrier R" assumes "a divides b" assumes "a divides c" shows "a divides (b \ c)" proof - obtain r1 where r1_def: "r1 \ carrier R" "a \ r1 = b" using assms by (auto simp:factor_def) obtain r2 where r2_def: "r2 \ carrier R" "a \ r2 = c" using assms by (auto simp:factor_def) have "a \ (r1 \ r2) = (a \ r1) \ (a \ r2)" using assms(1) r1_def(1) r2_def(1) by algebra also have "... = b \ c" using r1_def(2) r2_def(2) by simp finally have "b \ c = a \ (r1 \ r2)" by simp moreover have "r1 \ r2 \ carrier R" using r1_def(1) r2_def(1) by simp ultimately show ?thesis by (auto simp:factor_def) qed lemma (in domain) div_sum_iff: assumes "a \ carrier R" "b \ carrier R" "c \ carrier R" assumes "a divides b" shows "a divides (b \ c) \ a divides c" proof assume "a divides (b \ c)" moreover have "a divides (\ b)" using div_neg assms(1,2,4) by simp ultimately have "a divides ((b \ c) \ (\ b))" using div_sum assms by simp also have "... = c" using assms(1,2,3) by algebra finally show "a divides c" by simp next assume "a divides c" thus "a divides (b \ c)" using assms by (intro div_sum) auto qed +lemma (in comm_monoid) irreducible_prod_unit: + assumes "f \ carrier G" "x \ Units G" + shows "irreducible G f = irreducible G (x \ f)" (is "?L = ?R") +proof + assume "?L" + thus ?R using irreducible_prod_lI assms by auto +next + have "inv x \ (x \ f) = (inv x \ x) \ f" + using assms by (intro m_assoc[symmetric]) auto + also have "... = f" using assms by simp + finally have 0: "inv x \ (x \ f) = f" by simp + assume ?R + hence "irreducible G (inv x \ (x \ f) )" using irreducible_prod_lI assms by blast + thus ?L using 0 by simp +qed + end diff --git a/thys/Finite_Fields/Rabin_Irreducibility_Test.thy b/thys/Finite_Fields/Rabin_Irreducibility_Test.thy --- a/thys/Finite_Fields/Rabin_Irreducibility_Test.thy +++ b/thys/Finite_Fields/Rabin_Irreducibility_Test.thy @@ -1,371 +1,344 @@ section \Rabin's test for irreducible polynomials\ theory Rabin_Irreducibility_Test imports Card_Irreducible_Polynomials_Aux begin text \This section introduces an effective test for irreducibility of polynomials (in finite fields) based on Rabin~\cite[rabin1980].\ -lemma (in domain) coeff_a_inv: - assumes "subring K R" - assumes "f \ carrier (K[X])" - shows "coeff (\\<^bsub>K[X]\<^esub> f) i = \ (coeff f i)" (is "?L = ?R") -proof - - have "?L = coeff (map (a_inv R) f) i" - unfolding univ_poly_a_inv_def'[OF assms(1,2)] by simp - also have "... = ?R" by (induction f) auto - finally show ?thesis by simp -qed - -lemma (in comm_monoid) irreducible_prod_unit: - assumes "f \ carrier G" "x \ Units G" - shows "irreducible G f = irreducible G (x \ f)" (is "?L = ?R") -proof - assume "?L" - thus ?R using irreducible_prod_lI assms by auto -next - have "inv x \ (x \ f) = (inv x \ x) \ f" - using assms by (intro m_assoc[symmetric]) auto - also have "... = f" using assms by simp - finally have 0: "inv x \ (x \ f) = f" by simp - assume ?R - hence "irreducible G (inv x \ (x \ f) )" using irreducible_prod_lI assms by blast - thus ?L using 0 by simp -qed - definition pcoprime :: "_ \ 'a list \ 'a list \ bool" ("pcoprime\") where "pcoprime\<^bsub>R\<^esub> p q = (\r \ carrier (poly_ring R). r pdivides\<^bsub>R\<^esub> p \ r pdivides\<^bsub>R\<^esub> q \ degree r = 0)" lemma pcoprimeI: assumes "\r. r \ carrier (poly_ring R) \ r pdivides \<^bsub>R\<^esub> p \ r pdivides\<^bsub>R\<^esub> q \ degree r = 0" shows "pcoprime\<^bsub>R\<^esub> p q" using assms unfolding pcoprime_def by auto context field begin interpretation r:polynomial_ring R "(carrier R)" unfolding polynomial_ring_def polynomial_ring_axioms_def using carrier_is_subfield field_axioms by force lemma pcoprime_one: "pcoprime\<^bsub>R\<^esub> p \\<^bsub>poly_ring R\<^esub>" proof (rule pcoprimeI) fix r assume r_carr: "r \ carrier (poly_ring R)" moreover assume "r pdivides \<^bsub>R\<^esub> \\<^bsub>poly_ring R\<^esub>" moreover have "\\<^bsub>poly_ring R\<^esub> \ []" by (simp add:univ_poly_one) ultimately have "degree r \ degree \\<^bsub>poly_ring R\<^esub>" by (intro pdivides_imp_degree_le[OF carrier_is_subring] r_carr) auto also have "... = 0" by (simp add:univ_poly_one) finally show "degree r = 0" by auto qed lemma pcoprime_left_factor: assumes "x \ carrier (poly_ring R)" assumes "y \ carrier (poly_ring R)" assumes "z \ carrier (poly_ring R)" assumes "pcoprime\<^bsub>R\<^esub> (x \\<^bsub>poly_ring R\<^esub> y) z" shows "pcoprime\<^bsub>R\<^esub> x z" proof (rule pcoprimeI) fix r assume r_carr: "r \ carrier (poly_ring R)" assume "r pdivides \<^bsub>R\<^esub> x" hence "r pdivides \<^bsub>R\<^esub> (x \\<^bsub>poly_ring R\<^esub> y)" using assms(1,2) r_carr r.p.divides_prod_r unfolding pdivides_def by simp moreover assume "r pdivides \<^bsub>R\<^esub> z" ultimately show "degree r = 0" using assms(4) r_carr unfolding pcoprime_def by simp qed lemma pcoprime_sym: shows "pcoprime x y = pcoprime y x" unfolding pcoprime_def by auto lemma pcoprime_left_assoc_cong_aux: assumes "x1 \ carrier (poly_ring R)" "x2 \ carrier (poly_ring R)" assumes "x2 \\<^bsub>poly_ring R\<^esub> x1" assumes "y \ carrier (poly_ring R)" assumes "pcoprime x1 y" shows "pcoprime x2 y" using assms r.p.divides_cong_r[OF _ assms(3)] unfolding pcoprime_def pdivides_def by simp lemma pcoprime_left_assoc_cong: assumes "x1 \ carrier (poly_ring R)" "x2 \ carrier (poly_ring R)" assumes "x1 \\<^bsub>poly_ring R\<^esub> x2" assumes "y \ carrier (poly_ring R)" shows "pcoprime x1 y = pcoprime x2 y" using assms pcoprime_left_assoc_cong_aux r.p.associated_sym by metis lemma pcoprime_right_assoc_cong: assumes "x1 \ carrier (poly_ring R)" "x2 \ carrier (poly_ring R)" assumes "x1 \\<^bsub>poly_ring R\<^esub> x2" assumes "y \ carrier (poly_ring R)" shows "pcoprime y x1 = pcoprime y x2" using assms pcoprime_sym pcoprime_left_assoc_cong by metis lemma pcoprime_step: assumes "f \ carrier (poly_ring R)" assumes "g \ carrier (poly_ring R)" shows "pcoprime f g \ pcoprime g (f pmod g)" proof - have "d pdivides f \ d pdivides (f pmod g)" if "d \ carrier (poly_ring R)" "d pdivides g" for d proof - have "d pdivides f \ d pdivides (g \\<^bsub>r.P\<^esub> (f pdiv g) \\<^bsub>r.P\<^esub> (f pmod g))" using pdiv_pmod[OF carrier_is_subfield assms] by simp also have "... \ d pdivides ((f pmod g))" using that assms long_division_closed[OF carrier_is_subfield] r.p.divides_prod_r unfolding pdivides_def by (intro r.p.div_sum_iff) simp_all finally show ?thesis by simp qed hence "d pdivides f \ d pdivides g \ d pdivides g \ d pdivides (f pmod g)" if "d \ carrier (poly_ring R)" for d using that by auto thus ?thesis unfolding pcoprime_def by auto qed lemma pcoprime_zero_iff: assumes "f \ carrier (poly_ring R)" shows "pcoprime f [] \ length f = 1" proof - consider (i) "length f = 0" | (ii) "length f = 1" | (iii) "length f > 1" by linarith thus ?thesis proof (cases) case i hence "f = []" by simp moreover have "X pdivides []" using r.pdivides_zero r.var_closed(1) by blast moreover have "degree X = 1" using degree_var by simp ultimately have "\pcoprime f []" using r.var_closed(1) unfolding pcoprime_def by auto then show ?thesis using i by auto next case ii hence "f \ []" "degree f = 0" by auto hence "degree d = 0" if "d pdivides f" "d \ carrier (poly_ring R)" for d using that(1) pdivides_imp_degree_le[OF carrier_is_subring that(2) assms] by simp hence "pcoprime f []" unfolding pcoprime_def by auto then show ?thesis using ii by simp next case iii have "f pdivides f" using assms unfolding pdivides_def by simp moreover have "f pdivides []" using assms r.pdivides_zero by blast moreover have "degree f > 0" using iii by simp ultimately have "\pcoprime f []" using assms unfolding pcoprime_def by auto then show ?thesis using iii by auto qed qed end context finite_field begin interpretation r:polynomial_ring R "(carrier R)" unfolding polynomial_ring_def polynomial_ring_axioms_def using carrier_is_subfield field_axioms by force lemma exists_irreducible_proper_factor: assumes "monic_poly R f" "degree f > 0" "\monic_irreducible_poly R f" shows "\g. monic_irreducible_poly R g \ g pdivides\<^bsub>R\<^esub> f \ degree g < degree f" proof - define S where "S = {d. monic_irreducible_poly R d \ 0 < pmult d f}" have f_carr: "f \ carrier (poly_ring R)" "f \ \\<^bsub>poly_ring R\<^esub>" using assms(1) unfolding monic_poly_def univ_poly_zero by auto have "S \ {}" proof (rule ccontr) assume S_empty: "\(S \ {})" have "f = (\\<^bsub>poly_ring R\<^esub>d\S. d [^]\<^bsub>poly_ring R\<^esub> pmult d f)" unfolding S_def by (intro factor_monic_poly assms(1)) also have "... = \\<^bsub>poly_ring R\<^esub>" using S_empty by simp finally have "f = \\<^bsub>poly_ring R\<^esub>" by simp hence "degree f = 0" using degree_one by simp thus "False" using assms(2) by simp qed then obtain g where g_irred: "monic_irreducible_poly R g" and "0 < pmult g f" unfolding S_def by auto hence "1 \ pmult g f" by simp hence g_div: "g pdivides f" using multiplicity_ge_1_iff_pdivides f_carr g_irred by blast then obtain h where f_def: "f = g \\<^bsub>poly_ring R\<^esub> h" and h_carr:"h \ carrier (poly_ring R)" unfolding pdivides_def by auto have g_nz: "g \ \\<^bsub>poly_ring R\<^esub>" and h_nz: "h \ \\<^bsub>poly_ring R\<^esub>" and g_carr: "g \ carrier (poly_ring R)" using f_carr(2) h_carr g_irred unfolding f_def monic_irreducible_poly_def monic_poly_def by auto have "degree f = degree g + degree h" using g_nz h_nz g_carr h_carr unfolding f_def by (intro degree_mult[OF r.K_subring]) auto moreover have "degree h > 0" proof (rule ccontr) assume "\(degree h > 0)" hence "degree h = 0" by simp hence "h \ Units (poly_ring R)" using h_carr h_nz by (simp add: carrier_is_subfield univ_poly_units' univ_poly_zero) hence "f \\<^bsub>poly_ring R\<^esub> g" unfolding f_def using g_carr r.p.associatedI2' by force hence "f \\<^bsub>mult_of (poly_ring R)\<^esub> g" using f_carr g_nz g_carr by (simp add: r.p.assoc_iff_assoc_mult) hence "f = g" using monic_poly_not_assoc assms(1) g_irred unfolding monic_irreducible_poly_def by simp hence "monic_irreducible_poly R f" using g_irred by simp thus "False" using assms(3) by auto qed ultimately have "degree g < degree f" by simp thus ?thesis using g_irred g_div by auto qed theorem rabin_irreducibility_condition: assumes "monic_poly R f" "degree f > 0" defines "N \ {degree f div p | p . Factorial_Ring.prime p \ p dvd degree f}" shows "monic_irreducible_poly R f \ (f pdivides gauss_poly R (order R^degree f) \ (\n \ N. pcoprime (gauss_poly R (order R^n)) f))" (is "?L \ ?R1 \ ?R2") proof - have f_carr: "f \ carrier (poly_ring R)" using assms(1) unfolding monic_poly_def by blast have "?R1" if "?L" using div_gauss_poly_iff[where n="degree f"] that assms(2) by simp moreover have "False" if cthat:"\pcoprime (gauss_poly R (order R^n)) f" "?L" "n \ N" for n proof - obtain d where d_def: "d pdivides f" "d pdivides (gauss_poly R (order R^n))" "degree d > 0" "d \ carrier (poly_ring R)" using cthat(1) unfolding pcoprime_def by auto obtain p where p_def: "n = degree f div p" "Factorial_Ring.prime p" "p dvd degree f" using cthat(3) unfolding N_def by auto have n_gt_0: "n > 0" using p_def assms(2) by (metis dvd_div_eq_0_iff gr0I) have "d \ Units (poly_ring R)" using d_def(3,4) univ_poly_units'[OF carrier_is_subfield] by simp hence "f pdivides d" using cthat(2) d_def(1,4) unfolding monic_irreducible_poly_def ring_irreducible_def Divisibility.irreducible_def properfactor_def pdivides_def f_carr by auto hence "f pdivides (gauss_poly R (order R^n))" using d_def(2,4) f_carr r.p.divides_trans unfolding pdivides_def by metis hence "degree f dvd n" using n_gt_0 div_gauss_poly_iff[OF _ cthat(2)] by auto thus "False" using p_def by (metis assms(2) div_less_dividend n_gt_0 nat_dvd_not_less prime_gt_1_nat) qed moreover have "False" if not_l:"\?L" and r1:"?R1" and r2: "?R2" proof - obtain g where g_def: "g pdivides f" "degree g < degree f" "monic_irreducible_poly R g" using r1 not_l exists_irreducible_proper_factor assms(1,2) by auto have g_carr: "g \ carrier (poly_ring R)" and g_nz: "g \ \\<^bsub>poly_ring R\<^esub>" using g_def(3) unfolding monic_irreducible_poly_def monic_poly_def by (auto simp:univ_poly_zero) have "g pdivides gauss_poly R (order R^degree f)" using g_carr r1 g_def(1) unfolding pdivides_def using r.p.divides_trans by blast hence "degree g dvd degree f" using div_gauss_poly_iff[OF assms(2) g_def(3)] by auto then obtain t where deg_f_def:"degree f = t * degree g" by fastforce hence "t > 1" using g_def(2) by simp then obtain p where p_prime: "Factorial_Ring.prime p" "p dvd t" by (metis order_less_irrefl prime_factor_nat) hence p_div_deg_f: "p dvd degree f" unfolding deg_f_def by simp define n where "n = degree f div p" have n_in_N: "n \ N" unfolding N_def n_def using p_prime(1) p_div_deg_f by auto have deg_g_dvd_n: "degree g dvd n" using p_prime(2) unfolding n_def deg_f_def by auto have n_gt_0: "n > 0" using p_div_deg_f assms(2) p_prime(1) unfolding n_def by (metis dvd_div_eq_0_iff gr0I) have deg_g_gt_0: "degree g > 0" using monic_poly_min_degree[OF g_def(3)] by simp have 0:"g pdivides gauss_poly R (order R^n)" using deg_g_dvd_n div_gauss_poly_iff[OF n_gt_0 g_def(3)] by simp have "pcoprime (gauss_poly R (order R^n)) f" using n_in_N r2 by simp thus "False" using 0 g_def(1) g_carr deg_g_gt_0 unfolding pcoprime_def by simp qed ultimately show ?thesis by auto qed text \A more general variance of the previous theorem for non-monic polynomials. The result is from Lemma~1 \cite[rabin1980].\ theorem rabin_irreducibility_condition_2: assumes "f \ carrier (poly_ring R)" "degree f > 0" defines "N \ {degree f div p | p . Factorial_Ring.prime p \ p dvd degree f}" shows "pirreducible (carrier R) f \ (f pdivides gauss_poly R (order R^degree f) \ (\n \ N. pcoprime (gauss_poly R (order R^n)) f))" (is "?L \ ?R1 \ ?R2") proof - define \ where "\ = [inv (hd f)]" let ?g = "(\x. gauss_poly R (order R^x))" let ?h = "\ \\<^bsub>poly_ring R\<^esub> f" have f_nz: "f \ \\<^bsub>poly_ring R\<^esub>" unfolding univ_poly_zero using assms(2) by auto hence "hd f \ carrier R - {\}" using assms(1) lead_coeff_carr by simp hence "inv (hd f) \ carrier R - {\}" using field_Units by auto hence \_unit: "\ \ Units (poly_ring R)" unfolding \_def using univ_poly_carrier_units by simp have \_nz: "\ \ \\<^bsub>poly_ring R\<^esub>" unfolding univ_poly_zero \_def by simp have "hd ?h = hd \ \ hd f" using \_nz f_nz assms(1) \_unit by (intro lead_coeff_mult) auto also have "... = inv (hd f) \ hd f" unfolding \_def by simp also have "... = \" using lead_coeff_carr f_nz assms(1) by (simp add: field_Units) finally have "hd ?h = \" by simp moreover have "?h \ []" using \_nz f_nz univ_poly_zero by (metis \_unit assms(1) r.p.Units_closed r.p.integral) ultimately have h_monic: "monic_poly R ?h" using r.p.Units_closed[OF \_unit] assms(1) unfolding monic_poly_def by auto have "degree ?h = degree \ + degree f" using assms(1) f_nz \_unit \_nz by (intro degree_mult[OF carrier_is_subring]) auto also have "... = degree f" unfolding \_def by simp finally have deg_f: "degree f = degree ?h" by simp have hf_cong:"?h \\<^bsub>r.P\<^esub> f" using assms(1) \_unit by (simp add: r.p.Units_closed r.p.associatedI2 r.p.m_comm) hence 0: "f pdivides ?g (degree f) \ ?h pdivides ?g (degree f)" unfolding pdivides_def using r.p.divides_cong_l r.p.associated_sym using r.p.Units_closed[OF \_unit] assms(1) gauss_poly_carr by blast have 1: "pcoprime (?g n) f \ pcoprime (?g n) ?h" for n using hf_cong r.p.associated_sym r.p.Units_closed[OF \_unit] assms(1) by (intro pcoprime_right_assoc_cong gauss_poly_carr) auto have "?L \ pirreducible (carrier R) (\ \\<^bsub>poly_ring R\<^esub> f)" using \_unit \_nz assms(1) f_nz r.p.integral unfolding ring_irreducible_def by (intro arg_cong2[where f="(\)"] r.p.irreducible_prod_unit assms) auto also have "... \ monic_irreducible_poly R (\ \\<^bsub>poly_ring R\<^esub> f)" using h_monic unfolding monic_irreducible_poly_def by auto also have "... \ ?h pdivides ?g (degree f) \ (\n \ N. pcoprime (?g n) ?h)" using assms(2) unfolding N_def deg_f by (intro rabin_irreducibility_condition h_monic) auto also have "... \ f pdivides ?g (degree f) \ (\n \ N. pcoprime (?g n) f)" using 0 1 by simp finally show ?thesis by simp qed end end \ No newline at end of file