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> \