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,40 @@ 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] 2024-01-17 = "Added Rabin's test for the irreducibility of polynomials in finite fields." +2024-01-18 = "Added exectuable algorithms for the construction of (and calculations in) finite fields." [extra] [related] diff --git a/thys/Finite_Fields/Card_Irreducible_Polynomials.thy b/thys/Finite_Fields/Card_Irreducible_Polynomials.thy --- a/thys/Finite_Fields/Card_Irreducible_Polynomials.thy +++ b/thys/Finite_Fields/Card_Irreducible_Polynomials.thy @@ -1,235 +1,235 @@ subsection \Gauss Formula\label{sec:card_irred}\ theory Card_Irreducible_Polynomials imports Dirichlet_Series.Moebius_Mu Card_Irreducible_Polynomials_Aux begin hide_const "Polynomial.order" text \The following theorem is a slightly generalized form of the formula discovered by Gauss for the number of monic irreducible polynomials over a finite field. He originally verified the result for the case when @{term "R"} is a simple prime field. The version of the formula here for the case where @{term "R"} may be an arbitrary finite field can be found in Chebolu and Min{\'a}{\v{c}}~\<^cite>\"chebolu2010"\.\ theorem (in finite_field) card_irred: assumes "n > 0" shows "n * card {f. monic_irreducible_poly R f \ degree f = n} = (\d | d dvd n. moebius_mu d * (order R^(n div d)))" (is "?lhs = ?rhs") proof - have "?lhs = dirichlet_prod moebius_mu (\x. int (order R) ^ x) n" using card_irred_aux by (intro moebius_inversion assms) (simp flip:of_nat_power) also have "... = ?rhs" by (simp add:dirichlet_prod_def) finally show ?thesis by simp qed text \In the following an explicit analytic lower bound for the cardinality of monic irreducible polynomials is shown, with which existence follows. This part deviates from the classic approach, where existence is verified using a divisibility argument. The reason for the deviation is that an analytic bound can also be used to estimate the runtime of a randomized algorithm selecting an irreducible polynomial, by randomly sampling monic polynomials.\ lemma (in finite_field) card_irred_1: "card {f. monic_irreducible_poly R f \ degree f = 1} = order R" proof - have "int (1 * card {f. monic_irreducible_poly R f \ degree f = 1}) = int (order R)" by (subst card_irred, auto) thus ?thesis by simp qed lemma (in finite_field) card_irred_2: "real (card {f. monic_irreducible_poly R f \ degree f = 2}) = (real (order R)^2 - order R) / 2" proof - have "x dvd 2 \ x = 1 \ x = 2" for x :: nat using nat_dvd_not_less[where m="2"] by (metis One_nat_def even_zero gcd_nat.strict_trans2 less_2_cases nat_neq_iff pos2) hence a: "{d. d dvd 2} = {1,2::nat}" by (auto simp add:set_eq_iff) have "2*real (card {f. monic_irreducible_poly R f \ degree f = 2}) = of_int (2* card {f. monic_irreducible_poly R f \ degree f = 2})" by simp also have "... = of_int (\d | d dvd 2. moebius_mu d * int (order R) ^ (2 div d))" by (subst card_irred, auto) also have "... = order R^2 - int (order R)" by (subst a, simp) also have "... = real (order R)^2 - order R" by simp finally have "2 * real (card {f. monic_irreducible_poly R f \ degree f = 2}) = real (order R)^2 - order R" by simp thus ?thesis by simp qed lemma (in finite_field) card_irred_gt_2: assumes "n > 2" shows "real (order R)^n / (2*real n) \ card {f. monic_irreducible_poly R f \ degree f = n}" (is "?lhs \ ?rhs") proof - let ?m = "real (order R)" have a:"?m \ 2" using finite_field_min_order by simp have b:"moebius_mu n \ -(1::real)" for n :: nat using abs_moebius_mu_le[where n="n"] unfolding abs_le_iff by auto have c: "n > 0" using assms by simp have d: "x < n - 1" if d_assms: "x dvd n" "x \ n" for x :: nat proof - have "x < n" using d_assms dvd_nat_bounds c by auto moreover have "\(n-1 dvd n)" using assms by (metis One_nat_def Suc_diff_Suc c diff_zero dvd_add_triv_right_iff nat_dvd_1_iff_1 nat_neq_iff numeral_2_eq_2 plus_1_eq_Suc) hence "x \ n-1" using d_assms by auto ultimately show "x < n-1" by simp qed have "?m^n / 2 = ?m^n - ?m^n/2" by simp also have "... \ ?m^n - ?m^n/?m^1" using a by (intro diff_mono divide_left_mono, simp_all) also have "... \ ?m^n - ?m^(n-1)" using a c by (subst power_diff, simp_all) also have "... \ ?m^n - (?m^(n-1) - 1)/1" by simp also have "... \ ?m^n - (?m^(n-1)-1)/(?m-1)" using a by (intro diff_left_mono divide_left_mono, simp_all) also have "... = ?m^n - (\i \ {.. ?m^n - (\i \ {k. k dvd n \ k \ n}. ?m^i)" using d by (intro diff_mono sum_mono2 subsetI, auto simp add:not_less) also have "... = ?m^n + (\i \ {k. k dvd n \ k \ n}. (-1) * ?m^i)" by (subst sum_distrib_left[symmetric], simp) also have "... \ moebius_mu 1 * ?m^n + (\i \ {k. k dvd n \ k \ n}. moebius_mu (n div i) * ?m^i)" using b by (intro add_mono sum_mono mult_right_mono) (simp_all add:not_less) also have "... = (\i \ insert n {k. k dvd n \ k \ n}. moebius_mu (n div i) * ?m^i)" using c by (subst sum.insert, auto) also have "... = (\i \ {k. k dvd n}. moebius_mu (n div i) * ?m^i)" by (intro sum.cong, auto simp add:set_eq_iff) also have "... = dirichlet_prod (\i. ?m^i) moebius_mu n" unfolding dirichlet_prod_def by (intro sum.cong, auto) also have "... = dirichlet_prod moebius_mu (\i. ?m^i) n" using dirichlet_prod_commutes by metis also have "... = of_int (\d | d dvd n. moebius_mu d * order R^(n div d))" unfolding dirichlet_prod_def by simp also have "... = of_int (n * card {f. monic_irreducible_poly R f \ length f - 1 = n})" using card_irred[OF c] by simp also have "... = n * ?rhs" by simp finally have "?m^n / 2 \ n * ?rhs" by simp hence "?m ^ n \ 2 * n * ?rhs" by simp hence "?m^n/(2*real n) \ ?rhs" using c by (subst pos_divide_le_eq, simp_all add:algebra_simps) thus ?thesis by simp qed lemma (in finite_field) card_irred_gt_0: assumes "d > 0" shows "real(order R)^d / (2*real d) \ real (card {f. monic_irreducible_poly R f \ degree f = d})" (is "?L \ ?R") proof - consider (a) "d = 1" | (b) "d = 2" | (c) "d > 2" using assms by linarith thus ?thesis proof (cases) case a hence "?L = real (order R)/2" by simp also have "... \ real (order R)" using finite_field_min_order by simp also have "... = ?R" unfolding a card_irred_1 by simp finally show ?thesis by simp next case b hence "?L = real (order R^2)/4 + 0" by simp also have "... \ real (order R^2)/4 + real (order R)/2 * (real (order R)/2 - 1)" using finite_field_min_order by (intro add_mono mult_nonneg_nonneg) auto - also have "... = (real (order R^2) - real (order R))/2" + also have "... = (real (order R^2) - real (order R))/2" by (simp add:algebra_simps power2_eq_square) also have "... = ?R" unfolding b card_irred_2 by simp finally show ?thesis by simp next case c thus ?thesis by (rule card_irred_gt_2) qed qed lemma (in finite_field) exist_irred: assumes "n > 0" obtains f where "monic_irreducible_poly R f" "degree f = n" proof - have "0 < real(order R)^n / (2*real n)" using finite_field_min_order assms by (intro divide_pos_pos mult_pos_pos zero_less_power) auto - also have "... \ real (card {f. monic_irreducible_poly R f \ degree f = n})" + also have "... \ real (card {f. monic_irreducible_poly R f \ degree f = n})" (is "_ \ real(card ?A)") by (intro card_irred_gt_0 assms) finally have "0 < card {f. monic_irreducible_poly R f \ degree f = n}" by auto hence "?A \ {}" by (metis card.empty nless_le) then obtain f where "monic_irreducible_poly R f" "degree f = n" by auto thus ?thesis using that by simp qed theorem existence: assumes "n > 0" assumes "Factorial_Ring.prime p" shows "\(F:: int set list set ring). finite_field F \ order F = p^n" proof - interpret zf: finite_field "ZFact (int p)" using zfact_prime_is_finite_field assms by simp interpret zfp: polynomial_ring "ZFact p" "carrier (ZFact p)" unfolding polynomial_ring_def polynomial_ring_axioms_def using zf.field_axioms zf.carrier_is_subfield by simp have p_gt_0: "p > 0" using prime_gt_0_nat assms(2) by simp obtain f where f_def: "monic_irreducible_poly (ZFact (int p)) f" "degree f = n" using zf.exist_irred assms by auto let ?F = "Rupt\<^bsub>(ZFact p)\<^esub> (carrier (ZFact p)) f" have "f \ carrier (poly_ring (ZFact (int p)))" using f_def(1) zf.monic_poly_carr unfolding monic_irreducible_poly_def by simp moreover have "degree f > 0" using assms(1) f_def by simp ultimately have "order ?F = card (carrier (ZFact p))^degree f" by (intro zf.rupture_order[OF zf.carrier_is_subfield]) auto hence a:"order ?F = p^n" unfolding f_def(2) card_zfact_carr[OF p_gt_0] by simp have "field ?F" using f_def(1) zf.monic_poly_carr monic_irreducible_poly_def by (subst zfp.rupture_is_field_iff_pirreducible) auto moreover have "order ?F > 0" unfolding a using assms(1,2) p_gt_0 by simp ultimately have b:"finite_field ?F" using card_ge_0_finite by (intro finite_fieldI, auto simp add:Coset.order_def) show ?thesis using a b by (intro exI[where x="?F"], simp) qed end diff --git a/thys/Finite_Fields/Find_Irreducible_Poly.thy b/thys/Finite_Fields/Find_Irreducible_Poly.thy new file mode 100644 --- /dev/null +++ b/thys/Finite_Fields/Find_Irreducible_Poly.thy @@ -0,0 +1,794 @@ +section \Algorithms for finding irreducible polynomials\ + +theory Find_Irreducible_Poly + imports + Finite_Fields_Poly_Factor_Ring_Code + Rabin_Irreducibility_Test_Code + Probabilistic_While.While_SPMF + Card_Irreducible_Polynomials + Executable_Randomized_Algorithms.Randomized_Algorithm + "HOL-Library.Log_Nat" +begin + +hide_const (open) Numeral_Type.mod_ring +hide_const (open) Polynomial.degree +hide_const (open) Polynomial.order + +text \Enumeration of the monic polynomials in lexicographic order.\ + +definition enum_monic_poly :: "('a,'b) idx_ring_enum_scheme \ nat \ nat \ 'a list" + where "enum_monic_poly A d i = 1\<^sub>C\<^bsub>A\<^esub>#[ idx_enum A (nth_digit i j (idx_size A)). j \ rev [0..C R" "enum\<^sub>C R" + shows "bij_betw (enum_monic_poly R d) {.. degree f = d}" +proof - + let ?f = " (\x. 1\<^sub>C\<^bsub>R\<^esub> # map (\j. idx_enum R (x j)) (rev [ 0..C_def by auto + + have 1:"enum_monic_poly R d = ?f \ (\v. \x\{..x. 1\<^sub>C\<^bsub>R\<^esub> # map x (rev [ 0.. (\x. \i\{..x. \\<^bsub>ring_of R\<^esub>#map x (rev [0..x. \\<^bsub>ring_of R\<^esub>#x) \rev\ (\x. map x [0..\<^bsub>?R\<^esub>) {x. set x\carrier ?R\length x=d} {f. monic_poly ?R f \ degree f=d}" + using list.collapse unfolding monic_poly_def univ_poly_carrier[symmetric] polynomial_def + by (intro bij_betwI[where g="tl"]) (fastforce intro:in_set_tlD)+ + + have rev_bij: + "bij_betw rev {x. set x \ carrier ?R \ length x = d} {x. set x \ carrier ?R \ length x = d}" + by (intro bij_betwI[where g="rev"]) auto + + have "bij_betw (\x. \\<^bsub>?R\<^esub>#map x (rev [ 0..\<^sub>E carrier ?R) {f. monic_poly ?R f\degree f=d}" + unfolding 3 by (intro bij_betw_trans[OF lists_bij] bij_betw_trans[OF rev_bij] ap_bij) + hence "bij_betw ?f ({..\<^sub>E {.. degree f = d}" + unfolding 2 by (intro bij_betw_trans[OF lift_bij_betw[OF select_bij]]) (simp add:fo) + thus ?thesis + unfolding 1 by (intro bij_betw_trans[OF nth_digit_bij]) +qed + +lemma measure_bind_pmf: + "measure (bind_pmf m f) s = (\x. measure (f x) s \m)" (is "?L = ?R") +proof - + have "ennreal ?L = emeasure (bind_pmf m f) s" + unfolding measure_pmf.emeasure_eq_measure by simp + also have "... = (\\<^sup>+x. emeasure (f x) s \m)" + unfolding emeasure_bind_pmf by simp + also have "... = (\\<^sup>+x. measure (f x) s \m)" + unfolding measure_pmf.emeasure_eq_measure by simp + also have "... = ennreal ?R" + by (intro nn_integral_eq_integral measure_pmf.integrable_const_bound[where B="1"] AE_pmfI) auto + finally have "ennreal ?L = ennreal ?R" by simp + thus ?thesis + by (intro iffD1[OF ennreal_inj]) simp_all +qed + +lemma powr_mono_rev: + fixes x :: real + assumes "a \ b" and "x > 0" "x \ 1" + shows "x powr b \ x powr a" +proof - + have "x powr b = (1/x) powr (-b)" using assms by (simp add: powr_divide powr_minus_divide) + also have "... \ (1/x) powr (-a)" using assms by (intro powr_mono) auto + also have "... = x powr a" using assms by (simp add: powr_divide powr_minus_divide) + finally show ?thesis by simp +qed + +abbreviation tick_spmf :: "('a \ nat) spmf \ ('a \ nat) spmf" + where "tick_spmf \ map_spmf (\(x,c). (x,c+1))" + +text \Finds an irreducible polynomial in the finite field @{term "mod_ring p"} with given degree n:\ + +partial_function (spmf) sample_irreducible_poly :: "nat \ nat \ (nat list \ nat) spmf" + where + "sample_irreducible_poly p n = + do { + k \ spmf_of_set {..The following is a deterministic version. It returns the lexicographically minimal monic +irreducible polynomial. Note that contrary to the randomized algorithm, the run time of the +deterministic algorithm may be exponential (w.r.t. to the size of the field and degree of the +polynomial).\ + +fun find_irreducible_poly :: "nat \ nat \ nat list" + where "find_irreducible_poly p n = (let f = enum_monic_poly (mod_ring p) n in + f (while ((\k. \rabin_test (mod_ring p) (f k))) (\x. x + 1) 0))" + +definition cost :: "('a \ nat) option \ enat" + where "cost x = (case x of None \ \ | Some (_,r) \ enat r)" + +lemma cost_tick: "cost (map_option (\(x, c). (x, Suc c)) c) = eSuc (cost c)" + by (cases c) (auto simp:cost_def eSuc_enat) + +context + fixes n p :: nat + assumes p_prime: "Factorial_Ring.prime p" + assumes n_gt_0: "n > 0" +begin + +private definition S where "S = {f. monic_poly (ring_of (mod_ring p)) f \ degree f = n }" +private definition T where "T = {f. monic_irreducible_poly (ring_of (mod_ring p)) f \ degree f = n}" + +lemmas field_c = mod_ring_is_field_c[OF p_prime] +lemmas enum_c = mod_ring_is_enum_c[where n="p"] + +interpretation finite_field "ring_of (mod_ring p)" + unfolding finite_field_def finite_field_axioms_def + by (intro mod_ring_is_field conjI mod_ring_finite p_prime) + +private lemmas field_ops = field_cD[OF field_c] + +private lemma S_fin: "finite S" + unfolding S_def + using enum_monic_poly[OF field_c enum_c, where d="n"] + bij_betw_finite by auto + +private lemma T_sub_S: "T \ S" + unfolding S_def T_def monic_irreducible_poly_def by auto + +private lemma T_card_gt_0: "real (card T) > 0" +proof - + have "0 < real (order (ring_of (mod_ring p))) ^ n / (2 * real n)" + using n_gt_0 finite_field_min_order by (intro divide_pos_pos) (simp_all) + also have "... \ real (card T)" unfolding T_def by (intro card_irred_gt_0 n_gt_0) + finally show "real (card T) > 0" by auto +qed + +private lemma S_card_gt_0: "real (card S) > 0" +proof - + have "0 < card T" using T_card_gt_0 by simp + also have "... \ card S" by (intro card_mono T_sub_S S_fin) + finally have "0 < card S" by simp + thus ?thesis by simp +qed + +private lemma S_ne: "S \ {}" using S_card_gt_0 by auto + +private lemma sample_irreducible_poly_step_aux: + "do { + k \ spmf_of_set {.. spmf_of_set S; + if monic_irreducible_poly (ring_of (mod_ring p)) poly + then return_spmf (poly,c) + else x + }" + (is "?L = ?R") +proof - + have "order (ring_of (mod_ring p)) = p" + unfolding Finite_Fields_Mod_Ring_Code.mod_ring_def Coset.order_def ring_of_def by simp + hence 0:"spmf_of_set S = map_spmf (enum_monic_poly (mod_ring p) n) (spmf_of_set {.. spmf_of_set S; if rabin_test (mod_ring p) f then return_spmf (f,c) else x}" + unfolding 0 bind_map_spmf by (simp add:Let_def comp_def) + also have "... = ?R" + using set_spmf_of_set_finite[OF S_fin] + by (intro bind_spmf_cong refl if_cong rabin_test field_c enum_c) (simp add:S_def) + finally show ?thesis by simp +qed + +private lemma sample_irreducible_poly_step: + "sample_irreducible_poly p n = + do { + poly \ spmf_of_set S; + if monic_irreducible_poly (ring_of (mod_ring p)) poly + then return_spmf (poly,1) + else tick_spmf (sample_irreducible_poly p n) + }" + by (subst sample_irreducible_poly.simps) (simp add:sample_irreducible_poly_step_aux) + +private lemma sample_irreducible_poly_aux_1: + "ord_spmf (=) (map_spmf fst (sample_irreducible_poly p n)) (spmf_of_set T)" +proof (induction rule:sample_irreducible_poly.fixp_induct) + case 1 thus ?case by simp +next + case 2 thus ?case by simp +next + case (3 rec) + let ?f = "monic_irreducible_poly (ring_of (mod_ring p))" + + have "real (card (S\-{x. ?f x})) = real (card (S - T))" + unfolding S_def T_def by (intro arg_cong[where f="card"] arg_cong[where f="of_nat"]) (auto) + also have "... = real (card S - card T)" + by (intro arg_cong[where f="of_nat"] card_Diff_subset T_sub_S finite_subset[OF T_sub_S S_fin]) + also have "... = real (card S) - card T" + by (intro of_nat_diff card_mono S_fin T_sub_S) + finally have 0:"real (card (S\-{x. ?f x})) = real (card S) - card T" by simp + + have S_card_gt_0: "real (card S) > 0" using S_ne S_fin by auto + + have "do {f \ spmf_of_set S;if ?f f then return_spmf f else spmf_of_set T} = spmf_of_set T" + (is "?L = ?R") + proof (rule spmf_eqI) + fix i + have "spmf ?L i = spmf (pmf_of_set S \(\x. if ?f x then return_spmf x else spmf_of_set T)) i" + unfolding spmf_of_pmf_pmf_of_set[OF S_fin S_ne, symmetric] spmf_of_pmf_def + by (simp add:bind_spmf_def bind_map_pmf) + also have "... = (\x. (if ?f x then of_bool (x=i) else spmf (spmf_of_set T) i) \pmf_of_set S)" + unfolding pmf_bind if_distrib if_distribR pmf_return_spmf indicator_def by (simp cong:if_cong) + also have "... = (\x \ S. (if ?f x then of_bool (x = i) else spmf (spmf_of_set T) i))/card S" + by (subst integral_pmf_of_set[OF S_ne S_fin]) simp + also have "... = (of_bool (i \ T) + spmf (spmf_of_set T) i*real (card (S\-{x. ?f x})))/card S" + using S_fin S_ne + by (subst sum.If_cases[OF S_fin]) (simp add:of_bool_def T_def monic_irreducible_poly_def S_def) + also have "... = (of_bool (i \ T)*(1 + real (card (S\-{x. ?f x}))/real (card T)))/card S" + unfolding spmf_of_set indicator_def by (simp add:algebra_simps) + also have "... = (of_bool (i \ T)*(real (card S)/real (card T)))/card S" + using T_card_gt_0 unfolding 0 by (simp add:field_simps) + also have "... = of_bool (i \ T)/real (card T)" + using S_card_gt_0 by (simp add:field_simps) + also have "... = spmf ?R i" + unfolding spmf_of_set by simp + finally show "spmf ?L i = spmf ?R i" + by simp + qed + hence "ord_spmf (=) + (spmf_of_set S \ (\x. if ?f x then return_spmf x else spmf_of_set T)) (spmf_of_set T)" + by simp + moreover have "ord_spmf (=) + (do { poly \ spmf_of_set S; if ?f poly then return_spmf poly else map_spmf fst (rec p n)}) + (do { poly \ spmf_of_set S; if ?f poly then return_spmf poly else spmf_of_set T})" + using 3 by (intro bind_spmf_mono') simp_all + ultimately have "ord_spmf (=) (spmf_of_set S \ + (\x. if ?f x then return_spmf x else map_spmf fst (rec p n))) (spmf_of_set T)" + using spmf.leq_trans by force + thus ?case unfolding sample_irreducible_poly_step_aux map_spmf_bind_spmf + by (simp add:comp_def if_distribR if_distrib spmf.map_comp case_prod_beta cong:if_cong) +qed + +lemma cost_sample_irreducible_poly: + "(\\<^sup>+x. cost x \sample_irreducible_poly p n) \ 2*real n" (is "?L \ ?R") +proof - + let ?f = "monic_irreducible_poly (ring_of (mod_ring p))" + let ?a = "(\t. measure (sample_irreducible_poly p n) {\. enat t < cost \})" + let ?b = "(\t. measure (sample_irreducible_poly p n) {\. enat t \ cost \})" + + define \ where "\ = measure (pmf_of_set S) {x. ?f x}" + have \_le_1: "\ \ 1" unfolding \_def by simp + + have "1 / (2* real n) = (card S / (2 * real n)) / card S" + using S_card_gt_0 by (simp add:algebra_simps) + also have "... = (real (order (ring_of (mod_ring p)))^n / (2 * real n)) / card S" + unfolding S_def bij_betw_same_card[OF enum_monic_poly[OF field_c enum_c, where d="n"],symmetric] + by simp + also have "... \ card T / card S" + unfolding T_def by (intro divide_right_mono card_irred_gt_0 n_gt_0) auto + also have "... = \" + unfolding \_def measure_pmf_of_set[OF S_ne S_fin] + by (intro arg_cong2[where f="(/)"] refl arg_cong[where f="of_nat"] arg_cong[where f="card"]) + (auto simp: S_def T_def monic_irreducible_poly_def) + finally have \_lb: "1/ (2*real n) \ \" + by simp + have "0 < 1/ (2*real n)" using n_gt_0 by simp + also have "... \ \" using \_lb by simp + finally have \_gt_0: "\ > 0" by simp + + have a_step_aux: "norm (a * b) \ 1" if "norm a \ 1" "norm b \ 1" for a b :: real + using that by (simp add:abs_mult mult_le_one) + + have b_eval: "?b t = (\x. (if ?f x then of_bool(t \ 1) else + measure (sample_irreducible_poly p n) {\. enat t \ eSuc (cost \)}) \pmf_of_set S)" + (is "?L1 = ?R1") for t + proof - + have "?b t = measure (bind_spmf (spmf_of_set S) (\x. if ?f x then return_spmf (x,1) else + tick_spmf (sample_irreducible_poly p n))) {\. enat t \ cost \}" + by (subst sample_irreducible_poly_step) simp + also have "... = measure (bind_pmf (pmf_of_set S) (\x. if ?f x then return_spmf (x,1) else + tick_spmf (sample_irreducible_poly p n))) {\. enat t \ cost \}" + unfolding spmf_of_pmf_pmf_of_set[OF S_fin S_ne, symmetric] + by (simp add:spmf_of_pmf_def bind_map_pmf bind_spmf_def) + also have "... = (\x. (if ?f x then of_bool(t \ 1) else + measure (tick_spmf (sample_irreducible_poly p n)) {\. enat t \ cost \}) \pmf_of_set S)" + unfolding measure_bind_pmf if_distrib if_distribR emeasure_return_pmf + by (simp add:indicator_def cost_def comp_def cong:if_cong) + also have "... = ?R1" + unfolding measure_map_pmf vimage_def + by (intro arg_cong2[where f="integral\<^sup>L"] refl ext if_cong arg_cong2[where f="measure"]) + (auto simp add:vimage_def cost_tick eSuc_enat[symmetric]) + finally show ?thesis by simp + qed + + have b_eval_2: "?b t = 1 - (1-\)^t" for t + proof (induction t) + case 0 + have "?b 0 = 0" unfolding b_eval by (simp add:enat_0 cong:if_cong ) + thus ?case by simp + next + case (Suc t) + have "?b (Suc t) = (\x. (if ?f x then 1 else ?b t) \pmf_of_set S)" + unfolding b_eval[of "Suc t"] + by (intro arg_cong2[where f="integral\<^sup>L"] if_cong arg_cong2[where f="measure"]) + (auto simp add: eSuc_enat[symmetric]) + also have "... = (\x. indicator {x. ?f x} x + ?b t * indicator {x. \?f x} x \pmf_of_set S)" + by (intro Bochner_Integration.integral_cong) (auto simp:algebra_simps) + also have "... = (\x. indicator {x. ?f x} x \pmf_of_set S) + + (\x. ?b t * indicator {x. \?f x} x \pmf_of_set S)" + by (intro Bochner_Integration.integral_add measure_pmf.integrable_const_bound[where B="1"] + AE_pmfI a_step_aux) auto + also have "... = \ + ?b t * measure (pmf_of_set S) {x. \?f x}" unfolding \_def by simp + also have "... = \ + (1-\) * ?b t" + unfolding \_def + by (subst measure_pmf.prob_compl[symmetric]) (auto simp:Compl_eq_Diff_UNIV Collect_neg_eq) + also have "... = 1 - (1-\)^Suc t" + unfolding Suc by (simp add:algebra_simps) + finally show ?case by simp + qed + + hence a_eval: "?a t = (1-\)^t" for t + proof - + have "?a t = 1 - ?b t" + by (simp add: measure_pmf.prob_compl[symmetric] Compl_eq_Diff_UNIV[symmetric] + Collect_neg_eq[symmetric] not_le) + also have "... = (1-\)^t" + unfolding b_eval_2 by simp + finally show ?thesis by simp + qed + + have "?L = (\t. emeasure (sample_irreducible_poly p n) {\. enat t < cost \})" + by (subst nn_integral_enat_function) simp_all + also have "... = (\t. ennreal (?a t))" + unfolding measure_pmf.emeasure_eq_measure by simp + also have "... = (\t. ennreal ((1-\)^t))" + unfolding a_eval by (intro arg_cong[where f="suminf"] ext) (simp add: \_def ennreal_mult') + also have "... = ennreal (1 / (1-(1-\)))" + using \_le_1 \_gt_0 + by (intro arg_cong2[where f="(*)"] refl suminf_ennreal_eq geometric_sums) auto + also have "... = ennreal (1 / \)" using \_le_1 \_gt_0 by auto + also have "... \ ?R" + using \_lb n_gt_0 \_gt_0 by (intro ennreal_leI) (simp add:field_simps) + finally show ?thesis by simp +qed + +private lemma weight_sample_irreducible_poly: + "weight_spmf (sample_irreducible_poly p n) = 1" (is "?L = ?R") +proof (rule ccontr) + assume "?L \ 1" + hence "?L < 1" using less_eq_real_def weight_spmf_le_1 by blast + hence "(\::ennreal) = \ * ennreal (1-?L)" by simp + also have "... = \ * ennreal (pmf (sample_irreducible_poly p n) None)" + unfolding pmf_None_eq_weight_spmf[symmetric] by simp + also have "... = (\\<^sup>+x. \ * indicator {None} x \sample_irreducible_poly p n)" + by (simp add:emeasure_pmf_single) + also have "... \ (\\<^sup>+x. cost x \sample_irreducible_poly p n)" + unfolding cost_def by (intro nn_integral_mono) (auto simp:indicator_def) + also have "... \ 2*real n" by (intro cost_sample_irreducible_poly) + finally have "(\::ennreal) \ 2 * real n" by simp + thus "False" using linorder_not_le by fastforce +qed + +lemma sample_irreducible_poly_result: + "map_spmf fst (sample_irreducible_poly p n) = + spmf_of_set {f. monic_irreducible_poly (ring_of (mod_ring p)) f \ degree f = n}" (is "?L = ?R") +proof - + have "?L = spmf_of_set T" using weight_sample_irreducible_poly + by (intro eq_iff_ord_spmf sample_irreducible_poly_aux_1) (auto intro:weight_spmf_le_1) + thus ?thesis unfolding T_def by simp +qed + +lemma find_irreducible_poly_result: + defines "res \ find_irreducible_poly p n" + shows "monic_irreducible_poly (ring_of (mod_ring p)) res" "degree res = n" +proof - + let ?f = "enum_monic_poly (mod_ring p) n" + + have ex:"\k. ?f k \ T \ k < order (ring_of (mod_ring p))^n" + proof (rule ccontr) + assume "\k. ?f k \ T \ k < order (ring_of (mod_ring p)) ^ n" + hence "?f ` {.. T = {}" by auto + hence "S \ T = {}" + unfolding S_def using bij_betw_imp_surj_on[OF enum_monic_poly[OF field_c enum_c]] by auto + hence "T = {}" using T_sub_S by auto + thus "False" using T_card_gt_0 by simp + qed + + then obtain k :: nat where k_def: "?f k \ T" "\j T" + using exists_least_iff[where P="\x. ?f x \ T"] by auto + + have k_ub: "k < order (ring_of (mod_ring p))^n" + using ex k_def(2) by (meson dual_order.strict_trans1 not_less) + + have a: "monic_irreducible_poly (ring_of (mod_ring p)) (?f k)" + using k_def(1) unfolding T_def by simp + have b: "monic_poly (ring_of (mod_ring p)) (?f j)" "degree (?f j) = n" if "j \ k" for j + proof - + have "j < order (ring_of (mod_ring p)) ^n" using k_ub that by simp + hence "?f j \ S" unfolding S_def using bij_betw_apply[OF enum_monic_poly[OF field_c enum_c]] by auto + thus "monic_poly (ring_of (mod_ring p)) (?f j)" "degree (?f j) = n" unfolding S_def by auto + qed + + have c: "\monic_irreducible_poly (ring_of (mod_ring p)) (?f j)" if " j < k" for j + using b[of "j"] that k_def(2) unfolding T_def by auto + + have 2: "while ((\k. \rabin_test (mod_ring p) (?f k))) (\x. x + 1) (k-j) = k" if "j \ k" for j + using that proof (induction j) + case 0 + have "rabin_test (mod_ring p) (?f k)" by (intro iffD2[OF rabin_test] a b field_c enum_c) auto + thus ?case by (subst while_unfold) simp + next + case (Suc j) + hence "\rabin_test (mod_ring p) (?f (k-Suc j))" + using b c by (subst rabin_test[OF field_c enum_c]) auto + moreover have "Suc (Suc (k - Suc j)) = Suc (k-j)" using Suc by simp + ultimately show ?case using Suc(1) by (subst while_unfold) simp + qed + + have 3:"while ((\k. \rabin_test (mod_ring p) (?f k))) (\x. x + 1) 0 = k" + using 2[of "k"] by simp + + have "?f k \ T" using a b unfolding T_def by auto + hence "res \ T" unfolding res_def find_irreducible_poly.simps Let_def 3 by simp + thus "monic_irreducible_poly (ring_of (mod_ring p)) res" "degree res = n" unfolding T_def by auto +qed + +lemma monic_irred_poly_set_nonempty_finite: + "{f. monic_irreducible_poly (ring_of (mod_ring p)) f \ degree f = n} \ {}" (is "?R1") + "finite {f. monic_irreducible_poly (ring_of (mod_ring p)) f \ degree f = n}" (is "?R2") +proof - + have "card T > 0" using T_card_gt_0 by auto + hence "T \ {}" "finite T" using card_ge_0_finite by auto + thus ?R1 ?R2 unfolding T_def by auto +qed + +end + +text \Returns @{term "m"} @{term "e"} such that @{term "n = m^e"}, where @{term "e"} is maximal.\ + +definition split_power :: "nat \ nat \ nat" + where "split_power n = ( + let e = last (filter (\x. is_nth_power_nat x n) (1#[2..k. n > 1 \ k>e \ \is_nth_power k n" +proof - + define es where "es = filter (\x. is_nth_power_nat x n) (1#[2.. 1" for x + proof (rule ccontr) + assume a:"\(x < m)" + obtain y where n_def:"n = y^x" using that0 is_nth_power_def is_nth_power_nat_def by auto + have "y \ 0" using that(2) unfolding n_def + by (metis (mono_tags) nat_power_eq_Suc_0_iff not_less0 power_0_left power_inject_exp) + moreover have "y \ 1" using that(2) unfolding n_def by auto + ultimately have y_ge_2: "y \ 2" by simp + have "n < 2^floorlog 2 n" using that floorlog_bounds by simp + also have "... \ 2^x" using a unfolding m_def by (intro power_increasing) auto + also have "... \ y^x" using y_ge_2 by (intro power_mono) auto + also have "... = n" using n_def by auto + finally show "False" by simp + qed + + have 1: "m = 2" if "\(n > 1)" + proof - + have "floorlog 2 n \ 2" using that by (intro floorlog_leI) auto + thus ?thesis unfolding m_def by auto + qed + + have 2: "n = 1" if "is_nth_power_nat 0 n" using that by (simp add: is_nth_power_nat_code) + + have "set es = {x \ insert 1 {2.. 0 \ x < m \ is_nth_power_nat x n}" unfolding m_def by auto + also have "... = {x. is_nth_power_nat x n \ (n > 1 \ x = 1)}" + using 0 1 2 zero_neq_one by (intro Collect_cong iffI conjI) fastforce+ + finally have set_es: "set es = {x. is_nth_power_nat x n \ (n > 1 \ x = 1)}" by simp + + have "is_nth_power_nat 1 n" unfolding is_nth_power_nat_def by simp + hence es_ne: "es \ []" unfolding es_def by auto + + have sorted: "sorted es" unfolding es_def by (intro sorted_wrt_filter) simp + + have e_def: "e = last es" and x_def: "x = nth_root_nat e n" + using assms unfolding es_def split_power_def by (simp_all add:Let_def) + + hence e_in_set_es: "e \ set es" unfolding e_def using es_ne by (intro last_in_set) auto + + have e_max: "x \ e" if that1:"x \ set es" for x + proof - + obtain k where "k < length es" "x = es ! k" using that1 by (metis in_set_conv_nth) + moreover have "e = es ! (length es -1)" unfolding e_def using es_ne last_conv_nth by auto + ultimately show ?thesis using sorted_nth_mono[OF sorted] es_ne by simp + qed + have 3:"is_nth_power_nat e n \ (1 < n \ e = 1)" using e_in_set_es unfolding set_es by simp + hence "e > 0" using 2 zero_neq_one by fast + thus "n = x^e" using 3 unfolding x_def using nth_root_nat_nth_power + by (metis is_nth_power_nat_code nth_root_nat_naive_code power_eq_0_iff) + show "\is_nth_power k n" if "n > 1" "k > e" for k + proof (rule ccontr) + assume "\(\is_nth_power k n)" + hence "k \ set es" using that unfolding set_es is_nth_power_nat_def by auto + hence "k \ e" using e_max by auto + thus "False" using that(2) by auto + qed +qed + +definition not_perfect_power :: "nat \ bool" + where "not_perfect_power n = (n > 1 \ (\x k. n = x ^ k \ k = 1))" + +lemma is_nth_power_from_multiplicities: + assumes "n > (0::nat)" + assumes "\p. Factorial_Ring.prime p \ k dvd (multiplicity p n)" + shows "is_nth_power k n" +proof - + have "n = (\p \ prime_factors n. p^multiplicity p n)" using assms(1) + by (simp add: prod_prime_factors) + also have "... = (\p \ prime_factors n. p^((multiplicity p n div k)*k))" + by (intro prod.cong arg_cong2[where f="power"] dvd_div_mult_self[symmetric] refl assms(2)) auto + also have "... = (\p \ prime_factors n. p^(multiplicity p n div k))^k" + unfolding power_mult prod_power_distrib[symmetric] by simp + finally have "n = (\p \ prime_factors n. p^(multiplicity p n div k))^k" by simp + thus ?thesis by (intro is_nth_powerI) simp +qed + +lemma power_inj_aux: + assumes "not_perfect_power a" "not_perfect_power b" + assumes "n > 0" "m > n" + assumes "a ^ n = b ^ m" + shows "False" +proof - + define s where "s = gcd n m" + define u where "u = n div gcd n m" + define t where "t = m div gcd n m" + + have a_nz: "a \ 0" and b_nz: "b \ 0" using assms(1,2) unfolding not_perfect_power_def by auto + + have "gcd n m \ 0" using assms (3,4) by simp + + then obtain t u where n_def: "n = t * s" and m_def: "m = u * s" and cp: "coprime t u" + using gcd_coprime_exists unfolding s_def t_def u_def by blast + + have s_gt_0: "s > 0" and t_gt_0: "t > 0" and u_gt_t: "u > t" + using assms(3,4) unfolding n_def m_def by auto + + have "(a ^ t) ^ s = (b ^ u) ^ s" using assms(5) unfolding n_def m_def power_mult by simp + hence 0: "a^t = b^u" using s_gt_0 by (metis nth_root_nat_nth_power) + + have "u dvd multiplicity p a" if "Factorial_Ring.prime p" for p + proof - + have "prime_elem p" using that by simp + hence "t * multiplicity p a = u * multiplicity p b" + using 0 a_nz b_nz by (subst (1 2) prime_elem_multiplicity_power_distrib[symmetric]) auto + hence "u dvd t * multiplicity p a" by simp + thus ?thesis using cp coprime_commute coprime_dvd_mult_right_iff by blast + qed + + hence "is_nth_power u a" using a_nz by (intro is_nth_power_from_multiplicities) auto + moreover have "u > 1" using u_gt_t t_gt_0 by auto + ultimately show "False" using assms(1) unfolding not_perfect_power_def is_nth_power_def by auto +qed + +text \Generalization of @{thm [source] prime_power_inj'}\ + +lemma power_inj: + assumes "not_perfect_power a" "not_perfect_power b" + assumes "n > 0" "m > 0" + assumes "a ^ n = b ^ m" + shows "a = b \ n = m" +proof - + consider (a) "n < m" | (b) "m < n" | (c) "n = m" by linarith + thus ?thesis + proof (cases) + case a thus ?thesis using assms power_inj_aux by auto + next + case b thus ?thesis using assms power_inj_aux[OF assms(2,1,4) b] by auto + next + case c thus ?thesis using assms by (simp add: power_eq_iff_eq_base) + qed +qed + +lemma split_power_base_not_perfect: + assumes "n > 1" + shows "not_perfect_power (fst (split_power n))" +proof (rule ccontr) + obtain b e where be_def: "(b,e) = split_power n" by (metis surj_pair) + have n_def:"n = b ^ e" and e_max: "\k. e < k \ \ is_nth_power k n" + using assms split_power_result[OF be_def] by auto + + have e_gt_0: "e > 0" using assms unfolding n_def by (cases e) auto + + assume "\not_perfect_power (fst (split_power n))" + hence "\not_perfect_power b" unfolding be_def[symmetric] by simp + moreover have b_gt_1: "b > 1" using assms unfolding n_def + by (metis less_one nat_neq_iff nat_power_eq_Suc_0_iff power_0_left) + ultimately obtain k b' where "k \ 1" and b_def: "b = b'^k" + unfolding not_perfect_power_def by auto + hence k_gt_1: "k > 1" using b_gt_1 nat_neq_iff by force + have "n = b'^(k*e)" unfolding power_mult n_def b_def by auto + moreover have "k*e > e" using k_gt_1 e_gt_0 by simp + hence "\is_nth_power (k*e) n" using e_max by auto + ultimately show "False" unfolding is_nth_power_def by auto +qed + +lemma prime_not_perfect: + assumes "Factorial_Ring.prime p" + shows "not_perfect_power p" +proof - + have "k=1" if "p = x^k" for x k using assms unfolding that by (simp add:prime_power_iff) + thus ?thesis using prime_gt_1_nat[OF assms] unfolding not_perfect_power_def by auto +qed + +lemma split_power_prime: + assumes "Factorial_Ring.prime p" "n > 0" + shows "split_power (p^n) = (p,n)" +proof - + obtain x e where xe:"(x,e) = split_power (p^n)" by (metis surj_pair) + + have "1 < p^1" using prime_gt_1_nat[OF assms(1)] by simp + also have "... \ p^n" using assms(2) prime_gt_0_nat[OF assms(1)] by (intro power_increasing) auto + finally have 0:"p^n > 1" by simp + + have "not_perfect_power x" + using split_power_base_not_perfect[OF 0] unfolding xe[symmetric] by simp + moreover have "not_perfect_power p" by (rule prime_not_perfect[OF assms(1)]) + moreover have 1:"p^n = x^e" using split_power_result[OF xe] by simp + moreover have "e > 0" using 0 1 by (cases e) auto + ultimately have "p=x \ n = e" by (intro power_inj assms(2)) + thus ?thesis using xe by simp +qed + +definition "is_prime_power n = (\p k. Factorial_Ring.prime p \ k > 0 \ n = p^k)" + +definition GF where + "GF n = ( + let (p,k) = split_power n; + f = find_irreducible_poly p k + in poly_mod_ring (mod_ring p) f)" + + +definition GF\<^sub>R where + "GF\<^sub>R n = + do { + let (p,k) = split_power n; + f \ sample_irreducible_poly p k; + return_spmf (poly_mod_ring (mod_ring p) (fst f)) + }" + +lemma GF_in_GF_R: + assumes "is_prime_power n" + shows "GF n \ set_spmf (GF\<^sub>R n)" +proof- + obtain p k where n_def: "n = p^k" and p_prime: "prime p" and k_gt_0: "k > 0" + using assms unfolding is_prime_power_def by blast + have pk_def: "(p,k) = split_power n" + unfolding n_def using split_power_prime[OF p_prime k_gt_0] by auto + let ?S = "{f. monic_irreducible_poly (ring_of (mod_ring p)) f \ degree f = k}" + + have S_fin: "finite ?S" by (intro monic_irred_poly_set_nonempty_finite p_prime k_gt_0) + + have "find_irreducible_poly p k \ ?S" + using find_irreducible_poly_result[OF p_prime k_gt_0] by auto + also have "... = set_spmf (map_spmf fst (sample_irreducible_poly p k))" + unfolding sample_irreducible_poly_result[OF p_prime k_gt_0] set_spmf_of_set_finite[OF S_fin] + by simp + finally have 0: "find_irreducible_poly p k \ set_spmf(map_spmf fst (sample_irreducible_poly p k))" + by simp + + have "GF n = poly_mod_ring (mod_ring p) (find_irreducible_poly p k)" + unfolding GF_def pk_def[symmetric] by (simp del:find_irreducible_poly.simps) + also have "... \ set_spmf (map_spmf fst (sample_irreducible_poly p k)) \ (\x. {poly_mod_ring (mod_ring p) x})" + using 0 by force + also have "... = set_spmf (GF\<^sub>R n)" + unfolding GF\<^sub>R_def pk_def[symmetric] by (simp add:set_bind_spmf comp_def bind_image) + finally show ?thesis by simp +qed + +lemma galois_field_random_1: + assumes "is_prime_power n" + shows "\\. \ \ set_spmf (GF\<^sub>R n) \ enum\<^sub>C \ \ field\<^sub>C \ \ order (ring_of \) = n" + and "lossless_spmf (GF\<^sub>R n)" +proof - + let ?pred = "\\. enum\<^sub>C \ \ field\<^sub>C \ \ order (ring_of \) = n" + + obtain p k where n_def: "n = p^k" and p_prime: "prime p" and k_gt_0: "k > 0" + using assms unfolding is_prime_power_def by blast + let ?r = "(\f. poly_mod_ring (mod_ring p) f)" + let ?S = "{f. monic_irreducible_poly (ring_of (mod_ring p)) f \ degree f = k}" + + have fc: "field\<^sub>C (mod_ring p)" by (intro mod_ring_is_field_c p_prime) + have ec: "enum\<^sub>C (mod_ring p)" by (intro mod_ring_is_enum_c) + + have S_fin: "finite ?S" by (intro monic_irred_poly_set_nonempty_finite p_prime k_gt_0) + have S_ne: "?S \ {}" by (intro monic_irred_poly_set_nonempty_finite p_prime k_gt_0) + + have pk_def: "(p,k) = split_power n" + unfolding n_def using split_power_prime[OF p_prime k_gt_0] by auto + + have cond: "?pred (?r x)" if "x \ ?S" for x + proof - + have "order (ring_of (poly_mod_ring (mod_ring p) x)) = idx_size (poly_mod_ring (mod_ring p) x)" + using enum_cD[OF enum_c_poly_mod_ring[OF ec field_c_imp_ring[OF fc]]] by simp + also have "... = p^(degree x)" + by (simp add:poly_mod_ring_def Finite_Fields_Mod_Ring_Code.mod_ring_def) + also have "... = n" unfolding n_def using that by simp + finally have "order (ring_of (poly_mod_ring (mod_ring p) x)) = n" by simp + + thus ?thesis using that + by (intro conjI enum_c_poly_mod_ring field_c_poly_mod_ring ec field_c_imp_ring fc) auto + qed + + have "GF\<^sub>R n = bind_spmf (map_spmf fst (sample_irreducible_poly p k)) (\x. return_spmf (?r x))" + unfolding GF\<^sub>R_def pk_def[symmetric] map_spmf_conv_bind_spmf by simp + also have "... = spmf_of_set ?S \ (\f. return_spmf ((?r f)))" + unfolding sample_irreducible_poly_result[OF p_prime k_gt_0] by (simp) + also have "... = pmf_of_set ?S \ (\f. return_spmf (?r f))" + unfolding spmf_of_pmf_pmf_of_set[OF S_fin S_ne, symmetric] spmf_of_pmf_def + by (simp add:bind_spmf_def bind_map_pmf) + finally have 0:"GF\<^sub>R n = map_pmf (Some \ ?r) (pmf_of_set ?S) " by (simp add:comp_def map_pmf_def) + + show "enum\<^sub>C \ \ field\<^sub>C \ \ order (ring_of \) = n" if "\ \ set_spmf (GF\<^sub>R n)" for \ + proof - + have "Some \ \ set_pmf (GF\<^sub>R n)" unfolding in_set_spmf[symmetric] by (rule that) + also have "... = (Some \ ?r) ` ?S" unfolding 0 set_map_pmf set_pmf_of_set[OF S_ne S_fin] by simp + finally have "Some \ \ (Some \ ?r) ` ?S" by simp + hence "\ \ ?r ` ?S" by auto + then obtain x where x:"x \ ?S" and \_def:"\ = ?r x" by auto + show ?thesis unfolding \_def by (intro cond x) + qed + + have "None \ set_pmf(GF\<^sub>R n)" unfolding 0 set_map_pmf set_pmf_of_set[OF S_ne S_fin] by auto + thus "lossless_spmf (GF\<^sub>R n)" using lossless_iff_set_pmf_None by blast +qed + +lemma galois_field: + assumes "is_prime_power n" + shows "enum\<^sub>C (GF n)" "field\<^sub>C (GF n)" "order (ring_of (GF n)) = n" + using galois_field_random_1(1)[OF assms(1) GF_in_GF_R[OF assms(1)]] by auto + +lemma lossless_imp_spmf_of_pmf: + assumes "lossless_spmf M" + shows "spmf_of_pmf (map_pmf the M) = M" +proof - + have "spmf_of_pmf (map_pmf the M) = map_pmf (Some \ the) M" + unfolding spmf_of_pmf_def by (simp add: pmf.map_comp) + also have "... = map_pmf id M" + using assms unfolding lossless_iff_set_pmf_None + by (intro map_pmf_cong refl) (metis id_apply o_apply option.collapse) + also have "... = M" by simp + finally show ?thesis by simp +qed + +lemma galois_field_random_2: + assumes "is_prime_power n" + shows "map_spmf (\\. enum\<^sub>C \ \ field\<^sub>C \ \ order (ring_of \) = n) (GF\<^sub>R n) = return_spmf True" + (is "?L = _") +proof - + have "?L = map_spmf (\\. True) (GF\<^sub>R n)" + using galois_field_random_1[OF assms] by (intro map_spmf_cong refl) auto + also have "... = map_pmf (\\. Some True) (GF\<^sub>R n)" + by (subst lossless_imp_spmf_of_pmf[OF galois_field_random_1(2)[OF assms],symmetric]) simp + also have "... = return_spmf True" unfolding map_pmf_def by simp + finally show ?thesis by simp +qed + +lemma bind_galois_field_cong: + assumes "is_prime_power n" + assumes "\\. enum\<^sub>C \ \ field\<^sub>C \ \ order (ring_of \) = n \ f \ = g \" + shows "bind_spmf (GF\<^sub>R n) f = bind_spmf (GF\<^sub>R n) g" + using galois_field_random_1(1)[OF assms(1)] + by (intro bind_spmf_cong refl assms(2)) auto + +end \ No newline at end of file diff --git a/thys/Finite_Fields/Finite_Fields_Factorization_Ext.thy b/thys/Finite_Fields/Finite_Fields_Factorization_Ext.thy --- a/thys/Finite_Fields/Finite_Fields_Factorization_Ext.thy +++ b/thys/Finite_Fields/Finite_Fields_Factorization_Ext.thy @@ -1,516 +1,516 @@ subsection "Factorization" theory Finite_Fields_Factorization_Ext imports Finite_Fields_Preliminary_Results begin text \This section contains additional results building on top of the development in @{theory "HOL-Algebra.Divisibility"} about factorization in a @{locale "factorial_monoid"}.\ -definition factor_mset where "factor_mset G x = +definition factor_mset where "factor_mset G x = (THE f. (\ as. f = fmset G as \ wfactors G as x \ set as \ carrier G))" text \In @{theory "HOL-Algebra.Divisibility"} it is already verified that the multiset representing the factorization of an element of a factorial monoid into irreducible factors is well-defined. With these results it is then possible to define @{term "factor_mset"} and show its properties, without referring to a factorization in list form first.\ definition multiplicity where "multiplicity G d g = Max {(n::nat). (d [^]\<^bsub>G\<^esub> n) divides\<^bsub>G\<^esub> g}" -definition canonical_irreducibles where +definition canonical_irreducibles where "canonical_irreducibles G A = ( A \ {a. a \ carrier G \ irreducible G a} \ (\x y. x \ A \ y \ A \ x \\<^bsub>G\<^esub> y \ x = y) \ (\x \ carrier G. irreducible G x \ (\y \ A. x \\<^bsub>G\<^esub> y)))" text \A set of irreducible elements that contains exactly one element from each equivalence class -of an irreducible element formed by association, is called a set of +of an irreducible element formed by association, is called a set of @{term "canonical_irreducibles"}. An example is the set of monic irreducible polynomials as representatives of all irreducible polynomials.\ context factorial_monoid begin lemma assoc_as_fmset_eq: assumes "wfactors G as a" and "wfactors G bs b" and "a \ carrier G" and "b \ carrier G" and "set as \ carrier G" and "set bs \ carrier G" shows "a \ b \ (fmset G as = fmset G bs)" proof - have "a \ b \ (a divides b \ b divides a)" by (simp add:associated_def) - also have "... \ + also have "... \ (fmset G as \# fmset G bs \ fmset G bs \# fmset G as)" using divides_as_fmsubset assms by blast also have "... \ (fmset G as = fmset G bs)" by auto finally show ?thesis by simp qed lemma factor_mset_aux_1: assumes "a \ carrier G" "set as \ carrier G" "wfactors G as a" shows "factor_mset G a = fmset G as" proof - define H where "H = {as. wfactors G as a \ set as \ carrier G}" have b:"as \ H" using H_def assms by simp have c: "x \ H \ y \ H \ fmset G x = fmset G y" for x y - unfolding H_def using assoc_as_fmset_eq - using associated_refl assms by blast + unfolding H_def using assoc_as_fmset_eq + using associated_refl assms by blast have "factor_mset G a = (THE f. \as \ H. f= fmset G as)" - by (simp add:factor_mset_def H_def, metis) + by (simp add:factor_mset_def H_def, metis) also have "... = fmset G as" using b c by (intro the1_equality) blast+ finally have "factor_mset G a = fmset G as" by simp thus ?thesis using b unfolding H_def by auto qed lemma factor_mset_aux: assumes "a \ carrier G" - shows "\as. factor_mset G a = fmset G as \ wfactors G as a \ + shows "\as. factor_mset G a = fmset G as \ wfactors G as a \ set as \ carrier G" proof - obtain as where as_def: "wfactors G as a" "set as \ carrier G" using wfactors_exist assms by blast thus ?thesis using factor_mset_aux_1 assms by blast qed lemma factor_mset_set: assumes "a \ carrier G" - assumes "x \# factor_mset G a" - obtains y where - "y \ carrier G" - "irreducible G y" - "assocs G y = x" + assumes "x \# factor_mset G a" + obtains y where + "y \ carrier G" + "irreducible G y" + "assocs G y = x" proof - - obtain as where as_def: - "factor_mset G a = fmset G as" + obtain as where as_def: + "factor_mset G a = fmset G as" "wfactors G as a" "set as \ carrier G" using factor_mset_aux assms by blast hence "x \# fmset G as" using assms by simp hence "x \ assocs G ` set as" using assms as_def by (simp add:fmset_def) hence "\y. y \ set as \ x = assocs G y" by auto - moreover have "y \ carrier G \ irreducible G y" + moreover have "y \ carrier G \ irreducible G y" if "y \ set as" for y using as_def that wfactors_def by (simp add: wfactors_def) auto ultimately show ?thesis using that by blast qed lemma factor_mset_mult: assumes "a \ carrier G" "b \ carrier G" shows "factor_mset G (a \ b) = factor_mset G a + factor_mset G b" proof - - obtain as where as_def: - "factor_mset G a = fmset G as" + obtain as where as_def: + "factor_mset G a = fmset G as" "wfactors G as a" "set as \ carrier G" using factor_mset_aux assms by blast - obtain bs where bs_def: - "factor_mset G b = fmset G bs" + obtain bs where bs_def: + "factor_mset G b = fmset G bs" "wfactors G bs b" "set bs \ carrier G" using factor_mset_aux assms(2) by blast have "a \ b \ carrier G" using assms by auto then obtain cs where cs_def: - "factor_mset G (a \ b) = fmset G cs" - "wfactors G cs (a \ b)" + "factor_mset G (a \ b) = fmset G cs" + "wfactors G cs (a \ b)" "set cs \ carrier G" using factor_mset_aux assms by blast have "fmset G cs = fmset G as + fmset G bs" - using as_def bs_def cs_def assms + using as_def bs_def cs_def assms by (intro mult_wfactors_fmset[where a="a" and b="b"]) auto thus ?thesis using as_def bs_def cs_def by auto qed lemma factor_mset_unit: "factor_mset G \ = {#}" proof - have "factor_mset G \ = factor_mset G (\ \ \)" by simp also have "... = factor_mset G \ + factor_mset G \" by (intro factor_mset_mult, auto) finally show "factor_mset G \ = {#}" by simp qed -lemma factor_mset_irred: +lemma factor_mset_irred: assumes "x \ carrier G" "irreducible G x" shows "factor_mset G x = image_mset (assocs G) {#x#}" proof - have "wfactors G [x] x" using assms by (simp add:wfactors_def) hence "factor_mset G x = fmset G [x]" using factor_mset_aux_1 assms by simp also have "... = image_mset (assocs G) {#x#}" by (simp add:fmset_def) finally show ?thesis by simp qed lemma factor_mset_divides: assumes "a \ carrier G" "b \ carrier G" shows "a divides b \ factor_mset G a \# factor_mset G b" proof - - obtain as where as_def: - "factor_mset G a = fmset G as" + obtain as where as_def: + "factor_mset G a = fmset G as" "wfactors G as a" "set as \ carrier G" using factor_mset_aux assms by blast - obtain bs where bs_def: - "factor_mset G b = fmset G bs" + obtain bs where bs_def: + "factor_mset G b = fmset G bs" "wfactors G bs b" "set bs \ carrier G" using factor_mset_aux assms(2) by blast hence "a divides b \ fmset G as \# fmset G bs" using as_def bs_def assms by (intro divides_as_fmsubset) auto also have "... \ factor_mset G a \# factor_mset G b" using as_def bs_def by simp finally show ?thesis by simp qed lemma factor_mset_sim: assumes "a \ carrier G" "b \ carrier G" shows "a \ b \ factor_mset G a = factor_mset G b" using factor_mset_divides assms by (simp add:associated_def) auto lemma factor_mset_prod: assumes "finite A" - assumes "f ` A \ carrier G" - shows "factor_mset G (\a \ A. f a) = + assumes "f ` A \ carrier G" + shows "factor_mset G (\a \ A. f a) = (\a \ A. factor_mset G (f a))" using assms proof (induction A rule:finite_induct) case empty then show ?case by (simp add:factor_mset_unit) next case (insert x F) - have "factor_mset G (finprod G f (insert x F)) = + have "factor_mset G (finprod G f (insert x F)) = factor_mset G (f x \ finprod G f F)" using insert by (subst finprod_insert) auto also have "... = factor_mset G (f x) + factor_mset G (finprod G f F)" using insert by (intro factor_mset_mult finprod_closed) auto - also have + also have "... = factor_mset G (f x) + (\a \ F. factor_mset G (f a))" using insert by simp also have "... = (\a\insert x F. factor_mset G (f a))" using insert by simp finally show ?case by simp qed lemma factor_mset_pow: assumes "a \ carrier G" shows "factor_mset G (a [^] n) = repeat_mset n (factor_mset G a)" proof (induction n) case 0 then show ?case by (simp add:factor_mset_unit) next case (Suc n) have "factor_mset G (a [^] Suc n) = factor_mset G (a [^] n \ a)" by simp also have "... = factor_mset G (a [^] n) + factor_mset G a" using assms by (intro factor_mset_mult) auto also have "... = repeat_mset n (factor_mset G a) + factor_mset G a" using Suc by simp also have "... = repeat_mset (Suc n) (factor_mset G a)" by simp finally show ?case by simp qed lemma image_mset_sum: assumes "finite F" - shows + shows "image_mset h (\x \ F. f x) = (\x \ F. image_mset h (f x))" using assms by (induction F rule:finite_induct, simp, simp) -lemma decomp_mset: +lemma decomp_mset: "(\x\set_mset R. replicate_mset (count R x) x) = R" by (rule multiset_eqI, simp add:count_sum count_eq_zero_iff) lemma factor_mset_count: assumes "a \ carrier G" "d \ carrier G" "irreducible G d" shows "count (factor_mset G a) (assocs G d) = multiplicity G d a" proof - - have a: + have a: "count (factor_mset G a) (assocs G d) \ m \ d [^] m divides a" (is "?lhs \ ?rhs") for m proof - have "?lhs \ replicate_mset m (assocs G d) \# factor_mset G a" by (simp add:count_le_replicate_mset_subset_eq) also have "... \ factor_mset G (d [^] m) \# factor_mset G a" using assms(2,3) by (simp add:factor_mset_pow factor_mset_irred) also have "... \ ?rhs" using assms(1,2) by (subst factor_mset_divides) auto finally show ?thesis by simp qed define M where "M = {(m::nat). d [^] m divides a}" have M_alt: "M = {m. m \ count (factor_mset G a) (assocs G d)}" using a by (simp add:M_def) hence "Max M = count (factor_mset G a) (assocs G d)" by (intro Max_eqI, auto) thus ?thesis unfolding multiplicity_def M_def by auto qed lemma multiplicity_ge_iff: assumes "d \ carrier G" "irreducible G d" "a \ carrier G" - shows "multiplicity G d a \ k \ d [^] k divides a" + shows "multiplicity G d a \ k \ d [^] k divides a" (is "?lhs \ ?rhs") proof - have "?lhs \ count (factor_mset G a) (assocs G d) \ k" using factor_mset_count[OF assms(3,1,2)] by simp also have "... \ replicate_mset k (assocs G d) \# factor_mset G a" - by (subst count_le_replicate_mset_subset_eq, simp) + by (subst count_le_replicate_mset_subset_eq, simp) also have "... \ - repeat_mset k (factor_mset G d) \# factor_mset G a" + repeat_mset k (factor_mset G d) \# factor_mset G a" by (subst factor_mset_irred[OF assms(1,2)], simp) - also have "... \ factor_mset G (d [^]\<^bsub>G\<^esub> k) \# factor_mset G a" + also have "... \ factor_mset G (d [^]\<^bsub>G\<^esub> k) \# factor_mset G a" by (subst factor_mset_pow[OF assms(1)], simp) also have "... \ (d [^] k) divides\<^bsub>G\<^esub> a" using assms(1) factor_mset_divides[OF _ assms(3)] by simp finally show ?thesis by simp qed lemma multiplicity_gt_0_iff: assumes "d \ carrier G" "irreducible G d" "a \ carrier G" shows "multiplicity G d a > 0 \ d divides a" using multiplicity_ge_iff[OF assms(1,2,3), where k="1"] assms by auto lemma factor_mset_count_2: - assumes "a \ carrier G" + assumes "a \ carrier G" assumes "\z. z \ carrier G \ irreducible G z \ y \ assocs G z" shows "count (factor_mset G a) y = 0" using factor_mset_set [OF assms(1)] assms(2) by (metis count_inI) lemma factor_mset_choose: assumes "a \ carrier G" "set_mset R \ carrier G" - assumes "image_mset (assocs G) R = factor_mset G a" + assumes "image_mset (assocs G) R = factor_mset G a" shows "a \ (\x\set_mset R. x [^] count R x)" (is "a \ ?rhs") proof - have b:"irreducible G x" if a:"x \# R" for x proof - - have x_carr: "x \ carrier G" + have x_carr: "x \ carrier G" using a assms(2) by auto have "assocs G x \ assocs G ` set_mset R" using a by simp hence "assocs G x \# factor_mset G a" using assms(3) a in_image_mset by metis - then obtain z where z_def: + then obtain z where z_def: "z \ carrier G" "irreducible G z" "assocs G x = assocs G z" using factor_mset_set assms(1) by metis - have "z \ x" using z_def(1,3) assocs_eqD x_carr by simp + have "z \ x" using z_def(1,3) assocs_eqD x_carr by simp thus ?thesis using z_def(1,2) x_carr irreducible_cong by simp qed - have "factor_mset G ?rhs = + have "factor_mset G ?rhs = (\x\set_mset R. factor_mset G (x [^] count R x))" - using assms(2) by (subst factor_mset_prod, auto) - also have "... = + using assms(2) by (subst factor_mset_prod, auto) + also have "... = (\x\set_mset R. repeat_mset (count R x) (factor_mset G x))" using assms(2) by (intro sum.cong, auto simp add:factor_mset_pow) - also have "... = (\x\set_mset R. + also have "... = (\x\set_mset R. repeat_mset (count R x) (image_mset (assocs G) {#x#}))" using assms(2) b by (intro sum.cong, auto simp add:factor_mset_irred) - also have "... = (\x\set_mset R. + also have "... = (\x\set_mset R. image_mset (assocs G) (replicate_mset (count R x) x))" by simp - also have "... = image_mset (assocs G) + also have "... = image_mset (assocs G) (\x\set_mset R. (replicate_mset (count R x) x))" by (simp add: image_mset_sum) also have "... = image_mset (assocs G) R" by (simp add:decomp_mset) also have "... = factor_mset G a" using assms by simp finally have "factor_mset G ?rhs = factor_mset G a" by simp moreover have "(\x\set_mset R. x [^] count R x) \ carrier G" using assms(2) by (intro finprod_closed, auto) - ultimately show ?thesis + ultimately show ?thesis using assms(1) by (subst factor_mset_sim) auto qed lemma divides_iff_mult_mono: - assumes "a \ carrier G" "b \ carrier G" + assumes "a \ carrier G" "b \ carrier G" assumes "canonical_irreducibles G R" assumes "\d. d \ R \ multiplicity G d a \ multiplicity G d b" shows "a divides b" proof - have "count (factor_mset G a) d \ count (factor_mset G b) d" for d proof (cases "\y \ carrier G. irreducible G y \ d = assocs G y") case True - then obtain y where y_def: + then obtain y where y_def: "irreducible G y" "y \ carrier G" "d = assocs G y" by blast then obtain z where z_def: "z \ R" "y \ z" using assms(3) unfolding canonical_irreducibles_def by metis have z_more: "irreducible G z" "z \ carrier G" using z_def(1) assms(3) unfolding canonical_irreducibles_def by auto - have "y \ assocs G z" using z_def(2) z_more(2) y_def(2) + have "y \ assocs G z" using z_def(2) z_more(2) y_def(2) by (simp add: closure_ofI2) hence d_def: "d = assocs G z" using y_def(2,3) z_more(2) assocs_repr_independence by blast have "count (factor_mset G a) d = multiplicity G z a" unfolding d_def by (intro factor_mset_count[OF assms(1) z_more(2,1)]) also have "... \ multiplicity G z b" using assms(4) z_def(1) by simp also have "... = count (factor_mset G b) d" unfolding d_def by (intro factor_mset_count[symmetric, OF assms(2) z_more(2,1)]) - finally show ?thesis by simp + finally show ?thesis by simp next case False have "count (factor_mset G a) d = 0" using False by (intro factor_mset_count_2[OF assms(1)], simp) moreover have "count (factor_mset G b) d = 0" using False by (intro factor_mset_count_2[OF assms(2)], simp) ultimately show ?thesis by simp qed - hence "factor_mset G a \# factor_mset G b" + hence "factor_mset G a \# factor_mset G b" unfolding subseteq_mset_def by simp thus ?thesis using factor_mset_divides assms(1,2) by simp qed lemma count_image_mset_inj: assumes "inj_on f R" "x \ R" "set_mset A \ R" shows "count (image_mset f A) (f x) = count A x" proof (cases "x \# A") case True - hence "(f y = f x \ y \# A) = (y = x)" for y + hence "(f y = f x \ y \# A) = (y = x)" for y by (meson assms(1) assms(3) inj_onD subsetD) - hence "(f -` {f x} \ set_mset A) = {x}" + hence "(f -` {f x} \ set_mset A) = {x}" by (simp add:set_eq_iff) thus ?thesis by (subst count_image_mset, simp) next case False hence "x \ set_mset A" by simp hence "f x \ f ` set_mset A" using assms by (simp add: inj_on_image_mem_iff) - hence "count (image_mset f A) (f x) = 0" + hence "count (image_mset f A) (f x) = 0" by (simp add:count_eq_zero_iff) thus ?thesis by (metis count_inI False) qed -text \Factorization of an element from a @{locale "factorial_monoid"} using a selection of representatives +text \Factorization of an element from a @{locale "factorial_monoid"} using a selection of representatives from each equivalence class formed by @{term "(\)"}.\ lemma split_factors: assumes "canonical_irreducibles G R" assumes "a \ carrier G" - shows + shows "finite {d. d \ R \ multiplicity G d a > 0}" - "a \ (\d\{d. d \ R \ multiplicity G d a > 0}. + "a \ (\d\{d. d \ R \ multiplicity G d a > 0}. d [^] multiplicity G d a)" (is "a \ ?rhs") proof - - have r_1: "R \ {x. x \ carrier G \ irreducible G x}" - using assms(1) unfolding canonical_irreducibles_def by simp - have r_2: "\x y. x \ R \ y \ R \ x \ y \ x = y" + have r_1: "R \ {x. x \ carrier G \ irreducible G x}" using assms(1) unfolding canonical_irreducibles_def by simp - + have r_2: "\x y. x \ R \ y \ R \ x \ y \ x = y" + using assms(1) unfolding canonical_irreducibles_def by simp + have assocs_inj: "inj_on (assocs G) R" - using r_1 r_2 assocs_eqD by (intro inj_onI, blast) - + using r_1 r_2 assocs_eqD by (intro inj_onI, blast) + define R' where "R' = (\d\ {d. d \ R \ multiplicity G d a > 0}. replicate_mset (multiplicity G d a) d)" - have "count (factor_mset G a) (assocs G x) > 0" + have "count (factor_mset G a) (assocs G x) > 0" if "x \ R" "0 < multiplicity G x a" for x using assms r_1 r_2 that by (subst factor_mset_count[OF assms(2)]) auto - hence "assocs G ` {d \ R. 0 < multiplicity G d a} + hence "assocs G ` {d \ R. 0 < multiplicity G d a} \ set_mset (factor_mset G a)" by (intro image_subsetI, simp) hence a:"finite (assocs G ` {d \ R. 0 < multiplicity G d a})" using finite_subset by auto - show "finite {d \ R. 0 < multiplicity G d a}" + show "finite {d \ R. 0 < multiplicity G d a}" using assocs_inj inj_on_subset[OF assocs_inj] by (intro finite_imageD[OF a], simp) - hence count_R': + hence count_R': "count R' d = (if d \ R then multiplicity G d a else 0)" for d - by (auto simp add:R'_def count_sum) + by (auto simp add:R'_def count_sum) have set_R': "set_mset R' = {d \ R. 0 < multiplicity G d a}" unfolding set_mset_def using count_R' by auto - have "count (image_mset (assocs G) R') x = + have "count (image_mset (assocs G) R') x = count (factor_mset G a) x" for x proof (cases "\x'. x' \ R \ x = assocs G x'") case True then obtain x' where x'_def: "x' \ R" "x = assocs G x'" by blast have "count (image_mset (assocs G) R') x = count R' x'" using assocs_inj inj_on_subset[OF assocs_inj] x'_def by (subst x'_def(2), subst count_image_mset_inj[OF assocs_inj]) - (auto simp:set_R') + (auto simp:set_R') also have "... = multiplicity G x' a" using count_R' x'_def by simp also have "... = count (factor_mset G a) (assocs G x')" using x'_def(1) r_1 by (subst factor_mset_count[OF assms(2)]) auto also have "... = count (factor_mset G a) x" using x'_def(2) by simp finally show ?thesis by simp next case False - have a:"x \ assocs G z" + have a:"x \ assocs G z" if a1: "z \ carrier G" and a2: "irreducible G z" for z proof - obtain v where v_def: "v \ R" "z \ v" using a1 a2 assms(1) unfolding canonical_irreducibles_def by auto hence "z \ assocs G v" using a1 r_1 v_def(1) by (simp add: closure_ofI2) hence "assocs G z = assocs G v" using a1 r_1 v_def(1) assocs_repr_independence by auto moreover have "x \ assocs G v" using False v_def(1) by simp ultimately show ?thesis by simp qed have "count (image_mset (assocs G) R') x = 0" using False count_R' by (simp add: count_image_mset) auto also have "... = count (factor_mset G a) x" using a - by (intro factor_mset_count_2[OF assms(2), symmetric]) auto + by (intro factor_mset_count_2[OF assms(2), symmetric]) auto finally show ?thesis by simp qed hence "image_mset (assocs G) R' = factor_mset G a" by (rule multiset_eqI) - moreover have "set_mset R' \ carrier G" - using r_1 by (auto simp add:set_R') + moreover have "set_mset R' \ carrier G" + using r_1 by (auto simp add:set_R') ultimately have "a \ (\x\set_mset R'. x [^] count R' x)" using assms(2) by (intro factor_mset_choose, auto) also have "... = ?rhs" using set_R' assms r_1 r_2 by (intro finprod_cong', auto simp add:count_R') finally show "a \ ?rhs" by simp qed end end \ No newline at end of file diff --git a/thys/Finite_Fields/Finite_Fields_Indexed_Algebra_Code.thy b/thys/Finite_Fields/Finite_Fields_Indexed_Algebra_Code.thy new file mode 100644 --- /dev/null +++ b/thys/Finite_Fields/Finite_Fields_Indexed_Algebra_Code.thy @@ -0,0 +1,194 @@ +section \Executable Structures\ + +theory Finite_Fields_Indexed_Algebra_Code + imports "HOL-Algebra.Ring" "HOL-Algebra.Coset" +begin + +text \In the following, we introduce records for executable operations for algebraic structures, +which can be used for code-generation and evaluation. These are then shown to be equivalent to the +(not-necessarily constructive) definitions using \<^verbatim>\HOL-Algebra\. A more direct approach, i.e., +instantiating the structures in the framework with effective operations fails. For example the +structure records represent the domain of the algebraic structure as a set, which implies the +evaluation of @{term "(\\<^bsub>residue_ring (10^100)\<^esub>)"} requires the construction of +@{term "{0..10^100-1}"}. This is technically constructive but very impractical. +Moreover, the additive/multiplicative inverse is defined non-constructively using the +description operator \<^verbatim>\THE\ in \<^verbatim>\HOL-Algebra\. + +The above could be avoided, if it were possible to introduce code equations conditionally, e.g., +for example for @{term "a_inv (residue_ring n) x y"} (if @{term "x y"} are in the carrier of the +structure, but this does not seem to be possible. + +Note that, the algebraic structures defined in \<^verbatim>\HOL-Computational_Algebra\ are type-based, +which prevents using them in some algorithmic settings. For example, choosing an +irreducible polynomial dynamically and performing operations in the factoring ring with respect to +it is not possible in the type-based approach.\ + +record 'a idx_ring = + idx_pred :: "'a \ bool" + idx_uminus :: "'a \ 'a" + idx_plus :: "'a \ 'a \ 'a" + idx_udivide :: "'a \ 'a" + idx_mult :: "'a \ 'a \ 'a" + idx_zero :: "'a" + idx_one :: "'a" + +record 'a idx_ring_enum = "'a idx_ring" + + idx_size :: nat + idx_enum :: "nat \ 'a" + idx_enum_inv :: "'a \ nat" + +fun idx_pow :: "('a,'b) idx_ring_scheme \ 'a \ nat \ 'a" where + "idx_pow E x 0 = idx_one E" | + "idx_pow E x (Suc n) = idx_mult E (idx_pow E x n) x" + +bundle index_algebra_notation +begin +notation idx_zero ("0\<^sub>C\") +notation idx_one ("1\<^sub>C\") +notation idx_plus (infixl "+\<^sub>C\" 65) +notation idx_mult (infixl "*\<^sub>C\" 70) +notation idx_uminus ("-\<^sub>C\ _" [81] 80) +notation idx_udivide ("_ \\<^sub>C\" [81] 80) +notation idx_pow (infixr "^\<^sub>C\" 75) +end +unbundle index_algebra_notation + +bundle no_index_algebra_notation +begin +no_notation idx_zero ("0\<^sub>C\") +no_notation idx_one ("1\<^sub>C\") +no_notation idx_plus (infixl "+\<^sub>C\" 65) +no_notation idx_mult (infixl "*\<^sub>C\" 70) +no_notation idx_uminus ("-\<^sub>C\ _" [81] 80) +no_notation idx_udivide ("_ \\<^sub>C\" [81] 80) +no_notation idx_pow (infixr "^\<^sub>C\" 75) +end + +definition ring_of :: "('a,'b) idx_ring_scheme \ 'a ring" + where "ring_of A = \ + carrier = {x. idx_pred A x}, + mult = (\ x y. x *\<^sub>C\<^bsub>A\<^esub> y), + one = 1\<^sub>C\<^bsub>A\<^esub>, + zero = 0\<^sub>C\<^bsub>A\<^esub>, + add = (\ x y. x +\<^sub>C\<^bsub>A\<^esub> y) \" + +definition ring\<^sub>C where + "ring\<^sub>C A = (ring (ring_of A) \ (\x. idx_pred A x \ -\<^sub>C\<^bsub>A\<^esub> x = \\<^bsub>ring_of A\<^esub> x) \ + (\x. x \ Units (ring_of A) \ x \\<^sub>C\<^bsub>A\<^esub> = inv\<^bsub>ring_of A\<^esub> x))" + +lemma ring_cD_aux: + "x ^\<^sub>C\<^bsub>A\<^esub> n = x [^]\<^bsub>ring_of A\<^esub> n" + by (induction n) (auto simp:ring_of_def) + +lemma ring_cD: + assumes "ring\<^sub>C A" + shows + "0\<^sub>C\<^bsub>A\<^esub> = \\<^bsub>ring_of A\<^esub>" + "1\<^sub>C\<^bsub>A\<^esub> = \\<^bsub>ring_of A\<^esub>" + "\x y. x *\<^sub>C\<^bsub>A\<^esub> y = x \\<^bsub>ring_of A\<^esub> y" + "\x y. x +\<^sub>C\<^bsub>A\<^esub> y = x \\<^bsub>ring_of A\<^esub> y" + "\x. x \ carrier (ring_of A) \ -\<^sub>C\<^bsub>A\<^esub> x = \\<^bsub>ring_of A\<^esub> x" + "\x. x \ Units (ring_of A) \ x \\<^sub>C\<^bsub>A\<^esub> = inv\<^bsub>ring_of A\<^esub> x" + "\x. x ^\<^sub>C\<^bsub>A\<^esub> n = x [^]\<^bsub>ring_of A\<^esub> n" + using assms ring_cD_aux unfolding ring\<^sub>C_def ring_of_def by auto + +lemma ring_cI: + assumes "ring (ring_of A)" + assumes "\x. x \ carrier (ring_of A) \ -\<^sub>C\<^bsub>A\<^esub> x = \\<^bsub>ring_of A\<^esub> x" + assumes "\x. x \ Units (ring_of A) \ x\\<^sub>C\<^bsub>A\<^esub> = inv\<^bsub>ring_of A\<^esub> x" + shows "ring\<^sub>C A" +proof - + have " x \ carrier (ring_of A) \ idx_pred A x" for x unfolding ring_of_def by auto + thus ?thesis using assms unfolding ring\<^sub>C_def by auto +qed + +definition cring\<^sub>C where "cring\<^sub>C A = (ring\<^sub>C A \ cring (ring_of A))" + +lemma cring_cI: + assumes "cring (ring_of A)" + assumes "\x. x \ carrier (ring_of A) \ -\<^sub>C\<^bsub>A\<^esub> x = \\<^bsub>ring_of A\<^esub> x" + assumes "\x. x \ Units (ring_of A) \ x\\<^sub>C\<^bsub>A\<^esub> = inv\<^bsub>ring_of A\<^esub> x" + shows "cring\<^sub>C A" + unfolding cring\<^sub>C_def by (intro ring_cI conjI assms cring.axioms(1)) + +lemma cring_c_imp_ring: "cring\<^sub>C A \ ring\<^sub>C A" + unfolding cring\<^sub>C_def by simp + +lemmas cring_cD = ring_cD[OF cring_c_imp_ring] + +definition domain\<^sub>C where "domain\<^sub>C A = (cring\<^sub>C A \ domain (ring_of A))" + +lemma domain_cI: + assumes "domain (ring_of A)" + assumes "\x. x \ carrier (ring_of A) \ -\<^sub>C\<^bsub>A\<^esub> x = \\<^bsub>ring_of A\<^esub> x" + assumes "\x. x \ Units (ring_of A) \ x\\<^sub>C\<^bsub>A\<^esub> = inv\<^bsub>ring_of A\<^esub> x" + shows "domain\<^sub>C A" + unfolding domain\<^sub>C_def by (intro conjI cring_cI assms domain.axioms(1)) + +lemma domain_c_imp_ring: "domain\<^sub>C A \ ring\<^sub>C A" + unfolding cring\<^sub>C_def domain\<^sub>C_def by simp + +lemmas domain_cD = ring_cD[OF domain_c_imp_ring] + +definition field\<^sub>C where "field\<^sub>C A = (domain\<^sub>C A \ field (ring_of A))" + +lemma field_cI: + assumes "field (ring_of A)" + assumes "\x. x \ carrier (ring_of A) \ -\<^sub>C\<^bsub>A\<^esub> x = \\<^bsub>ring_of A\<^esub> x" + assumes "\x. x \ Units (ring_of A) \ x\\<^sub>C\<^bsub>A\<^esub> = inv\<^bsub>ring_of A\<^esub> x" + shows "field\<^sub>C A" + unfolding field\<^sub>C_def by (intro conjI domain_cI assms field.axioms(1)) + +lemma field_c_imp_ring: "field\<^sub>C A \ ring\<^sub>C A" + unfolding field\<^sub>C_def cring\<^sub>C_def domain\<^sub>C_def by simp + +lemmas field_cD = ring_cD[OF field_c_imp_ring] + +definition enum\<^sub>C where "enum\<^sub>C A = ( + finite (carrier (ring_of A)) \ + idx_size A = order (ring_of A) \ + bij_betw (idx_enum A) {.. + (\x < order (ring_of A). idx_enum_inv A (idx_enum A x) = x))" + +lemma enum_cI: + assumes "finite (carrier (ring_of A))" + assumes "idx_size A = order (ring_of A)" + assumes "bij_betw (idx_enum A) {..x. x < order (ring_of A) \ idx_enum_inv A (idx_enum A x) = x" + shows "enum\<^sub>C A" + using assms unfolding enum\<^sub>C_def by auto + +lemma enum_cD: + assumes "enum\<^sub>C R" + shows "finite (carrier (ring_of R))" + and "idx_size R = order (ring_of R)" + and "bij_betw (idx_enum R) {..x. x < order (ring_of R) \ idx_enum_inv R (idx_enum R x) = x" + and "\x. x \ carrier (ring_of R) \ idx_enum R (idx_enum_inv R x) = x" + using assms +proof - + let ?n = "order (ring_of R)" + have a:"idx_enum_inv R x = the_inv_into {.. carrier (ring_of R)" for x + proof - + have "idx_enum R ` {..C_def by simp + then obtain y where y_carr: "y \ {..< order (ring_of R)}" and x_def: "x = idx_enum R y" + using x_carr by auto + have "idx_enum_inv R x = y" using assms y_carr unfolding x_def enum\<^sub>C_def by simp + also have "... = the_inv_into {..C_def unfolding x_def + by (intro the_inv_into_f_f[symmetric] y_carr) auto + finally show ?thesis by simp + qed + + have "bij_betw (the_inv_into {..C_def by (intro bij_betw_the_inv_into) auto + thus "bij_betw (idx_enum_inv R) (carrier (ring_of R)) {.. carrier (ring_of R)" for x + using that assms unfolding a[OF that] enum\<^sub>C_def bij_betw_def by (intro f_the_inv_into_f) auto +qed (use assms enum\<^sub>C_def in auto) + +end \ No newline at end of file diff --git a/thys/Finite_Fields/Finite_Fields_Isomorphic.thy b/thys/Finite_Fields/Finite_Fields_Isomorphic.thy --- a/thys/Finite_Fields/Finite_Fields_Isomorphic.thy +++ b/thys/Finite_Fields/Finite_Fields_Isomorphic.thy @@ -1,367 +1,367 @@ section \Isomorphism between Finite Fields\label{sec:uniqueness}\ theory Finite_Fields_Isomorphic imports Card_Irreducible_Polynomials begin lemma (in finite_field) eval_on_root_is_iso: defines "p \ char R" - assumes "f \ carrier (poly_ring (ZFact p))" - assumes "pirreducible\<^bsub>(ZFact p)\<^esub> (carrier (ZFact p)) f" + assumes "f \ carrier (poly_ring (ZFact p))" + assumes "pirreducible\<^bsub>(ZFact p)\<^esub> (carrier (ZFact p)) f" assumes "order R = p^degree f" - assumes "x \ carrier R" + assumes "x \ carrier R" assumes "eval (map (char_iso R) f) x = \" - shows "ring_hom_ring (Rupt\<^bsub>(ZFact p)\<^esub> (carrier (ZFact p)) f) R + shows "ring_hom_ring (Rupt\<^bsub>(ZFact p)\<^esub> (carrier (ZFact p)) f) R (\g. the_elem ((\g'. eval (map (char_iso R) g') x) ` g))" proof - let ?P = "poly_ring (ZFact p)" have char_pos: "char R > 0" using finite_carr_imp_char_ge_0[OF finite_carrier] by simp - have p_prime: "Factorial_Ring.prime p" - unfolding p_def + have p_prime: "Factorial_Ring.prime p" + unfolding p_def using characteristic_is_prime[OF char_pos] by simp interpret zf: finite_field "ZFact p" using zfact_prime_is_finite_field p_prime by simp interpret pzf: principal_domain "poly_ring (ZFact p)" using zf.univ_poly_is_principal[OF zf.carrier_is_subfield] by simp - interpret i: ideal "(PIdl\<^bsub>?P\<^esub> f)" "?P" + interpret i: ideal "(PIdl\<^bsub>?P\<^esub> f)" "?P" by (intro pzf.cgenideal_ideal assms(2)) have rupt_carr: "y \ carrier (poly_ring (ZFact p))" if "y \ carrier (Rupt\<^bsub>ZFact p\<^esub> (carrier (ZFact p)) f)" for y using that pzf.quot_carr i.ideal_axioms by (simp add:rupture_def) have rupt_is_ring: "ring (Rupt\<^bsub>ZFact p\<^esub> (carrier (ZFact p)) f)" unfolding rupture_def by (intro i.quotient_is_ring) - have "map (char_iso R) \ + have "map (char_iso R) \ ring_iso ?P (poly_ring (R\carrier := char_subring R\))" - using lift_iso_to_poly_ring[OF char_iso] zf.domain_axioms + using lift_iso_to_poly_ring[OF char_iso] zf.domain_axioms using char_ring_is_subdomain subdomain_is_domain by (simp add:p_def) - moreover have "(char_subring R)[X] = + moreover have "(char_subring R)[X] = poly_ring (R \carrier := char_subring R\)" using univ_poly_consistent[OF char_ring_is_subring] by simp - ultimately have + ultimately have "map (char_iso R) \ ring_hom ?P ((char_subring R)[X])" by (simp add:ring_iso_def) moreover have "(\p. eval p x) \ ring_hom ((char_subring R)[X]) R" using eval_is_hom char_ring_is_subring assms(5) by simp - ultimately have + ultimately have "(\p. eval p x) \ map (char_iso R) \ ring_hom ?P R" using ring_hom_trans by blast hence a:"(\p. eval (map (char_iso R) p) x) \ ring_hom ?P R" by (simp add:comp_def) interpret h:ring_hom_ring "?P" "R" "(\p. eval (map (char_iso R) p) x)" by (intro ring_hom_ringI2 pzf.ring_axioms a ring_axioms) let ?h = "(\p. eval (map (char_iso R) p) x)" let ?J = "a_kernel (poly_ring (ZFact (int p))) R ?h" have "?h ` a_kernel (poly_ring (ZFact (int p))) R ?h \ {\}" by auto - moreover have - "\\<^bsub>?P\<^esub> \ a_kernel (poly_ring (ZFact (int p))) R ?h" - "?h \\<^bsub>?P\<^esub> = \" + moreover have + "\\<^bsub>?P\<^esub> \ a_kernel (poly_ring (ZFact (int p))) R ?h" + "?h \\<^bsub>?P\<^esub> = \" unfolding a_kernel_def' by simp_all hence "{\} \ ?h ` a_kernel (poly_ring (ZFact (int p))) R ?h" by simp ultimately have c: "?h ` a_kernel (poly_ring (ZFact (int p))) R ?h = {\}" by auto have d: "PIdl\<^bsub>?P\<^esub> f \ a_kernel ?P R ?h" - proof (rule subsetI) + proof (rule subsetI) fix y assume "y \ PIdl\<^bsub>?P\<^esub> f" - then obtain y' where y'_def: "y' \ carrier ?P" "y = y' \\<^bsub>?P\<^esub> f" + then obtain y' where y'_def: "y' \ carrier ?P" "y = y' \\<^bsub>?P\<^esub> f" unfolding cgenideal_def by auto have "?h y = ?h (y' \\<^bsub>?P\<^esub> f)" by (simp add:y'_def) also have "... = ?h y' \ ?h f" using y'_def assms(2) by simp also have "... = ?h y' \ \" using assms(6) by simp also have "... = \" using y'_def by simp finally have "?h y = \" by simp moreover have "y \ carrier ?P" using y'_def assms(2) by simp ultimately show "y \ a_kernel ?P R ?h" unfolding a_kernel_def kernel_def by simp qed - have "(\y. the_elem ((\p. eval (map (char_iso R) p) x) ` y)) + have "(\y. the_elem ((\p. eval (map (char_iso R) p) x) ` y)) \ ring_hom (?P Quot ?J) R" using h.the_elem_hom by simp - moreover have "(\y. ?J <+>\<^bsub>?P\<^esub> y) + moreover have "(\y. ?J <+>\<^bsub>?P\<^esub> y) \ ring_hom (Rupt\<^bsub>(ZFact p)\<^esub> (carrier (ZFact p)) f) (?P Quot ?J)" unfolding rupture_def using h.kernel_is_ideal d assms(2) by (intro pzf.quot_quot_hom pzf.cgenideal_ideal) auto ultimately have "(\y. the_elem (?h ` y)) \ (\y. ?J <+>\<^bsub>?P\<^esub> y) \ ring_hom (Rupt\<^bsub>(ZFact p)\<^esub> (carrier (ZFact p)) f) R" using ring_hom_trans by blast - hence b: "(\y. the_elem (?h ` (?J <+>\<^bsub>?P\<^esub> y))) \ + hence b: "(\y. the_elem (?h ` (?J <+>\<^bsub>?P\<^esub> y))) \ ring_hom (Rupt\<^bsub>(ZFact p)\<^esub> (carrier (ZFact p)) f) R" by (simp add:comp_def) have "?h ` y = ?h ` (?J <+>\<^bsub>?P\<^esub> y)" if "y \ carrier (Rupt\<^bsub>ZFact p\<^esub> (carrier (ZFact p)) f)" for y proof - have y_range: "y \ carrier ?P" using rupt_carr that by simp have "?h ` y = {\} <+>\<^bsub>R\<^esub> ?h ` y" using y_range h.hom_closed by (subst set_add_zero, auto) also have "... = ?h ` ?J <+>\<^bsub>R\<^esub> ?h ` y" by (subst c, simp) also have "... = ?h ` (?J <+>\<^bsub>?P\<^esub> y)" by (subst set_add_hom[OF a _ y_range], subst a_kernel_def') auto finally show ?thesis by simp qed - hence "(\y. the_elem (?h ` y)) \ + hence "(\y. the_elem (?h ` y)) \ ring_hom (Rupt\<^bsub>(ZFact p)\<^esub> (carrier (ZFact p)) f) R" by (intro ring_hom_cong[OF _ rupt_is_ring b]) simp thus ?thesis by (intro ring_hom_ringI2 rupt_is_ring ring_axioms, simp) qed lemma (in domain) pdivides_consistent: assumes "subfield K R" "f \ carrier (K[X])" "g \ carrier (K[X])" shows "f pdivides g \ f pdivides\<^bsub>R \ carrier := K \\<^esub> g" proof - - have a:"subring K R" + have a:"subring K R" using assms(1) subfieldE(1) by auto let ?S = "R \ carrier := K \" have "f pdivides g \ f divides\<^bsub>K[X]\<^esub> g" using pdivides_iff_shell[OF assms] by simp also have "... \ (\x \ carrier (K[X]). f \\<^bsub>K[X]\<^esub> x = g)" unfolding pdivides_def factor_def by auto - also have "... \ + also have "... \ (\x \ carrier (poly_ring ?S). f \\<^bsub>poly_ring ?S\<^esub> x = g)" using univ_poly_consistent[OF a] by simp also have "... \ f divides\<^bsub>poly_ring ?S\<^esub> g" unfolding pdivides_def factor_def by auto also have "... \ f pdivides\<^bsub>?S\<^esub> g" unfolding pdivides_def by simp finally show ?thesis by simp qed lemma (in finite_field) find_root: assumes "subfield K R" assumes "monic_irreducible_poly (R \ carrier := K \) f" assumes "order R = card K^degree f" obtains x where "eval f x = \" "x \ carrier R" proof - define \ :: "'a list \ 'a list" where "\ = id" let ?K = "R \ carrier := K \" - have "finite K" + have "finite K" using assms(1) by (intro finite_subset[OF _ finite_carrier], simp) - hence fin_K: "finite (carrier (?K))" - by simp + hence fin_K: "finite (carrier (?K))" + by simp interpret f: finite_field "?K" using assms(1) subfield_iff fin_K finite_fieldI by blast - have b:"subring K R" + have b:"subring K R" using assms(1) subfieldE(1) by blast interpret e: ring_hom_ring "(K[X])" "(poly_ring R)" "\" using embed_hom[OF b] by (simp add:\_def) have a: "card K^degree f > 1" using assms(3) finite_field_min_order by simp have "f \ carrier (poly_ring ?K)" using f.monic_poly_carr assms(2) unfolding monic_irreducible_poly_def by simp hence f_carr_2: "f \ carrier (K[X])" using univ_poly_consistent[OF b] by simp have f_carr: "f \ carrier (poly_ring R)" using e.hom_closed[OF f_carr_2] unfolding \_def by simp have gp_carr: "gauss_poly ?K (order ?K^degree f) \ carrier (K[X])" using f.gauss_poly_carr univ_poly_consistent[OF b] by simp - have "gauss_poly ?K (order ?K^degree f) = + have "gauss_poly ?K (order ?K^degree f) = gauss_poly ?K (card K^degree f)" by (simp add:Coset.order_def) - also have "... = + also have "... = X\<^bsub>?K\<^esub> [^]\<^bsub>poly_ring ?K\<^esub> card K ^ degree f \\<^bsub>poly_ring ?K\<^esub> X\<^bsub>?K\<^esub>" unfolding gauss_poly_def by simp also have "... = X\<^bsub>R\<^esub> [^]\<^bsub>K[X]\<^esub> card K ^ degree f \\<^bsub>K[X]\<^esub> X\<^bsub>R\<^esub>" unfolding var_def using univ_poly_consistent[OF b] by simp also have "... = \ (X\<^bsub>R\<^esub> [^]\<^bsub>K[X]\<^esub> card K ^ degree f \\<^bsub>K[X]\<^esub> X\<^bsub>R\<^esub>)" unfolding \_def by simp also have "... = gauss_poly R (card K^degree f)" unfolding gauss_poly_def a_minus_def using var_closed[OF b] by (simp add:e.hom_nat_pow, simp add:\_def) - finally have gp_consistent: "gauss_poly ?K (order ?K^degree f) = + finally have gp_consistent: "gauss_poly ?K (order ?K^degree f) = gauss_poly R (card K^degree f)" by simp - have deg_f: "degree f > 0" + have deg_f: "degree f > 0" using f.monic_poly_min_degree[OF assms(2)] by simp have "splitted f" proof (cases "degree f > 1") case True - + have "f pdivides\<^bsub>?K\<^esub> gauss_poly ?K (order ?K^degree f)" using f.div_gauss_poly_iff[OF deg_f assms(2)] by simp hence "f pdivides gauss_poly ?K (order ?K^degree f)" using pdivides_consistent[OF assms(1)] f_carr_2 gp_carr by simp hence "f pdivides gauss_poly R (card K^degree f)" using gp_consistent by simp - moreover have "splitted (gauss_poly R (card K^degree f))" + moreover have "splitted (gauss_poly R (card K^degree f))" unfolding assms(3)[symmetric] using gauss_poly_splitted by simp - moreover have "gauss_poly R (card K^degree f) \ []" + moreover have "gauss_poly R (card K^degree f) \ []" using gauss_poly_not_zero a by (simp add: univ_poly_zero) ultimately show "splitted f" using pdivides_imp_splitted f_carr gauss_poly_carr by auto next case False hence "degree f = 1" using deg_f by simp thus ?thesis using f_carr degree_one_imp_splitted by auto qed hence "size (roots f) > 0" using deg_f unfolding splitted_def by simp then obtain x where x_def: "x \ carrier R" "is_root f x" using roots_mem_iff_is_root[OF f_carr] by (metis f_carr nonempty_has_size not_empty_rootsE) have "eval f x = \" using x_def is_root_def by blast thus ?thesis using x_def using that by simp qed lemma (in finite_field) find_iso_from_zfact: defines "p \ int (char R)" assumes "monic_irreducible_poly (ZFact p) f" assumes "order R = char R^degree f" shows "\\. \ \ ring_iso (Rupt\<^bsub>(ZFact p)\<^esub> (carrier (ZFact p)) f) R" proof - have char_pos: "char R > 0" using finite_carr_imp_char_ge_0[OF finite_carrier] by simp interpret zf: finite_field "ZFact p" - unfolding p_def using zfact_prime_is_finite_field + unfolding p_def using zfact_prime_is_finite_field using characteristic_is_prime[OF char_pos] by simp interpret zfp: polynomial_ring "ZFact p" "carrier (ZFact p)" unfolding polynomial_ring_def polynomial_ring_axioms_def using zf.field_axioms zf.carrier_is_subfield by simp - let ?f' = "map (char_iso R) f" + let ?f' = "map (char_iso R) f" let ?F = "Rupt\<^bsub>(ZFact p)\<^esub> (carrier (ZFact p)) f" have "domain (R\carrier := char_subring R\)" - using char_ring_is_subdomain subdomain_is_domain by simp + using char_ring_is_subdomain subdomain_is_domain by simp - hence "monic_irreducible_poly (R \ carrier := char_subring R \) ?f'" + hence "monic_irreducible_poly (R \ carrier := char_subring R \) ?f'" using char_iso p_def zf.domain_axioms by (intro monic_irreducible_poly_hom[OF assms(2)]) auto moreover have "order R = card (char_subring R)^degree ?f'" using assms(3) unfolding char_def by simp ultimately obtain x where x_def: "eval ?f' x = \" "x \ carrier R" using find_root[OF char_ring_is_subfield[OF char_pos]] by blast let ?\ = "(\g. the_elem ((\g'. eval (map (char_iso R) g') x) ` g))" interpret r: ring_hom_ring "?F" "R" "?\" using assms(2,3) unfolding monic_irreducible_poly_def monic_poly_def p_def - by (intro eval_on_root_is_iso x_def, auto) - have a:"?\ \ ring_hom ?F R" + by (intro eval_on_root_is_iso x_def, auto) + have a:"?\ \ ring_hom ?F R" using r.homh by auto have "field (Rupt\<^bsub>ZFact p\<^esub> (carrier (ZFact p)) f)" using assms(2) unfolding monic_irreducible_poly_def monic_poly_def - by (subst zfp.rupture_is_field_iff_pirreducible, simp_all) + by (subst zfp.rupture_is_field_iff_pirreducible, simp_all) hence b:"inj_on ?\ (carrier ?F)" using non_trivial_field_hom_is_inj[OF a _ field_axioms] by simp have "card (?\ ` carrier ?F) = order ?F" using card_image[OF b] unfolding Coset.order_def by simp also have "... = card (carrier (ZFact p))^degree f" using assms(2) zf.monic_poly_min_degree[OF assms(2)] unfolding monic_irreducible_poly_def monic_poly_def by (intro zf.rupture_order[OF zf.carrier_is_subfield]) auto also have "... = char R ^degree f" unfolding p_def by (subst card_zfact_carr[OF char_pos], simp) also have "... = card (carrier R)" - using assms(3) unfolding Coset.order_def by simp + using assms(3) unfolding Coset.order_def by simp finally have "card (?\ ` carrier ?F) = card (carrier R)" by simp moreover have "?\ ` carrier ?F \ carrier R" by (intro image_subsetI, simp) ultimately have "?\ ` carrier ?F = carrier R" - by (intro card_seteq finite_carrier, auto) + by (intro card_seteq finite_carrier, auto) hence "bij_betw ?\ (carrier ?F) (carrier R)" using b bij_betw_imageI by auto thus ?thesis unfolding ring_iso_def using a b by auto qed theorem uniqueness: assumes "finite_field F\<^sub>1" assumes "finite_field F\<^sub>2" assumes "order F\<^sub>1 = order F\<^sub>2" shows "F\<^sub>1 \ F\<^sub>2" proof - obtain n where o1: "order F\<^sub>1 = char F\<^sub>1^n" "n > 0" using finite_field.finite_field_order[OF assms(1)] by auto obtain m where o2: "order F\<^sub>2 = char F\<^sub>2^m" "m > 0" using finite_field.finite_field_order[OF assms(2)] by auto - interpret f1: "finite_field" F\<^sub>1 using assms(1) by simp - interpret f2: "finite_field" F\<^sub>2 using assms(2) by simp + interpret f1: "finite_field" F\<^sub>1 using assms(1) by simp + interpret f2: "finite_field" F\<^sub>2 using assms(2) by simp have char_pos: "char F\<^sub>1 > 0" "char F\<^sub>2 > 0" - using f1.finite_carrier f1.finite_carr_imp_char_ge_0 + using f1.finite_carrier f1.finite_carr_imp_char_ge_0 using f2.finite_carrier f2.finite_carr_imp_char_ge_0 by auto - hence char_prime: - "Factorial_Ring.prime (char F\<^sub>1)" + hence char_prime: + "Factorial_Ring.prime (char F\<^sub>1)" "Factorial_Ring.prime (char F\<^sub>2)" using f1.characteristic_is_prime f2.characteristic_is_prime by auto - have "char F\<^sub>1^n = char F\<^sub>2^m" + have "char F\<^sub>1^n = char F\<^sub>2^m" using o1 o2 assms(3) by simp hence eq: "n = m" "char F\<^sub>1 = char F\<^sub>2" using char_prime char_pos o1(2) o2(2) prime_power_inj' by auto - obtain p where p_def: "p = char F\<^sub>1" "p = char F\<^sub>2" + obtain p where p_def: "p = char F\<^sub>1" "p = char F\<^sub>2" using eq by simp - have p_prime: "Factorial_Ring.prime p" + have p_prime: "Factorial_Ring.prime p" unfolding p_def(1) using f1.characteristic_is_prime char_pos by simp interpret zf: finite_field "ZFact (int p)" - using zfact_prime_is_finite_field p_prime o1(2) + using zfact_prime_is_finite_field p_prime o1(2) using prime_nat_int_transfer by blast interpret zfp: polynomial_ring "ZFact p" "carrier (ZFact p)" unfolding polynomial_ring_def polynomial_ring_axioms_def using zf.field_axioms zf.carrier_is_subfield by simp - obtain f where f_def: + obtain f where f_def: "monic_irreducible_poly (ZFact (int p)) f" "degree f = n" using zf.exist_irred o1(2) by auto - let ?F\<^sub>0 = "Rupt\<^bsub>(ZFact p)\<^esub> (carrier (ZFact p)) f" + let ?F\<^sub>0 = "Rupt\<^bsub>(ZFact p)\<^esub> (carrier (ZFact p)) f" obtain \\<^sub>1 where \\<^sub>1_def: "\\<^sub>1 \ ring_iso ?F\<^sub>0 F\<^sub>1" using f1.find_iso_from_zfact f_def o1 unfolding p_def by auto obtain \\<^sub>2 where \\<^sub>2_def: "\\<^sub>2 \ ring_iso ?F\<^sub>0 F\<^sub>2" using f2.find_iso_from_zfact f_def o2 unfolding p_def(2) eq(1) by auto have "?F\<^sub>0 \ F\<^sub>1" using \\<^sub>1_def is_ring_iso_def by auto moreover have "?F\<^sub>0 \ F\<^sub>2" using \\<^sub>2_def is_ring_iso_def by auto - moreover have "field ?F\<^sub>0" + moreover have "field ?F\<^sub>0" using f_def(1) zf.monic_poly_carr monic_irreducible_poly_def by (subst zfp.rupture_is_field_iff_pirreducible) auto hence "ring ?F\<^sub>0" using field.is_ring by auto - ultimately show ?thesis + ultimately show ?thesis using ring_iso_trans ring_iso_sym by blast qed end diff --git a/thys/Finite_Fields/Finite_Fields_Mod_Ring_Code.thy b/thys/Finite_Fields/Finite_Fields_Mod_Ring_Code.thy new file mode 100644 --- /dev/null +++ b/thys/Finite_Fields/Finite_Fields_Mod_Ring_Code.thy @@ -0,0 +1,301 @@ +section \Executable Factor Rings\ + +theory Finite_Fields_Mod_Ring_Code + imports Finite_Fields_Indexed_Algebra_Code Ring_Characteristic +begin + +definition mod_ring :: "nat \ nat idx_ring_enum" + where "mod_ring n = \ + idx_pred = (\x. x < n), + idx_uminus = (\x. (n-x) mod n), + idx_plus = (\x y. (x+y) mod n), + idx_udivide = (\x. nat (fst (bezout_coefficients (int x) (int n)) mod (int n))), + idx_mult = (\x y. (x*y) mod n), + idx_zero = 0, + idx_one = 1, + idx_size = n, + idx_enum = id, + idx_enum_inv = id + \" + +lemma zfact_iso_0: + assumes "n > 0" + shows "zfact_iso n 0 = \\<^bsub>ZFact (int n)\<^esub>" +proof - + let ?I = "Idl\<^bsub>\\<^esub> {int n}" + have ideal_I: "ideal ?I \" + by (simp add: int.genideal_ideal) + + interpret i:ideal "?I" "\" using ideal_I by simp + interpret s:ring_hom_ring "\" "ZFact (int n)" "(+>\<^bsub>\\<^esub>) ?I" + using i.rcos_ring_hom_ring ZFact_def by auto + + show ?thesis + by (simp add:zfact_iso_def ZFact_def) +qed + +lemma zfact_prime_is_field: + assumes "Factorial_Ring.prime (p :: nat)" + shows "field (ZFact (int p))" + using zfact_prime_is_finite_field[OF assms] finite_field_def by auto + +definition zfact_iso_inv :: "nat \ int set \ nat" where + "zfact_iso_inv p = the_inv_into {.. 0" + shows "zfact_iso_inv n \\<^bsub>ZFact (int n)\<^esub> = 0" + unfolding zfact_iso_inv_def zfact_iso_0[OF n_ge_0, symmetric] using n_ge_0 + by (rule the_inv_into_f_f[OF zfact_iso_inj], simp add:mod_ring_def) + +lemma zfact_coset: + assumes n_ge_0: "n > 0" + assumes "x \ carrier (ZFact (int n))" + defines "I \ Idl\<^bsub>\\<^esub> {int n}" + shows "x = I +>\<^bsub>\\<^esub> (int (zfact_iso_inv n x))" +proof - + have "x \ zfact_iso n ` {.. 0" + shows "bij_betw (zfact_iso_inv n) (carrier (ZFact (int n))) (carrier (ring_of (mod_ring n)))" +proof - + have "bij_betw (the_inv_into {.. 1" + shows "zfact_iso_inv n \ ring_iso (ZFact (int n)) (ring_of (mod_ring n))" (is "?f \ _") +proof (rule ring_iso_memI) + interpret r:cring "(ZFact (int n))" + using ZFact_is_cring by simp + + define I where "I = Idl\<^bsub>\\<^esub> {int n}" + + have n_ge_0: "n > 0" using n_ge_1 by simp + + interpret i:ideal "I" "\" + unfolding I_def using int.genideal_ideal by simp + + interpret s:ring_hom_ring "\" "ZFact (int n)" "(+>\<^bsub>\\<^esub>) I" + using i.rcos_ring_hom_ring ZFact_def I_def by auto + + show "zfact_iso_inv n x \ carrier (ring_of (mod_ring n))" if "x \ carrier (ZFact (int n))" for x + proof - + have "zfact_iso_inv n x \ {.. carrier (ring_of (mod_ring n))" + by (simp add:ring_of_def mod_ring_def) + qed + + show "?f (x \\<^bsub>ZFact (int n)\<^esub> y) = ?f x \\<^bsub>ring_of (mod_ring n)\<^esub> ?f y" + if x_carr: "x \ carrier (ZFact (int n))" and y_carr: "y \ carrier (ZFact (int n))" for x y + proof - + define x' where "x' = zfact_iso_inv n x" + define y' where "y' = zfact_iso_inv n y" + have "x \\<^bsub>ZFact (int n)\<^esub> y = (I +>\<^bsub>\\<^esub> (int x')) \\<^bsub>ZFact (int n)\<^esub> (I +>\<^bsub>\\<^esub> (int y'))" + unfolding x'_def y'_def + using x_carr y_carr zfact_coset[OF n_ge_0] I_def by simp + also have "... = (I +>\<^bsub>\\<^esub> (int x' * int y'))" + by simp + also have "... = (I +>\<^bsub>\\<^esub> (int ((x' * y') mod n)))" + unfolding I_def zmod_int by (rule int_cosetI[OF n_ge_0],simp) + also have "... = (I +>\<^bsub>\\<^esub> (x' \\<^bsub>ring_of (mod_ring n)\<^esub> y'))" + unfolding ring_of_def mod_ring_def by simp + also have "... = zfact_iso n (x' \\<^bsub>ring_of (mod_ring n)\<^esub> y')" + unfolding zfact_iso_def I_def by simp + finally have a:"x \\<^bsub>ZFact (int n)\<^esub> y = zfact_iso n (x' \\<^bsub>ring_of (mod_ring n)\<^esub> y')" + by simp + have b:"x' \\<^bsub>ring_of (mod_ring n)\<^esub> y' \ {..\<^bsub>ring_of (mod_ring n)\<^esub> y')) = x' \\<^bsub>ring_of (mod_ring n)\<^esub> y'" + unfolding zfact_iso_inv_def + by (rule the_inv_into_f_f[OF zfact_iso_inj[OF n_ge_0] b]) + thus + "zfact_iso_inv n (x \\<^bsub>ZFact (int n)\<^esub> y) = + zfact_iso_inv n x \\<^bsub>ring_of (mod_ring n)\<^esub> zfact_iso_inv n y" + using a x'_def y'_def by simp + qed + + show "zfact_iso_inv n (x \\<^bsub>ZFact (int n)\<^esub> y) = + zfact_iso_inv n x \\<^bsub>ring_of (mod_ring n)\<^esub> zfact_iso_inv n y" + if x_carr: "x \ carrier (ZFact (int n))" and y_carr: "y \ carrier (ZFact (int n))" for x y + proof - + define x' where "x' = zfact_iso_inv n x" + define y' where "y' = zfact_iso_inv n y" + have "x \\<^bsub>ZFact (int n)\<^esub> y = (I +>\<^bsub>\\<^esub> (int x')) \\<^bsub>ZFact (int n)\<^esub> (I +>\<^bsub>\\<^esub> (int y'))" + unfolding x'_def y'_def + using x_carr y_carr zfact_coset[OF n_ge_0] I_def by simp + also have "... = (I +>\<^bsub>\\<^esub> (int x' + int y'))" + by simp + also have "... = (I +>\<^bsub>\\<^esub> (int ((x' + y') mod n)))" + unfolding I_def zmod_int by (rule int_cosetI[OF n_ge_0],simp) + also have "... = (I +>\<^bsub>\\<^esub> (x' \\<^bsub>ring_of (mod_ring n)\<^esub> y'))" + unfolding mod_ring_def ring_of_def by simp + also have "... = zfact_iso n (x' \\<^bsub>ring_of (mod_ring n)\<^esub> y')" + unfolding zfact_iso_def I_def by simp + finally have a:"x \\<^bsub>ZFact (int n)\<^esub> y = zfact_iso n (x' \\<^bsub>ring_of (mod_ring n)\<^esub> y')" + by simp + have b:"x' \\<^bsub>ring_of (mod_ring n)\<^esub> y' \ {..\<^bsub>ring_of (mod_ring n)\<^esub> y')) = x' \\<^bsub>ring_of (mod_ring n)\<^esub> y'" + unfolding zfact_iso_inv_def + by (rule the_inv_into_f_f[OF zfact_iso_inj[OF n_ge_0] b]) + thus "?f (x \\<^bsub>ZFact (int n)\<^esub> y) = ?f x \\<^bsub>ring_of (mod_ring n)\<^esub> ?f y" + using a x'_def y'_def by simp + qed + + have "\\<^bsub>ZFact (int n)\<^esub> = zfact_iso n (\\<^bsub>ring_of (mod_ring n)\<^esub>)" + by (simp add:zfact_iso_def ZFact_def I_def[symmetric] ring_of_def mod_ring_def) + + thus "zfact_iso_inv n \\<^bsub>ZFact (int n)\<^esub> = \\<^bsub>ring_of (mod_ring n)\<^esub>" + unfolding zfact_iso_inv_def mod_ring_def ring_of_def + using the_inv_into_f_f[OF zfact_iso_inj] n_ge_1 by simp + + show "bij_betw (zfact_iso_inv n) (carrier (ZFact (int n))) (carrier (ring_of (mod_ring n)))" + by (intro zfact_iso_inv_bij n_ge_0) +qed + +lemma mod_ring_finite: + "finite (carrier (ring_of (mod_ring n)))" + by (simp add:mod_ring_def ring_of_def) + +lemma mod_ring_carr: + "x \ carrier (ring_of (mod_ring n)) \ x < n" + by (simp add:mod_ring_def ring_of_def) + +lemma mod_ring_is_cring: + assumes n_ge_1: "n > 1" + shows "cring (ring_of (mod_ring n))" +proof - + have n_ge_0: "n > 0" using n_ge_1 by simp + + interpret cring "ZFact (int n)" + using ZFact_is_cring by simp + + have "cring ((ring_of (mod_ring n)) \ zero := zfact_iso_inv n \\<^bsub>ZFact (int n)\<^esub> \)" + by (rule ring_iso_imp_img_cring[OF zfact_iso_inv_is_ring_iso[OF n_ge_1]]) + moreover have + "ring_of (mod_ring n) \ zero := zfact_iso_inv n \\<^bsub>ZFact (int n)\<^esub> \ = ring_of (mod_ring n)" + using zfact_iso_inv_0[OF n_ge_0] by (simp add:mod_ring_def ring_of_def) + ultimately show ?thesis by simp +qed + +lemma zfact_iso_is_ring_iso: + assumes n_ge_1: "n > 1" + shows "zfact_iso n \ ring_iso (ring_of (mod_ring n)) (ZFact (int n))" +proof - + have r:"ring (ZFact (int n))" + using ZFact_is_cring cring.axioms(1) by blast + + interpret s: ring "(ring_of (mod_ring n))" + using mod_ring_is_cring cring.axioms(1) n_ge_1 by blast + have n_ge_0: "n > 0" using n_ge_1 by linarith + + have "inv_into (carrier (ZFact (int n))) (zfact_iso_inv n) + \ ring_iso (ring_of (mod_ring n)) (ZFact (int n))" + using ring_iso_set_sym[OF r zfact_iso_inv_is_ring_iso[OF n_ge_1]] by simp + moreover have "inv_into (carrier (ZFact (int n))) (zfact_iso_inv n) x = zfact_iso n x" + if "x \ carrier (ring_of (mod_ring n))" for x + proof - + have "x \ {..If @{term "p"} is a prime than @{term "mod_ring p"} is a field:\ + +lemma mod_ring_is_field: + assumes"Factorial_Ring.prime p" + shows "field (ring_of (mod_ring p))" +proof - + have p_ge_0: "p > 0" using assms prime_gt_0_nat by blast + have p_ge_1: "p > 1" using assms prime_gt_1_nat by blast + + interpret field "ZFact (int p)" + using zfact_prime_is_field[OF assms] by simp + + have "field ((ring_of (mod_ring p)) \ zero := zfact_iso_inv p \\<^bsub>ZFact (int p)\<^esub> \)" + by (rule ring_iso_imp_img_field[OF zfact_iso_inv_is_ring_iso[OF p_ge_1]]) + + moreover have + "(ring_of (mod_ring p)) \ zero := zfact_iso_inv p \\<^bsub>ZFact (int p)\<^esub> \ = ring_of (mod_ring p)" + using zfact_iso_inv_0[OF p_ge_0] by (simp add:mod_ring_def ring_of_def) + ultimately show ?thesis by simp +qed + +lemma mod_ring_is_ring_c: + assumes "n > 1" + shows "cring\<^sub>C (mod_ring n)" +proof (intro cring_cI mod_ring_is_cring assms) + fix x + assume a:"x \ carrier (ring_of (mod_ring n))" + hence x_le_n: "x < n" unfolding mod_ring_def ring_of_def by simp + + interpret cring "(ring_of (mod_ring n))" by (intro mod_ring_is_cring assms) + + show "-\<^sub>C\<^bsub>mod_ring n\<^esub> x = \\<^bsub>ring_of (mod_ring n)\<^esub> x" using x_le_n + by (intro minus_equality[symmetric] a) (simp_all add:ring_of_def mod_ring_def mod_simps) +next + fix x + assume a:"x \ Units (ring_of (mod_ring n))" + + let ?l = "fst (bezout_coefficients (int x) (int n))" + let ?r = "snd (bezout_coefficients (int x) (int n))" + + interpret cring "ring_of (mod_ring n)" by (intro mod_ring_is_cring assms) + + obtain y where "x \\<^bsub>ring_of (mod_ring n)\<^esub> y = \\<^bsub>ring_of (mod_ring n)\<^esub>" + using a by (meson Units_r_inv_ex) + hence "x * y mod n = 1" by (simp_all add:mod_ring_def ring_of_def) + hence "gcd x n = 1" by (metis dvd_triv_left gcd.assoc gcd_1_nat gcd_nat.absorb_iff1 gcd_red_nat) + hence 0:"gcd (int x) (int n) = 1" unfolding gcd_int_int_eq by simp + + have "int x * ?l mod int n = (?l * int x + ?r * int n) mod int n" + using assms by (simp add:mod_simps algebra_simps) + also have "... = (gcd (int x) (int n)) mod int n" + by (intro arg_cong2[where f="(mod)"] refl bezout_coefficients) simp + also have "... = 1" unfolding 0 using assms by simp + finally have "int x * ?l mod int n = 1" by simp + hence "int x * nat (fst (bezout_coefficients (int x) (int n)) mod int n) mod n = 1" + using assms by (simp add:mod_simps) + hence "x * nat (fst (bezout_coefficients (int x) (int n)) mod int n) mod n = 1" + by (metis nat_mod_as_int nat_one_as_int of_nat_mult) + hence "x \\<^bsub>ring_of (mod_ring n)\<^esub> x \\<^sub>C\<^bsub>mod_ring n\<^esub> = \\<^bsub>ring_of (mod_ring n)\<^esub>" + using assms unfolding mod_ring_def ring_of_def by simp + moreover have "nat (fst (bezout_coefficients (int x) (int n)) mod int n) < n" + using assms by (subst nat_less_iff) auto + hence "x \\<^sub>C\<^bsub>mod_ring n\<^esub> \ carrier (ring_of (mod_ring n))" + using assms unfolding mod_ring_def ring_of_def by simp + moreover have "x \ carrier (ring_of (mod_ring n))" using a by auto + ultimately show "x \\<^sub>C\<^bsub>mod_ring n\<^esub> = inv\<^bsub>ring_of (mod_ring n)\<^esub> x" + by (intro comm_inv_char[symmetric]) +qed + +lemma mod_ring_is_field_c: + assumes"Factorial_Ring.prime p" + shows "field\<^sub>C (mod_ring p)" + unfolding field\<^sub>C_def domain\<^sub>C_def + by (intro conjI mod_ring_is_ring_c mod_ring_is_field assms prime_gt_1_nat + domain.axioms(1) field.axioms(1)) + +lemma mod_ring_is_enum_c: + shows "enum\<^sub>C (mod_ring n)" + by (intro enum_cI) (simp_all add:mod_ring_def ring_of_def Coset.order_def lessThan_def) + +end \ No newline at end of file diff --git a/thys/Finite_Fields/Finite_Fields_More_Bijections.thy b/thys/Finite_Fields/Finite_Fields_More_Bijections.thy new file mode 100644 --- /dev/null +++ b/thys/Finite_Fields/Finite_Fields_More_Bijections.thy @@ -0,0 +1,192 @@ +section \Additional results about Bijections and Digit Representations\ + +theory Finite_Fields_More_Bijections + imports "HOL-Library.FuncSet" Digit_Expansions.Bits_Digits +begin + +lemma nth_digit_0: + assumes "x < b^k" + shows "nth_digit x k b = 0" + using assms unfolding nth_digit_def by auto + +lemma nth_digit_bounded': + assumes "b > 0" + shows "nth_digit v x b < b" + using assms by (simp add: nth_digit_def) + +lemma digit_gen_sum_repr': + assumes "n < b^c" + shows "n = (\k 0" | (c) "b = 1" | (d) "b>1" by linarith + thus ?thesis + proof (cases) + case a thus ?thesis using assms by simp + next + case b thus ?thesis using assms by (simp add: zero_power) + next + case c thus ?thesis using assms by (simp add:nth_digit_def) + next + case d thus ?thesis by (intro digit_gen_sum_repr assms d) + qed +qed + +lemma + assumes "\x. x \ A \ f (g x) = x" + shows "\y. y \ g ` A \ g (f y) = y" +proof - + show "g (f y) = y" if 0:"y\ g`A" for y + proof - + obtain x where x_dom: "x \ A" and y_def: "y = g x" using 0 by auto + hence "g (f y) = g (f (g x))" by simp + also have "... = g x" by (intro arg_cong[where f="g"] assms(1) x_dom) + also have "... = y" unfolding y_def by simp + finally show ?thesis by simp + qed +qed + +lemma nth_digit_bij: + "bij_betw (\v. (\x\{..\<^sub>E {..0" | (c) "b > 0" by linarith + hence "nth_digit x i b \ {.. ?B" if "x \ ?A" for x using that unfolding restrict_PiE_iff by auto + hence "?f ` ?A = ?B" + using card_image[OF inj_f] by (intro card_seteq finite_PiE image_subsetI) (auto simp:card_PiE) + thus ?thesis using inj_f unfolding bij_betw_def by auto +qed + +lemma nth_digit_sum: + assumes "\i. i < l \ f i < b" + shows "\k. k < l \ nth_digit (\i< l. f i * b^i) k b = f k" + and "(\ii< l. f i * b^i)" + + have "restrict f {.. {..\<^sub>E {..x\{.. {..i< l. nth_digit m i b * b^i)" + using b by (intro digit_gen_sum_repr') auto + also have "... = (\i< l. f i * b^i)" + using a by (intro sum.cong arg_cong2[where f="(*)"] refl) (metis restrict_apply') + also have "... = n" unfolding n_def by simp + finally have c:"n = m" by simp + show "(\ii< l. f i * b^i) k b = f k" if "k < l" for k + proof - + have "nth_digit (\i< l. f i * b^i) k b = nth_digit m k b" unfolding n_def[symmetric] c by simp + also have "... = f k" using a that by (metis lessThan_iff restrict_apply') + finally show ?thesis by simp + qed +qed + +lemma bij_betw_reindex: + assumes "bij_betw f I J" + shows "bij_betw (\x. \i\I. x (f i)) (J \\<^sub>E S) (I \\<^sub>E S)" +proof (rule bij_betwI[where g="(\x. \i\J. x (the_inv_into I f i))"]) + have 0:"bij_betw (the_inv_into I f) J I" + using assms bij_betw_the_inv_into by auto + + show "(\x. \i\I. x (f i)) \ (J \\<^sub>E S) \ I \\<^sub>E S" + using bij_betw_apply[OF assms] by auto + show "(\x. \i\J. x (the_inv_into I f i)) \ (I \\<^sub>E S) \ J \\<^sub>E S" + using bij_betw_apply[OF 0] by auto + show "(\j\J. (\i\I. x (f i)) (the_inv_into I f j)) = x" if "x \ J \\<^sub>E S" for x + proof - + have "(\i\I. x (f i)) (the_inv_into I f j) = x j" if "j \ J" for j + using 0 assms f_the_inv_into_f_bij_betw bij_betw_apply that by fastforce + thus ?thesis using PiE_arb[OF that] by auto + qed + show " (\i\I. (\j\J. y (the_inv_into I f j)) (f i)) = y" if "y \ I \\<^sub>E S" for y + proof - + have "(\j\J. y (the_inv_into I f j)) (f i) = y i" if "i \ I" for i + using assms 0 that the_inv_into_f_f[OF bij_betw_imp_inj_on[OF assms]] bij_betw_apply by force + thus ?thesis using PiE_arb[OF that] by auto + qed +qed + +lemma lift_bij_betw: + assumes "bij_betw f S T" + shows "bij_betw (\x. \i\I. f (x i)) (I \\<^sub>E S) (I \\<^sub>E T)" +proof - + let ?g = "the_inv_into S f" + + have bij_g: "bij_betw ?g T S" using bij_betw_the_inv_into[OF assms] by simp + have 0:"?g(f x)=x" if "x \ S" for x by (intro the_inv_into_f_f that bij_betw_imp_inj_on[OF assms]) + have 1:"f(?g x)=x" if "x \ T" for x by (intro f_the_inv_into_f_bij_betw[OF assms] that) + + have "(\i\I. f (x i)) \ I \\<^sub>E T" if "x \ (I \\<^sub>E S)" for x + using bij_betw_apply[OF assms] that by (auto simp: Pi_def) + moreover have "(\i\I. ?g (x i)) \ I \\<^sub>E S" if "x \ (I \\<^sub>E T)" for x + using bij_betw_apply[OF bij_g] that by (auto simp: Pi_def) + moreover have "(\i\I. ?g ((\i\I. f (x i)) i)) = x" if "x \ (I \\<^sub>E S)" for x + proof - + have "(\i\I. ?g ((\i\I. f (x i)) i)) i = x i" for i + using PiE_mem[OF that] using PiE_arb[OF that] by (cases "i \ I") (simp add:0)+ + thus ?thesis by auto + qed + moreover have "(\i\I. f ((\i\I. ?g (x i)) i)) = x" if "x \ (I \\<^sub>E T)" for x + proof - + have "(\i\I. f ((\i\I. ?g (x i)) i)) i = x i" for i + using PiE_mem[OF that] using PiE_arb[OF that] by (cases "i \ I") (simp add:1)+ + thus ?thesis by auto + qed + ultimately show ?thesis + by (intro bij_betwI[where g="(\x. \i\I. ?g (x i))"]) simp_all +qed + +lemma lists_bij: + "bij_betw (\x. map x [ 0..\<^sub>E S) {x. set x \ S \ length x = d}" +proof (intro bij_betwI[where g="(\x. \i\{.. S" by (intro image_subsetI) auto + thus ?case by simp +next + case (2 x) thus ?case by auto +next + case (3 x) + have "restrict ((!) (map x [ 0.. {..x. (x mod s, x div s)) {.. {.. s * t" using that by (intro mult_left_mono) auto + finally show ?thesis by simp + qed + + show ?thesis + proof (cases "s > 0 \ t > 0") + case True + then show ?thesis using less_mult_imp_div_less bij_betw_aux + by (intro bij_betwI[where g="(\x. fst x + s * snd x)"]) (auto simp:mult.commute) + next + case False then show ?thesis by (auto simp:bij_betw_def) + qed +qed + +end \ No newline at end of file diff --git a/thys/Finite_Fields/Finite_Fields_Poly_Factor_Ring_Code.thy b/thys/Finite_Fields/Finite_Fields_Poly_Factor_Ring_Code.thy new file mode 100644 --- /dev/null +++ b/thys/Finite_Fields/Finite_Fields_Poly_Factor_Ring_Code.thy @@ -0,0 +1,663 @@ +section \Executable Polynomial Factor Rings\ + +theory Finite_Fields_Poly_Factor_Ring_Code + imports + Finite_Fields_Poly_Ring_Code + Rabin_Irreducibility_Test_Code + Finite_Fields_More_Bijections +begin + +text \Enumeration of the polynomials with a given degree:\ + +definition poly_enum :: "('a,'b) idx_ring_enum_scheme \ nat \ nat \ 'a list" + where "poly_enum R l n = + dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>) (map (\p. idx_enum R (nth_digit n (l-1-p) (idx_size R))) [0.. list_all p (dropWhile q xs)" + by (induction xs) auto + +lemma bij_betw_poly_enum: + assumes "enum\<^sub>C R" "ring\<^sub>C R" + shows "bij_betw (poly_enum R l) {.. carrier (poly_ring (ring_of R)) \ length xs \ l}" +proof - + let ?b = "idx_size R" + let ?S0 = "{..\<^sub>E {..C_def by simp + + have "0 < order (ring_of R)" using enum_cD(1)[OF assms(1)] order_gt_0_iff_finite by metis + also have "... = ?b" using enum_cD[OF assms(1)] by auto + finally have b_gt_0: "?b > 0" by simp + + note bij0 = lift_bij_betw[OF enum_cD(3)[OF assms(1)], where I="{..C\<^bsub>R\<^esub>)) ?S2 ?S3" + proof (rule bij_betwI[where g="\xs. replicate (l - length xs) 0\<^sub>C\<^bsub>R\<^esub> @ xs"]) + have "dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>) xs \ ?S3" if "xs \ ?S2" for xs + proof - + have "dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>) xs = [] \ hd (dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>) xs) \ 0\<^sub>C\<^bsub>R\<^esub>" + using hd_dropWhile by (metis (full_types)) + moreover have "length (dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>) xs) \ l" + by (metis (mono_tags, lifting) mem_Collect_eq length_dropWhile_le that) + ultimately show ?thesis using that by (auto simp:list_all_dropwhile) + qed + thus "dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>) \ ?S2 \ ?S3" by auto + have "replicate (l - length xs) 0\<^sub>C\<^bsub>R\<^esub> @ xs \ ?S2" if "xs \ ?S3" for xs + proof - + have "idx_pred R 0\<^sub>C\<^bsub>R\<^esub>" using add.one_closed by (simp add:ring_of_def) + moreover have "length (replicate (l - length xs) 0\<^sub>C\<^bsub>R\<^esub> @ xs) = l" using that by auto + ultimately show ?thesis using that by (auto simp:list_all_iff) + qed + thus "(\xs. replicate (l - length xs) 0\<^sub>C\<^bsub>R\<^esub> @ xs) \ ?S3 \ ?S2" by auto + + show "replicate (l - length (dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>) x)) 0\<^sub>C\<^bsub>R\<^esub> @ dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>) x = x" + if "x \ ?S2" for x + proof - + have "length (takeWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>) x) + length (dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>) x) = length x" + unfolding length_append[symmetric] by simp + thus ?thesis using that by (intro replicate_drop_while_cancel) auto + qed + show "dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>) (replicate (l - length y) 0\<^sub>C\<^bsub>R\<^esub> @ y) = y" + if "y \ ?S3" for y + proof - + have "dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>) (replicate (l - length y) 0\<^sub>C\<^bsub>R\<^esub> @ y) = dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>) y" + by (intro dropWhile_append2) simp + also have "... = y" using that by (intro iffD2[OF dropWhile_eq_self_iff]) auto + finally show ?thesis by simp + qed + qed + moreover have "?S3 = ?S4" + unfolding ring_of_poly[OF assms(2),symmetric] by (simp add:ring_of_def poly_def) + ultimately have bij2: "bij_betw (dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>)) ?S2 ?S4" by simp + + have bij3: "bij_betw (\x. l-1-x) {..n. (\p\{..n. (\p\{..n. (\p\{..n. map (\p. idx_enum R (nth_digit n (l-1-p) ?b)) [0.. nat \ 'a list \ nat" + where "poly_enum_inv R l f = + (let f' = replicate (l - length f) 0\<^sub>C\<^bsub>R\<^esub> @ f in + (\iiC R" "ring\<^sub>C R" + assumes "x \ {xs. xs \ carrier (poly_ring (ring_of R)) \ length xs \ l}" + shows "the_inv_into {..C\<^bsub>R\<^esub> @ x" + let ?b = "idx_size R" + let ?d = "dropWhile ((=) 0\<^sub>C\<^bsub>R\<^esub>)" + + have len_f: "length f = l" using assms(3) unfolding f_def by auto + note enum_c = enum_cD[OF assms(1)] + + interpret ring "ring_of R" using assms(2) unfolding ring\<^sub>C_def by simp + + have 0: "idx_enum_inv R y < ?b" if "y \ carrier (ring_of R)" for y + using bij_betw_imp_surj_on[OF enum_c(4)] enum_c(2) that by auto + have 1: "(x = [] \ lead_coeff x \ 0\<^sub>C\<^bsub>R\<^esub>) \ list_all (idx_pred R) x \ length x \ l" + using assms(3) unfolding ring_of_poly[OF assms(2),symmetric] by (simp add:ring_of_def poly_def) + moreover have "\\<^bsub>ring_of R\<^esub> \ carrier (ring_of R)" by simp + hence "idx_pred R 0\<^sub>C\<^bsub>R\<^esub>" unfolding ring_of_def by simp + ultimately have 2: "set f \ carrier (ring_of R)" + unfolding f_def by (auto simp add:ring_of_def list_all_iff) + + have "poly_enum R l(poly_enum_inv R l x)= poly_enum R l (\ip. idx_enum R (idx_enum_inv R (f ! (l - 1 - (l - 1 - p))))) [0..p. (f ! (l-1 - (l-1-p)))) [0..p. (f ! p)) [0.. 'a list => 'a list idx_ring_enum" + where "poly_mod_ring R f = \ + idx_pred = (\xs. idx_pred (poly R) xs \ length xs \ degree f), + idx_uminus = idx_uminus (poly R), + idx_plus = (\x y. pmod\<^sub>C R (x +\<^sub>C\<^bsub>poly R\<^esub> y) f), + idx_udivide = (\x. let ((u,v),r) = ext_euclidean R x f in pmod\<^sub>C R (r\\<^sub>C\<^bsub>poly R\<^esub> *\<^sub>C\<^bsub>poly R\<^esub> u) f), + idx_mult = (\x y. pmod\<^sub>C R (x *\<^sub>C\<^bsub>poly R\<^esub> y) f), + idx_zero = 0\<^sub>C\<^bsub>poly R\<^esub>, + idx_one = 1\<^sub>C\<^bsub>poly R\<^esub>, + idx_size = idx_size R ^ degree f, + idx_enum = poly_enum R (degree f), + idx_enum_inv = poly_enum_inv R (degree f) \" + +definition poly_mod_ring_iso :: "('a,'b) idx_ring_enum_scheme \ 'a list \ 'a list \ 'a list set" + where "poly_mod_ring_iso R f x = PIdl\<^bsub>poly_ring (ring_of R)\<^esub> f +>\<^bsub>poly_ring (ring_of R)\<^esub> x" + +definition poly_mod_ring_iso_inv :: "('a,'b) idx_ring_enum_scheme \ 'a list \ 'a list set \ 'a list" + where "poly_mod_ring_iso_inv R f = + the_inv_into (carrier (ring_of (poly_mod_ring R f))) (poly_mod_ring_iso R f)" + +context + fixes f + fixes R :: "('a,'b) idx_ring_enum_scheme" + assumes field_R: "field\<^sub>C R" + assumes f_carr: "f \ carrier (poly_ring (ring_of R))" + assumes deg_f: "degree f > 0" +begin + +private abbreviation P where "P \ poly_ring (ring_of R)" +private abbreviation I where "I \ PIdl\<^bsub>poly_ring (ring_of R)\<^esub> f" + +interpretation field "ring_of R" + using field_R unfolding field\<^sub>C_def by auto + +interpretation d: domain "P" + by (intro univ_poly_is_domain carrier_is_subring) + +interpretation i: ideal I P + using f_carr by (intro d.cgenideal_ideal) auto + +interpretation s: ring_hom_ring P "P Quot I" "(+>\<^bsub>P\<^esub>) I" + using i.rcos_ring_hom_ring by auto + +interpretation cr: cring "P Quot I" + by (intro i.quotient_is_cring d.cring_axioms) + +lemma ring_c: "ring\<^sub>C R" + using field_R unfolding field\<^sub>C_def domain\<^sub>C_def cring\<^sub>C_def by auto + +lemma d_poly: "domain\<^sub>C (poly R)" using field_R unfolding field\<^sub>C_def by (intro poly_domain) auto + +lemma ideal_mod: + assumes "y \ carrier P" + shows "I +>\<^bsub>P\<^esub> (pmod y f) = I +>\<^bsub>P\<^esub> y" +proof - + have "f \ I" by (intro d.cgenideal_self f_carr) + hence "(f \\<^bsub>P\<^esub> (pdiv y f)) \ I" + using long_division_closed[OF carrier_is_subfield] assms f_carr + by (intro i.I_r_closed) (simp_all) + hence "y \ I +>\<^bsub>P\<^esub> (pmod y f)" + using assms f_carr unfolding a_r_coset_def' + by (subst pdiv_pmod[OF carrier_is_subfield, where q="f"]) auto + thus ?thesis + by (intro i.a_repr_independence' assms long_division_closed[OF carrier_is_subfield] f_carr) +qed + +lemma poly_mod_ring_carr_1: + "carrier (ring_of (poly_mod_ring R f)) = {xs. xs \ carrier P \ degree xs < degree f}" + (is "?L = ?R") +proof - + have "?L = {xs. xs \ carrier (ring_of (poly R)) \ degree xs < degree f}" + using deg_f unfolding poly_mod_ring_def ring_of_def by auto + also have "... = ?R" unfolding ring_of_poly[OF ring_c] by simp + finally show ?thesis by simp +qed + +lemma poly_mod_ring_carr: + assumes "y \ carrier P" + shows "pmod y f \ carrier (ring_of (poly_mod_ring R f))" +proof - + have "f \ []" using deg_f by auto + hence "pmod y f = [] \ degree (pmod y f) < degree f" + by (intro pmod_degree[OF carrier_is_subfield] assms f_carr) + hence "degree (pmod y f) < degree f" using deg_f by auto + moreover have "pmod y f \ carrier P" + using f_carr assms long_division_closed[OF carrier_is_subfield] by auto + ultimately show ?thesis unfolding poly_mod_ring_carr_1 by auto +qed + +lemma poly_mod_ring_iso_ran: + "poly_mod_ring_iso R f ` carrier (ring_of (poly_mod_ring R f)) = carrier (P Quot I)" +proof - + have "poly_mod_ring_iso R f x \ carrier (P Quot I)" + if "x \ carrier (ring_of (poly_mod_ring R f))" for x + proof - + have "I \ carrier P" by auto + moreover have "x \ carrier P" using that unfolding poly_mod_ring_carr_1 by auto + ultimately have "poly_mod_ring_iso R f x \ a_rcosets\<^bsub>P\<^esub> I" + using that f_carr unfolding poly_mod_ring_iso_def by (intro d.a_rcosetsI) auto + thus ?thesis unfolding FactRing_def by simp + qed + moreover have "x \ poly_mod_ring_iso R f ` carrier (ring_of (poly_mod_ring R f))" + if "x \ carrier (P Quot I)" for x + proof - + have "x \ a_rcosets\<^bsub>P\<^esub> I" using that unfolding FactRing_def by auto + then obtain y where y_def: "x = I +>\<^bsub>P\<^esub> y" "y \ carrier P" + using that unfolding A_RCOSETS_def' by auto + define z where "z = pmod y f" + have "I +>\<^bsub>P\<^esub> z = I +>\<^bsub>P\<^esub> y" unfolding z_def by (intro ideal_mod y_def) + hence "poly_mod_ring_iso R f z = x" unfolding poly_mod_ring_iso_def y_def by simp + moreover have "z \ carrier (ring_of (poly_mod_ring R f))" + unfolding z_def by (intro poly_mod_ring_carr y_def) + ultimately show ?thesis by auto + qed + ultimately show ?thesis by auto +qed + +lemma poly_mod_ring_iso_inj: + "inj_on (poly_mod_ring_iso R f) (carrier (ring_of (poly_mod_ring R f)))" +proof (rule inj_onI) + fix x y + assume "x \ carrier (ring_of (poly_mod_ring R f))" + hence x:"x \ carrier P" "degree x < degree f" unfolding poly_mod_ring_carr_1 by auto + assume "y \ carrier (ring_of (poly_mod_ring R f))" + hence y:"y \ carrier P" "degree y < degree f" unfolding poly_mod_ring_carr_1 by auto + + have "degree (x \\<^bsub>P\<^esub> y) \ max (degree x) (degree (\\<^bsub>P\<^esub>y))" + unfolding a_minus_def by (intro degree_add) + also have "... = max (degree x) (degree y)" + unfolding univ_poly_a_inv_degree[OF carrier_is_subring y(1)] by simp + also have "... < degree f" using x(2) y(2) by simp + finally have d:"degree (x \\<^bsub>P\<^esub> y) < degree f" by simp + + assume "poly_mod_ring_iso R f x = poly_mod_ring_iso R f y" + hence "I +>\<^bsub>P\<^esub> x = I +>\<^bsub>P\<^esub> y" unfolding poly_mod_ring_iso_def by simp + hence "x \\<^bsub>P\<^esub> y \ I" using x y by (subst d.quotient_eq_iff_same_a_r_cos[OF i.ideal_axioms]) auto + hence "f pdivides\<^bsub>ring_of R\<^esub> (x \\<^bsub>P\<^esub> y)" + using f_carr x(1) y d.m_comm unfolding cgenideal_def pdivides_def factor_def by auto + hence "(x \\<^bsub>P\<^esub> y) = [] \ degree (x \\<^bsub>P\<^esub> y) \ degree f" + using x(1) y(1) f_carr pdivides_imp_degree_le[OF carrier_is_subring] by (meson d.minus_closed) + hence "(x \\<^bsub>P\<^esub> y) = \\<^bsub>P\<^esub>" unfolding univ_poly_zero using d by simp + thus "x = y" using x(1) y(1) by simp +qed + +lemma poly_mod_iso_ring_bij: + "bij_betw (poly_mod_ring_iso R f) (carrier (ring_of (poly_mod_ring R f))) (carrier (P Quot I))" + using poly_mod_ring_iso_ran poly_mod_ring_iso_inj unfolding bij_betw_def by simp + +lemma poly_mod_iso_ring_bij_2: + "bij_betw (poly_mod_ring_iso_inv R f) (carrier (P Quot I)) (carrier (ring_of (poly_mod_ring R f)))" + unfolding poly_mod_ring_iso_inv_def using poly_mod_iso_ring_bij bij_betw_the_inv_into by blast + +lemma poly_mod_ring_iso_inv_1: + assumes "x \ carrier (P Quot I)" + shows "poly_mod_ring_iso R f (poly_mod_ring_iso_inv R f x) = x" + unfolding poly_mod_ring_iso_inv_def using assms poly_mod_iso_ring_bij + by (intro f_the_inv_into_f_bij_betw) auto + +lemma poly_mod_ring_iso_inv_2: + assumes "x \ carrier (ring_of (poly_mod_ring R f))" + shows "poly_mod_ring_iso_inv R f (poly_mod_ring_iso R f x) = x" + unfolding poly_mod_ring_iso_inv_def using assms + by (intro the_inv_into_f_f poly_mod_ring_iso_inj) + +lemma poly_mod_ring_add: + assumes "x \ carrier P" + assumes "y \ carrier P" + shows "x \\<^bsub>ring_of (poly_mod_ring R f)\<^esub> y = pmod (x \\<^bsub>P\<^esub> y) f" (is "?L = ?R") +proof - + have "?L = pmod\<^sub>C R (x \\<^bsub>ring_of (poly R)\<^esub> y) f" + unfolding poly_mod_ring_def ring_of_def using domain_cD[OF d_poly] by simp + also have "... = ?R" + using assms unfolding ring_of_poly[OF ring_c] by (intro pmod_c[OF field_R] f_carr) auto + finally show ?thesis + by simp +qed + +lemma poly_mod_ring_zero: "\\<^bsub>ring_of (poly_mod_ring R f)\<^esub> = \\<^bsub>P\<^esub>" +proof- + have "\\<^bsub>ring_of (poly_mod_ring R f)\<^esub> = \\<^bsub>ring_of (poly R)\<^esub>" + using domain_cD[OF d_poly] unfolding ring_of_def poly_mod_ring_def by simp + also have "... = \\<^bsub>P\<^esub>" unfolding ring_of_poly[OF ring_c] by simp + finally show ?thesis by simp +qed + +lemma poly_mod_ring_one: "\\<^bsub>ring_of (poly_mod_ring R f)\<^esub> = \\<^bsub>P\<^esub>" +proof- + have "\\<^bsub>ring_of (poly_mod_ring R f)\<^esub> = \\<^bsub>ring_of (poly R)\<^esub>" + using domain_cD[OF d_poly] unfolding ring_of_def poly_mod_ring_def by simp + also have "... = \\<^bsub>P\<^esub>" unfolding ring_of_poly[OF ring_c] by simp + finally show "\\<^bsub>ring_of (poly_mod_ring R f)\<^esub> = \\<^bsub>P\<^esub>" by simp +qed + +lemma poly_mod_ring_mult: + assumes "x \ carrier P" + assumes "y \ carrier P" + shows "x \\<^bsub>ring_of (poly_mod_ring R f)\<^esub> y = pmod (x \\<^bsub>P\<^esub> y) f" (is "?L = ?R") +proof - + have "?L = pmod\<^sub>C R (x \\<^bsub>ring_of (poly R)\<^esub> y) f" + unfolding poly_mod_ring_def ring_of_def using domain_cD[OF d_poly] by simp + also have "... = ?R" + using assms unfolding poly_mod_ring_carr_1 ring_of_poly[OF ring_c] + by (intro pmod_c[OF field_R] f_carr) auto + finally show ?thesis + by simp +qed + +lemma poly_mod_ring_iso_inv: + "poly_mod_ring_iso_inv R f \ ring_iso (P Quot I) (ring_of (poly_mod_ring R f))" + (is "?f \ ring_iso ?S ?T") +proof (rule ring_iso_memI) + fix x assume "x \ carrier ?S" + thus "?f x \ carrier ?T" using bij_betw_apply[OF poly_mod_iso_ring_bij_2] by auto +next + fix x y assume x:"x \ carrier ?S" and y: "y \ carrier ?S" + have "?f x \ carrier (ring_of (poly_mod_ring R f))" + by (rule bij_betw_apply[OF poly_mod_iso_ring_bij_2 x]) + hence x':"?f x \ carrier P" unfolding poly_mod_ring_carr_1 by simp + have "?f y \ carrier (ring_of (poly_mod_ring R f))" + by (rule bij_betw_apply[OF poly_mod_iso_ring_bij_2 y]) + hence y':"?f y \ carrier P" unfolding poly_mod_ring_carr_1 by simp + + have 0:"?f x \\<^bsub>?T\<^esub> ?f y = pmod (?f x \\<^bsub>P\<^esub> ?f y) f" + by (intro poly_mod_ring_mult x' y') + also have "... \ carrier (ring_of (poly_mod_ring R f))" + using x' y' by (intro poly_mod_ring_carr) auto + finally have xy: "?f x \\<^bsub>?T\<^esub> ?f y \ carrier (ring_of (poly_mod_ring R f))" by simp + + have "?f (x \\<^bsub>?S\<^esub> y) = ?f (poly_mod_ring_iso R f (?f x) \\<^bsub>?S\<^esub> poly_mod_ring_iso R f (?f y))" + using x y by (simp add:poly_mod_ring_iso_inv_1) + also have "... = ?f ((I +>\<^bsub>P\<^esub> (?f x)) \\<^bsub>?S\<^esub> (I +>\<^bsub>P\<^esub> (?f y)))" + unfolding poly_mod_ring_iso_def by simp + also have "... = ?f (I +>\<^bsub>P\<^esub> (?f x \\<^bsub>P\<^esub> ?f y))" + using x' y' by simp + also have "... = ?f (I +>\<^bsub>P\<^esub> (pmod (?f x \\<^bsub>P\<^esub> ?f y) f))" + using x' y' by (subst ideal_mod) auto + also have "... = ?f (I +>\<^bsub>P\<^esub> (?f x \\<^bsub>?T\<^esub> ?f y))" + unfolding 0 by simp + also have "... = ?f (poly_mod_ring_iso R f (?f x \\<^bsub>?T\<^esub> ?f y))" + unfolding poly_mod_ring_iso_def by simp + also have "... = ?f x \\<^bsub>?T\<^esub> ?f y" + using xy by (intro poly_mod_ring_iso_inv_2) + finally show "?f (x \\<^bsub>?S\<^esub> y) = ?f x \\<^bsub>?T\<^esub> ?f y" by simp +next + fix x y assume x:"x \ carrier ?S" and y: "y \ carrier ?S" + have "?f x \ carrier (ring_of (poly_mod_ring R f))" + by (rule bij_betw_apply[OF poly_mod_iso_ring_bij_2 x]) + hence x':"?f x \ carrier P" unfolding poly_mod_ring_carr_1 by simp + have "?f y \ carrier (ring_of (poly_mod_ring R f))" + by (rule bij_betw_apply[OF poly_mod_iso_ring_bij_2 y]) + hence y':"?f y \ carrier P" unfolding poly_mod_ring_carr_1 by simp + + have 0:"?f x \\<^bsub>?T\<^esub> ?f y = pmod (?f x \\<^bsub>P\<^esub> ?f y) f" by (intro poly_mod_ring_add x' y') + also have "... \ carrier (ring_of (poly_mod_ring R f))" + using x' y' by (intro poly_mod_ring_carr) auto + finally have xy: "?f x \\<^bsub>?T\<^esub> ?f y \ carrier (ring_of (poly_mod_ring R f))" by simp + + have "?f (x \\<^bsub>?S\<^esub> y) = ?f (poly_mod_ring_iso R f (?f x) \\<^bsub>?S\<^esub> poly_mod_ring_iso R f (?f y))" + using x y by (simp add:poly_mod_ring_iso_inv_1) + also have "... = ?f ((I +>\<^bsub>P\<^esub> (?f x)) \\<^bsub>?S\<^esub> (I +>\<^bsub>P\<^esub> (?f y)))" + unfolding poly_mod_ring_iso_def by simp + also have "... = ?f (I +>\<^bsub>P\<^esub> (?f x \\<^bsub>P\<^esub> ?f y))" + using x' y' by simp + also have "... = ?f (I +>\<^bsub>P\<^esub> (pmod (?f x \\<^bsub>P\<^esub> ?f y) f))" + using x' y' by (subst ideal_mod) auto + also have "... = ?f (I +>\<^bsub>P\<^esub> (?f x \\<^bsub>?T\<^esub> ?f y))" + unfolding 0 by simp + also have "... = ?f (poly_mod_ring_iso R f (?f x \\<^bsub>?T\<^esub> ?f y))" + unfolding poly_mod_ring_iso_def by simp + also have "... = ?f x \\<^bsub>?T\<^esub> ?f y" + using xy by (intro poly_mod_ring_iso_inv_2) + finally show "?f (x \\<^bsub>?S\<^esub> y) = ?f x \\<^bsub>?T\<^esub> ?f y" by simp +next + have "poly_mod_ring_iso R f \\<^bsub>ring_of (poly_mod_ring R f)\<^esub> = (I +>\<^bsub>P\<^esub> \\<^bsub>P\<^esub>)" + unfolding poly_mod_ring_one poly_mod_ring_iso_def by simp + also have "... = \\<^bsub>P Quot I\<^esub>" using s.hom_one by simp + finally have "poly_mod_ring_iso R f \\<^bsub>ring_of (poly_mod_ring R f)\<^esub> = \\<^bsub>P Quot I\<^esub>" by simp + moreover have "degree \\<^bsub>P\<^esub> < degree f" + using deg_f unfolding univ_poly_one by simp + hence "\\<^bsub>ring_of (poly_mod_ring R f)\<^esub> \ carrier (ring_of (poly_mod_ring R f))" + unfolding poly_mod_ring_one poly_mod_ring_carr_1 by simp + ultimately show "?f (\\<^bsub>?S\<^esub>) = \\<^bsub>?T\<^esub>" + unfolding poly_mod_ring_iso_inv_def by (intro the_inv_into_f_eq poly_mod_ring_iso_inj) +next + show "bij_betw ?f (carrier ?S) (carrier ?T)" by (rule poly_mod_iso_ring_bij_2) +qed + +lemma cring_poly_mod_ring_1: + shows "ring_of (poly_mod_ring R f)\zero := poly_mod_ring_iso_inv R f \\<^bsub>P Quot I\<^esub>\ = + ring_of (poly_mod_ring R f)" + and "cring (ring_of (poly_mod_ring R f))" +proof - + let ?f = "poly_mod_ring_iso_inv R f" + + have "poly_mod_ring_iso R f \\<^bsub>P\<^esub> = \\<^bsub>P Quot PIdl\<^bsub>P\<^esub> f\<^esub>" + unfolding poly_mod_ring_iso_def by simp + moreover have "[] \ carrier P" using univ_poly_zero[where K="carrier (ring_of R)"] by auto + ultimately have "?f \\<^bsub>P Quot I\<^esub> = \\<^bsub>P\<^esub>" + unfolding univ_poly_zero poly_mod_ring_iso_inv_def using deg_f + by (intro the_inv_into_f_eq bij_betw_imp_inj_on[OF poly_mod_iso_ring_bij]) + (simp_all add:add:poly_mod_ring_carr_1) + also have "... = 0\<^sub>C\<^bsub>poly R\<^esub>" using ring_of_poly[OF ring_c] domain_cD[OF d_poly] by auto + finally have "?f \\<^bsub>P Quot I\<^esub> = 0\<^sub>C\<^bsub>poly R\<^esub>" by simp + thus "ring_of (poly_mod_ring R f)\zero := ?f \\<^bsub>P Quot I\<^esub>\ = ring_of (poly_mod_ring R f)" + unfolding ring_of_def poly_mod_ring_def by auto + thus "cring (ring_of (poly_mod_ring R f))" + using cr.ring_iso_imp_img_cring[OF poly_mod_ring_iso_inv] by simp +qed + +interpretation cr_p: cring "(ring_of (poly_mod_ring R f))" + by (rule cring_poly_mod_ring_1) + +lemma cring_c_poly_mod_ring: "cring\<^sub>C (poly_mod_ring R f)" +proof - + let ?P = "ring_of (poly_mod_ring R f)" + have "-\<^sub>C\<^bsub>poly_mod_ring R f\<^esub> x = \\<^bsub>ring_of (poly_mod_ring R f)\<^esub> x" (is "?L = ?R") + if "x \ carrier (ring_of (poly_mod_ring R f))" for x + proof (rule cr_p.minus_equality[symmetric, OF _ that]) + have "-\<^sub>C\<^bsub>poly_mod_ring R f\<^esub> x = -\<^sub>C\<^bsub>poly R\<^esub> x" unfolding poly_mod_ring_def by simp + also have "... = \\<^bsub>P\<^esub> x" using that unfolding poly_mod_ring_carr_1 + by (subst domain_cD[OF d_poly]) (simp_all add:ring_of_poly[OF ring_c]) + finally have 0:"-\<^sub>C\<^bsub>poly_mod_ring R f\<^esub> x = \\<^bsub>P\<^esub> x" by simp + + have 1:"\\<^bsub>P\<^esub> x \ carrier (ring_of (poly_mod_ring R f))" + using that univ_poly_a_inv_degree[OF carrier_is_subring] unfolding poly_mod_ring_carr_1 + by auto + + have "-\<^sub>C\<^bsub>poly_mod_ring R f\<^esub> x \\<^bsub>?P\<^esub> x = pmod (\\<^bsub>P\<^esub> x \\<^bsub>P\<^esub> x) f" + using that 1 unfolding 0 poly_mod_ring_carr_1 by (intro poly_mod_ring_add) auto + also have "... = pmod \\<^bsub>P\<^esub> f" + using that unfolding poly_mod_ring_carr_1 by simp algebra + also have "... = []" + unfolding univ_poly_zero using carrier_is_subfield f_carr long_division_zero(2) by presburger + also have "... = \\<^bsub>?P\<^esub>" by (simp add:poly_mod_ring_def ring_of_def poly_def) + finally show "-\<^sub>C\<^bsub>poly_mod_ring R f\<^esub> x \\<^bsub>?P\<^esub> x = \\<^bsub>?P\<^esub>" by simp + + show " -\<^sub>C\<^bsub>poly_mod_ring R f\<^esub> x \ carrier (ring_of (poly_mod_ring R f))" + unfolding 0 by (rule 1) + qed + moreover have "x \\<^sub>C\<^bsub>poly_mod_ring R f\<^esub> = inv\<^bsub>ring_of (poly_mod_ring R f)\<^esub> x" + if x_unit: "x \ Units (ring_of (poly_mod_ring R f))" for x + proof (rule cr_p.comm_inv_char[symmetric]) + show x_carr: "x \ carrier (ring_of (poly_mod_ring R f))" + using that unfolding Units_def by auto + + obtain y where y:"x \\<^bsub>ring_of (poly_mod_ring R f)\<^esub> y = \\<^bsub>ring_of (poly_mod_ring R f)\<^esub>" + and y_carr: "y \ carrier (ring_of (poly_mod_ring R f))" + using x_unit unfolding Units_def by auto + + have "pmod (x \\<^bsub>P\<^esub> y) f =x \\<^bsub>ring_of (poly_mod_ring R f)\<^esub> y" + using x_carr y_carr by (intro poly_mod_ring_mult[symmetric]) (auto simp:poly_mod_ring_carr_1) + also have "... = \\<^bsub>P\<^esub>" + unfolding y poly_mod_ring_one by simp + finally have 1:"pmod (x \\<^bsub>P\<^esub> y) f = \\<^bsub>P\<^esub>" by simp + + have "pcoprime\<^bsub>ring_of R\<^esub> (x \\<^bsub>P\<^esub> y) f = pcoprime\<^bsub>ring_of R\<^esub> f (pmod (x \\<^bsub>P\<^esub> y) f)" + using x_carr y_carr f_carr unfolding poly_mod_ring_carr_1 by (intro pcoprime_step) auto + also have "... = pcoprime \<^bsub>ring_of R\<^esub> f \\<^bsub>P\<^esub>" unfolding 1 by simp + also have "... = True" using pcoprime_one by simp + finally have "pcoprime\<^bsub>ring_of R\<^esub> (x \\<^bsub>P\<^esub> y) f" by simp + hence "pcoprime\<^bsub>ring_of R\<^esub> x f" + using x_carr y_carr f_carr pcoprime_left_factor unfolding poly_mod_ring_carr_1 by blast + hence 2:"length (snd ( ext_euclidean R x f)) = 1" + using f_carr x_carr pcoprime_c[OF field_R] unfolding poly_mod_ring_carr_1 pcoprime\<^sub>C.simps + by auto + + obtain u v r where uvr_def: "((u,v),r) = ext_euclidean R x f" by (metis surj_pair) + + have x_carr': "x \ carrier P" using x_carr unfolding poly_mod_ring_carr_1 by auto + have r_eq:"r = x \\<^bsub>P\<^esub> u \\<^bsub>P\<^esub> f \\<^bsub>P\<^esub> v" and ruv_carr: "{r, u, v} \ carrier P" + using uvr_def[symmetric] ext_euclidean[OF field_R x_carr' f_carr] by auto + + have "length r = 1" using 2 uvr_def[symmetric] by simp + hence 3:"r = [hd r]" by (cases r) auto + hence "r \ \\<^bsub>P\<^esub>" unfolding univ_poly_zero by auto + hence "hd r \ carrier (ring_of R) - {\\<^bsub>ring_of R\<^esub>}" + using ruv_carr by (intro lead_coeff_carr) auto + hence r_unit: "r \ Units P" using 3 univ_poly_units[OF carrier_is_subfield] by auto + hence inv_r_carr: "inv\<^bsub>P\<^esub> r \ carrier P" by simp + + have 0: "x \\<^sub>C\<^bsub>poly_mod_ring R f\<^esub> = pmod\<^sub>C R (r \\<^sub>C\<^bsub>poly R\<^esub> *\<^sub>C\<^bsub>poly R\<^esub> u) f" + by (simp add:poly_mod_ring_def uvr_def[symmetric]) + also have "... = pmod\<^sub>C R (inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> u) f" + using r_unit unfolding domain_cD[OF d_poly] + by (subst domain_cD[OF d_poly]) (simp_all add:ring_of_poly[OF ring_c]) + also have "... = pmod (inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> u) f" + using ruv_carr inv_r_carr by (intro pmod_c[OF field_R] f_carr) simp + finally have 0: "x \\<^sub>C\<^bsub>poly_mod_ring R f\<^esub> = pmod (inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> u) f" + by simp + + show "x \\<^sub>C\<^bsub>poly_mod_ring R f\<^esub> \ carrier (ring_of (poly_mod_ring R f))" + using ruv_carr r_unit unfolding 0 by (intro poly_mod_ring_carr) simp + + have 4: "degree \\<^bsub>P\<^esub> < degree f" unfolding univ_poly_one using deg_f by auto + + have "f divides\<^bsub>P\<^esub> inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> f \\<^bsub>P\<^esub> v" + using inv_r_carr ruv_carr f_carr + by (intro dividesI[where c="inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> v"]) (simp_all, algebra) + hence 5: "pmod (inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> f \\<^bsub>P\<^esub> v) f = []" + using f_carr ruv_carr inv_r_carr + by (intro iffD2[OF pmod_zero_iff_pdivides[OF carrier_is_subfield]]) (auto simp:pdivides_def) + + have "x \\<^bsub>?P\<^esub> x \\<^sub>C\<^bsub>poly_mod_ring R f\<^esub> = pmod (x \\<^bsub>P\<^esub> pmod (inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> u) f) f" + using ruv_carr inv_r_carr f_carr unfolding 0 + by (intro poly_mod_ring_mult x_carr' long_division_closed[OF carrier_is_subfield]) simp_all + also have "... = pmod (x \\<^bsub>P\<^esub> (inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> u)) f" + using ruv_carr inv_r_carr f_carr by (intro pmod_mult_right[symmetric] x_carr') auto + also have "... = pmod (inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> (x \\<^bsub>P\<^esub> u)) f" + using x_carr' ruv_carr inv_r_carr by (intro arg_cong2[where f="pmod"] refl) (simp, algebra) + also have "... = pmod (inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> (r \\<^bsub>P\<^esub> f \\<^bsub>P\<^esub> v)) f" using ruv_carr f_carr x_carr' + by (intro arg_cong2[where f="pmod"] arg_cong2[where f="(\\<^bsub>P\<^esub>)"] refl) (simp add:r_eq, algebra) + also have "... = pmod (inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> f \\<^bsub>P\<^esub> v) f" + using ruv_carr inv_r_carr f_carr by (intro arg_cong2[where f="pmod"] refl) (simp, algebra) + also have "... = pmod \\<^bsub>P\<^esub> f \\<^bsub>P\<^esub> pmod (\\<^bsub>P\<^esub> (inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> f \\<^bsub>P\<^esub> v)) f" + using ruv_carr inv_r_carr f_carr unfolding d.Units_l_inv[OF r_unit] a_minus_def + by (intro long_division_add[OF carrier_is_subfield]) simp_all + also have "... = \\<^bsub>P\<^esub> \\<^bsub>P\<^esub> pmod (inv\<^bsub>P\<^esub> r \\<^bsub>P\<^esub> f \\<^bsub>P\<^esub> v) f" + using ruv_carr f_carr inv_r_carr unfolding a_minus_def + by (intro arg_cong2[where f="(\\<^bsub>P\<^esub>)"] pmod_const[OF carrier_is_subfield] + long_division_a_inv[OF carrier_is_subfield] 4) simp_all + also have "... = \\<^bsub>P\<^esub> \\<^bsub>P\<^esub> \\<^bsub>P\<^esub>" unfolding 5 univ_poly_zero by simp + also have "... = \\<^bsub>ring_of (poly_mod_ring R f)\<^esub>" unfolding poly_mod_ring_one by algebra + finally show "x \\<^bsub>ring_of (poly_mod_ring R f)\<^esub> x \\<^sub>C\<^bsub>poly_mod_ring R f\<^esub> = \\<^bsub>?P\<^esub>" by simp + qed + ultimately show ?thesis using cring_poly_mod_ring_1 by (intro cring_cI) +qed + + +end + +lemma field_c_poly_mod_ring: + assumes field_R: "field\<^sub>C R" + assumes "monic_irreducible_poly (ring_of R) f" + shows "field\<^sub>C (poly_mod_ring R f)" +proof - + interpret field "ring_of R" using field_R unfolding field\<^sub>C_def by auto + + have f_carr: "f \ carrier (poly_ring (ring_of R))" + using assms(2) monic_poly_carr unfolding monic_irreducible_poly_def by auto + + have deg_f: "degree f > 0" using monic_poly_min_degree assms(2) by fastforce + + have f_irred: "pirreducible\<^bsub>ring_of R\<^esub> (carrier (ring_of R)) f" + using assms(2) unfolding monic_irreducible_poly_def by auto + + interpret r:field "poly_ring (ring_of R) Quot (PIdl\<^bsub>poly_ring (ring_of R)\<^esub> f)" + using f_irred f_carr iffD2[OF rupture_is_field_iff_pirreducible[OF carrier_is_subfield]] + unfolding rupture_def by blast + + have "field (ring_of (poly_mod_ring R f))" + using r.ring_iso_imp_img_field[OF poly_mod_ring_iso_inv[OF field_R f_carr deg_f]] + using cring_poly_mod_ring_1(1)[OF field_R f_carr deg_f] by simp + moreover have "cring\<^sub>C (poly_mod_ring R f)" + by (rule cring_c_poly_mod_ring[OF field_R f_carr deg_f]) + ultimately show ?thesis unfolding field\<^sub>C_def domain\<^sub>C_def using field.axioms(1) by blast +qed + + +lemma enum_c_poly_mod_ring: + assumes "enum\<^sub>C R" "ring\<^sub>C R" + shows "enum\<^sub>C (poly_mod_ring R f)" +proof (rule enum_cI) + let ?l = "degree f" + let ?b = "idx_size R" + let ?S = "carrier (ring_of (poly_mod_ring R f))" + + note bij_0 = bij_betw_poly_enum[where l="degree f", OF assms(1,2)] + have "?S = {xs \ carrier (poly_ring (ring_of R)). length xs \ ?l}" + unfolding ring_of_poly[OF assms(2),symmetric] poly_mod_ring_def by (simp add:ring_of_def) + hence bij_1:"bij_betw (poly_enum R (degree f)) {..Executable Polynomial Rings\ + +theory Finite_Fields_Poly_Ring_Code + imports + Finite_Fields_Indexed_Algebra_Code + "HOL-Algebra.Polynomials" + Finite_Fields.Card_Irreducible_Polynomials_Aux +begin + +fun o_normalize :: "('a,'b) idx_ring_scheme \ 'a list \ 'a list" + where + "o_normalize E [] = []" + | "o_normalize E p = (if lead_coeff p \ 0\<^sub>C\<^bsub>E\<^esub> then p else o_normalize E (tl p))" + +fun o_poly_add :: "('a,'b) idx_ring_scheme \ 'a list \ 'a list \ 'a list" where + "o_poly_add E p1 p2 = ( + if length p1 \ length p2 + then o_normalize E (map2 (idx_plus E) p1 ((replicate (length p1 - length p2) 0\<^sub>C\<^bsub>E\<^esub> ) @ p2)) + else o_poly_add E p2 p1)" + +fun o_poly_mult :: "('a,'b) idx_ring_scheme \ 'a list \ 'a list \ 'a list" + where + "o_poly_mult E [] p2 = []" + | "o_poly_mult E p1 p2 = + o_poly_add E ((map (idx_mult E (hd p1)) p2) @ + (replicate (degree p1) 0\<^sub>C\<^bsub>E\<^esub> )) (o_poly_mult E (tl p1) p2)" + +definition poly :: "('a,'b) idx_ring_scheme \ 'a list idx_ring" + where "poly E = \ + idx_pred = (\x. (x = [] \ hd x \ 0\<^sub>C\<^bsub>E\<^esub>) \ list_all (idx_pred E) x), + idx_uminus = (\x. map (idx_uminus E) x), + idx_plus = o_poly_add E, + idx_udivide = (\x. [idx_udivide E (hd x)]), + idx_mult = o_poly_mult E, + idx_zero = [], + idx_one = [idx_one E] \" + +definition poly_var :: "('a,'b) idx_ring_scheme \ 'a list" ("X\<^sub>C\") + where "poly_var E = [idx_one E, idx_zero E]" + +lemma poly_var: "poly_var R = X\<^bsub>ring_of R\<^esub>" + unfolding var_def poly_var_def by (simp add:ring_of_def) + +fun poly_eval :: "('a,'b) idx_ring_scheme \ 'a list \ 'a \ 'a" + where "poly_eval R fs x = fold (\a b. b *\<^sub>C\<^bsub>R\<^esub> x +\<^sub>C\<^bsub>R\<^esub> a) fs 0\<^sub>C\<^bsub>R\<^esub>" + + + +lemma ring_of_poly: + assumes "ring\<^sub>C A" + shows "ring_of (poly A) = poly_ring (ring_of A)" +proof (intro ring.equality) + interpret ring "ring_of A" using assms unfolding ring\<^sub>C_def by auto + + have b: "\\<^bsub>ring_of A\<^esub> = 0\<^sub>C\<^bsub>A\<^esub>" unfolding ring_of_def by simp + have c: "(\\<^bsub>ring_of A\<^esub>) = (*\<^sub>C\<^bsub>A\<^esub>)" unfolding ring_of_def by simp + have d: "(\\<^bsub>ring_of A\<^esub>) = (+\<^sub>C\<^bsub>A\<^esub>)" unfolding ring_of_def by simp + + have " o_normalize A x = normalize x" for x + using b by (induction x) simp_all + + hence "o_poly_add A x y = poly_add x y" if "length y \ length x" for x y + using that by (subst o_poly_add.simps, subst poly_add.simps) (simp add: b d) + hence a:"o_poly_add A x y = poly_add x y" for x y + by (subst o_poly_add.simps, subst poly_add.simps) simp + + hence "x \\<^bsub>ring_of (poly A)\<^esub> y = x \\<^bsub>poly_ring (ring_of A)\<^esub> y" for x y + by (simp add:univ_poly_def poly_def ring_of_def) + + thus "(\\<^bsub>ring_of (poly A)\<^esub>) = (\\<^bsub>poly_ring (ring_of A)\<^esub>)" by (intro ext) + + show "carrier (ring_of (poly A)) = carrier (poly_ring (ring_of A))" + by (auto simp add: ring_of_def poly_def univ_poly_def polynomial_def list_all_iff) + + have "o_poly_mult A x y = poly_mult x y" for x y + proof (induction x) + case Nil then show ?case by simp + next + case (Cons a x) then show ?case + by (subst o_poly_mult.simps,subst poly_mult.simps) + (simp add:a b c del:poly_add.simps o_poly_add.simps) + qed + hence "x \\<^bsub>ring_of (poly A)\<^esub> y = x \\<^bsub>poly_ring (ring_of A)\<^esub> y" for x y + by (simp add: univ_poly_def poly_def ring_of_def) + thus "(\\<^bsub>ring_of (poly A)\<^esub>) = (\\<^bsub>poly_ring (ring_of A)\<^esub>)" by (intro ext) + +qed (simp_all add:ring_of_def poly_def univ_poly_def) + +lemma poly_eval: + assumes "ring\<^sub>C R" + assumes fsc:"fs \ carrier (ring_of (poly R))" and xc:"x \ carrier (ring_of R)" + shows "poly_eval R fs x = ring.eval (ring_of R) fs x" +proof - + interpret ring "ring_of R" using assms unfolding ring\<^sub>C_def by auto + + have fs_carr:"fs \ carrier (poly_ring (ring_of R))" using ring_of_poly[OF assms(1)] fsc by auto + hence "set fs \ carrier (ring_of R)" by (simp add: polynomial_incl univ_poly_carrier) + thus ?thesis + proof (induction rule:rev_induct) + case Nil thus ?case by simp (simp add:ring_of_def) + next + case (snoc ft fh) + have "poly_eval R (fh @ [ft]) x = poly_eval R fh x *\<^sub>C\<^bsub>R\<^esub> x +\<^sub>C\<^bsub>R\<^esub> ft" by simp + also have "... = eval fh x *\<^sub>C\<^bsub>R\<^esub> x +\<^sub>C\<^bsub>R\<^esub> ft" using snoc by (subst snoc) auto + also have "... = eval fh x \\<^bsub>ring_of R\<^esub> x \\<^bsub>ring_of R\<^esub> ft " by (simp add:ring_of_def) + also have " ... = eval (fh@[ft]) x" using snoc by (intro eval_append_aux[symmetric] xc) auto + finally show ?case by auto + qed +qed + +lemma poly_domain: + assumes "domain\<^sub>C A" + shows "domain\<^sub>C (poly A)" +proof - + interpret domain "ring_of A" using assms unfolding domain\<^sub>C_def by auto + + have a:"\\<^bsub>ring_of A\<^esub> x = -\<^sub>C\<^bsub>A\<^esub> x" if "x \ carrier (ring_of A)" for x + using that by (intro domain_cD[symmetric] assms) + have "ring\<^sub>C A" + using assms unfolding domain\<^sub>C_def cring\<^sub>C_def by auto + hence b:"ring_of (poly A) = poly_ring (ring_of A)" + by (subst ring_of_poly) auto + + have c:"domain (ring_of (poly A))" + unfolding b by (rule univ_poly_is_domain[OF carrier_is_subring]) + + interpret d: domain "poly_ring (ring_of A)" + using c unfolding b by simp + + have "-\<^sub>C\<^bsub>poly A\<^esub> x = \\<^bsub>ring_of (poly A)\<^esub> x" if "x \ carrier (ring_of (poly A))" for x + proof - + have "\\<^bsub>ring_of (poly A)\<^esub> x = map (a_inv (ring_of A)) x" + using that unfolding b by (subst univ_poly_a_inv_def'[OF carrier_is_subring]) auto + also have "... = map (\r. -\<^sub>C\<^bsub>A\<^esub> r) x" + using that unfolding b univ_poly_carrier[symmetric] polynomial_def + by (intro map_cong refl a) auto + also have "... = -\<^sub>C\<^bsub>poly A\<^esub> x" + unfolding poly_def by simp + finally show ?thesis by simp + qed + moreover have "x \\<^sub>C\<^bsub>poly A\<^esub> = inv\<^bsub>ring_of (poly A)\<^esub> x" if "x \ Units (ring_of (poly A))" for x + proof - + have "x \ {[k] |k. k \ carrier (ring_of A) - {\\<^bsub>ring_of A\<^esub>}}" + using that univ_poly_carrier_units_incl unfolding b by auto + then obtain k where x_eq: "k \ carrier (ring_of A) - {\\<^bsub>ring_of A\<^esub>}" "x = [k]" by auto + have "inv\<^bsub>ring_of (poly A)\<^esub> x \ Units (poly_ring (ring_of A))" + using that unfolding b by simp + hence "inv\<^bsub>ring_of (poly A)\<^esub> x \ {[k] |k. k \ carrier (ring_of A) - {\\<^bsub>ring_of A\<^esub>}}" + using that univ_poly_carrier_units_incl unfolding b by auto + then obtain v where x_inv_eq: "v\ carrier (ring_of A) - {\\<^bsub>ring_of A\<^esub>}" + "inv\<^bsub>ring_of (poly A)\<^esub> x = [v]" by auto + + have "poly_mult [k] [v] = [k] \\<^bsub>ring_of (poly A)\<^esub> [v]" unfolding b univ_poly_mult by simp + also have "... = x \\<^bsub>ring_of (poly A)\<^esub> inv\<^bsub>ring_of (poly A)\<^esub> x" using x_inv_eq x_eq by auto + also have "... = \\<^bsub>ring_of (poly A)\<^esub>" using that unfolding b by simp + also have "... = [\\<^bsub>ring_of A\<^esub>]" unfolding b univ_poly_one by (simp add:ring_of_def) + finally have "poly_mult [k] [v] = [\\<^bsub>ring_of A\<^esub>]" by simp + hence "k \\<^bsub>ring_of A\<^esub> v \\<^bsub>ring_of A\<^esub> \\<^bsub>ring_of A\<^esub> = \\<^bsub>ring_of A\<^esub>" + by (simp add:if_distribR if_distrib) (simp cong:if_cong, metis) + hence e: "k \\<^bsub>ring_of A\<^esub> v = \\<^bsub>ring_of A\<^esub>" using x_eq(1) x_inv_eq(1) by simp + hence f: "v \\<^bsub>ring_of A\<^esub> k = \\<^bsub>ring_of A\<^esub>" using x_eq(1) x_inv_eq(1) m_comm by simp + have g: "v = inv\<^bsub>ring_of A\<^esub> k" + using e x_eq(1) x_inv_eq(1) by (intro comm_inv_char[symmetric]) auto + hence h: "k \ Units (ring_of A)" unfolding Units_def using e f x_eq(1) x_inv_eq(1) by blast + + have "x \\<^sub>C\<^bsub>poly A\<^esub> = [k] \\<^sub>C\<^bsub>poly A\<^esub>" unfolding x_eq by simp + also have "... = [k \\<^sub>C\<^bsub>A\<^esub>]" unfolding poly_def by simp + also have "... = [v]" + unfolding g by (intro domain_cD[OF assms(1)] arg_cong2[where f="(#)"] h refl) + also have "... = inv\<^bsub>ring_of (poly A)\<^esub> x" unfolding x_inv_eq by simp + finally show ?thesis by simp + qed + ultimately show ?thesis using c by (intro domain_cI) +qed + +function long_division\<^sub>C :: "('a,'b) idx_ring_scheme \ 'a list \ 'a list \ 'a list \ 'a list" + where "long_division\<^sub>C F f g = ( + if (length g = 0 \ length f < length g) + then ([], f) + else ( + let k = length f - length g; + \ = -\<^sub>C\<^bsub>F\<^esub> (hd f *\<^sub>C\<^bsub>F\<^esub> (hd g) \\<^sub>C\<^bsub>F\<^esub>); + h = [\] *\<^sub>C\<^bsub>poly F\<^esub> X\<^sub>C\<^bsub>F\<^esub> ^\<^sub>C\<^bsub>poly F\<^esub> k; + f' = f +\<^sub>C\<^bsub>poly F\<^esub> (h *\<^sub>C\<^bsub>poly F\<^esub> g); + f'' = take (length f - 1) f' + in apfst (\x. x +\<^sub>C\<^bsub>poly F\<^esub> -\<^sub>C\<^bsub>poly F\<^esub> h) (long_division\<^sub>C F f'' g)))" + by pat_completeness auto + +lemma pmod_termination_helper: + "g \ [] \ \length f < length g \ min x (length f - 1) < length f" + by (metis diff_less length_greater_0_conv list.size(3) min.strict_coboundedI2 zero_less_one) + +termination by (relation "measure (\(_, f, _). length f)") (use pmod_termination_helper in auto) + +declare long_division\<^sub>C.simps[simp del] + +lemma long_division_c_length: + assumes "length g > 0" + shows "length (snd (long_division\<^sub>C R f g)) < length g" +proof (induction "length f" arbitrary:f rule:nat_less_induct) + case 1 + have 0:"length (snd (long_division\<^sub>C R x g)) < length g" + if "length x < length f" for x using 1 that by blast + + show "length (snd (long_division\<^sub>C R f g)) < length g" + proof (cases "length f < length g") + case True then show ?thesis by (subst long_division\<^sub>C.simps) simp + next + case False + hence "length f > 0" using assms by auto + thus ?thesis using assms by (subst long_division\<^sub>C.simps) + (auto intro!:0 simp: min.commute min.strict_coboundedI1 Let_def) + qed +qed + + +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 poly_length_from_coeff: + assumes "p \ carrier (poly_ring R)" + assumes "\i. i \ k \ coeff p i = \" + shows "length p \ k" +proof (rule ccontr) + assume a:"\length p \ k" + hence p_nz: "p \ []" by auto + have "k < length p" using a by simp + hence "k \ length p - 1" by simp + hence "\ = coeff p (degree p)" by (intro assms(2)[symmetric]) + also have "... = lead_coeff p" by (intro lead_coeff_simp[OF p_nz]) + finally have "\ = lead_coeff p" by simp + thus "False" + using p_nz assms(1) unfolding univ_poly_def polynomial_def by simp +qed + +lemma poly_add_cancel_len: + assumes "f \ carrier (poly_ring R) - {\\<^bsub>poly_ring R\<^esub>}" + assumes "g \ carrier (poly_ring R) - {\\<^bsub>poly_ring R\<^esub>}" + assumes "hd f = \ hd g" "degree f = degree g" + shows "length (f \\<^bsub>poly_ring R\<^esub> g) < length f" +proof - + have f_ne: "f \ []" using assms(1) unfolding univ_poly_zero by simp + have g_ne: "g \ []" using assms(2) unfolding univ_poly_zero by simp + + have "coeff f i = \coeff g i" if "i \ degree f" for i + proof (cases "i = degree f") + case True + have "coeff f i = hd f" unfolding True by (subst lead_coeff_simp[OF f_ne]) simp + also have "... = \hd g" using assms(3) by simp + also have "... = \coeff g i" unfolding True assms(4) by (subst lead_coeff_simp[OF g_ne]) simp + finally show ?thesis by simp + next + case False + hence "i > degree f" "i > degree g" using assms(4) that by auto + thus "coeff f i = \ coeff g i" using coeff_degree by simp + qed + hence "coeff (f \\<^bsub>poly_ring R\<^esub> g) i = \" if "i \ degree f" for i + using assms(1,2) that by (subst r.coeff_add) (auto intro:l_neg simp: r.coeff_range) + + hence "length (f \\<^bsub>poly_ring R\<^esub> g) \ length f - 1" + using assms(1,2) by (intro poly_length_from_coeff) auto + also have "... < length f" using f_ne by simp + finally show ?thesis by simp +qed + +lemma pmod_mult_left: + assumes "f \ carrier (poly_ring R)" + assumes "g \ carrier (poly_ring R)" + assumes "h \ carrier (poly_ring R)" + shows "(f \\<^bsub>poly_ring R\<^esub> g) pmod h = ((f pmod h) \\<^bsub>poly_ring R\<^esub> g) pmod h" (is "?L = ?R") +proof - + have "h pdivides (h \\<^bsub>poly_ring R\<^esub> (f pdiv h)) \\<^bsub>poly_ring R\<^esub> g" + using assms long_division_closed[OF carrier_is_subfield] + by (simp add: dividesI' pdivides_def r.p.m_assoc) + hence 0:"(h \\<^bsub>poly_ring R\<^esub> (f pdiv h)) \\<^bsub>poly_ring R\<^esub> g pmod h = \\<^bsub>poly_ring R\<^esub>" + using pmod_zero_iff_pdivides[OF carrier_is_subfield] assms + long_division_closed[OF carrier_is_subfield] univ_poly_zero + by (metis (no_types, opaque_lifting) r.p.m_closed) + + have "?L = (h \\<^bsub>poly_ring R\<^esub> (f pdiv h) \\<^bsub>poly_ring R\<^esub> (f pmod h)) \\<^bsub>poly_ring R\<^esub> g pmod h" + using assms by (intro arg_cong2[where f="(\\<^bsub>poly_ring R\<^esub>)"] arg_cong2[where f="(pmod)"] + pdiv_pmod[OF carrier_is_subfield]) auto + also have "... = ((h \\<^bsub>poly_ring R\<^esub> (f pdiv h)) \\<^bsub>poly_ring R\<^esub> g \\<^bsub>poly_ring R\<^esub> + (f pmod h) \\<^bsub>poly_ring R\<^esub> g) pmod h" + using assms long_division_closed[OF carrier_is_subfield] + by (intro r.p.l_distr arg_cong2[where f="(pmod)"]) auto + also have "... = ((h \\<^bsub>poly_ring R\<^esub> (f pdiv h)) \\<^bsub>poly_ring R\<^esub> g) pmod h \\<^bsub>poly_ring R\<^esub> + ((f pmod h) \\<^bsub>poly_ring R\<^esub> g pmod h)" + using assms long_division_closed[OF carrier_is_subfield] + by (intro long_division_add[OF carrier_is_subfield]) auto + also have "... = ?R" + using assms long_division_closed[OF carrier_is_subfield] unfolding 0 by auto + finally show ?thesis + by simp +qed + +lemma pmod_mult_right: + assumes "f \ carrier (poly_ring R)" + assumes "g \ carrier (poly_ring R)" + assumes "h \ carrier (poly_ring R)" + shows "(f \\<^bsub>poly_ring R\<^esub> g) pmod h = (f \\<^bsub>poly_ring R\<^esub> (g pmod h)) pmod h" (is "?L = ?R") +proof - + have "?L = (g \\<^bsub>poly_ring R\<^esub> f) pmod h" using assms by algebra + also have "... = ((g pmod h) \\<^bsub>poly_ring R\<^esub> f) pmod h" by (intro pmod_mult_left assms) + also have "... = ?R" using assms long_division_closed[OF carrier_is_subfield] by algebra + finally show ?thesis by simp +qed + +lemma pmod_mult_both: + assumes "f \ carrier (poly_ring R)" + assumes "g \ carrier (poly_ring R)" + assumes "h \ carrier (poly_ring R)" + shows "(f \\<^bsub>poly_ring R\<^esub> g) pmod h = ((f pmod h) \\<^bsub>poly_ring R\<^esub> (g pmod h)) pmod h" + (is "?L = ?R") +proof - + have "(f \\<^bsub>poly_ring R\<^esub> g) pmod h = ((f pmod h) \\<^bsub>poly_ring R\<^esub> g) pmod h" + by (intro pmod_mult_left assms) + also have "... = ?R" + using assms long_division_closed[OF carrier_is_subfield] by (intro pmod_mult_right) auto + finally show ?thesis by simp +qed + +lemma field_Unit_minus_closed: + assumes "x \ Units R" + shows "\ x \ Units R" + using assms mult_of.Units_eq by auto + +end + +lemma long_division_c: + assumes "field\<^sub>C R" + assumes "f \ carrier (poly_ring (ring_of R))" + assumes "g \ carrier (poly_ring (ring_of R))" + shows "long_division\<^sub>C R f g = (ring.pdiv (ring_of R) f g, ring.pmod (ring_of R) f g)" +proof - + let ?P = "poly_ring (ring_of R)" + let ?result = "(\f r. f = snd r \\<^bsub>poly_ring (ring_of R)\<^esub> (fst r \\<^bsub>poly_ring (ring_of R)\<^esub> g))" + + define r where "r = long_division\<^sub>C R f g" + + interpret field "ring_of R" using assms(1) unfolding field\<^sub>C_def by auto + interpret d_poly_ring: domain "poly_ring (ring_of R)" + by (rule univ_poly_is_domain[OF carrier_is_subring]) + + have ring_c: "ring\<^sub>C R" using assms(1) unfolding field\<^sub>C_def domain\<^sub>C_def cring\<^sub>C_def by auto + have d_poly: "domain\<^sub>C (poly R)" using assms (1) unfolding field\<^sub>C_def by (intro poly_domain) auto + + have "r = long_division\<^sub>C R f g \ ?result f r \ {fst r, snd r} \ carrier (poly_ring (ring_of R))" + using assms(2) + proof (induction "length f" arbitrary: f r rule:nat_less_induct) + case 1 + + have ind: "x = snd q \\<^bsub>?P\<^esub> fst q \\<^bsub>?P\<^esub> g" "{fst q, snd q} \ carrier (poly_ring (ring_of R))" + if "length x < length f " "q = long_division\<^sub>C R x g" "x \ carrier (poly_ring (ring_of R)) " + for x q using 1(1) that by auto + + show ?case + proof (cases "length g = 0 \ length f < length g") + case True + hence "r = (\\<^bsub>poly_ring (ring_of R)\<^esub>, f)" + unfolding 1(2) univ_poly_zero by (subst long_division\<^sub>C.simps) simp + then show ?thesis using assms(3) 1(3) by simp + next + case False + hence "length g > 0" "length f \ length g" by auto + hence "f \ []" "g \ []" by auto + hence f_carr: "f \ carrier ?P - {\\<^bsub>?P\<^esub>}" and g_carr: "g \ carrier ?P - {\\<^bsub>?P\<^esub>}" + using 1(3) assms(3) univ_poly_zero by auto + + define k where "k = length f - length g" + define \ where "\ = -\<^sub>C\<^bsub>R\<^esub> (hd f *\<^sub>C\<^bsub>R\<^esub> (hd g) \\<^sub>C\<^bsub>R\<^esub>)" + define h where "h = [\] *\<^sub>C\<^bsub>poly R\<^esub> X\<^sub>C\<^bsub>R\<^esub> ^\<^sub>C\<^bsub>poly R\<^esub> k" + define f' where "f' = f +\<^sub>C\<^bsub>poly R\<^esub> (h *\<^sub>C\<^bsub>poly R\<^esub> g)" + define f'' where "f'' = take (length f - 1) f'" + obtain s t where st_def: "(s,t) = long_division\<^sub>C R f'' g" by (metis surj_pair) + + have "r = apfst (\x. x +\<^sub>C\<^bsub>poly R\<^esub> -\<^sub>C\<^bsub>poly R\<^esub> h) (long_division\<^sub>C R f'' g)" + using False unfolding 1(2) + by (subst long_division\<^sub>C.simps) (simp add:Let_def f''_def f'_def h_def \_def k_def) + + hence r_def: "r = (s +\<^sub>C\<^bsub>poly R\<^esub> -\<^sub>C\<^bsub>poly R\<^esub> h, t)" + unfolding st_def[symmetric] by simp + + have "monic_poly (ring_of R) (X\<^bsub>ring_of R\<^esub> [^]\<^bsub>poly_ring (ring_of R)\<^esub> k)" + by (intro monic_poly_pow monic_poly_var) + hence [simp]: "lead_coeff (X\<^bsub>ring_of R\<^esub> [^]\<^bsub>poly_ring (ring_of R)\<^esub> k) = \\<^bsub>ring_of R\<^esub>" + unfolding monic_poly_def by simp + + have hd_f_unit: "hd f \ Units (ring_of R)" and hd_g_unit: "hd g \ Units (ring_of R)" + using f_carr g_carr lead_coeff_carr field_Units by auto + hence hd_f_carr: "hd f \ carrier (ring_of R)" and hd_g_carr: "hd g \ carrier (ring_of R)" + by auto + + have k_def': "k = degree f - degree g" using False unfolding k_def by auto + have \_def': "\ = \\<^bsub>ring_of R\<^esub> (hd f \\<^bsub>ring_of R\<^esub> inv\<^bsub>ring_of R\<^esub> hd g)" + unfolding \_def using hd_g_unit hd_f_carr field_cD[OF assms(1)] by simp + + have \_unit: "\ \ Units (ring_of R)" unfolding \_def' using hd_f_unit hd_g_unit + by (intro field_Unit_minus_closed) simp + hence \_carr: "\ \ carrier (ring_of R) - {\\<^bsub>ring_of R\<^esub>}" unfolding field_Units by simp + hence \_poly_carr: "[\] \ carrier (poly_ring (ring_of R)) - {\\<^bsub>poly_ring (ring_of R)\<^esub>}" + by (simp add: univ_poly_carrier[symmetric] univ_poly_zero polynomial_def) + + have h_def': "h = [\] \\<^bsub>?P\<^esub> X\<^bsub>ring_of R\<^esub> [^]\<^bsub>?P\<^esub> k" + unfolding h_def poly_var domain_cD[OF d_poly] by (simp add:ring_of_poly[OF ring_c]) + have f'_def': "f' = f \\<^bsub>?P\<^esub> (h \\<^bsub>?P\<^esub> g)" + unfolding f'_def domain_cD[OF d_poly] by (simp add:ring_of_poly[OF ring_c]) + + have h_carr: "h \ carrier (poly_ring (ring_of R)) - {\\<^bsub>poly_ring (ring_of R)\<^esub>}" + using d_poly_ring.mult_of.m_closed \_poly_carr var_pow_carr[OF carrier_is_subring] + unfolding h_def' by auto + + have "degree f = k + degree g" using False unfolding k_def by linarith + also have "... = degree [\] + degree (X\<^bsub>ring_of R\<^esub> [^]\<^bsub>?P\<^esub> k) + degree g" + unfolding var_pow_degree[OF carrier_is_subring] by simp + also have "... = degree h + degree g" unfolding h_def' + by (intro arg_cong2[where f="(+)"] degree_mult[symmetric] + carrier_is_subring \_poly_carr var_pow_carr refl) + also have "... = degree (h \\<^bsub>poly_ring (ring_of R)\<^esub> g)" + by (intro degree_mult[symmetric] carrier_is_subring h_carr g_carr) + finally have deg_f: "degree f = degree (h \\<^bsub>poly_ring (ring_of R)\<^esub> g)" by simp + + have f'_carr: "f' \ carrier (poly_ring (ring_of R))" + using f_carr h_carr g_carr unfolding f'_def' by auto + + have "hd f = \\<^bsub>ring_of R\<^esub> (\ \\<^bsub>ring_of R\<^esub> lead_coeff g)" + using hd_g_unit hd_f_carr hd_g_carr \_unit \_carr unfolding \_def' + by (simp add: m_assoc l_minus) + also have "... = \\<^bsub>ring_of R\<^esub> (hd h \\<^bsub>ring_of R\<^esub> hd g)" + using hd_f_carr \_carr \_poly_carr var_pow_carr[OF carrier_is_subring] unfolding h_def' + by (subst lead_coeff_mult) (simp_all add:algebra_simps) + also have "... = \\<^bsub>ring_of R\<^esub> hd (h \\<^bsub>poly_ring (ring_of R)\<^esub> g)" + using h_carr g_carr by (subst lead_coeff_mult) auto + finally have "hd f = \\<^bsub>ring_of R\<^esub> hd (h \\<^bsub>poly_ring (ring_of R)\<^esub> g)" + by simp + hence len_f': "length f' < length f" using deg_f h_carr g_carr d_poly_ring.integral + unfolding f'_def' by (intro poly_add_cancel_len f_carr) auto + hence f''_def': "f'' = f'" unfolding f''_def by simp + + have "{fst (s,t),snd (s,t)} \ carrier (poly_ring (ring_of R))" + using len_f' f''_def' f'_carr by (intro ind(2)[where x="f''"] st_def) auto + hence s_carr: "s \ carrier ?P" and t_carr: "t \ carrier ?P" by auto + + have r_def': "r = (s \\<^bsub>poly_ring (ring_of R)\<^esub> h, t)" + using h_carr domain_cD[OF d_poly] unfolding r_def a_minus_def + using ring_of_poly[OF ring_c,symmetric] by simp + + have r_carr: "{fst r, snd r} \ carrier (poly_ring (ring_of R))" + using s_carr t_carr h_carr unfolding r_def' by auto + have "f = f'' \\<^bsub>?P\<^esub> h \\<^bsub>?P\<^esub> g" + using h_carr g_carr f_carr unfolding f''_def' f'_def' by simp algebra + also have "... = (snd (s,t) \\<^bsub>?P\<^esub> fst (s,t) \\<^bsub>?P\<^esub> g) \\<^bsub>?P\<^esub> h \\<^bsub>?P\<^esub> g" + using f'_carr f''_def' len_f' + by (intro arg_cong2[where f="\x y. x \\<^bsub>?P\<^esub> y"] ind(1) st_def) auto + also have "... = t \\<^bsub>?P\<^esub> (s \\<^bsub>?P\<^esub> h) \\<^bsub>?P\<^esub> g" + using s_carr t_carr h_carr g_carr by simp algebra + also have "... = snd r \\<^bsub>poly_ring (ring_of R)\<^esub> fst r \\<^bsub>poly_ring (ring_of R)\<^esub> g" + unfolding r_def' by simp + finally have "f = snd r \\<^bsub>poly_ring (ring_of R)\<^esub> fst r \\<^bsub>poly_ring (ring_of R)\<^esub> g" by simp + thus ?thesis using r_carr by auto + qed + qed + hence result: "?result f r" "{fst r, snd r} \ carrier (poly_ring (ring_of R))" + using r_def by auto + show ?thesis + proof (cases "g = []") + case True then show ?thesis by (simp add:long_division\<^sub>C.simps pmod_def pdiv_def) + next + case False + hence "snd r = [] \ degree (snd r) < degree g" + using long_division_c_length unfolding r_def + by (metis One_nat_def Suc_pred length_greater_0_conv not_less_eq) + moreover have "f = g \\<^bsub>?P\<^esub> (fst r) \\<^bsub>poly_ring (ring_of R)\<^esub> (snd r)" + using result(1,2) assms(2,3) by simp algebra + ultimately have "long_divides f g (fst r, snd r)" + using result(2) unfolding long_divides_def by (auto simp:mem_Times_iff) + hence "(fst r, snd r) = (pdiv f g, pmod f g)" + by (intro long_divisionI[OF carrier_is_subfield] False assms) + then show ?thesis unfolding r_def by simp + qed +qed + +definition pdiv\<^sub>C :: "('a,'b) idx_ring_scheme \ 'a list \ 'a list \ 'a list" where + "pdiv\<^sub>C R f g = fst (long_division\<^sub>C R f g)" + +lemma pdiv_c: + assumes "field\<^sub>C R" + assumes "f \ carrier (poly_ring (ring_of R))" + assumes "g \ carrier (poly_ring (ring_of R))" + shows "pdiv\<^sub>C R f g = ring.pdiv (ring_of R) f g" + unfolding pdiv\<^sub>C_def long_division_c[OF assms] by simp + +definition pmod\<^sub>C :: "('a,'b) idx_ring_scheme \ 'a list \ 'a list \ 'a list" where + "pmod\<^sub>C R f g = snd (long_division\<^sub>C R f g)" + +lemma pmod_c: + assumes "field\<^sub>C R" + assumes "f \ carrier (poly_ring (ring_of R))" + assumes "g \ carrier (poly_ring (ring_of R))" + shows "pmod\<^sub>C R f g = ring.pmod (ring_of R) f g" + unfolding pmod\<^sub>C_def long_division_c[OF assms] by simp + +function ext_euclidean :: + "('a,'b) idx_ring_scheme \ 'a list \ 'a list \ ('a list \ 'a list) \ 'a list" + where "ext_euclidean F f g = ( + if f = [] \ g = [] then + ((1\<^sub>C\<^bsub>poly F\<^esub>, 1\<^sub>C\<^bsub>poly F\<^esub>),f +\<^sub>C\<^bsub>poly F\<^esub> g) + else ( + let (p,q) = long_division\<^sub>C F f g; + ((u,v),r) = ext_euclidean F g q + in ((v,u +\<^sub>C\<^bsub>poly F\<^esub> (-\<^sub>C\<^bsub>poly F\<^esub> (p *\<^sub>C\<^bsub>poly F\<^esub> v))),r)))" + by pat_completeness auto + +termination + apply (relation "measure (\(_, _, f). length f)") + subgoal by simp + by (metis case_prod_conv in_measure length_greater_0_conv long_division_c_length prod.sel(2)) + +(* TODO MOVE *) +lemma (in domain) pdivides_self: + assumes "x \ carrier (poly_ring R)" + shows "x pdivides x" +proof - + interpret d:domain "poly_ring R" by (rule univ_poly_is_domain[OF carrier_is_subring]) + show ?thesis + using assms unfolding pdivides_def + by (intro dividesI[where c="\\<^bsub>poly_ring R\<^esub>"]) simp_all +qed + +declare ext_euclidean.simps[simp del] + +lemma ext_euclidean: + assumes "field\<^sub>C R" + defines "P \ poly_ring (ring_of R)" + assumes "f \ carrier (poly_ring (ring_of R))" + assumes "g \ carrier (poly_ring (ring_of R))" + defines "r \ ext_euclidean R f g" + shows "snd r = f \\<^bsub>P\<^esub> (fst (fst r)) \\<^bsub>P\<^esub> g \\<^bsub>P\<^esub> (snd (fst r))" (is "?T1") + and "snd r pdivides\<^bsub>ring_of R\<^esub> f" (is "?T2") "snd r pdivides\<^bsub>ring_of R\<^esub> g" (is "?T3") + and "{snd r, fst (fst r), snd (fst r)} \ carrier P" (is "?T4") + and "snd r = [] \ f = [] \ g = []" (is "?T5") +proof - + let ?P= "poly_ring (ring_of R)" + + interpret field "ring_of R" using assms(1) unfolding field\<^sub>C_def by auto + interpret d_poly_ring: domain "poly_ring (ring_of R)" + by (rule univ_poly_is_domain[OF carrier_is_subring]) + + have ring_c: "ring\<^sub>C R" using assms(1) unfolding field\<^sub>C_def domain\<^sub>C_def cring\<^sub>C_def by auto + have d_poly: "domain\<^sub>C (poly R)" using assms (1) unfolding field\<^sub>C_def by (intro poly_domain) auto + + have pdiv_zero: "x pdivides\<^bsub>ring_of R\<^esub> \\<^bsub>?P\<^esub>" if "x \ carrier ?P" for x + using that unfolding univ_poly_zero by (intro pdivides_zero[OF carrier_is_subring]) + + have "snd r = f \\<^bsub>?P\<^esub> (fst (fst r)) \\<^bsub>?P\<^esub> g \\<^bsub>?P\<^esub> (snd (fst r)) \ + snd r pdivides\<^bsub>ring_of R\<^esub> f \ snd r pdivides\<^bsub>ring_of R\<^esub> g \ + {snd r, fst (fst r), snd (fst r)} \ carrier ?P \ + (snd r = [] \ f = [] \ g = [])" + if "r = ext_euclidean R f g" "{f,g} \ carrier ?P" + using that + proof (induction "length g" arbitrary: f g r rule:nat_less_induct) + case 1 + have ind: + "snd s = x \\<^bsub>?P\<^esub> fst (fst s) \\<^bsub>?P\<^esub> y \\<^bsub>?P\<^esub> snd (fst s)" + "snd s pdivides\<^bsub>ring_of R\<^esub> x" "snd s pdivides\<^bsub>ring_of R\<^esub> y" + "{snd s, fst (fst s), snd (fst s)} \ carrier ?P" + "(snd s = [] \ x = [] \ y = [])" + if "length y < length g" "s = ext_euclidean R x y" "{x, y} \ carrier ?P" + for x y s using that 1(1) by metis+ + show ?case + proof (cases "f = [] \ g = []") + case True + hence r_def: "r = ((\\<^bsub>?P\<^esub>, \\<^bsub>?P\<^esub>), f \\<^bsub>?P\<^esub> g)" unfolding 1(2) + by (simp add:ext_euclidean.simps domain_cD[OF d_poly] ring_of_poly[OF ring_c]) + + consider "f = \\<^bsub>?P\<^esub>" | "g = \\<^bsub>?P\<^esub>" + using True unfolding univ_poly_zero by auto + hence "snd r pdivides\<^bsub>ring_of R\<^esub> f \ snd r pdivides\<^bsub>ring_of R\<^esub> g" + using 1(3) pdiv_zero pdivides_self unfolding r_def by cases auto + moreover have "snd r = f \\<^bsub>?P\<^esub> fst (fst r) \\<^bsub>?P\<^esub> g \\<^bsub>?P\<^esub> snd (fst r)" + using 1(3) unfolding r_def by simp + moreover have "{snd r, fst (fst r), snd (fst r)} \ carrier ?P" + using 1(3) unfolding r_def by auto + moreover have "snd r = [] \ f = [] \ g = []" + using 1(3) True unfolding r_def by (auto simp:univ_poly_zero) + ultimately show ?thesis by (intro conjI) metis+ + next + case False + obtain p q where pq_def: "(p,q) = long_division\<^sub>C R f g" + by (metis surj_pair) + obtain u v s where uvs_def: "((u,v),s) = ext_euclidean R g q" + by (metis surj_pair) + + have "(p,q) = (pdiv f g, pmod f g)" + using 1(3) unfolding pq_def by (intro long_division_c[OF assms(1)]) auto + hence p_def: "p = pdiv f g" and q_def: "q = pmod f g" by auto + have p_carr: "p \ carrier ?P" and q_carr: "q \ carrier ?P" + using 1(3) long_division_closed[OF carrier_is_subfield] unfolding p_def q_def by auto + + have "length g > 0" using False by auto + hence len_q: "length q < length g" using long_division_c_length pq_def by (metis snd_conv) + have s_eq: "s = g \\<^bsub>?P\<^esub> u \\<^bsub>?P\<^esub> q \\<^bsub>?P\<^esub> v" + and s_div_g: "s pdivides\<^bsub>ring_of R\<^esub> g" + and s_div_q: "s pdivides\<^bsub>ring_of R\<^esub> q" + and suv_carr: "{s,u,v} \ carrier ?P" + and s_zero_iff: "s = [] \ g = [] \ q = []" + using ind[OF len_q uvs_def _] q_carr 1(3) by auto + + have "r = ((v,u +\<^sub>C\<^bsub>poly R\<^esub> (-\<^sub>C\<^bsub>poly R\<^esub> (p *\<^sub>C\<^bsub>poly R\<^esub> v))),s)" unfolding 1(2) using False + by (subst ext_euclidean.simps) (simp add: pq_def[symmetric] uvs_def[symmetric]) + also have "... = ((v, u \\<^bsub>?P\<^esub> (p \\<^bsub>?P\<^esub> v)), s)" using p_carr suv_carr domain_cD[OF d_poly] + unfolding a_minus_def ring_of_poly[OF ring_c] by (intro arg_cong2[where f="Pair"] refl) simp + finally have r_def: "r = ((v, u \\<^bsub>?P\<^esub> (p \\<^bsub>?P\<^esub> v)), s)" by simp + + have "snd r = g \\<^bsub>?P\<^esub> u \\<^bsub>?P\<^esub> q \\<^bsub>?P\<^esub> v" unfolding r_def s_eq by simp + also have "... = g \\<^bsub>?P\<^esub> u \\<^bsub>?P\<^esub> (f \\<^bsub>?P\<^esub> g \\<^bsub>?P\<^esub> p) \\<^bsub>?P\<^esub> v" + using 1(3) p_carr q_carr suv_carr + by (subst pdiv_pmod[OF carrier_is_subfield, of "f" "g"]) + (simp_all add:p_def[symmetric] q_def[symmetric], algebra) + also have "... = f \\<^bsub>?P\<^esub> v \\<^bsub>?P\<^esub> g \\<^bsub>?P\<^esub> (u \\<^bsub>?P\<^esub> ((p \\<^bsub>?P\<^esub> v)))" + using 1(3) p_carr q_carr suv_carr by simp algebra + finally have r1: "snd r = f \\<^bsub>?P\<^esub> fst (fst r) \\<^bsub>?P\<^esub> g \\<^bsub>?P\<^esub> snd (fst r)" + unfolding r_def by simp + have "pmod f s = pmod (g \\<^bsub>?P\<^esub> p \\<^bsub>?P\<^esub> q) s" using 1(3) + by (subst pdiv_pmod[OF carrier_is_subfield, of "f" "g"]) + (simp_all add:p_def[symmetric] q_def[symmetric]) + also have "... = pmod (g \\<^bsub>?P\<^esub> p) s \\<^bsub>?P\<^esub> pmod q s" + using 1(3) p_carr q_carr suv_carr + by (subst long_division_add[OF carrier_is_subfield]) simp_all + also have "... = pmod (pmod g s \\<^bsub>?P\<^esub> p) s \\<^bsub>?P\<^esub> []" + using 1(3) p_carr q_carr suv_carr s_div_q + by (intro arg_cong2[where f="(\\<^bsub>?P\<^esub>)"] pmod_mult_left) + (simp_all add: pmod_zero_iff_pdivides[OF carrier_is_subfield]) + also have "... = pmod (\\<^bsub>?P\<^esub> \\<^bsub>?P\<^esub> p) s \\<^bsub>?P\<^esub> \\<^bsub>?P\<^esub>" unfolding univ_poly_zero + using 1(3) p_carr q_carr suv_carr s_div_g by (intro arg_cong2[where f="(\\<^bsub>?P\<^esub>)"] + arg_cong2[where f="(\\<^bsub>?P\<^esub>)"] arg_cong2[where f="pmod"]) + (simp_all add: pmod_zero_iff_pdivides[OF carrier_is_subfield]) + also have "... = pmod \\<^bsub>?P\<^esub> s" + using p_carr suv_carr long_division_closed[OF carrier_is_subfield] by simp + also have "... = []" unfolding univ_poly_zero + using suv_carr long_division_zero(2)[OF carrier_is_subfield] by simp + finally have "pmod f s = []" by simp + hence r2: "snd r pdivides\<^bsub>ring_of R\<^esub> f" using suv_carr 1(3) unfolding r_def + by (subst pmod_zero_iff_pdivides[OF carrier_is_subfield,symmetric]) simp_all + have r3: "snd r pdivides\<^bsub>ring_of R\<^esub> g" unfolding r_def using s_div_g by auto + have r4: "{snd r, fst (fst r), snd (fst r)} \ carrier ?P" + using suv_carr p_carr unfolding r_def by simp_all + have r5: "f = [] \ g = []" if "snd r = []" + proof - + have r5_a: "g = [] \ q = []" using that s_zero_iff unfolding r_def by simp + hence "pmod f [] = []" unfolding q_def by auto + hence "f = []" using pmod_def by simp + thus ?thesis using r5_a by auto + qed + + show ?thesis using r1 r2 r3 r4 r5 by (intro conjI) metis+ + qed + qed + thus ?T1 ?T2 ?T3 ?T4 ?T5 using assms by auto +qed + +end \ No newline at end of file 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,1037 +1,1041 @@ 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). +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 +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$ +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 +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. +\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. +\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. +\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) + 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) + 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) + 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}" + 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}" + 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) + 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 + 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" + 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" + 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 "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) + 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 ring) degree_add: + "degree (f \\<^bsub>K[X]\<^esub> g) \ max (degree f) (degree g)" + unfolding univ_poly_add by (intro poly_add_degree) + lemma (in domain) degree_mult: - assumes "subring K R" + 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) + 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: +lemma (in domain) pow_non_zero: "x \ carrier R \ x \ \ \ x [^] (n :: nat) \ \" - using integral by (induction n, auto) + using integral by (induction n, auto) lemma (in domain) degree_pow: - assumes "subring K R" + 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])" + 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])" + 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 "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)) = + 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) + 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) + 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 assms(1,2) univ_poly_carrier using subringE(1)[OF assms(1)] polynomial_incl by blast - have b:"set g \ carrier R" + 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.. + also have "... = + (\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 \ \" + 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])" + 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" + 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])" + 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>)" + 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" + 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)" + 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 + 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] + 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" + 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 + 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" + 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) + 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] + 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) + 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 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>" + 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" + have "map h \ carrier ?R \ carrier ?S" using t_1 by simp - moreover have "?hinv x \ carrier ?R" + moreover have "?hinv x \ carrier ?R" if "x \ carrier ?S" for x proof (cases "x = []") case True - then show ?thesis + then show ?thesis by (simp add:univ_poly_carrier[symmetric] polynomial_def) next case False - have set_x: "set x \ h ` carrier R" + 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 + 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] + 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>" + 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" + 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 + 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 + moreover have "?hinv (map h x) = x" if "x \ carrier ?R" for x proof - - have set_x: "set x \ carrier R" + have set_x: "set x \ carrier R" using that unfolding univ_poly_carrier[symmetric] unfolding polynomial_def by auto - have "?hinv (map h x) = + 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" + moreover have "map h (?hinv x) = x" if "x \ carrier ?S" for x proof - - have set_x: "set x \ h ` carrier R" + 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) = + 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) + 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)] + 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 "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 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" + 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) = + 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 "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)" + 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" + 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) + 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" + 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 "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)" + 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 "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" + 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)" + 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 \ + 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 "... \ + 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 "... \ + 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 "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" + 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 \ + 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 \ + 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 \ + 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 \ + 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 "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)" + 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))" + 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: + 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 "... \ + 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 "... \ + 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 "\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 + show ?thesis using assms(1) ring_hom_memE[OF assms(3)] - by (intro ring_hom_memI, auto) + 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: +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)" + 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" + 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 + using y_def unfolding FactRing_def A_RCOSETS_def' by auto qed - show "J <+>\<^bsub>R\<^esub> x \\<^bsub>R Quot I\<^esub> y = + 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)" + 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" + 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 + 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)" + 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)" + also have "... = + [mod J:] ((J <+>\<^bsub>R\<^esub> I) +> x1) \ ((J <+>\<^bsub>R\<^esub> I) +> y1)" using a by simp - also have "... = + 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 = + 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" + 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 + 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 = + 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 "... = + 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))" + 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) +> \" + 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>" + 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" + 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 "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) + 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) = + 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: +lemma (in field) f_comm_group_1: assumes "x \ carrier R" "y \ carrier R" assumes "x \ \" "y \ \" assumes "x \ y = \" - shows "False" + 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) + 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) + 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) + 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) + 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) + 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 +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/Formal_Polynomial_Derivatives.thy b/thys/Finite_Fields/Formal_Polynomial_Derivatives.thy --- a/thys/Finite_Fields/Formal_Polynomial_Derivatives.thy +++ b/thys/Finite_Fields/Formal_Polynomial_Derivatives.thy @@ -1,414 +1,414 @@ section \Formal Derivatives\label{sec:pderiv}\ theory Formal_Polynomial_Derivatives imports "HOL-Algebra.Polynomial_Divisibility" "Ring_Characteristic" begin -definition pderiv ("pderiv\") where +definition pderiv ("pderiv\") where "pderiv\<^bsub>R\<^esub> x = ring.normalize R ( map (\i. int_embed R i \\<^bsub>R\<^esub> ring.coeff R x i) (rev [1.. carrier (K[X])" shows "coeff f i \ K" proof - have "coeff f i \ set f \ {\}" using coeff_img(3) by auto also have "... \ K \ {\}" using assms(2) univ_poly_carrier polynomial_incl by blast - also have "... \ K" + also have "... \ K" using subringE[OF assms(1)] by simp finally show ?thesis by simp qed lemma pderiv_carr: assumes "subring K R" assumes "f \ carrier (K[X])" shows "pderiv f \ carrier (K[X])" proof - have "int_embed R i \ coeff f i \ K" for i - using coeff_range[OF assms] int_embed_range[OF assms(1)] + using coeff_range[OF assms] int_embed_range[OF assms(1)] using subringE[OF assms(1)] by simp hence "polynomial K (pderiv f)" unfolding pderiv_def by (intro normalize_gives_polynomial, auto) thus ?thesis using univ_poly_carrier by auto qed lemma pderiv_coeff: assumes "subring K R" assumes "f \ carrier (K[X])" shows "coeff (pderiv f) k = int_embed R (Suc k) \ coeff f (Suc k)" (is "?lhs = ?rhs") proof (cases "k + 1 < length f") case True define j where "j = length f - k - 2" - define d where + define d where "d = map (\i. int_embed R i \ coeff f i) (rev [1.. coeff f (length f - j - 1)" using b e unfolding d_def by simp also have "... = ?rhs" using f by simp finally show ?thesis by simp next case False hence "Suc k \ length f" by simp hence a:"coeff f (Suc k) = \" using coeff_img by blast have b:"coeff (pderiv f) k = \" unfolding pderiv_def normalize_coeff[symmetric] using False by (intro coeff_length, simp) - show ?thesis - using int_embed_range[OF carrier_is_subring] by (simp add:a b) + show ?thesis + using int_embed_range[OF carrier_is_subring] by (simp add:a b) qed lemma pderiv_const: assumes "degree x = 0" shows "pderiv x = \\<^bsub>K[X]\<^esub>" proof (cases "length x = 0") case True then show ?thesis by (simp add:univ_poly_zero pderiv_def) next case False hence "length x = 1" using assms by linarith - then obtain y where "x = [y]" by (cases x, auto) + then obtain y where "x = [y]" by (cases x, auto) then show ?thesis by (simp add:univ_poly_zero pderiv_def) qed lemma pderiv_var: shows "pderiv X = \\<^bsub>K[X]\<^esub>" unfolding var_def pderiv_def by (simp add:univ_poly_one int_embed_def) lemma pderiv_zero: shows "pderiv \\<^bsub>K[X]\<^esub> = \\<^bsub>K[X]\<^esub>" unfolding pderiv_def univ_poly_zero by simp lemma pderiv_add: assumes "subring K R" assumes [simp]: "f \ carrier (K[X])" "g \ carrier (K[X])" shows "pderiv (f \\<^bsub>K[X]\<^esub> g) = pderiv f \\<^bsub>K[X]\<^esub> pderiv g" (is "?lhs = ?rhs") proof - interpret p: ring "(K[X])" using univ_poly_is_ring[OF assms(1)] by simp let ?n = "(\i. int_embed R i)" have a[simp]:"?n k \ carrier R" for k using int_embed_range[OF carrier_is_subring] by auto have b[simp]:"coeff f k \ carrier R" if "f \ carrier (K[X])" for k f using coeff_range[OF assms(1)] that using subringE(1)[OF assms(1)] by auto have "coeff ?lhs i = coeff ?rhs i" for i proof - have "coeff ?lhs i = ?n (i+1) \ coeff (f \\<^bsub>K [X]\<^esub> g) (i+1)" by (simp add: pderiv_coeff[OF assms(1)]) also have "... = ?n (i+1) \ (coeff f (i+1) \ coeff g (i+1))" by (subst coeff_add[OF assms], simp) - also have "... = ?n (i+1) \ coeff f (i+1) + also have "... = ?n (i+1) \ coeff f (i+1) \ int_embed R (i+1) \ coeff g (i+1)" by (subst r_distr, simp_all) also have "... = coeff (pderiv f) i \ coeff (pderiv g) i" by (simp add: pderiv_coeff[OF assms(1)]) also have "... = coeff (pderiv f \\<^bsub>K [X]\<^esub> pderiv g) i" - using pderiv_carr[OF assms(1)] - by (subst coeff_add[OF assms(1)], auto) + using pderiv_carr[OF assms(1)] + by (subst coeff_add[OF assms(1)], auto) finally show ?thesis by simp qed hence "coeff ?lhs = coeff ?rhs" by auto thus "?lhs = ?rhs" using pderiv_carr[OF assms(1)] by (subst coeff_iff_polynomial_cond[where K="K"]) (simp_all add:univ_poly_carrier)+ qed lemma pderiv_inv: assumes "subring K R" assumes [simp]: "f \ carrier (K[X])" shows "pderiv (\\<^bsub>K[X]\<^esub> f) = \\<^bsub>K[X]\<^esub> pderiv f" (is "?lhs = ?rhs") proof - interpret p: cring "(K[X])" using univ_poly_is_cring[OF assms(1)] by simp have "pderiv (\\<^bsub>K[X]\<^esub> f) = pderiv (\\<^bsub>K[X]\<^esub> f) \\<^bsub>K[X]\<^esub> \\<^bsub>K[X]\<^esub>" using pderiv_carr[OF assms(1)] by (subst p.r_zero, simp_all) - also have "... = pderiv (\\<^bsub>K[X]\<^esub> f) \\<^bsub>K[X]\<^esub> (pderiv f \\<^bsub>K[X]\<^esub> pderiv f)" + also have "... = pderiv (\\<^bsub>K[X]\<^esub> f) \\<^bsub>K[X]\<^esub> (pderiv f \\<^bsub>K[X]\<^esub> pderiv f)" using pderiv_carr[OF assms(1)] by simp - also have "... = pderiv (\\<^bsub>K[X]\<^esub> f) \\<^bsub>K[X]\<^esub> pderiv f \\<^bsub>K[X]\<^esub> pderiv f" + also have "... = pderiv (\\<^bsub>K[X]\<^esub> f) \\<^bsub>K[X]\<^esub> pderiv f \\<^bsub>K[X]\<^esub> pderiv f" using pderiv_carr[OF assms(1)] unfolding a_minus_def by (simp add:p.a_assoc) - also have "... = pderiv (\\<^bsub>K[X]\<^esub> f \\<^bsub>K[X]\<^esub> f) \\<^bsub>K[X]\<^esub> pderiv f" + also have "... = pderiv (\\<^bsub>K[X]\<^esub> f \\<^bsub>K[X]\<^esub> f) \\<^bsub>K[X]\<^esub> pderiv f" by (subst pderiv_add[OF assms(1)], simp_all) also have "... = pderiv \\<^bsub>K[X]\<^esub> \\<^bsub>K[X]\<^esub> pderiv f" by (subst p.l_neg, simp_all) also have "... = \\<^bsub>K[X]\<^esub> \\<^bsub>K[X]\<^esub> pderiv f" by (subst pderiv_zero, simp) also have "... = \\<^bsub>K[X]\<^esub> pderiv f" unfolding a_minus_def using pderiv_carr[OF assms(1)] by (subst p.l_zero, simp_all) finally show "pderiv (\\<^bsub>K[X]\<^esub> f) = \\<^bsub>K[X]\<^esub> pderiv f" by simp qed lemma coeff_mult: assumes "subring K R" assumes "f \ carrier (K[X])" "g \ carrier (K[X])" - shows "coeff (f \\<^bsub>K[X]\<^esub> g) i = + shows "coeff (f \\<^bsub>K[X]\<^esub> g) i = (\ k \ {..i}. (coeff f) k \ (coeff g) (i - k))" proof - have a:"set f \ carrier R" - using assms(1,2) univ_poly_carrier + using assms(1,2) univ_poly_carrier using subringE(1)[OF assms(1)] polynomial_incl by blast - have b:"set g \ carrier R" + 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_mult poly_mult_coeff[OF a b] by simp qed lemma pderiv_mult: assumes "subring K R" assumes [simp]: "f \ carrier (K[X])" "g \ carrier (K[X])" - shows "pderiv (f \\<^bsub>K[X]\<^esub> g) = - pderiv f \\<^bsub>K[X]\<^esub> g \\<^bsub>K[X]\<^esub> f \\<^bsub>K[X]\<^esub> pderiv g" + shows "pderiv (f \\<^bsub>K[X]\<^esub> g) = + pderiv f \\<^bsub>K[X]\<^esub> g \\<^bsub>K[X]\<^esub> f \\<^bsub>K[X]\<^esub> pderiv g" (is "?lhs = ?rhs") proof - interpret p: cring "(K[X])" using univ_poly_is_cring[OF assms(1)] by simp let ?n = "(\i. int_embed R i)" - have a[simp]:"?n k \ carrier R" for k + have a[simp]:"?n k \ carrier R" for k using int_embed_range[OF carrier_is_subring] by auto have b[simp]:"coeff f k \ carrier R" if "f \ carrier (K[X])" for k f - using coeff_range[OF assms(1)] + using coeff_range[OF assms(1)] using subringE(1)[OF assms(1)] that by auto have "coeff ?lhs i = coeff ?rhs i" for i proof - have "coeff ?lhs i = ?n (i+1) \ coeff (f \\<^bsub>K [X]\<^esub> g) (i+1)" using assms(2,3) by (simp add: pderiv_coeff[OF assms(1)]) - also have "... = ?n (i+1) \ + also have "... = ?n (i+1) \ (\k \ {..i+1}. coeff f k \ (coeff g (i + 1 - k)))" by (subst coeff_mult[OF assms], simp) - also have "... = + also have "... = (\k \ {..i+1}. ?n (i+1) \ (coeff f k \ coeff g (i + 1 - k)))" - by (intro finsum_rdistr, simp_all add:Pi_def) - also have "... = + by (intro finsum_rdistr, simp_all add:Pi_def) + also have "... = (\k \ {..i+1}. ?n k \ (coeff f k \ coeff g (i + 1 - k)) \ - ?n (i+1-k) \ (coeff f k \ coeff g (i + 1 - k)))" + ?n (i+1-k) \ (coeff f k \ coeff g (i + 1 - k)))" using int_embed_add[symmetric] of_nat_diff - by (intro finsum_cong') - (simp_all add:l_distr[symmetric] of_nat_diff) - also have "... = + by (intro finsum_cong') + (simp_all add:l_distr[symmetric] of_nat_diff) + also have "... = (\k \ {..i+1}. ?n k \ coeff f k \ coeff g (i + 1 - k) \ - coeff f k \ (?n (i+1-k) \ coeff g (i + 1 - k)))" + coeff f k \ (?n (i+1-k) \ coeff g (i + 1 - k)))" using Pi_def a b m_assoc m_comm by (intro finsum_cong' arg_cong2[where f="(\)"], simp_all) - also have "... = + also have "... = (\k \ {..i+1}. ?n k \ coeff f k \ coeff g (i+1-k)) \ - (\k \ {..i+1}. coeff f k \ (?n (i+1-k) \ coeff g (i+1-k)))" - by (subst finsum_addf[symmetric], simp_all add:Pi_def) - also have "... = + (\k \ {..i+1}. coeff f k \ (?n (i+1-k) \ coeff g (i+1-k)))" + by (subst finsum_addf[symmetric], simp_all add:Pi_def) + also have "... = (\k\insert 0 {1..i+1}. ?n k \ coeff f k \ coeff g (i+1-k)) \ - (\k\insert (i+1) {..i}. coeff f k \ (?n (i+1-k) \ coeff g (i+1-k)))" + (\k\insert (i+1) {..i}. coeff f k \ (?n (i+1-k) \ coeff g (i+1-k)))" using subringE(1)[OF assms(1)] by (intro arg_cong2[where f="(\)"] finsum_cong') (auto simp:set_eq_iff) - also have "... = + also have "... = (\k \ {1..i+1}. ?n k \ coeff f k \ coeff g (i+1-k)) \ - (\k \ {..i}. coeff f k \ (?n (i+1-k) \ coeff g (i+1-k)))" + (\k \ {..i}. coeff f k \ (?n (i+1-k) \ coeff g (i+1-k)))" by (subst (1 2) finsum_insert, auto simp add:int_embed_zero) - also have "... = + also have "... = (\k \ Suc ` {..i}. ?n k \ coeff f (k) \ coeff g (i+1-k)) \ - (\k \ {..i}. coeff f k \ (?n (i+1-k) \ coeff g (i+1-k)))" + (\k \ {..i}. coeff f k \ (?n (i+1-k) \ coeff g (i+1-k)))" by (intro arg_cong2[where f="(\)"] finsum_cong') (simp_all add:Pi_def atMost_atLeast0) - also have "... = + also have "... = (\k \ {..i}. ?n (k+1) \ coeff f (k+1) \ coeff g (i-k)) \ - (\k \ {..i}. coeff f k \ (?n (i+1-k) \ coeff g (i+1-k)))" + (\k \ {..i}. coeff f k \ (?n (i+1-k) \ coeff g (i+1-k)))" by (subst finsum_reindex, auto) - also have "... = + also have "... = (\k \ {..i}. coeff (pderiv f) k \ coeff g (i-k)) \ - (\k \ {..i}. coeff f k \ coeff (pderiv g) (i-k))" + (\k \ {..i}. coeff f k \ coeff (pderiv g) (i-k))" using Suc_diff_le - by (subst (1 2) pderiv_coeff[OF assms(1)]) + by (subst (1 2) pderiv_coeff[OF assms(1)]) (auto intro!: finsum_cong') - also have "... = + also have "... = coeff (pderiv f \\<^bsub>K[X]\<^esub> g) i \ coeff (f \\<^bsub>K[X]\<^esub> pderiv g) i" using pderiv_carr[OF assms(1)] by (subst (1 2) coeff_mult[OF assms(1)], auto) - also have "... = coeff ?rhs i" + also have "... = coeff ?rhs i" using pderiv_carr[OF assms(1)] by (subst coeff_add[OF assms(1)], auto) finally show ?thesis by simp qed hence "coeff ?lhs = coeff ?rhs" by auto thus "?lhs = ?rhs" using pderiv_carr[OF assms(1)] by (subst coeff_iff_polynomial_cond[where K="K"]) (simp_all add:univ_poly_carrier) qed lemma pderiv_pow: assumes "n > (0 :: nat)" assumes "subring K R" assumes [simp]: "f \ carrier (K[X])" - shows "pderiv (f [^]\<^bsub>K[X]\<^esub> n) = - int_embed (K[X]) n \\<^bsub>K[X]\<^esub> f [^]\<^bsub>K[X]\<^esub> (n-1) \\<^bsub>K[X]\<^esub> pderiv f" + shows "pderiv (f [^]\<^bsub>K[X]\<^esub> n) = + int_embed (K[X]) n \\<^bsub>K[X]\<^esub> f [^]\<^bsub>K[X]\<^esub> (n-1) \\<^bsub>K[X]\<^esub> pderiv f" (is "?lhs = ?rhs") proof - interpret p: cring "(K[X])" using univ_poly_is_cring[OF assms(2)] by simp let ?n = "\n. int_embed (K[X]) n" - have [simp]: "?n i \ carrier (K[X])" for i + have [simp]: "?n i \ carrier (K[X])" for i using p.int_embed_range[OF p.carrier_is_subring] by simp obtain m where n_def: "n = Suc m" using assms(1) lessE by blast - have "pderiv (f [^]\<^bsub>K[X]\<^esub> (m+1)) = - ?n (m+1) \\<^bsub>K[X]\<^esub> f [^]\<^bsub>K[X]\<^esub> m \\<^bsub>K[X]\<^esub> pderiv f" + have "pderiv (f [^]\<^bsub>K[X]\<^esub> (m+1)) = + ?n (m+1) \\<^bsub>K[X]\<^esub> f [^]\<^bsub>K[X]\<^esub> m \\<^bsub>K[X]\<^esub> pderiv f" proof (induction m) case 0 - then show ?case - using pderiv_carr[OF assms(2)] assms(3) + then show ?case + using pderiv_carr[OF assms(2)] assms(3) using p.int_embed_one by simp next case (Suc m) - have "pderiv (f [^]\<^bsub>K [X]\<^esub> (Suc m + 1)) = + have "pderiv (f [^]\<^bsub>K [X]\<^esub> (Suc m + 1)) = pderiv (f [^]\<^bsub>K [X]\<^esub> (m+1) \\<^bsub>K[X]\<^esub> f) " by simp - also have "... = - pderiv (f [^]\<^bsub>K [X]\<^esub> (m+1)) \\<^bsub>K[X]\<^esub> f \\<^bsub>K[X]\<^esub> + also have "... = + pderiv (f [^]\<^bsub>K [X]\<^esub> (m+1)) \\<^bsub>K[X]\<^esub> f \\<^bsub>K[X]\<^esub> f [^]\<^bsub>K [X]\<^esub> (m+1) \\<^bsub>K[X]\<^esub> pderiv f" using assms(3) by (subst pderiv_mult[OF assms(2)], auto) - also have "... = - (?n (m+1) \\<^bsub>K [X]\<^esub> f [^]\<^bsub>K [X]\<^esub> m \\<^bsub>K [X]\<^esub> pderiv f) \\<^bsub>K[X]\<^esub> f + also have "... = + (?n (m+1) \\<^bsub>K [X]\<^esub> f [^]\<^bsub>K [X]\<^esub> m \\<^bsub>K [X]\<^esub> pderiv f) \\<^bsub>K[X]\<^esub> f \\<^bsub>K[X]\<^esub> f [^]\<^bsub>K [X]\<^esub> (m+1) \\<^bsub>K[X]\<^esub> pderiv f" - by (subst Suc(1), simp) - also have - "... = ?n (m+1) \\<^bsub>K[X]\<^esub> (f [^]\<^bsub>K [X]\<^esub> (m+1) \\<^bsub>K[X]\<^esub> pderiv f) + by (subst Suc(1), simp) + also have + "... = ?n (m+1) \\<^bsub>K[X]\<^esub> (f [^]\<^bsub>K [X]\<^esub> (m+1) \\<^bsub>K[X]\<^esub> pderiv f) \\<^bsub>K[X]\<^esub> \\<^bsub>K [X]\<^esub> \\<^bsub>K[X]\<^esub> (f [^]\<^bsub>K [X]\<^esub> (m+1) \\<^bsub>K[X]\<^esub> pderiv f)" using assms(3) pderiv_carr[OF assms(2)] apply (intro arg_cong2[where f="(\\<^bsub>K[X]\<^esub>)"]) apply (simp add:p.m_assoc) apply (simp add:p.m_comm) by simp - also have - "... = (?n (m+1) \\<^bsub>K[X]\<^esub> \\<^bsub>K [X]\<^esub>) \\<^bsub>K [X]\<^esub> + also have + "... = (?n (m+1) \\<^bsub>K[X]\<^esub> \\<^bsub>K [X]\<^esub>) \\<^bsub>K [X]\<^esub> (f [^]\<^bsub>K [X]\<^esub> (m+1) \\<^bsub>K [X]\<^esub> pderiv f)" - using assms(3) pderiv_carr[OF assms(2)] + using assms(3) pderiv_carr[OF assms(2)] by (subst p.l_distr[symmetric], simp_all) - also have "... = - (\\<^bsub>K [X]\<^esub> \\<^bsub>K[X]\<^esub> ?n (m+1)) \\<^bsub>K [X]\<^esub> + also have "... = + (\\<^bsub>K [X]\<^esub> \\<^bsub>K[X]\<^esub> ?n (m+1)) \\<^bsub>K [X]\<^esub> (f [^]\<^bsub>K [X]\<^esub> (m+1) \\<^bsub>K [X]\<^esub> pderiv f)" using assms(3) pderiv_carr[OF assms(2)] by (subst p.a_comm, simp_all) - also have "... = ?n (1+ Suc m) + also have "... = ?n (1+ Suc m) \\<^bsub>K [X]\<^esub> f [^]\<^bsub>K [X]\<^esub> (Suc m) \\<^bsub>K [X]\<^esub> pderiv f" using assms(3) pderiv_carr[OF assms(2)] of_nat_add apply (subst (2) of_nat_add, subst p.int_embed_add) - by (simp add:p.m_assoc p.int_embed_one) + by (simp add:p.m_assoc p.int_embed_one) finally show ?case by simp qed thus "?thesis" using n_def by auto qed lemma pderiv_var_pow: assumes "n > (0::nat)" assumes "subring K R" - shows "pderiv (X [^]\<^bsub>K[X]\<^esub> n) = + shows "pderiv (X [^]\<^bsub>K[X]\<^esub> n) = int_embed (K[X]) n \\<^bsub>K[X]\<^esub> X [^]\<^bsub>K[X]\<^esub> (n-1)" proof - interpret p: cring "(K[X])" using univ_poly_is_cring[OF assms(2)] by simp have [simp]: "int_embed (K[X]) i \ carrier (K[X])" for i using p.int_embed_range[OF p.carrier_is_subring] by simp show ?thesis - using var_closed[OF assms(2)] + using var_closed[OF assms(2)] using pderiv_var[where K="K"] pderiv_carr[OF assms(2)] by (subst pderiv_pow[OF assms(1,2)], simp_all) qed lemma int_embed_consistent_with_poly_of_const: assumes "subring K R" shows "int_embed (K[X]) m = poly_of_const (int_embed R m)" proof - define K' where "K' = R \ carrier := K \" interpret p: cring "(K[X])" using univ_poly_is_cring[OF assms] by simp interpret d: domain "K'" unfolding K'_def using assms(1) subdomainI' subdomain_is_domain by simp interpret h: ring_hom_ring "K'" "K[X]" "poly_of_const" unfolding K'_def using canonical_embedding_ring_hom[OF assms(1)] by simp define n where "n=nat (abs m)" have a1: "int_embed (K[X]) (int n) = poly_of_const (int_embed K' n)" proof (induction n) case 0 then show ?case by (simp add:d.int_embed_zero p.int_embed_zero) next case (Suc n) then show ?case using d.int_embed_closed d.int_embed_add d.int_embed_one by (simp add:p.int_embed_add p.int_embed_one) qed also have "... = poly_of_const (int_embed R n)" unfolding K'_def using int_embed_consistent[OF assms] by simp - finally have a: + finally have a: "int_embed (K[X]) (int n) = poly_of_const (int_embed R (int n))" by simp - have "int_embed (K[X]) (-(int n)) = + have "int_embed (K[X]) (-(int n)) = poly_of_const (int_embed K' (- (int n)))" using d.int_embed_closed a1 by (simp add: p.int_embed_inv d.int_embed_inv) also have "... = poly_of_const (int_embed R (- (int n)))" unfolding K'_def using int_embed_consistent[OF assms] by simp finally have b: "int_embed (K[X]) (-int n) = poly_of_const (int_embed R (-int n))" by simp show ?thesis using a b n_def by (cases "m \ 0", simp, simp) qed end end diff --git a/thys/Finite_Fields/Monic_Polynomial_Factorization.thy b/thys/Finite_Fields/Monic_Polynomial_Factorization.thy --- a/thys/Finite_Fields/Monic_Polynomial_Factorization.thy +++ b/thys/Finite_Fields/Monic_Polynomial_Factorization.thy @@ -1,658 +1,658 @@ section \Factorization into Monic Polynomials\label{sec:monic}\ theory Monic_Polynomial_Factorization imports Finite_Fields_Factorization_Ext Formal_Polynomial_Derivatives begin hide_const Factorial_Ring.multiplicity hide_const Factorial_Ring.irreducible lemma (in domain) finprod_mult_of: assumes "finite A" assumes "\x. x \ A \ f x \ carrier (mult_of R)" shows "finprod R f A = finprod (mult_of R) f A" - using assms by (induction A rule:finite_induct, auto) + using assms by (induction A rule:finite_induct, auto) lemma (in ring) finite_poly: assumes "subring K R" assumes "finite K" - shows + shows "finite {f. f \ carrier (K[X]) \ degree f = n}" (is "finite ?A") "finite {f. f \ carrier (K[X]) \ degree f \ n}" (is "finite ?B") proof - have "finite {f. set f \ K \ length f \ n + 1}" (is "finite ?C") using assms(2) finite_lists_length_le by auto moreover have "?B \ ?C" - by (intro subsetI) + by (intro subsetI) (auto simp:univ_poly_carrier[symmetric] polynomial_def) - ultimately show a: "finite ?B" + ultimately show a: "finite ?B" using finite_subset by auto - moreover have "?A \ ?B" + moreover have "?A \ ?B" by (intro subsetI, simp) ultimately show "finite ?A" using finite_subset by auto qed -definition pmult :: "_ \ 'a list \ 'a list \ nat" ("pmult\") - where "pmult\<^bsub>R\<^esub> d p = multiplicity (mult_of (poly_ring R)) d p" +definition pmult :: "_ \ 'a list \ 'a list \ nat" ("pmult\") + where "pmult\<^bsub>R\<^esub> d p = multiplicity (mult_of (poly_ring R)) d p" definition monic_poly :: "_ \ 'a list \ bool" - where "monic_poly R f = + where "monic_poly R f = (f \ [] \ lead_coeff f = \\<^bsub>R\<^esub> \ f \ carrier (poly_ring R))" definition monic_irreducible_poly where "monic_irreducible_poly R f = (monic_poly R f \ pirreducible\<^bsub>R\<^esub> (carrier R) f)" abbreviation "m_i_p \ monic_irreducible_poly" locale polynomial_ring = field + fixes K assumes polynomial_ring_assms: "subfield K R" begin lemma K_subring: "subring K R" using polynomial_ring_assms subfieldE(1) by auto abbreviation P where "P \ K[X]" text \This locale is used to specialize the following lemmas for a fixed coefficient ring. It can be introduced in a context as an intepretation to be able to use the following specialized lemmas. Because it is not (and should not) introduced as a sublocale it has no lasting effect -for the field locale itself.\ +for the field locale itself.\ lemmas poly_mult_lead_coeff = poly_mult_lead_coeff[OF K_subring] and degree_add_distinct = degree_add_distinct[OF K_subring] and coeff_add = coeff_add[OF K_subring] and var_closed = var_closed[OF K_subring] and degree_prod = degree_prod[OF _ K_subring] and degree_pow = degree_pow[OF K_subring] and pirreducible_degree = pirreducible_degree[OF polynomial_ring_assms] -and degree_one_imp_pirreducible = +and degree_one_imp_pirreducible = degree_one_imp_pirreducible[OF polynomial_ring_assms] and var_pow_closed = var_pow_closed[OF K_subring] and var_pow_carr = var_pow_carr[OF K_subring] and univ_poly_a_inv_degree = univ_poly_a_inv_degree[OF K_subring] and var_pow_degree = var_pow_degree[OF K_subring] and pdivides_zero = pdivides_zero[OF K_subring] and pdivides_imp_degree_le = pdivides_imp_degree_le[OF K_subring] and var_carr = var_carr[OF K_subring] and rupture_eq_0_iff = rupture_eq_0_iff[OF polynomial_ring_assms] and rupture_is_field_iff_pirreducible = rupture_is_field_iff_pirreducible[OF polynomial_ring_assms] and rupture_surj_hom = rupture_surj_hom[OF K_subring] and canonical_embedding_ring_hom = canonical_embedding_ring_hom[OF K_subring] and rupture_surj_norm_is_hom = rupture_surj_norm_is_hom[OF K_subring] and rupture_surj_as_eval = rupture_surj_as_eval[OF K_subring] and eval_cring_hom = eval_cring_hom[OF K_subring] and coeff_range = coeff_range[OF K_subring] and finite_poly = finite_poly[OF K_subring] and int_embed_consistent_with_poly_of_const = int_embed_consistent_with_poly_of_const[OF K_subring] and pderiv_var_pow = pderiv_var_pow[OF _ K_subring] and pderiv_add = pderiv_add[OF K_subring] and pderiv_inv = pderiv_inv[OF K_subring] and pderiv_mult = pderiv_mult[OF K_subring] and pderiv_pow = pderiv_pow[OF _ K_subring] and pderiv_carr = pderiv_carr[OF K_subring] sublocale p:principal_domain "poly_ring R" by (simp add: carrier_is_subfield univ_poly_is_principal) end context field begin -interpretation polynomial_ring "R" "carrier R" +interpretation polynomial_ring "R" "carrier R" using carrier_is_subfield field_axioms by (simp add:polynomial_ring_def polynomial_ring_axioms_def) -lemma pdivides_mult_r: - assumes "a \ carrier (mult_of P)" - assumes "b \ carrier (mult_of P)" +lemma pdivides_mult_r: + assumes "a \ carrier (mult_of P)" + assumes "b \ carrier (mult_of P)" assumes "c \ carrier (mult_of P)" - shows "a \\<^bsub>P\<^esub> c pdivides b \\<^bsub>P\<^esub> c \ a pdivides b" + shows "a \\<^bsub>P\<^esub> c pdivides b \\<^bsub>P\<^esub> c \ a pdivides b" (is "?lhs \ ?rhs") proof - have a:"b \\<^bsub>P\<^esub> c \ carrier P - {\\<^bsub>P\<^esub>}" using assms p.mult_of.m_closed by force have b:"a \\<^bsub>P\<^esub> c \ carrier P" using assms by simp have c:"b \ carrier P - {\\<^bsub>P\<^esub>}" using assms p.mult_of.m_closed by force have d:"a \ carrier P" using assms by simp have "?lhs \ a \\<^bsub>P\<^esub> c divides\<^bsub>mult_of P\<^esub> b \\<^bsub>P\<^esub> c" unfolding pdivides_def using p.divides_imp_divides_mult a b by (meson divides_mult_imp_divides) also have "... \ a divides\<^bsub>mult_of P\<^esub> b" using p.mult_of.divides_mult_r[OF assms] by simp also have "... \ ?rhs" unfolding pdivides_def using p.divides_imp_divides_mult c d by (meson divides_mult_imp_divides) finally show ?thesis by simp qed lemma lead_coeff_carr: assumes "x \ carrier (mult_of P)" shows "lead_coeff x \ carrier R - {\}" proof (cases x) case Nil then show ?thesis using assms by (simp add:univ_poly_zero) next case (Cons a list) hence a: "polynomial (carrier R) (a # list)" using assms univ_poly_carrier by auto have "lead_coeff x = a" using Cons by simp also have "a \ carrier R - {\}" using lead_coeff_not_zero a by simp finally show ?thesis by simp qed lemma lead_coeff_poly_of_const: assumes "r \ \" shows "lead_coeff (poly_of_const r) = r" using assms by (simp add:poly_of_const_def) lemma lead_coeff_mult: assumes "f \ carrier (mult_of P)" assumes "g \ carrier (mult_of P)" shows "lead_coeff (f \\<^bsub>P\<^esub> g) = lead_coeff f \ lead_coeff g" - unfolding univ_poly_mult using assms + unfolding univ_poly_mult using assms using univ_poly_carrier[where R="R" and K="carrier R"] by (subst poly_mult_lead_coeff) (simp_all add:univ_poly_zero) lemma monic_poly_carr: assumes "monic_poly R f" shows "f \ carrier P" using assms unfolding monic_poly_def by simp -lemma monic_poly_add_distinct: +lemma monic_poly_add_distinct: assumes "monic_poly R f" assumes "g \ carrier P" "degree g < degree f" shows "monic_poly R (f \\<^bsub>P\<^esub> g)" proof (cases "g \ \\<^bsub>P\<^esub>") case True define n where "n = degree f" have "f \ carrier P - {\\<^bsub>P\<^esub>}" using assms(1) univ_poly_zero unfolding monic_poly_def by auto hence "degree (f \\<^bsub>P\<^esub> g) = max (degree f) (degree g)" using assms(2,3) True by (subst degree_add_distinct, simp_all) also have "... = degree f" using assms(3) by simp finally have b: "degree (f \\<^bsub>P\<^esub> g) = n" unfolding n_def by simp moreover have "n > 0" using assms(3) unfolding n_def by simp ultimately have "degree (f \\<^bsub>P\<^esub> g) \ degree ([])" by simp hence a:"f \\<^bsub>P\<^esub> g \ []" by auto have "degree [] = 0" by simp also have "... < degree f" using assms(3) by simp finally have "degree f \ degree []" by simp hence c: "f \ []" by auto - have d: "length g \ n" - using assms(3) unfolding n_def by simp + have d: "length g \ n" + using assms(3) unfolding n_def by simp have "lead_coeff (f \\<^bsub>P\<^esub> g) = coeff (f \\<^bsub>P\<^esub> g) n" using a b by (cases "f \\<^bsub>P\<^esub> g", auto) - also have "... = coeff f n \ coeff g n" + also have "... = coeff f n \ coeff g n" using monic_poly_carr assms - by (subst coeff_add, auto) + by (subst coeff_add, auto) also have "... = lead_coeff f \ coeff g n" using c unfolding n_def by (cases "f", auto) also have "... = \ \ \" - using assms(1) unfolding monic_poly_def + using assms(1) unfolding monic_poly_def unfolding subst coeff_length[OF d] by simp also have "... = \" by simp finally have "lead_coeff (f \\<^bsub>P\<^esub> g) = \" by simp moreover have "f \\<^bsub>P\<^esub> g \ carrier P" using monic_poly_carr assms by simp ultimately show ?thesis using a unfolding monic_poly_def by auto next case False then show ?thesis using assms monic_poly_carr by simp qed lemma monic_poly_one: "monic_poly R \\<^bsub>P\<^esub>" proof - have "\\<^bsub>P\<^esub> \ carrier P" by simp thus ?thesis by (simp add:univ_poly_one monic_poly_def) qed lemma monic_poly_var: "monic_poly R X" proof - have "X \ carrier P" using var_closed by simp thus ?thesis by (simp add:var_def monic_poly_def) qed lemma monic_poly_carr_2: assumes "monic_poly R f" shows "f \ carrier (mult_of P)" using assms unfolding monic_poly_def by (simp add:univ_poly_zero) lemma monic_poly_mult: assumes "monic_poly R f" assumes "monic_poly R g" shows "monic_poly R (f \\<^bsub>P\<^esub> g)" proof - have "lead_coeff (f \\<^bsub>P\<^esub> g) = lead_coeff f \\<^bsub>R\<^esub> lead_coeff g" using assms monic_poly_carr_2 by (subst lead_coeff_mult) auto also have "... = \" using assms unfolding monic_poly_def by simp finally have "lead_coeff (f \\<^bsub>P\<^esub> g) = \\<^bsub>R\<^esub>" by simp moreover have "(f \\<^bsub>P\<^esub> g) \ carrier (mult_of P)" using monic_poly_carr_2 assms by blast ultimately show ?thesis by (simp add:monic_poly_def univ_poly_zero) qed lemma monic_poly_pow: assumes "monic_poly R f" shows "monic_poly R (f [^]\<^bsub>P\<^esub> (n::nat))" using assms monic_poly_one monic_poly_mult by (induction n, auto) lemma monic_poly_prod: assumes "finite A" assumes "\x. x \ A \ monic_poly R (f x)" shows "monic_poly R (finprod P f A)" - using assms + using assms proof (induction A rule:finite_induct) case empty then show ?case by (simp add:monic_poly_one) next case (insert x F) - have a: "f \ F \ carrier P" + have a: "f \ F \ carrier P" using insert monic_poly_carr by simp - have b: "f x \ carrier P" + have b: "f x \ carrier P" using insert monic_poly_carr by simp have "monic_poly R (f x \\<^bsub>P\<^esub> finprod P f F)" using insert by (intro monic_poly_mult) auto thus ?case using insert a b by (subst p.finprod_insert, auto) qed lemma monic_poly_not_assoc: assumes "monic_poly R f" assumes "monic_poly R g" assumes "f \\<^bsub>(mult_of P)\<^esub> g" shows "f = g" proof - obtain u where u_def: "f = g \\<^bsub>P\<^esub> u" "u \ Units (mult_of P)" using p.mult_of.associatedD2 assms monic_poly_carr_2 by blast hence "u \ Units P" by simp then obtain v where v_def: "u = [v]" "v \ \\<^bsub>R\<^esub>" "v \ carrier R" using univ_poly_carrier_units by auto have "\ = lead_coeff f" using assms(1) by (simp add:monic_poly_def) also have "... = lead_coeff (g \\<^bsub>P\<^esub> u)" by (simp add:u_def) also have "... = lead_coeff g \ lead_coeff u" using assms(2) monic_poly_carr_2 v_def u_def(2) - by (subst lead_coeff_mult, auto simp add:univ_poly_zero) + by (subst lead_coeff_mult, auto simp add:univ_poly_zero) also have "... = lead_coeff g \ v" using v_def by simp also have "... = v" using assms(2) v_def(3) by (simp add:monic_poly_def) finally have "\ = v" by simp - hence "u = \\<^bsub>P\<^esub>" + hence "u = \\<^bsub>P\<^esub>" using v_def by (simp add:univ_poly_one) thus "f = g" using u_def assms monic_poly_carr by simp qed lemma monic_poly_span: assumes "x \ carrier (mult_of P)" "irreducible (mult_of P) x" shows "\y. monic_irreducible_poly R y \ x \\<^bsub>(mult_of P)\<^esub> y" proof - define z where "z = poly_of_const (inv (lead_coeff x))" define y where "y = x \\<^bsub>P\<^esub> z" have x_carr: "x \ carrier (mult_of P)" using assms by simp - hence lx_ne_0: "lead_coeff x \ \" - and lx_unit: "lead_coeff x \ Units R" + hence lx_ne_0: "lead_coeff x \ \" + and lx_unit: "lead_coeff x \ Units R" using lead_coeff_carr[OF x_carr] by (auto simp add:field_Units) - have lx_inv_ne_0: "inv (lead_coeff x) \ \" - using lx_unit + have lx_inv_ne_0: "inv (lead_coeff x) \ \" + using lx_unit by (metis Units_closed Units_r_inv r_null zero_not_one) - have lx_inv_carr: "inv (lead_coeff x) \ carrier R" + have lx_inv_carr: "inv (lead_coeff x) \ carrier R" using lx_unit by simp have "z \ carrier P" using lx_inv_carr poly_of_const_over_carrier unfolding z_def by auto - moreover have "z \ \\<^bsub>P\<^esub>" + moreover have "z \ \\<^bsub>P\<^esub>" using lx_inv_ne_0 by (simp add:z_def poly_of_const_def univ_poly_zero) ultimately have z_carr: "z \ carrier (mult_of P)" by simp have z_unit: "z \ Units (mult_of P)" using lx_inv_ne_0 lx_inv_carr by (simp add:univ_poly_carrier_units z_def poly_of_const_def) - have y_exp: "y = x \\<^bsub>(mult_of P)\<^esub> z" + have y_exp: "y = x \\<^bsub>(mult_of P)\<^esub> z" by (simp add:y_def) - hence y_carr: "y \ carrier (mult_of P)" + hence y_carr: "y \ carrier (mult_of P)" using x_carr z_carr p.mult_of.m_closed by simp have "irreducible (mult_of P) y" unfolding y_def using assms z_unit z_carr by (intro p.mult_of.irreducible_prod_rI, auto) - moreover have "lead_coeff y = \\<^bsub>R\<^esub>" + moreover have "lead_coeff y = \\<^bsub>R\<^esub>" unfolding y_def using x_carr z_carr lx_inv_ne_0 lx_unit by (simp add: lead_coeff_mult z_def lead_coeff_poly_of_const) hence "monic_poly R y" using y_carr unfolding monic_poly_def - by (simp add:univ_poly_zero) + by (simp add:univ_poly_zero) ultimately have "monic_irreducible_poly R y" using p.irreducible_mult_imp_irreducible y_carr by (simp add:monic_irreducible_poly_def ring_irreducible_def) - moreover have "y \\<^bsub>(mult_of P)\<^esub> x" + moreover have "y \\<^bsub>(mult_of P)\<^esub> x" by (intro p.mult_of.associatedI2[OF z_unit] y_def x_carr) hence "x \\<^bsub>(mult_of P)\<^esub> y" using x_carr y_carr by (simp add:p.mult_of.associated_sym) ultimately show ?thesis by auto qed lemma monic_polys_are_canonical_irreducibles: "canonical_irreducibles (mult_of P) {d. monic_irreducible_poly R d}" (is "canonical_irreducibles (mult_of P) ?S") proof - - have sp_1: - "?S \ {x \ carrier (mult_of P). irreducible (mult_of P) x}" + have sp_1: + "?S \ {x \ carrier (mult_of P). irreducible (mult_of P) x}" unfolding monic_irreducible_poly_def ring_irreducible_def using monic_poly_carr - by (intro subsetI, simp add: p.irreducible_imp_irreducible_mult) - have sp_2: "x = y" - if "x \ ?S" "y \ ?S" "x \\<^bsub>(mult_of P)\<^esub> y" for x y + by (intro subsetI, simp add: p.irreducible_imp_irreducible_mult) + have sp_2: "x = y" + if "x \ ?S" "y \ ?S" "x \\<^bsub>(mult_of P)\<^esub> y" for x y using that monic_poly_not_assoc by (simp add:monic_irreducible_poly_def) - have sp_3: "\y \ ?S. x \\<^bsub>(mult_of P)\<^esub> y" + have sp_3: "\y \ ?S. x \\<^bsub>(mult_of P)\<^esub> y" if "x \ carrier (mult_of P)" "irreducible (mult_of P) x" for x using that monic_poly_span by simp thus ?thesis using sp_1 sp_2 sp_3 unfolding canonical_irreducibles_def by simp qed lemma assumes "monic_poly R a" - shows factor_monic_poly: - "a = (\\<^bsub>P\<^esub>d\{d. monic_irreducible_poly R d \ pmult d a > 0}. + shows factor_monic_poly: + "a = (\\<^bsub>P\<^esub>d\{d. monic_irreducible_poly R d \ pmult d a > 0}. d [^]\<^bsub>P\<^esub> pmult d a)" (is "?lhs = ?rhs") - and factor_monic_poly_fin: - "finite {d. monic_irreducible_poly R d \ pmult d a > 0}" + and factor_monic_poly_fin: + "finite {d. monic_irreducible_poly R d \ pmult d a > 0}" proof - let ?S = "{d. monic_irreducible_poly R d}" let ?T = "{d. monic_irreducible_poly R d \ pmult d a > 0}" let ?mip = "monic_irreducible_poly R" - have sp_4: "a \ carrier (mult_of P)" + have sp_4: "a \ carrier (mult_of P)" using assms monic_poly_carr_2 unfolding monic_irreducible_poly_def by simp - have b_1: "x \ carrier (mult_of P)" if "?mip x" for x + have b_1: "x \ carrier (mult_of P)" if "?mip x" for x using that monic_poly_carr_2 unfolding monic_irreducible_poly_def by simp have b_2:"irreducible (mult_of P) x" if "?mip x" for x using that - unfolding monic_irreducible_poly_def ring_irreducible_def + unfolding monic_irreducible_poly_def ring_irreducible_def by (simp add: monic_poly_carr p.irreducible_imp_irreducible_mult) have b_3:"x \ carrier P" if "?mip x" for x using that monic_poly_carr unfolding monic_irreducible_poly_def by simp - have a_carr: "a \ carrier P - {\\<^bsub>P\<^esub>}" + have a_carr: "a \ carrier P - {\\<^bsub>P\<^esub>}" using sp_4 by simp - have "?T = {d. ?mip d \ multiplicity (mult_of P) d a > 0}" + have "?T = {d. ?mip d \ multiplicity (mult_of P) d a > 0}" by (simp add:pmult_def) also have "... = {d \ ?S. multiplicity (mult_of P) d a > 0}" using p.mult_of.multiplicity_gt_0_iff[OF b_1 b_2 sp_4] by (intro order_antisym subsetI, auto) finally have t:"?T = {d \ ?S. multiplicity (mult_of P) d a > 0}" by simp show fin_T: "finite ?T" unfolding t using p.mult_of.split_factors(1) [OF monic_polys_are_canonical_irreducibles] using sp_4 by auto have a:"x [^]\<^bsub>P\<^esub> (n::nat) \ carrier (mult_of P)" if "?mip x" for x n proof - have "monic_poly R (x [^]\<^bsub>P\<^esub> n)" - using that monic_poly_pow + using that monic_poly_pow unfolding monic_irreducible_poly_def by auto thus ?thesis using monic_poly_carr_2 by simp qed - have "?lhs \\<^bsub>(mult_of P)\<^esub> - finprod (mult_of P) + have "?lhs \\<^bsub>(mult_of P)\<^esub> + finprod (mult_of P) (\d. d [^]\<^bsub>(mult_of P)\<^esub> (multiplicity (mult_of P) d a)) ?T" - unfolding t + unfolding t by (intro p.mult_of.split_factors(2) [OF monic_polys_are_canonical_irreducibles sp_4]) - also have "... = + also have "... = finprod (mult_of P) (\d. d [^]\<^bsub>P\<^esub> (multiplicity (mult_of P) d a)) ?T" by (simp add:nat_pow_mult_of) also have "... = ?rhs" using fin_T a - by (subst p.finprod_mult_of, simp_all add:pmult_def) + by (subst p.finprod_mult_of, simp_all add:pmult_def) finally have "?lhs \\<^bsub>(mult_of P)\<^esub> ?rhs" by simp - moreover have "monic_poly R ?rhs" - using fin_T + moreover have "monic_poly R ?rhs" + using fin_T by (intro monic_poly_prod monic_poly_pow) - (auto simp:monic_irreducible_poly_def) + (auto simp:monic_irreducible_poly_def) ultimately show "?lhs = ?rhs" using monic_poly_not_assoc assms monic_irreducible_poly_def by blast qed lemma degree_monic_poly': assumes "monic_poly R f" - shows - "sum' (\d. pmult d f * degree d) {d. monic_irreducible_poly R d} = - degree f" + shows + "sum' (\d. pmult d f * degree d) {d. monic_irreducible_poly R d} = + degree f" proof - let ?mip = "monic_irreducible_poly R" - have b: "d \ carrier P - {\\<^bsub>P\<^esub>}" if "?mip d" for d + have b: "d \ carrier P - {\\<^bsub>P\<^esub>}" if "?mip d" for d using that monic_poly_carr_2 unfolding monic_irreducible_poly_def by simp have a: "d [^]\<^bsub>P\<^esub> n \ carrier P - {\\<^bsub>P\<^esub>}" if "?mip d" for d and n :: "nat" using b that monic_poly_pow - unfolding monic_irreducible_poly_def + unfolding monic_irreducible_poly_def by (simp add: p.pow_non_zero) - have "degree f = + have "degree f = degree (\\<^bsub>P\<^esub>d\{d. ?mip d \ pmult d f > 0}. d [^]\<^bsub>P\<^esub> pmult d f)" using factor_monic_poly[OF assms(1)] by simp - also have "... = + also have "... = (\i\{d. ?mip d \ 0 < pmult d f}. degree (i [^]\<^bsub>P\<^esub> pmult i f))" using a assms(1) by (subst degree_prod[OF factor_monic_poly_fin]) (simp_all add:Pi_def) - also have "... = + also have "... = (\i\{d. ?mip d \ 0 < pmult d f}. degree i * pmult i f)" using b degree_pow by (intro sum.cong, auto) - also have "... = + also have "... = (\d\{d. ?mip d \ 0 < pmult d f}. pmult d f * degree d)" by (simp add:mult.commute) - also have "... = + also have "... = sum' (\d. pmult d f * degree d) {d. ?mip d \ 0 < pmult d f}" using sum.eq_sum factor_monic_poly_fin[OF assms(1)] by simp also have "... = sum' (\d. pmult d f * degree d) {d. ?mip d}" by (intro sum.mono_neutral_cong_left' subsetI, auto) finally show ?thesis by simp qed lemma monic_poly_min_degree: assumes "monic_irreducible_poly R f" shows "degree f \ 1" using assms unfolding monic_irreducible_poly_def monic_poly_def by (intro pirreducible_degree) auto lemma degree_one_monic_poly: - "monic_irreducible_poly R f \ degree f = 1 \ + "monic_irreducible_poly R f \ degree f = 1 \ (\x \ carrier R. f = [\, \x])" -proof +proof assume "monic_irreducible_poly R f \ degree f = 1" hence a:"monic_poly R f" "length f = 2" unfolding monic_irreducible_poly_def by auto then obtain u v where f_def: "f = [u,v]" by (cases f, simp, cases "tl f", auto) have "u = \" using a unfolding monic_poly_def f_def by simp - moreover have "v \ carrier R" + moreover have "v \ carrier R" using a unfolding monic_poly_def univ_poly_carrier[symmetric] - unfolding polynomial_def f_def by simp + unfolding polynomial_def f_def by simp ultimately have "f = [\, \(\v)]" "(\v) \ carrier R" using a_inv_closed f_def by auto thus "(\x \ carrier R. f = [\\<^bsub>R\<^esub>, \\<^bsub>R\<^esub>x])" by auto next assume "(\x \ carrier R. f = [\, \x])" then obtain x where f_def: "f = [\,\x]" "x \ carrier R" by auto have a:"degree f = 1" using f_def(2) unfolding f_def by simp have b:"f \ carrier P" using f_def(2) unfolding univ_poly_carrier[symmetric] unfolding f_def polynomial_def by simp - have c: "pirreducible (carrier R) f" + have c: "pirreducible (carrier R) f" by (intro degree_one_imp_pirreducible a b) have d: "lead_coeff f = \" unfolding f_def by simp show "monic_irreducible_poly R f \ degree f = 1" - using a b c d + using a b c d unfolding monic_irreducible_poly_def monic_poly_def by auto qed lemma multiplicity_ge_iff: - assumes "monic_irreducible_poly R d" + assumes "monic_irreducible_poly R d" assumes "f \ carrier P - {\\<^bsub>P\<^esub>}" shows "pmult d f \ k \ d [^]\<^bsub>P\<^esub> k pdivides f" proof - - have a:"f \ carrier (mult_of P)" + have a:"f \ carrier (mult_of P)" using assms(2) by simp - have b: "d \ carrier (mult_of P)" + have b: "d \ carrier (mult_of P)" using assms(1) monic_poly_carr_2 unfolding monic_irreducible_poly_def by simp - have c: "irreducible (mult_of P) d" - using assms(1) monic_poly_carr_2 + have c: "irreducible (mult_of P) d" + using assms(1) monic_poly_carr_2 using p.irreducible_imp_irreducible_mult - unfolding monic_irreducible_poly_def + unfolding monic_irreducible_poly_def unfolding ring_irreducible_def monic_poly_def by simp have d: "d [^]\<^bsub>P\<^esub> k \ carrier P" using b by simp have "pmult d f \ k \ d [^]\<^bsub>(mult_of P)\<^esub> k divides\<^bsub>(mult_of P)\<^esub> f" unfolding pmult_def by (intro p.mult_of.multiplicity_ge_iff a b c) also have "... \ d [^]\<^bsub>P\<^esub> k pdivides\<^bsub>R\<^esub> f" using p.divides_imp_divides_mult[OF d assms(2)] - using divides_mult_imp_divides + using divides_mult_imp_divides unfolding pdivides_def nat_pow_mult_of by auto finally show ?thesis by simp qed lemma multiplicity_ge_1_iff_pdivides: assumes "monic_irreducible_poly R d" "f \ carrier P - {\\<^bsub>P\<^esub>}" shows "pmult d f \ 1 \ d pdivides f" proof - - have "d \ carrier P" + have "d \ carrier P" using assms(1) monic_poly_carr unfolding monic_irreducible_poly_def by simp thus ?thesis using multiplicity_ge_iff[OF assms, where k="1"] by simp qed - + lemma divides_monic_poly: assumes "monic_poly R f" "monic_poly R g" - assumes "\d. monic_irreducible_poly R d - \ pmult d f \ pmult d g" + assumes "\d. monic_irreducible_poly R d + \ pmult d f \ pmult d g" shows "f pdivides g" proof - - have a:"f \ carrier (mult_of P)" "g \ carrier (mult_of P)" + have a:"f \ carrier (mult_of P)" "g \ carrier (mult_of P)" using monic_poly_carr_2 assms(1,2) by auto have "f divides\<^bsub>(mult_of P)\<^esub> g" - using assms(3) unfolding pmult_def + using assms(3) unfolding pmult_def by (intro p.mult_of.divides_iff_mult_mono [OF a monic_polys_are_canonical_irreducibles]) simp - thus ?thesis + thus ?thesis unfolding pdivides_def using divides_mult_imp_divides by simp qed end lemma monic_poly_hom: assumes "monic_poly R f" assumes "h \ ring_iso R S" "domain R" "domain S" shows "monic_poly S (map h f)" proof - have c: "h \ ring_hom R S" using assms(2) ring_iso_def by auto - have e: "f \ carrier (poly_ring R)" + have e: "f \ carrier (poly_ring R)" using assms(1) unfolding monic_poly_def by simp have a:"f \ []" using assms(1) unfolding monic_poly_def by simp hence "map h f \ []" by simp moreover have "lead_coeff f = \\<^bsub>R\<^esub>" using assms(1) unfolding monic_poly_def by simp - hence "lead_coeff (map h f) = \\<^bsub>S\<^esub>" + hence "lead_coeff (map h f) = \\<^bsub>S\<^esub>" using ring_hom_one[OF c] by (simp add: hd_map[OF a]) ultimately show ?thesis using carrier_hom[OF e assms(2-4)] unfolding monic_poly_def by simp qed lemma monic_irreducible_poly_hom: assumes "monic_irreducible_poly R f" assumes "h \ ring_iso R S" "domain R" "domain S" shows "monic_irreducible_poly S (map h f)" proof - have a: "pirreducible\<^bsub>R\<^esub> (carrier R) f" "f \ carrier (poly_ring R)" "monic_poly R f" using assms(1) unfolding monic_poly_def monic_irreducible_poly_def by auto - + have "pirreducible\<^bsub>S\<^esub> (carrier S) (map h f)" - using a pirreducible_hom assms by auto + using a pirreducible_hom assms by auto moreover have "monic_poly S (map h f)" using a monic_poly_hom[OF _ assms(2,3,4)] by simp ultimately show ?thesis unfolding monic_irreducible_poly_def by simp qed end diff --git a/thys/Finite_Fields/ROOT b/thys/Finite_Fields/ROOT --- a/thys/Finite_Fields/ROOT +++ b/thys/Finite_Fields/ROOT @@ -1,19 +1,29 @@ chapter AFP session Finite_Fields = "HOL-Algebra" + - options [timeout = 600] + options [timeout = 1200] sessions + Digit_Expansions Dirichlet_Series + Executable_Randomized_Algorithms + Probabilistic_While theories Card_Irreducible_Polynomials Card_Irreducible_Polynomials_Aux Finite_Fields_Factorization_Ext Finite_Fields_Isomorphic Finite_Fields_Preliminary_Results Formal_Polynomial_Derivatives Monic_Polynomial_Factorization Ring_Characteristic Rabin_Irreducibility_Test + Rabin_Irreducibility_Test_Code + Finite_Fields_More_Bijections + Finite_Fields_Indexed_Algebra_Code + Finite_Fields_Mod_Ring_Code + Finite_Fields_Poly_Factor_Ring_Code + Finite_Fields_Poly_Ring_Code + Find_Irreducible_Poly document_files "root.tex" "root.bib" 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,344 +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].\ +(in finite fields) based on Rabin~\cite{rabin1980}.\ 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].\ +text \A more general variant 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 diff --git a/thys/Finite_Fields/Rabin_Irreducibility_Test_Code.thy b/thys/Finite_Fields/Rabin_Irreducibility_Test_Code.thy new file mode 100644 --- /dev/null +++ b/thys/Finite_Fields/Rabin_Irreducibility_Test_Code.thy @@ -0,0 +1,330 @@ +section \Executable Code for Rabin's Irreducibility Test\ + +theory Rabin_Irreducibility_Test_Code + imports + Finite_Fields_Poly_Ring_Code + Finite_Fields_Mod_Ring_Code + Rabin_Irreducibility_Test +begin + +fun pcoprime\<^sub>C :: "('a, 'b) idx_ring_scheme \ 'a list \ 'a list \ bool" + where "pcoprime\<^sub>C R f g = (length (snd (ext_euclidean R f g)) = 1)" + +declare pcoprime\<^sub>C.simps[simp del] + +lemma pcoprime_c: + assumes "field\<^sub>C R" + assumes "f \ carrier (poly_ring (ring_of R))" + assumes "g \ carrier (poly_ring (ring_of R))" + shows "pcoprime\<^sub>C R f g \ pcoprime\<^bsub>ring_of R\<^esub> f g" (is "?L = ?R") +proof (cases "f = [] \ g = []") + case True + interpret field "ring_of R" + using assms(1) unfolding field\<^sub>C_def by simp + interpret d_poly_ring: domain "poly_ring (ring_of R)" + by (rule univ_poly_is_domain[OF carrier_is_subring]) + + have "?L = False" using True by (simp add: pcoprime\<^sub>C.simps ext_euclidean.simps poly_def) + also have "... \ (length \\<^bsub>poly_ring (ring_of R)\<^esub> = 1)" by (simp add:univ_poly_zero) + also have "... \ pcoprime\<^bsub>ring_of R\<^esub> \\<^bsub>poly_ring (ring_of R)\<^esub> []" + by (subst pcoprime_zero_iff) (simp_all) + also have "... \ ?R" using True by (simp add: univ_poly_zero) + finally show ?thesis by simp +next + case False + + let ?P = "poly_ring (ring_of R)" + interpret field "ring_of R" + using assms(1) unfolding field\<^sub>C_def by simp + interpret d_poly_ring: domain "poly_ring (ring_of R)" + by (rule univ_poly_is_domain[OF carrier_is_subring]) + + obtain s u v where suv_def: "((u,v),s) = ext_euclidean R f g" by (metis surj_pair) + + have s_eq:"s = f \\<^bsub>?P\<^esub> u \\<^bsub>?P\<^esub> g \\<^bsub>?P\<^esub> v" (is "?T1") + and s_div_f: "s pdivides\<^bsub>ring_of R\<^esub> f" and s_div_g: "s pdivides\<^bsub>ring_of R\<^esub> g" (is "?T3") + and suv_carr: "{s, u, v} \ carrier ?P" + and s_nz: "s \ []" + using False suv_def[symmetric] ext_euclidean[OF assms(1,2,3)] by auto + + have "?L \ length s = 1" using suv_def[symmetric] by (simp add:pcoprime\<^sub>C.simps) + also have "... \ ?R" + unfolding pcoprime_def + proof (intro iffI impI ballI) + fix r assume len_s: "length s = 1" + assume r_carr:"r \ carrier ?P" + and "r pdivides\<^bsub>ring_of R\<^esub> f \ r pdivides\<^bsub>ring_of R\<^esub> g" + hence r_div: "pmod f r = \\<^bsub>?P\<^esub>" "pmod g r = \\<^bsub>?P\<^esub>" unfolding univ_poly_zero + using assms(2,3) pmod_zero_iff_pdivides[OF carrier_is_subfield] by auto + + have "pmod s r = pmod (f \\<^bsub>?P\<^esub> u) r \\<^bsub>?P\<^esub> pmod (g \\<^bsub>?P\<^esub> v) r" + using r_carr suv_carr assms unfolding s_eq + by (intro long_division_add[OF carrier_is_subfield]) auto + also have "... = pmod (pmod f r \\<^bsub>?P\<^esub> u) r \\<^bsub>?P\<^esub> pmod (pmod g r \\<^bsub>?P\<^esub> v) r" + using r_carr suv_carr assms by (intro arg_cong2[where f="(\\<^bsub>?P\<^esub>)"] pmod_mult_left) auto + also have "... = pmod \\<^bsub>?P\<^esub> r \\<^bsub>?P\<^esub> pmod \\<^bsub>?P\<^esub> r" + using suv_carr unfolding r_div by simp + also have "... = []" using r_carr unfolding univ_poly_zero + by (simp add: long_division_zero[OF carrier_is_subfield] univ_poly_add) + finally have "pmod s r = []" by simp + hence "r pdivides\<^bsub>ring_of R\<^esub> s" + using r_carr suv_carr pmod_zero_iff_pdivides[OF carrier_is_subfield] by auto + hence "degree r \ degree s" + using s_nz r_carr suv_carr by (intro pdivides_imp_degree_le[OF carrier_is_subring]) auto + thus "degree r = 0" using len_s by simp + next + assume "\r\carrier ?P. r pdivides\<^bsub>ring_of R\<^esub> f \ r pdivides\<^bsub>ring_of R\<^esub> g \ degree r = 0" + hence "degree s = 0" using s_div_f s_div_g suv_carr by simp + thus "length s =1" using s_nz + by (metis diff_is_0_eq diffs0_imp_equal length_0_conv less_one linorder_le_less_linear) + qed + finally show ?thesis by simp +qed + +text \The following is a fast version of @{term "pmod"} for polynomials (to a high power) that +need to be reduced, this is used for the higher order term of the Gauss polynomial.\ + +fun pmod_pow\<^sub>C :: "('a,'b) idx_ring_scheme \ 'a list \ nat \ 'a list \ 'a list" + where "pmod_pow\<^sub>C F f n g = ( + let r = (if n \ 2 then pmod_pow\<^sub>C F f (n div 2) g ^\<^sub>C\<^bsub>poly F\<^esub> 2 else 1\<^sub>C\<^bsub>poly F\<^esub>) + in pmod\<^sub>C F (r *\<^sub>C\<^bsub>poly F\<^esub> (f ^\<^sub>C\<^bsub>poly F\<^esub> (n mod 2))) g)" + +declare pmod_pow\<^sub>C.simps[simp del] + +lemma pmod_pow_c: + assumes "field\<^sub>C R" + assumes "f \ carrier (poly_ring (ring_of R))" + assumes "g \ carrier (poly_ring (ring_of R))" + shows "pmod_pow\<^sub>C R f n g = ring.pmod (ring_of R) (f [^]\<^bsub>poly_ring (ring_of R)\<^esub> n) g" +proof (induction n rule:nat_less_induct) + case (1 n) + + let ?P = "poly_ring (ring_of R)" + interpret field "ring_of R" + using assms(1) unfolding field\<^sub>C_def by simp + interpret d_poly_ring: domain "poly_ring (ring_of R)" + by (rule univ_poly_is_domain[OF carrier_is_subring]) + + have ring_c: "ring\<^sub>C R" using assms(1) unfolding field\<^sub>C_def domain\<^sub>C_def cring\<^sub>C_def by auto + have d_poly: "domain\<^sub>C (poly R)" using assms (1) unfolding field\<^sub>C_def by (intro poly_domain) auto + + have ind: "pmod_pow\<^sub>C R f m g = pmod (f [^]\<^bsub>?P\<^esub> m) g" if "m < n" for m + using 1 that by auto + + define r where "r = (if n \ 2 then pmod_pow\<^sub>C R f (n div 2) g ^\<^sub>C\<^bsub>poly R\<^esub> 2 else 1\<^sub>C\<^bsub>poly R\<^esub>)" + + have "pmod r g = pmod (f [^]\<^bsub>?P\<^esub> (n - (n mod 2))) g \ r \ carrier ?P" + proof (cases "n \ 2") + case True + hence "r = pmod_pow\<^sub>C R f (n div 2) g [^]\<^bsub>?P\<^esub> (2 :: nat)" + unfolding r_def domain_cD[OF d_poly] by (simp add:ring_of_poly[OF ring_c]) + also have "... = pmod (f [^]\<^bsub>?P\<^esub> (n div 2)) g [^]\<^bsub>?P\<^esub> (2 :: nat)" + using True by (intro arg_cong2[where f="([^]\<^bsub>?P\<^esub>)"] refl ind) auto + finally have r_alt: "r = pmod (f [^]\<^bsub>?P\<^esub> (n div 2)) g [^]\<^bsub>?P\<^esub> (2 :: nat)" + by simp + + have "pmod r g = pmod (pmod (f [^]\<^bsub>?P\<^esub> (n div 2)) g \\<^bsub>?P\<^esub> pmod (f [^]\<^bsub>?P\<^esub> (n div 2)) g) g" + unfolding r_alt using assms(2,3) long_division_closed[OF carrier_is_subfield] + by (simp add:numeral_eq_Suc) algebra + also have "... = pmod (f [^]\<^bsub>?P\<^esub> (n div 2) \\<^bsub>?P\<^esub> f [^]\<^bsub>?P\<^esub> (n div 2)) g" + using assms(2,3) by (intro pmod_mult_both[symmetric]) auto + also have "... = pmod (f [^]\<^bsub>?P\<^esub> ((n div 2)+(n div 2))) g" + using assms(2,3) by (subst d_poly_ring.nat_pow_mult) auto + also have "... = pmod (f [^]\<^bsub>?P\<^esub> (n - (n mod 2))) g" + by (intro arg_cong2[where f="pmod"] refl arg_cong2[where f="([^]\<^bsub>?P\<^esub>)"]) presburger + finally have "pmod r g = pmod (f [^]\<^bsub>?P\<^esub> (n - (n mod 2))) g" + by simp + moreover have "r \ carrier ?P" + using assms(2,3) long_division_closed[OF carrier_is_subfield] unfolding r_alt by auto + ultimately show ?thesis by auto + next + case False + hence "r = \\<^bsub>?P\<^esub>" + unfolding r_def using domain_cD[OF d_poly] ring_of_poly[OF ring_c] by simp + also have "... = f [^]\<^bsub>?P\<^esub> (0 :: nat)" by simp + also have "... = f [^]\<^bsub>?P\<^esub> (n - (n mod 2))" + using False by (intro arg_cong2[where f="([^]\<^bsub>?P\<^esub>)"] refl) auto + finally have "r = f [^]\<^bsub>?P\<^esub> (n - (n mod 2))" by simp + then show ?thesis using assms(2) by simp + qed + + hence r_exp: "pmod r g = pmod (f [^]\<^bsub>?P\<^esub> (n - (n mod 2))) g" and r_carr: "r \ carrier ?P" + by auto + + have "pmod_pow\<^sub>C R f n g = pmod\<^sub>C R (r *\<^sub>C\<^bsub>poly R\<^esub> (f ^\<^sub>C\<^bsub>poly R\<^esub> (n mod 2))) g" + by (subst pmod_pow\<^sub>C.simps) (simp add:r_def[symmetric]) + also have "... = pmod\<^sub>C R (r \\<^bsub>?P\<^esub> (f [^]\<^bsub>?P\<^esub> (n mod 2))) g" + unfolding domain_cD[OF d_poly] by (simp add:ring_of_poly[OF ring_c]) + also have "... = pmod (r \\<^bsub>?P\<^esub> (f [^]\<^bsub>?P\<^esub> (n mod 2))) g" + using r_carr assms(2,3) by (intro pmod_c[OF assms(1)]) auto + also have "... = pmod (pmod r g \\<^bsub>?P\<^esub> (f [^]\<^bsub>?P\<^esub> (n mod 2))) g" + using r_carr assms(2,3) by (intro pmod_mult_left) auto + also have "... = pmod (f [^]\<^bsub>?P\<^esub> (n - (n mod 2)) \\<^bsub>?P\<^esub> (f [^]\<^bsub>?P\<^esub> (n mod 2))) g" + using assms(2,3) unfolding r_exp by (intro pmod_mult_left[symmetric]) auto + also have "... = pmod (f [^]\<^bsub>?P\<^esub> ((n - (n mod 2)) + (n mod 2))) g" + using assms(2,3) by (intro arg_cong2[where f="pmod"] refl d_poly_ring.nat_pow_mult) auto + also have "... = pmod (f [^]\<^bsub>?P\<^esub> n) g" by simp + finally show "pmod_pow\<^sub>C R f n g = pmod (f [^]\<^bsub>?P\<^esub> n) g" by simp +qed + +text \The following function checks whether a given polynomial is coprime with the +Gauss polynomial $X^n - X$.\ + +definition pcoprime_with_gauss_poly :: "('a,'b) idx_ring_scheme \ 'a list \ nat \ bool" + where "pcoprime_with_gauss_poly F p n = + (pcoprime\<^sub>C F p (pmod_pow\<^sub>C F X\<^sub>C\<^bsub>F\<^esub> n p +\<^sub>C\<^bsub>poly F\<^esub> (-\<^sub>C\<^bsub>poly F\<^esub> pmod\<^sub>C F X\<^sub>C\<^bsub>F\<^esub> p)))" + + +definition divides_gauss_poly :: "('a,'b) idx_ring_scheme \ 'a list \ nat \ bool" + where "divides_gauss_poly F p n = + (pmod_pow\<^sub>C F X\<^sub>C\<^bsub>F\<^esub> n p +\<^sub>C\<^bsub>poly F\<^esub> (-\<^sub>C\<^bsub>poly F\<^esub> pmod\<^sub>C F X\<^sub>C\<^bsub>F\<^esub> p) = [])" + +lemma mod_gauss_poly: + assumes "field\<^sub>C R" + assumes "f \ carrier (poly_ring (ring_of R))" + shows "pmod_pow\<^sub>C R X\<^sub>C\<^bsub>R\<^esub> n f +\<^sub>C\<^bsub>poly R\<^esub> (-\<^sub>C\<^bsub>poly R\<^esub> pmod\<^sub>C R X\<^sub>C\<^bsub>R\<^esub> f) = + ring.pmod (ring_of R) (gauss_poly (ring_of R) n) f" (is "?L = ?R") +proof - + interpret field "ring_of R" + using assms(1) unfolding field\<^sub>C_def by simp + interpret d_poly_ring: domain "poly_ring (ring_of R)" + by (rule univ_poly_is_domain[OF carrier_is_subring]) + + have ring_c: "ring\<^sub>C R" using assms(1) unfolding field\<^sub>C_def domain\<^sub>C_def cring\<^sub>C_def by auto + have d_poly: "domain\<^sub>C (poly R)" using assms (1) unfolding field\<^sub>C_def by (intro poly_domain) auto + let ?P = "poly_ring (ring_of R)" + + have "?L = pmod_pow\<^sub>C R X\<^bsub>ring_of R\<^esub> n f \\<^bsub>?P\<^esub> -\<^sub>C\<^bsub>poly R\<^esub> pmod\<^sub>C R X\<^bsub>ring_of R\<^esub> f" + by (simp add: poly_var domain_cD[OF d_poly] ring_of_poly[OF ring_c]) + also have "...= pmod (X\<^bsub>ring_of R\<^esub>[^]\<^bsub>?P\<^esub> n) f\\<^bsub>?P\<^esub> -\<^sub>C\<^bsub>poly R\<^esub> pmod X\<^bsub>ring_of R\<^esub> f" + using assms var_carr[OF carrier_is_subring] by (intro refl arg_cong2[where f="(\\<^bsub>?P\<^esub>)"] + pmod_pow_c arg_cong[where f="\x. (-\<^sub>C\<^bsub>poly R\<^esub> x)"] pmod_c) auto + also have "... =pmod (X\<^bsub>ring_of R\<^esub>[^]\<^bsub>?P\<^esub> n) f\\<^bsub>?P\<^esub> pmod X\<^bsub>ring_of R\<^esub> f" + unfolding a_minus_def using assms(1,2) var_carr[OF carrier_is_subring] + ring_of_poly[OF ring_c] long_division_closed[OF carrier_is_subfield] + by (subst domain_cD[OF d_poly]) auto + also have "... = pmod (X\<^bsub>ring_of R\<^esub>[^]\<^bsub>?P\<^esub> n) f \\<^bsub>?P\<^esub> pmod (\\<^bsub>?P\<^esub> X\<^bsub>ring_of R\<^esub>) f" + using assms(2) var_carr[OF carrier_is_subring] + unfolding a_minus_def by (subst long_division_a_inv[OF carrier_is_subfield]) auto + also have " ... = pmod (gauss_poly (ring_of R) n) f" + using assms(2) var_carr[OF carrier_is_subring] var_pow_carr[OF carrier_is_subring] + unfolding gauss_poly_def a_minus_def by (subst long_division_add[OF carrier_is_subfield]) auto + finally show ?thesis by simp +qed + +lemma pcoprime_with_gauss_poly: + assumes "field\<^sub>C R" + assumes "f \ carrier (poly_ring (ring_of R))" + shows "pcoprime_with_gauss_poly R f n \ pcoprime\<^bsub>ring_of R\<^esub> (gauss_poly (ring_of R) n) f" + (is "?L = ?R") +proof - + interpret field "ring_of R" + using assms(1) unfolding field\<^sub>C_def by simp + + have "?L \ pcoprime\<^sub>C R f (pmod (gauss_poly (ring_of R) n) f)" + unfolding pcoprime_with_gauss_poly_def using assms by (subst mod_gauss_poly) auto + also have "... = pcoprime\<^bsub>ring_of R\<^esub> f (pmod (gauss_poly (ring_of R) n) f)" + using assms gauss_poly_carr long_division_closed[OF carrier_is_subfield] + by (intro pcoprime_c) auto + also have "... = pcoprime\<^bsub>ring_of R\<^esub> (gauss_poly (ring_of R) n) f" + by (intro pcoprime_step[symmetric] gauss_poly_carr assms) + finally show ?thesis by simp +qed + +lemma divides_gauss_poly: + assumes "field\<^sub>C R" + assumes "f \ carrier (poly_ring (ring_of R))" + shows "divides_gauss_poly R f n \ f pdivides\<^bsub>ring_of R\<^esub> (gauss_poly (ring_of R) n)" + (is "?L = ?R") +proof - + interpret field "ring_of R" + using assms(1) unfolding field\<^sub>C_def by simp + have "?L \ (pmod (gauss_poly (ring_of R) n) f = [])" + unfolding divides_gauss_poly_def using assms by (subst mod_gauss_poly) auto + also have "... \ ?R" + using assms gauss_poly_carr by (intro pmod_zero_iff_pdivides[OF carrier_is_subfield]) auto + finally show ?thesis + by simp +qed + + +fun rabin_test_powers :: "('a, 'b) idx_ring_enum_scheme \ nat \ nat list" + where "rabin_test_powers F n = + map (\p. idx_size F^(n div p)) (filter (\p. prime p \ p dvd n) [2..<(n+1)] )" + +text \Given a monic polynomial with coefficients over a finite field returns true, if it is +irreducible\ + +fun rabin_test :: "('a, 'b) idx_ring_enum_scheme \ 'a list \ bool" + where "rabin_test F f = ( + if degree f = 0 then + False + else (if \divides_gauss_poly F f (idx_size F^degree f) then + False + else (list_all (pcoprime_with_gauss_poly F f) (rabin_test_powers F (degree f)))))" + +declare rabin_test.simps[simp del] + +context + fixes R + assumes field_R: "field\<^sub>C R" + assumes enum_R: "enum\<^sub>C R" +begin + +interpretation finite_field "(ring_of R)" + using field_R enum_cD[OF enum_R] unfolding field\<^sub>C_def + by (simp add:finite_field_def finite_field_axioms_def) + +lemma rabin_test_powers: + assumes "n > 0" + shows "set (rabin_test_powers R n) = + {order (ring_of R)^ (n div p) | p . Factorial_Ring.prime p \ p dvd n}" + (is "?L = ?R") +proof - + let ?f = "(\x. order (ring_of R) ^ (n div x))" + + have 0:"p \ {2..n}" if "Factorial_Ring.prime p" "p dvd n" for p + using assms that by (simp add: dvd_imp_le prime_ge_2_nat) + + have "?L = ?f ` {p \ {2..n}. Factorial_Ring.prime p \ p dvd n}" + using enum_cD[OF enum_R] by auto + also have "... = ?f ` {p. Factorial_Ring.prime p \ p dvd n}" + using 0 by (intro image_cong Collect_cong) auto + also have "... = ?R" + by auto + finally show ?thesis by simp +qed + +lemma rabin_test: + assumes "monic_poly (ring_of R) f" + shows "rabin_test R f \ monic_irreducible_poly (ring_of R) f" (is "?L = ?R") +proof (cases "degree f = 0") + case True + thus ?thesis unfolding rabin_test.simps using monic_poly_min_degree by fastforce +next + case False + define N where "N = {degree f div p | p . Factorial_Ring.prime p \ p dvd degree f}" + + have f_carr: "f \ carrier (poly_ring (ring_of R))" + using assms(1) unfolding monic_poly_def by auto + + have deg_f_gt_0: "degree f > 0" + using False by auto + have rt_powers: "set (rabin_test_powers R (degree f)) = (\x. order (ring_of R)^x) ` N" + unfolding rabin_test_powers[OF deg_f_gt_0] N_def by auto + + have "?L \ divides_gauss_poly R f (idx_size R ^ degree f) \ + (\n \ set (rabin_test_powers R (degree f)). (pcoprime_with_gauss_poly R f n))" + using False by (simp add: list_all_def rabin_test.simps del:rabin_test_powers.simps) + also have "... \ f pdivides\<^bsub>ring_of R\<^esub> (gauss_poly (ring_of R) (order (ring_of R) ^ degree f)) + \ (\n \ N. pcoprime\<^bsub>ring_of R\<^esub> (gauss_poly (ring_of R) (order (ring_of R) ^n)) f)" + unfolding divides_gauss_poly[OF field_R f_carr] pcoprime_with_gauss_poly[OF field_R f_carr] + rt_powers enum_cD[OF enum_R] by simp + also have "... \ ?R" + using False unfolding N_def by (intro rabin_irreducibility_condition[symmetric] assms(1)) auto + finally show ?thesis by simp +qed + +end + +end \ No newline at end of file diff --git a/thys/Finite_Fields/Ring_Characteristic.thy b/thys/Finite_Fields/Ring_Characteristic.thy --- a/thys/Finite_Fields/Ring_Characteristic.thy +++ b/thys/Finite_Fields/Ring_Characteristic.thy @@ -1,1016 +1,1016 @@ section \Characteristic of Rings\label{sec:ring_char}\ theory Ring_Characteristic - imports + imports "Finite_Fields_Factorization_Ext" - "HOL-Algebra.IntRing" + "HOL-Algebra.IntRing" "HOL-Algebra.Embedded_Algebras" begin locale finite_field = field + assumes finite_carrier: "finite (carrier R)" begin lemma finite_field_min_order: "order R > 1" proof (rule ccontr) assume a:"\(1 < order R)" have "{\\<^bsub>R\<^esub>,\\<^bsub>R\<^esub>} \ carrier R" by auto hence "card {\\<^bsub>R\<^esub>,\\<^bsub>R\<^esub>} \ card (carrier R)" using card_mono finite_carrier by blast also have "... \ 1" using a by (simp add:order_def) finally have "card {\\<^bsub>R\<^esub>,\\<^bsub>R\<^esub>} \ 1" by blast thus "False" by simp qed lemma (in finite_field) order_pow_eq_self: assumes "x \ carrier R" shows "x [^] (order R) = x" proof (cases "x = \") case True have "order R > 0" using assms(1) order_gt_0_iff_finite finite_carrier by simp - then obtain n where n_def:"order R = Suc n" + then obtain n where n_def:"order R = Suc n" using lessE by blast - have "x [^] (order R) = \" + have "x [^] (order R) = \" unfolding n_def using True by (subst nat_pow_Suc, simp) thus ?thesis using True by simp next case False have x_carr:"x \ carrier (mult_of R)" using False assms by simp - have carr_non_empty: "card (carrier R) > 0" + have carr_non_empty: "card (carrier R) > 0" using order_gt_0_iff_finite finite_carrier unfolding order_def by simp have "x [^] (order R) = x [^]\<^bsub>mult_of R\<^esub> (order R)" by (simp add:nat_pow_mult_of) also have "... = x [^]\<^bsub>mult_of R\<^esub> (order (mult_of R)+1)" using carr_non_empty unfolding order_def by (intro arg_cong[where f="\t. x [^]\<^bsub>mult_of R\<^esub> t"]) (simp) also have "... = x" using x_carr by (simp add:mult_of.pow_order_eq_1) finally show "x [^] (order R) = x" by simp qed lemma (in finite_field) order_pow_eq_self': assumes "x \ carrier R" shows "x [^] (order R ^ d) = x" proof (induction d) case 0 then show ?case using assms by simp next case (Suc d) have "x [^] order R ^ (Suc d) = x [^] (order R ^ d * order R)" by (simp add:mult.commute) also have "... = (x [^] (order R ^ d)) [^] order R" using assms by (simp add: nat_pow_pow) also have "... = (x [^] (order R ^ d))" using order_pow_eq_self assms by simp also have "... = x" using Suc by simp finally show ?case by simp qed end lemma finite_fieldI: assumes "field R" assumes "finite (carrier R)" shows "finite_field R" using assms unfolding finite_field_def finite_field_axioms_def by auto lemma (in domain) finite_domain_units: assumes "finite (carrier R)" shows "Units R = carrier R - {\}" (is "?lhs = ?rhs") -proof - have "Units R \ carrier R" by (simp add:Units_def) +proof + have "Units R \ carrier R" by (simp add:Units_def) moreover have "\ \ Units R" by (meson zero_is_prime(1) primeE) ultimately show "Units R \ carrier R - {\}" by blast next have "x \ Units R" if a: "x \ carrier R - {\}" for x proof - have x_carr: "x \ carrier R" using a by blast define f where "f = (\y. y \\<^bsub>R\<^esub> x)" have "inj_on f (carrier R)" unfolding f_def by (rule inj_onI, metis DiffD1 DiffD2 a m_rcancel insertI1) hence "card (carrier R) = card (f ` carrier R)" by (metis card_image) moreover have "f ` carrier R \ carrier R" unfolding f_def by (rule image_subsetI, simp add: ring.ring_simprules x_carr) ultimately have "f ` carrier R = carrier R" using card_subset_eq assms by metis moreover have "\\<^bsub>R\<^esub> \ carrier R" by simp - ultimately have "\y \ carrier R. f y = \\<^bsub>R\<^esub>" + ultimately have "\y \ carrier R. f y = \\<^bsub>R\<^esub>" by (metis image_iff) - then obtain y - where y_carrier: "y \ carrier R" - and y_left_inv: "y \\<^bsub>R\<^esub> x = \\<^bsub>R\<^esub>" + then obtain y + where y_carrier: "y \ carrier R" + and y_left_inv: "y \\<^bsub>R\<^esub> x = \\<^bsub>R\<^esub>" using f_def by blast hence y_right_inv: "x \\<^bsub>R\<^esub> y = \\<^bsub>R\<^esub>" by (metis DiffD1 a cring_simprules(14)) show "x \ Units R" using y_carrier y_left_inv y_right_inv by (metis DiffD1 a divides_one factor_def) qed thus "?rhs \ ?lhs" by auto qed text \The following theorem can be found in Lidl and Niederreiter~\<^cite>\\Theorem 1.31\ in "lidl1986"\.\ theorem finite_domains_are_fields: assumes "domain R" assumes "finite (carrier R)" shows "finite_field R" proof - interpret domain R using assms by auto have "Units R = carrier R - {\\<^bsub>R\<^esub>}" using finite_domain_units[OF assms(2)] by simp then have "field R" by (simp add: assms(1) field.intro field_axioms.intro) thus ?thesis - using assms(2) finite_fieldI by auto + using assms(2) finite_fieldI by auto qed definition zfact_iso :: "nat \ nat \ int set" where "zfact_iso p k = Idl\<^bsub>\\<^esub> {int p} +>\<^bsub>\\<^esub> (int k)" context fixes n :: nat assumes n_gt_0: "n > 0" begin private abbreviation I where "I \ Idl\<^bsub>\\<^esub> {int n}" private lemma ideal_I: "ideal I \" by (simp add: int.genideal_ideal) lemma int_cosetI: assumes "u mod (int n) = v mod (int n)" shows "Idl\<^bsub>\\<^esub> {int n} +>\<^bsub>\\<^esub> u = Idl\<^bsub>\\<^esub> {int n} +>\<^bsub>\\<^esub> v" proof - have "u - v \ I" by (metis Idl_subset_eq_dvd assms int_Idl_subset_ideal mod_eq_dvd_iff) thus ?thesis using ideal_I int.quotient_eq_iff_same_a_r_cos by simp qed lemma zfact_iso_inj: "inj_on (zfact_iso n) {.. {.. {..\<^bsub>\\<^esub> (int x) = I +>\<^bsub>\\<^esub> (int y)" by (simp add:zfact_iso_def) hence "int x - int y \ I" by (subst int.quotient_eq_iff_same_a_r_cos[OF ideal_I], auto) hence "int x mod int n = int y mod int n" by (meson Idl_subset_eq_dvd int_Idl_subset_ideal mod_eq_dvd_iff) thus "x = y" using a by simp qed lemma zfact_iso_ran: "zfact_iso n ` {.. carrier (ZFact (int n))" - unfolding zfact_iso_def ZFact_def FactRing_simps + unfolding zfact_iso_def ZFact_def FactRing_simps using int.a_rcosetsI by auto - moreover have "x \ zfact_iso n ` {.. zfact_iso n ` {.. carrier (ZFact (int n))" for x proof - obtain y where y_def: "x = I +>\<^bsub>\\<^esub> y" using a unfolding ZFact_def FactRing_simps by auto define z where \z = nat (y mod int n)\ with n_gt_0 have z_def: \int z mod int n = y mod int n\ \z < n\ by (simp_all add: z_def nat_less_iff) have "x = I +>\<^bsub>\\<^esub> y" by (simp add:y_def) also have "... = I +>\<^bsub>\\<^esub> (int z)" by (intro int_cosetI, simp add:z_def) also have "... = zfact_iso n z" by (simp add:zfact_iso_def) finally have "x = zfact_iso n z" by simp thus "x \ zfact_iso n ` {.. 0" using assms(1) prime_gt_0_nat by simp - have "Factorial_Ring.prime (int p)" + have "Factorial_Ring.prime (int p)" using assms by simp - moreover have "finite (carrier (ZFact (int p)))" + moreover have "finite (carrier (ZFact (int p)))" using fin_zfact[OF p_gt_0] by simp ultimately show ?thesis by (intro finite_domains_are_fields ZFact_prime_is_domain, auto) qed definition int_embed :: "_ \ int \ _" where "int_embed R k = add_pow R k \\<^bsub>R\<^esub>" lemma (in ring) add_pow_consistent: fixes i :: "int" assumes "subring K R" assumes "k \ K" shows "add_pow R i k = add_pow (R \ carrier := K \) i k" (is "?lhs = ?rhs") proof - - have a:"subgroup K (add_monoid R)" + have a:"subgroup K (add_monoid R)" using assms(1) subring.axioms by auto - have "add_pow R i k = k [^]\<^bsub>add_monoid R\carrier := K\\<^esub> i" + have "add_pow R i k = k [^]\<^bsub>add_monoid R\carrier := K\\<^esub> i" using add.int_pow_consistent[OF a assms(2)] by simp also have "... = ?rhs" unfolding add_pow_def by simp finally show ?thesis by simp qed lemma (in ring) int_embed_consistent: assumes "subring K R" shows "int_embed R i = int_embed (R \ carrier := K \) i" proof - have a:"\ = \\<^bsub>R \ carrier := K \\<^esub>" by simp - have b:"\\<^bsub>R\carrier := K\\<^esub> \ K" + have b:"\\<^bsub>R\carrier := K\\<^esub> \ K" using assms subringE(3) by auto show ?thesis unfolding int_embed_def a using b add_pow_consistent[OF assms(1)] by simp qed lemma (in ring) int_embed_closed: "int_embed R k \ carrier R" unfolding int_embed_def using add.int_pow_closed by simp lemma (in ring) int_embed_range: assumes "subring K R" shows "int_embed R k \ K" proof - let ?R' = "R \ carrier := K \" interpret x:ring ?R' using subring_is_ring[OF assms] by simp have "int_embed R k = int_embed ?R' k" using int_embed_consistent[OF assms] by simp also have "... \ K" using x.int_embed_closed by simp finally show ?thesis by simp qed lemma (in ring) int_embed_zero: "int_embed R 0 = \\<^bsub>R\<^esub>" - by (simp add:int_embed_def add_pow_def) + by (simp add:int_embed_def add_pow_def) lemma (in ring) int_embed_one: "int_embed R 1 = \\<^bsub>R\<^esub>" - by (simp add:int_embed_def) + by (simp add:int_embed_def) lemma (in ring) int_embed_add: "int_embed R (x+y) = int_embed R x \\<^bsub>R\<^esub> int_embed R y" - by (simp add:int_embed_def add.int_pow_mult) + by (simp add:int_embed_def add.int_pow_mult) lemma (in ring) int_embed_inv: "int_embed R (-x) = \\<^bsub>R\<^esub> int_embed R x" (is "?lhs = ?rhs") proof - have "?lhs = int_embed R (-x) \ (int_embed R x \ int_embed R x)" using int_embed_closed by simp - also have + also have "... = int_embed R (-x) \ int_embed R x \ (\ int_embed R x)" using int_embed_closed by (subst a_minus_def, subst a_assoc, auto) also have "... = int_embed R (-x +x) \ (\ int_embed R x)" by (subst int_embed_add, simp) also have "... = ?rhs" using int_embed_closed by (simp add:int_embed_zero) finally show ?thesis by simp qed lemma (in ring) int_embed_diff: "int_embed R (x-y) = int_embed R x \\<^bsub>R\<^esub> int_embed R y" (is "?lhs = ?rhs") proof - have "?lhs = int_embed R (x + (-y))" by simp also have "... = ?rhs" by (subst int_embed_add, simp add:a_minus_def int_embed_inv) finally show ?thesis by simp qed lemma (in ring) int_embed_mult_aux: "int_embed R (x*int y) = int_embed R x \ int_embed R y" proof (induction y) case 0 then show ?case by (simp add:int_embed_closed int_embed_zero) next case (Suc y) have "int_embed R (x * int (Suc y)) = int_embed R (x + x * int y)" - by (simp add:algebra_simps) + by (simp add:algebra_simps) also have "... = int_embed R x \ int_embed R (x * int y)" by (subst int_embed_add, simp) - also have + also have "... = int_embed R x \ \ \ int_embed R x \ int_embed R y" using int_embed_closed by (subst Suc, simp) also have "... = int_embed R x \ (int_embed R 1 \ int_embed R y)" using int_embed_closed by (subst r_distr, simp_all add:int_embed_one) also have "... = int_embed R x \ int_embed R (1+int y)" by (subst int_embed_add, simp) also have "... = int_embed R x \ int_embed R (Suc y)" by simp finally show ?case by simp qed lemma (in ring) int_embed_mult: "int_embed R (x*y) = int_embed R x \\<^bsub>R\<^esub> int_embed R y" proof (cases "y \ 0") case True then obtain y' where y_def: "y = int y'" using nonneg_int_cases by auto have "int_embed R (x * y) = int_embed R (x * int y')" unfolding y_def by simp also have "... = int_embed R x \ int_embed R y'" by (subst int_embed_mult_aux, simp) also have "... = int_embed R x \ int_embed R y" unfolding y_def by simp finally show ?thesis by simp next case False - then obtain y' where y_def: "y = - int y'" + then obtain y' where y_def: "y = - int y'" by (meson nle_le nonpos_int_cases) have "int_embed R (x * y) = int_embed R (-(x * int y'))" unfolding y_def by simp also have "... = \ (int_embed R (x * int y'))" by (subst int_embed_inv, simp) also have "... = \ (int_embed R x \ int_embed R y')" by (subst int_embed_mult_aux, simp) also have "... = int_embed R x \ \ int_embed R y'" using int_embed_closed by algebra also have "... = int_embed R x \ int_embed R (-y')" by (subst int_embed_inv, simp) also have "... = int_embed R x \ int_embed R y" unfolding y_def by simp finally show ?thesis by simp qed -lemma (in ring) int_embed_ring_hom: +lemma (in ring) int_embed_ring_hom: "ring_hom_ring int_ring R (int_embed R)" -proof (rule ring_hom_ringI) +proof (rule ring_hom_ringI) show "ring int_ring" using int.ring_axioms by simp show "ring R" using ring_axioms by simp show "int_embed R x \ carrier R" if "x \ carrier \" for x using int_embed_closed by simp - show "int_embed R (x\\<^bsub>\\<^esub>y) = int_embed R x \ int_embed R y" - if "x \ carrier \" "y \ carrier \" for x y + show "int_embed R (x\\<^bsub>\\<^esub>y) = int_embed R x \ int_embed R y" + if "x \ carrier \" "y \ carrier \" for x y using int_embed_mult by simp - show "int_embed R (x\\<^bsub>\\<^esub>y) = int_embed R x \ int_embed R y" - if "x \ carrier \" "y \ carrier \" for x y + show "int_embed R (x\\<^bsub>\\<^esub>y) = int_embed R x \ int_embed R y" + if "x \ carrier \" "y \ carrier \" for x y using int_embed_add by simp show "int_embed R \\<^bsub>\\<^esub> = \" by (simp add:int_embed_one) qed abbreviation char_subring where "char_subring R \ int_embed R ` UNIV" -definition char where +definition char where "char R = card (char_subring R)" -text \This is a non-standard definition for the characteristic of a ring. +text \This is a non-standard definition for the characteristic of a ring. Commonly~\<^cite>\\Definition 1.43\ in "lidl1986"\ it is defined to be the smallest natural number $n$ such -that n-times repeated addition of any number is zero. If no such number exists then it is defined +that n-times repeated addition of any number is zero. If no such number exists then it is defined to be $0$. In the case of rings with unit elements --- not that the locale @{locale "ring"} requires unit elements --- the above definition can be simplified to the number of times the unit elements needs to be repeatedly added to reach $0$. The following three lemmas imply that the definition of the characteristic here coincides with the latter definition.\ lemma (in ring) char_bound: assumes "x > 0" assumes "int_embed R (int x) = \" shows "char R \ x" "char R > 0" proof - have "char_subring R \ int_embed R ` ({0.. UNIV" define u where "u = y div (int x)" define v where "v = y mod (int x)" have "int x > 0" using assms by simp hence y_exp: "y = u * int x + v" "v \ 0" "v < int x" unfolding u_def v_def by simp_all have "int_embed R y = int_embed R v" using int_embed_closed unfolding y_exp by (simp add:int_embed_mult int_embed_add assms(2)) also have "... \ int_embed R ` ({0.. int_embed R ` {0.. card {0.. x" by simp have "1 = card {int_embed R 0}" by simp also have "... \ card (int_embed R ` {0.. 0" by simp qed lemma (in ring) embed_char_eq_0: "int_embed R (int (char R)) = \" proof (cases "finite (char_subring R)") case True interpret h: ring_hom_ring "int_ring" R "(int_embed R)" using int_embed_ring_hom by simp define A where "A = {0..int (char R)}" have "card (int_embed R ` A) \ card (char_subring R)" by (intro card_mono[OF True] image_subsetI, simp) also have "... = char R" unfolding char_def by simp also have "... < card A" unfolding A_def by simp finally have "card (int_embed R ` A) < card A" by simp hence "\inj_on (int_embed R) A" using pigeonhole by simp - then obtain x y where xy: + then obtain x y where xy: "x \ A" "y \ A" "x \ y" "int_embed R x = int_embed R y" unfolding inj_on_def by auto define v where "v = nat (max x y - min x y)" have a:"int_embed R v = \" using xy int_embed_closed by (cases "x < y", simp_all add:int_embed_diff v_def) moreover have "v > 0" using xy by (cases "x < y", simp_all add:v_def) ultimately have "char R \ v" using char_bound by simp moreover have "v \ char R" using xy v_def A_def by (cases "x < y", simp_all) ultimately have "char R = v" by simp then show ?thesis using a by simp next case False - hence "char R = 0" + hence "char R = 0" unfolding char_def by simp then show ?thesis by (simp add:int_embed_zero) qed lemma (in ring) embed_char_eq_0_iff: fixes n :: int shows "int_embed R n = \ \ char R dvd n" proof (cases "char R > 0") case True define r where "r = n mod char R" define s where "s = n div char R" - have rs: "r < char R" "r \ 0" "n = r + s * char R" + have rs: "r < char R" "r \ 0" "n = r + s * char R" using True by (simp_all add:r_def s_def) have "int_embed R n = int_embed R r" using int_embed_closed unfolding rs(3) by (simp add: int_embed_add int_embed_mult embed_char_eq_0) moreover have "nat r < char R" using rs by simp hence "int_embed R (nat r) \ \ \ nat r = 0" using True char_bound not_less by blast hence "int_embed R r \ \ \ r = 0" using rs by simp ultimately have "int_embed R n = \ \ r = 0" using int_embed_zero by auto also have "r = 0 \ char R dvd n" using r_def by auto finally show ?thesis by simp next case False hence "char R = 0" by simp hence a:"x > 0 \ int_embed R (int x) \ \" for x using char_bound by auto have c:"int_embed R (abs x) \ \ \ int_embed R x \ \" for x using int_embed_closed by (cases "x > 0", simp, simp add:int_embed_inv) - + have "int_embed R x \ \" if b:"x \ 0" for x proof - have "nat (abs x) > 0" using b by simp hence "int_embed R (nat (abs x)) \ \" using a by blast hence "int_embed R (abs x) \ \" by simp thus ?thesis using c by simp qed - hence "int_embed R n = \ \ n = 0" + hence "int_embed R n = \ \ n = 0" using int_embed_zero by auto also have "n = 0 \ char R dvd n" using False by simp finally show ?thesis by simp qed text \This result can be found in \<^cite>\\Theorem 1.44\ in "lidl1986"\.\ lemma (in domain) characteristic_is_prime: assumes "char R > 0" shows "prime (char R)" proof (rule ccontr) have "\(char R = 1)" using embed_char_eq_0 int_embed_one by auto hence "\(char R dvd 1)" using assms(1) by simp moreover assume "\(prime (char R))" hence "\(irreducible (char R))" using irreducible_imp_prime_elem_gcd prime_elem_nat_iff by blast - ultimately obtain p q where pq_def: "p * q = char R" "p > 1" "q > 1" + ultimately obtain p q where pq_def: "p * q = char R" "p > 1" "q > 1" using assms unfolding Factorial_Ring.irreducible_def by auto have "int_embed R p \ int_embed R q = \" - using embed_char_eq_0 pq_def + using embed_char_eq_0 pq_def by (subst int_embed_mult[symmetric]) (metis of_nat_mult) hence "int_embed R p = \ \ int_embed R q = \" using integral int_embed_closed by simp hence "p*q \ p \ p*q \ q" using char_bound pq_def by auto thus "False" using pq_def(2,3) by simp qed lemma (in ring) char_ring_is_subring: "subring (char_subring R) R" proof - have "subring (int_embed R ` carrier int_ring) R" by (intro ring.carrier_is_subring int.ring_axioms - ring_hom_ring.img_is_subring[OF int_embed_ring_hom]) + ring_hom_ring.img_is_subring[OF int_embed_ring_hom]) thus ?thesis by simp qed lemma (in cring) char_ring_is_subcring: "subcring (char_subring R) R" using subcringI'[OF char_ring_is_subring] by auto lemma (in domain) char_ring_is_subdomain: "subdomain (char_subring R) R" using subdomainI'[OF char_ring_is_subring] by auto lemma image_set_eqI: assumes "\x. x \ A \ f x \ B" - assumes "\x. x \ B \ g x \ A \ f (g x) = x" + assumes "\x. x \ B \ g x \ A \ f (g x) = x" shows "f ` A = B" using assms by force text \This is the binomial expansion theorem for commutative rings.\ lemma (in cring) binomial_expansion: fixes n :: nat assumes [simp]: "x \ carrier R" "y \ carrier R" - shows "(x \ y) [^] n = - (\k \ {..n}. int_embed R (n choose k) \ x [^] k \ y [^] (n-k))" + shows "(x \ y) [^] n = + (\k \ {..n}. int_embed R (n choose k) \ x [^] k \ y [^] (n-k))" proof - define A where "A = (\k. {A. A \ {.. card A = k})" - have fin_A: "finite (A i)" for i + have fin_A: "finite (A i)" for i unfolding A_def by simp - have disj_A: "pairwise (\i j. disjnt (A i) (A j)) {..n}" + have disj_A: "pairwise (\i j. disjnt (A i) (A j)) {..n}" unfolding pairwise_def disjnt_def A_def by auto - have card_A: "B \ A i \ card B = i" if " i \ {..n}" for i B + have card_A: "B \ A i \ card B = i" if " i \ {..n}" for i B unfolding A_def by simp - have card_A2: "card (A i) = (n choose i)" if "i \ {..n}" for i + have card_A2: "card (A i) = (n choose i)" if "i \ {..n}" for i unfolding A_def using n_subsets[where A="{.. n" - if "A \ {.. {.. {..<(n::nat)}" for n A + if "A \ {..<(n::nat)}" for n A using finite_subset that by (subst card_insert_disjoint, auto) - have embed_distr: "[m] \ y = int_embed R (int m) \ y" + have embed_distr: "[m] \ y = int_embed R (int m) \ y" if "y \ carrier R" for m y unfolding int_embed_def add_pow_def using that by (simp add:add_pow_def[symmetric] int_pow_int add_pow_ldistr) - have "(x \ y) [^] n = + have "(x \ y) [^] n = (\A \ Pow {.. y [^] (n-card A))" proof (induction n) case 0 then show ?case by simp next case (Suc n) - have s1: - "insert n ` Pow {.. {.. n \ A}" - by (intro image_set_eqI[where g="\x. x \ {.. {.. n \ A}" + by (intro image_set_eqI[where g="\x. x \ {.. {.. n \ A}" + "Pow {.. {.. n \ A}" using lessThan_Suc by auto have "(x \ y) [^] Suc n = (x \ y) [^] n \ (x \ y)" by simp - also have "... = - (\A \ Pow {.. y [^] (n-card A)) \ + also have "... = + (\A \ Pow {.. y [^] (n-card A)) \ (x \ y)" by (subst Suc, simp) - also have "... = + also have "... = (\A \ Pow {.. y [^] (n-card A)) \ x \ (\A \ Pow {.. y [^] (n-card A)) \ y" by (subst r_distr, auto) - also have "... = + also have "... = (\A \ Pow {.. y [^] (n-card A) \ x) \ (\A \ Pow {.. y [^] (n-card A) \ y)" by (simp add:finsum_ldistr) - also have "... = + also have "... = (\A \ Pow {.. y [^] (n-card A)) \ (\A \ Pow {.. y [^] (n-card A+1))" - using m_assoc m_comm + using m_assoc m_comm by (intro arg_cong2[where f="(\)"] finsum_cong', auto) - also have "... = - (\A \ Pow {..A \ Pow {.. y [^] (n+1-card (insert n A))) \ (\A \ Pow {.. y [^] (n+1-card A))" using finite_subset card_bound card_insert Suc_diff_le by (intro arg_cong2[where f="(\)"] finsum_cong', simp_all) - also have "... = - (\A \ insert n ` Pow {..A \ insert n ` Pow {.. y [^] (n+1-card A)) \ (\A \ Pow {.. y [^] (n+1-card A))" - by (subst finsum_reindex, auto simp add:inj_on_def) - also have "... = - (\A \ {A. A \ {.. n \ A}. + by (subst finsum_reindex, auto simp add:inj_on_def) + also have "... = + (\A \ {A. A \ {.. n \ A}. x [^] (card A) \ y [^] (n+1-card A)) \ - (\A \ {A. A \ {.. n \ A}. + (\A \ {A. A \ {.. n \ A}. x [^] (card A) \ y [^] (n+1-card A))" by (intro arg_cong2[where f="(\)"] finsum_cong' s1 s2, simp_all) - also have "... = (\A \ - {A. A \ {.. n \ A} \ {A. A \ {.. n \ A}. + also have "... = (\A \ + {A. A \ {.. n \ A} \ {A. A \ {.. n \ A}. x [^] (card A) \ y [^] (n+1-card A))" by (subst finsum_Un_disjoint, auto) - also have "... = + also have "... = (\A \ Pow {.. y [^] (n+1-card A))" by (intro finsum_cong', auto) finally show ?case by simp qed - also have "... = + also have "... = (\A \ (\ (A ` {..n})). x [^] (card A) \ y [^] (n-card A))" using card_bound by (intro finsum_cong', auto simp add:A_def) - also have "... = + also have "... = (\ k \ {..n}. (\ A \ A k. x [^] (card A) \ y [^] (n-card A)))" using fin_A disj_A by (subst add.finprod_UN_disjoint, auto) also have "... = (\ k \ {..n}. (\ A \ A k. x [^] k \ y [^] (n-k)))" using card_A by (intro finsum_cong', auto) - also have "... = + also have "... = (\ k \ {..n}. int_embed R (card (A k)) \ x [^] k \ y [^] (n-k))" using int_embed_closed by (subst add.finprod_const, simp_all add:embed_distr m_assoc) - also have "... = + also have "... = (\ k \ {..n}. int_embed R (n choose k) \ x [^] k \ y [^] (n-k))" using int_embed_closed card_A2 by (intro finsum_cong', simp_all) finally show ?thesis by simp qed lemma bin_prime_factor: assumes "prime p" assumes "k > 0" "k < p" shows "p dvd (p choose k)" proof - - have "p dvd fact p" + have "p dvd fact p" using assms(1) prime_dvd_fact_iff by auto hence "p dvd fact k * fact (p - k) * (p choose k)" using binomial_fact_lemma assms by simp hence "p dvd fact k \ p dvd fact (p-k) \ p dvd (p choose k)" by (simp add: assms(1) prime_dvd_mult_eq_nat) thus "p dvd (p choose k)" using assms(1,2,3) prime_dvd_fact_iff by auto qed theorem (in domain) freshmans_dream: assumes "char R > 0" assumes [simp]: "x \ carrier R" "y \ carrier R" - shows "(x \ y) [^] (char R) = x [^] char R \ y [^] char R" + shows "(x \ y) [^] (char R) = x [^] char R \ y [^] char R" (is "?lhs = ?rhs") proof - have c:"prime (char R)" using assms(1) characteristic_is_prime by auto - have a:"int_embed R (char R choose i) = \" + have a:"int_embed R (char R choose i) = \" if "i \ {..char R} - {0, char R}" for i proof - have "i > 0" "i < char R" using that by auto hence "char R dvd char R choose i" using c bin_prime_factor by simp thus ?thesis using embed_char_eq_0_iff by simp qed - have "?lhs = (\k \ {..char R}. int_embed R (char R choose k) + have "?lhs = (\k \ {..char R}. int_embed R (char R choose k) \ x [^] k \ y [^] (char R-k))" using binomial_expansion[OF assms(2,3)] by simp - also have "... = (\k \ {0,char R}.int_embed R (char R choose k) + also have "... = (\k \ {0,char R}.int_embed R (char R choose k) \ x [^] k \ y [^] (char R-k))" using a int_embed_closed by (intro add.finprod_mono_neutral_cong_right, simp, simp_all) also have "... = ?rhs" using int_embed_closed assms(1) by (simp add:int_embed_one a_comm) finally show ?thesis by simp qed text \The following theorem is somtimes called Freshman's dream for obvious reasons, it can be found in Lidl and Niederreiter~\<^cite>\\Theorem 1.46\ in "lidl1986"\.\ lemma (in domain) freshmans_dream_ext: fixes m assumes "char R > 0" assumes [simp]: "x \ carrier R" "y \ carrier R" - defines "n \ char R^m" + defines "n \ char R^m" shows "(x \ y) [^] n = x [^] n \ y [^] n" (is "?lhs = ?rhs") unfolding n_def proof (induction m) case 0 then show ?case by simp next case (Suc m) - have "(x \ y) [^] (char R^(m+1)) = + have "(x \ y) [^] (char R^(m+1)) = (x \ y) [^] (char R^m * char R)" by (simp add:mult.commute) also have "... = ((x \ y) [^] (char R^m)) [^] char R" using nat_pow_pow by simp also have "... = (x [^] (char R^m) \ y [^] (char R^m)) [^] char R" by (subst Suc, simp) - also have "... = + also have "... = (x [^] (char R^m)) [^] char R \ (y [^] (char R^m)) [^] char R" by (subst freshmans_dream[OF assms(1), symmetric], simp_all) - also have "... = + also have "... = x [^] (char R^m * char R) \ y [^] (char R^m * char R)" by (simp add:nat_pow_pow) also have "... = x [^] (char R^Suc m) \ y [^] (char R^Suc m)" by (simp add:mult.commute) finally show ?case by simp qed text \The following is a generalized version of the Frobenius homomorphism. The classic version of the theorem is the case where @{term "(k::nat) = 1"}.\ theorem (in domain) frobenius_hom: assumes "char R > 0" assumes "m = char R ^ k" shows "ring_hom_cring R R (\x. x [^] m)" proof - - have a:"(x \ y) [^] m = x [^] m \ y [^] m" - if b:"x \ carrier R" "y \ carrier R" for x y + have a:"(x \ y) [^] m = x [^] m \ y [^] m" + if b:"x \ carrier R" "y \ carrier R" for x y using b nat_pow_distrib by simp have b:"(x \ y) [^] m = x [^] m \ y [^] m" - if b:"x \ carrier R" "y \ carrier R" for x y - unfolding assms(2) freshmans_dream_ext[OF assms(1) b] + if b:"x \ carrier R" "y \ carrier R" for x y + unfolding assms(2) freshmans_dream_ext[OF assms(1) b] by simp have "ring_hom_ring R R (\x. x [^] m)" - by (intro ring_hom_ringI a b ring_axioms, simp_all) + by (intro ring_hom_ringI a b ring_axioms, simp_all) thus "?thesis" using RingHom.ring_hom_cringI is_cring by blast qed lemma (in domain) char_ring_is_subfield: assumes "char R > 0" shows "subfield (char_subring R) R" proof - interpret d:domain "R \ carrier := char_subring R \" using char_ring_is_subdomain subdomain_is_domain by simp - have "finite (char_subring R)" + have "finite (char_subring R)" using char_def assms by (metis card_ge_0_finite) - hence "Units (R \ carrier := char_subring R \) + hence "Units (R \ carrier := char_subring R \) = char_subring R - {\}" using d.finite_domain_units by simp thus ?thesis using subfieldI[OF char_ring_is_subcring] by simp qed -lemma card_lists_length_eq': +lemma card_lists_length_eq': fixes A :: "'a set" - shows "card {xs. set xs \ A \ length xs = n} = card A ^ n" + shows "card {xs. set xs \ A \ length xs = n} = card A ^ n" proof (cases "finite A") case True then show ?thesis using card_lists_length_eq by auto next case False hence inf_A: "infinite A" by simp show ?thesis proof (cases "n = 0") case True hence "card {xs. set xs \ A \ length xs = n} = card {([] :: 'a list)}" by (intro arg_cong[where f="card"], auto simp add:set_eq_iff) also have "... = 1" by simp also have "... = card A^n" using True inf_A by simp - finally show ?thesis by simp + finally show ?thesis by simp next case False - hence "inj (replicate n)" + hence "inj (replicate n)" by (meson inj_onI replicate_eq_replicate) - hence "inj_on (replicate n) A" using inj_on_subset - by (metis subset_UNIV) + hence "inj_on (replicate n) A" using inj_on_subset + by (metis subset_UNIV) hence "infinite (replicate n ` A)" using inf_A finite_image_iff by auto - moreover have + moreover have "replicate n ` A \ {xs. set xs \ A \ length xs = n}" by (intro image_subsetI, auto) ultimately have "infinite {xs. set xs \ A \ length xs = n}" using infinite_super by auto hence "card {xs. set xs \ A \ length xs = n} = 0" by simp then show ?thesis using inf_A False by simp qed qed lemma (in ring) card_span: assumes "subfield K R" assumes "independent K w" assumes "set w \ carrier R" shows "card (Span K w) = card K^(length w)" proof - define A where "A = {x. set x \ K \ length x = length w}" define f where "f = (\x. combine x w)" have "x \ f ` A" if a:"x \ Span K w" for x proof - obtain y where "y \ A" "x = f y" unfolding A_def f_def using unique_decomposition[OF assms(1,2) a] by auto thus ?thesis by simp qed moreover have "f x \ Span K w" if a: "x \ A" for x using Span_eq_combine_set[OF assms(1,3)] a unfolding A_def f_def by auto ultimately have b:"Span K w = f ` A" by auto have "False" if a: "x \ A" "y \ A" "f x = f y" "x \ y" for x y proof - have "f x \ Span K w" using b a by simp - thus "False" + thus "False" using a unique_decomposition[OF assms(1,2)] unfolding f_def A_def by blast qed - hence f_inj: "inj_on f A" + hence f_inj: "inj_on f A" unfolding inj_on_def by auto have "card (Span K w) = card (f ` A)" using b by simp - also have "... = card A" by (intro card_image f_inj) + also have "... = card A" by (intro card_image f_inj) also have "... = card K^length w" unfolding A_def by (intro card_lists_length_eq') finally show ?thesis by simp qed lemma (in ring) finite_carr_imp_char_ge_0: assumes "finite (carrier R)" shows "char R > 0" proof - have "char_subring R \ carrier R" using int_embed_closed by auto hence "finite (char_subring R)" using finite_subset assms by auto hence "card (char_subring R) > 0" using card_range_greater_zero by simp - thus "char R > 0" + thus "char R > 0" unfolding char_def by simp qed lemma (in ring) char_consistent: assumes "subring H R" shows "char (R \ carrier := H \) = char R" proof - show ?thesis using int_embed_consistent[OF assms(1)] unfolding char_def by simp qed lemma (in ring_hom_ring) char_consistent: assumes "inj_on h (carrier R)" shows "char R = char S" proof - have a:"h (int_embed R (int n)) = int_embed S (int n)" for n using R.int_embed_range[OF R.carrier_is_subring] using R.int_embed_range[OF R.carrier_is_subring] using S.int_embed_one R.int_embed_one using S.int_embed_zero R.int_embed_zero using S.int_embed_add R.int_embed_add by (induction n, simp_all) have b:"h (int_embed R (-(int n))) = int_embed S (-(int n))" for n using R.int_embed_range[OF R.carrier_is_subring] using S.int_embed_range[OF S.carrier_is_subring] a by (simp add:R.int_embed_inv S.int_embed_inv) have c:"h (int_embed R n) = int_embed S n" for n proof (cases "n \ 0") case True then obtain m where "n = int m" using nonneg_int_cases by auto - then show ?thesis + then show ?thesis by (simp add:a) next case False hence "n \ 0" by simp - then obtain m where "n = -int m" + then obtain m where "n = -int m" using nonpos_int_cases by auto then show ?thesis by (simp add:b) qed have "char S = card (h ` char_subring R)" unfolding char_def image_image c by simp also have "... = card (char_subring R)" using R.int_embed_range[OF R.carrier_is_subring] - by (intro card_image inj_on_subset[OF assms(1)]) auto + by (intro card_image inj_on_subset[OF assms(1)]) auto also have "... = char R" unfolding char_def by simp finally show ?thesis by simp qed -definition char_iso :: "_ \ int set \ 'a" +definition char_iso :: "_ \ int set \ 'a" where "char_iso R x = the_elem (int_embed R ` x)" text \The function @{term "char_iso R"} denotes the isomorphism between @{term "ZFact (char R)"} and the characteristic subring.\ -lemma (in ring) char_iso: "char_iso R \ +lemma (in ring) char_iso: "char_iso R \ ring_iso (ZFact (char R)) (R\carrier := char_subring R\)" proof - interpret h: ring_hom_ring "int_ring" "R" "int_embed R" using int_embed_ring_hom by simp have "a_kernel \ R (int_embed R) = {x. int_embed R x = \}" unfolding a_kernel_def kernel_def by simp also have "... = {x. char R dvd x}" using embed_char_eq_0_iff by simp - also have "... = PIdl\<^bsub>\\<^esub> (int (char R))" + also have "... = PIdl\<^bsub>\\<^esub> (int (char R))" unfolding cgenideal_def by auto also have "... = Idl\<^bsub>\\<^esub> {int (char R)}" using int.cgenideal_eq_genideal by simp finally have a:"a_kernel \ R (int_embed R) = Idl\<^bsub>\\<^esub> {int (char R)}" by simp show "?thesis" unfolding char_iso_def ZFact_def a[symmetric] by (intro h.FactRing_iso_set_aux) qed text \The size of a finite field must be a prime power. This can be found in Ireland and Rosen~\<^cite>\\Proposition 7.1.3\ in "ireland1982"\.\ theorem (in finite_field) finite_field_order: "\n. order R = char R ^ n \ n > 0" proof - have a:"char R > 0" using finite_carr_imp_char_ge_0[OF finite_carrier] by simp let ?CR = "char_subring R" obtain v where v_def: "set v = carrier R" using finite_carrier finite_list by auto hence b:"set v \ carrier R" by auto have "carrier R = set v" using v_def by simp also have "... \ Span ?CR v" using Span_base_incl[OF char_ring_is_subfield[OF a] b] by simp finally have "carrier R \ Span ?CR v" by simp moreover have "Span ?CR v \ carrier R" using int_embed_closed v_def by (intro Span_in_carrier, auto) ultimately have Span_v: "Span ?CR v = carrier R" by simp - obtain w where w_def: - "set w \ carrier R" - "independent ?CR w" + obtain w where w_def: + "set w \ carrier R" + "independent ?CR w" "Span ?CR v = Span ?CR w" using b filter_base[OF char_ring_is_subfield[OF a]] by metis have Span_w: "Span ?CR w = carrier R" using w_def(3) Span_v by simp hence "order R = card (Span ?CR w)" by (simp add:order_def) also have "... = card ?CR^length w" by (intro card_span char_ring_is_subfield[OF a] w_def(1,2)) finally have c: "order R = char R^(length w)" by (simp add:char_def) have "length w > 0" using finite_field_min_order c by auto thus ?thesis using c by auto qed end diff --git a/thys/Finite_Fields/document/root.tex b/thys/Finite_Fields/document/root.tex --- a/thys/Finite_Fields/document/root.tex +++ b/thys/Finite_Fields/document/root.tex @@ -1,37 +1,37 @@ \documentclass[11pt,a4paper]{article} \usepackage[T1]{fontenc} \usepackage{isabelle,isabellesym} \usepackage{amssymb} \usepackage{pdfsetup} \urlstyle{rm} \isabellestyle{it} \begin{document} \title{Finite Fields} \author{Emin Karayel} \maketitle \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~\cite{ireland1982}, Lidl -and Niederreiter~\cite{lidl1986}, as well as, Rabin~\cite{rabin1980}. +The proofs are based on the books and publications from Ireland and Rosen~\cite{ireland1982}, +Rabin~\cite{rabin1980} as well as, Lidl and Niederreiter~\cite{lidl1986}. } \parindent 0pt\parskip 0.5ex \tableofcontents \input{session} \bibliographystyle{abbrv} \bibliography{root} \end{document} \ No newline at end of file