diff -r 3f9bb52082c4 -r 274b4edca859 src/HOL/Computational_Algebra/Polynomial_Factorial.thy --- a/src/HOL/Computational_Algebra/Polynomial_Factorial.thy Sun Oct 08 22:28:20 2017 +0200 +++ b/src/HOL/Computational_Algebra/Polynomial_Factorial.thy Sun Oct 08 22:28:21 2017 +0200 @@ -1,61 +1,20 @@ (* Title: HOL/Computational_Algebra/Polynomial_Factorial.thy - Author: Brian Huffman - Author: Clemens Ballarin - Author: Amine Chaieb - Author: Florian Haftmann Author: Manuel Eberl *) +section \Polynomials, fractions and rings\ + theory Polynomial_Factorial imports Complex_Main Polynomial Normalized_Fraction - Field_as_Ring begin -subsection \Various facts about polynomials\ - -lemma prod_mset_const_poly: " (\x\#A. [:f x:]) = [:prod_mset (image_mset f A):]" - by (induct A) (simp_all add: ac_simps) - -lemma irreducible_const_poly_iff: - fixes c :: "'a :: {comm_semiring_1,semiring_no_zero_divisors}" - shows "irreducible [:c:] \ irreducible c" -proof - assume A: "irreducible c" - show "irreducible [:c:]" - proof (rule irreducibleI) - fix a b assume ab: "[:c:] = a * b" - hence "degree [:c:] = degree (a * b)" by (simp only: ) - also from A ab have "a \ 0" "b \ 0" by auto - hence "degree (a * b) = degree a + degree b" by (simp add: degree_mult_eq) - finally have "degree a = 0" "degree b = 0" by auto - then obtain a' b' where ab': "a = [:a':]" "b = [:b':]" by (auto elim!: degree_eq_zeroE) - from ab have "coeff [:c:] 0 = coeff (a * b) 0" by (simp only: ) - hence "c = a' * b'" by (simp add: ab' mult_ac) - from A and this have "a' dvd 1 \ b' dvd 1" by (rule irreducibleD) - with ab' show "a dvd 1 \ b dvd 1" - by (auto simp add: is_unit_const_poly_iff) - qed (insert A, auto simp: irreducible_def is_unit_poly_iff) -next - assume A: "irreducible [:c:]" - then have "c \ 0" and "\ c dvd 1" - by (auto simp add: irreducible_def is_unit_const_poly_iff) - then show "irreducible c" - proof (rule irreducibleI) - fix a b assume ab: "c = a * b" - hence "[:c:] = [:a:] * [:b:]" by (simp add: mult_ac) - from A and this have "[:a:] dvd 1 \ [:b:] dvd 1" by (rule irreducibleD) - then show "a dvd 1 \ b dvd 1" - by (auto simp add: is_unit_const_poly_iff) - qed -qed - - subsection \Lifting elements into the field of fractions\ -definition to_fract :: "'a :: idom \ 'a fract" where "to_fract x = Fract x 1" +definition to_fract :: "'a :: idom \ 'a fract" + where "to_fract x = Fract x 1" \ \FIXME: name \of_idom\, abbreviation\ lemma to_fract_0 [simp]: "to_fract 0 = 0" @@ -429,39 +388,6 @@ finally show ?thesis by simp qed -lemma primitive_part_mult: - fixes p q :: "'a :: {factorial_semiring, semiring_Gcd, ring_gcd, idom_divide} poly" - shows "primitive_part (p * q) = primitive_part p * primitive_part q" -proof - - have "primitive_part (p * q) = p * q div [:content (p * q):]" - by (simp add: primitive_part_def div_const_poly_conv_map_poly) - also have "\ = (p div [:content p:]) * (q div [:content q:])" - by (subst div_mult_div_if_dvd) (simp_all add: content_mult mult_ac) - also have "\ = primitive_part p * primitive_part q" - by (simp add: primitive_part_def div_const_poly_conv_map_poly) - finally show ?thesis . -qed - -lemma primitive_part_smult: - fixes p :: "'a :: {factorial_semiring, semiring_Gcd, ring_gcd, idom_divide} poly" - shows "primitive_part (smult a p) = smult (unit_factor a) (primitive_part p)" -proof - - have "smult a p = [:a:] * p" by simp - also have "primitive_part \ = smult (unit_factor a) (primitive_part p)" - by (subst primitive_part_mult) simp_all - finally show ?thesis . -qed - -lemma primitive_part_dvd_primitive_partI [intro]: - fixes p q :: "'a :: {factorial_semiring, semiring_Gcd, ring_gcd, idom_divide} poly" - shows "p dvd q \ primitive_part p dvd primitive_part q" - by (auto elim!: dvdE simp: primitive_part_mult) - -lemma content_prod_mset: - fixes A :: "'a :: {factorial_semiring, semiring_Gcd} poly multiset" - shows "content (prod_mset A) = prod_mset (image_mset content A)" - by (induction A) (simp_all add: content_mult mult_ac) - lemma fract_poly_dvdD: fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly" assumes "fract_poly p dvd fract_poly q" "content p = 1" @@ -481,104 +407,80 @@ thus ?thesis by (rule dvdI) qed -lemma content_prod_eq_1_iff: - fixes p q :: "'a :: {factorial_semiring, semiring_Gcd} poly" - shows "content (p * q) = 1 \ content p = 1 \ content q = 1" -proof safe - assume A: "content (p * q) = 1" - { - fix p q :: "'a poly" assume "content p * content q = 1" - hence "1 = content p * content q" by simp - hence "content p dvd 1" by (rule dvdI) - hence "content p = 1" by simp - } note B = this - from A B[of p q] B [of q p] show "content p = 1" "content q = 1" - by (simp_all add: content_mult mult_ac) -qed (auto simp: content_mult) - end subsection \Polynomials over a field are a Euclidean ring\ -definition unit_factor_field_poly :: "'a :: field poly \ 'a poly" where - "unit_factor_field_poly p = [:lead_coeff p:]" - -definition normalize_field_poly :: "'a :: field poly \ 'a poly" where - "normalize_field_poly p = smult (inverse (lead_coeff p)) p" - -definition euclidean_size_field_poly :: "'a :: field poly \ nat" where - "euclidean_size_field_poly p = (if p = 0 then 0 else 2 ^ degree p)" - -lemma dvd_field_poly: "dvd.dvd (op * :: 'a :: field poly \ _) = op dvd" - by (intro ext) (simp_all add: dvd.dvd_def dvd_def) +context +begin interpretation field_poly: unique_euclidean_ring where zero = "0 :: 'a :: field poly" - and one = 1 and plus = plus and uminus = uminus and minus = minus + and one = 1 and plus = plus + and uminus = uminus and minus = minus and times = times - and normalize = normalize_field_poly and unit_factor = unit_factor_field_poly - and euclidean_size = euclidean_size_field_poly + and normalize = "\p. smult (inverse (lead_coeff p)) p" + and unit_factor = "\p. [:lead_coeff p:]" + and euclidean_size = "\p. if p = 0 then 0 else 2 ^ degree p" and uniqueness_constraint = top and divide = divide and modulo = modulo -proof (standard, unfold dvd_field_poly) - fix p :: "'a poly" - show "unit_factor_field_poly p * normalize_field_poly p = p" - by (cases "p = 0") - (simp_all add: unit_factor_field_poly_def normalize_field_poly_def) -next - fix p :: "'a poly" assume "is_unit p" - then show "unit_factor_field_poly p = p" - by (elim is_unit_polyE) (auto simp: unit_factor_field_poly_def monom_0 one_poly_def field_simps) -next - fix p :: "'a poly" assume "p \ 0" - thus "is_unit (unit_factor_field_poly p)" - by (simp add: unit_factor_field_poly_def is_unit_pCons_iff) -next - fix p q s :: "'a poly" assume "s \ 0" - moreover assume "euclidean_size_field_poly p < euclidean_size_field_poly q" - ultimately show "euclidean_size_field_poly (p * s) < euclidean_size_field_poly (q * s)" - by (auto simp add: euclidean_size_field_poly_def degree_mult_eq) -next - fix p q r :: "'a poly" assume "p \ 0" - moreover assume "euclidean_size_field_poly r < euclidean_size_field_poly p" - ultimately show "(q * p + r) div p = q" - by (cases "r = 0") - (auto simp add: unit_factor_field_poly_def euclidean_size_field_poly_def div_poly_less) -qed (auto simp: unit_factor_field_poly_def normalize_field_poly_def lead_coeff_mult - euclidean_size_field_poly_def Rings.div_mult_mod_eq intro!: degree_mod_less' degree_mult_right_le) + rewrites "dvd.dvd (times :: 'a poly \ _) = Rings.dvd" + and "comm_monoid_mult.prod_mset times 1 = prod_mset" + and "comm_semiring_1.irreducible times 1 0 = irreducible" + and "comm_semiring_1.prime_elem times 1 0 = prime_elem" +proof - + show "dvd.dvd (times :: 'a poly \ _) = Rings.dvd" + by (simp add: dvd_dict) + show "comm_monoid_mult.prod_mset times 1 = prod_mset" + by (simp add: prod_mset_dict) + show "comm_semiring_1.irreducible times 1 0 = irreducible" + by (simp add: irreducible_dict) + show "comm_semiring_1.prime_elem times 1 0 = prime_elem" + by (simp add: prime_elem_dict) + show "class.unique_euclidean_ring divide plus minus (0 :: 'a poly) times 1 modulo + (\p. [:lead_coeff p:]) (\p. smult (inverse (lead_coeff p)) p) + (\p. if p = 0 then 0 else 2 ^ degree p) uminus top" + proof (standard, fold dvd_dict) + fix p :: "'a poly" + show "[:lead_coeff p:] * smult (inverse (lead_coeff p)) p = p" + by (cases "p = 0") simp_all + next + fix p :: "'a poly" assume "is_unit p" + then show "[:lead_coeff p:] = p" + by (elim is_unit_polyE) (auto simp: monom_0 one_poly_def field_simps) + next + fix p :: "'a poly" assume "p \ 0" + then show "is_unit [:lead_coeff p:]" + by (simp add: is_unit_pCons_iff) + next + fix p q s :: "'a poly" assume "s \ 0" + moreover assume "(if p = 0 then (0::nat) else 2 ^ degree p) < (if q = 0 then 0 else 2 ^ degree q)" + ultimately show "(if p * s = 0 then (0::nat) else 2 ^ degree (p * s)) < (if q * s = 0 then 0 else 2 ^ degree (q * s))" + by (auto simp add: degree_mult_eq) + next + fix p q r :: "'a poly" assume "p \ 0" + moreover assume "(if r = 0 then (0::nat) else 2 ^ degree r) + < (if p = 0 then 0 else 2 ^ degree p)" + ultimately show "(q * p + r) div p = q" + by (cases "r = 0") (auto simp add: div_poly_less) + qed (auto simp: lead_coeff_mult Rings.div_mult_mod_eq intro!: degree_mod_less' degree_mult_right_le) +qed lemma field_poly_irreducible_imp_prime: - assumes "irreducible (p :: 'a :: field poly)" - shows "prime_elem p" -proof - - have A: "class.comm_semiring_1 op * 1 op + (0 :: 'a poly)" .. - from field_poly.irreducible_imp_prime_elem[of p] assms - show ?thesis unfolding irreducible_def prime_elem_def dvd_field_poly - comm_semiring_1.irreducible_def[OF A] comm_semiring_1.prime_elem_def[OF A] by blast -qed + "prime_elem p" if "irreducible p" for p :: "'a :: field poly" + using that by (fact field_poly.irreducible_imp_prime_elem) lemma field_poly_prod_mset_prime_factorization: - assumes "(x :: 'a :: field poly) \ 0" - shows "prod_mset (field_poly.prime_factorization x) = normalize_field_poly x" -proof - - have A: "class.comm_monoid_mult op * (1 :: 'a poly)" .. - have "comm_monoid_mult.prod_mset op * (1 :: 'a poly) = prod_mset" - by (intro ext) (simp add: comm_monoid_mult.prod_mset_def[OF A] prod_mset_def) - with field_poly.prod_mset_prime_factorization[OF assms] show ?thesis by simp -qed + "prod_mset (field_poly.prime_factorization p) = smult (inverse (lead_coeff p)) p" + if "p \ 0" for p :: "'a :: field poly" + using that by (fact field_poly.prod_mset_prime_factorization) lemma field_poly_in_prime_factorization_imp_prime: - assumes "(p :: 'a :: field poly) \# field_poly.prime_factorization x" - shows "prime_elem p" -proof - - have A: "class.comm_semiring_1 op * 1 op + (0 :: 'a poly)" .. - have B: "class.normalization_semidom op div op + op - (0 :: 'a poly) op * 1 - unit_factor_field_poly normalize_field_poly" .. - from field_poly.in_prime_factors_imp_prime [of p x] assms - show ?thesis unfolding prime_elem_def dvd_field_poly - comm_semiring_1.prime_elem_def[OF A] normalization_semidom.prime_def[OF B] by blast -qed + "prime_elem p" if "p \# field_poly.prime_factorization x" + for p :: "'a :: field poly" + by (rule field_poly.prime_imp_prime_elem, rule field_poly.in_prime_factors_imp_prime) + (fact that) subsection \Primality and irreducibility in polynomial rings\ @@ -658,9 +560,6 @@ qed qed -context -begin - private lemma irreducible_imp_prime_poly: fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly" assumes "irreducible p" @@ -686,7 +585,6 @@ qed (insert assms, auto simp: irreducible_def) qed - lemma degree_primitive_part_fract [simp]: "degree (primitive_part_fract p) = degree p" proof - @@ -749,14 +647,9 @@ shows "b \ 0 \ coprime a b \ prime_elem [:a,b:]" by (rule irreducible_imp_prime_poly, rule irreducible_linear_poly) -end - subsection \Prime factorisation of polynomials\ -context -begin - private lemma poly_prime_factorization_exists_content_1: fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly" assumes "p \ 0" "content p = 1" @@ -775,11 +668,12 @@ finally have content_e: "content e = 1" by simp - have "fract_poly p = unit_factor_field_poly (fract_poly p) * - normalize_field_poly (fract_poly p)" by simp - also have "unit_factor_field_poly (fract_poly p) = [:to_fract (lead_coeff p):]" - by (simp add: unit_factor_field_poly_def monom_0 degree_map_poly coeff_map_poly) - also from assms have "normalize_field_poly (fract_poly p) = prod_mset ?P" + from \p \ 0\ have "fract_poly p = [:lead_coeff (fract_poly p):] * + smult (inverse (lead_coeff (fract_poly p))) (fract_poly p)" + by simp + also have "[:lead_coeff (fract_poly p):] = [:to_fract (lead_coeff p):]" + by (simp add: monom_0 degree_map_poly coeff_map_poly) + also from assms have "smult (inverse (lead_coeff (fract_poly p))) (fract_poly p) = prod_mset ?P" by (subst field_poly_prod_mset_prime_factorization) simp_all also have "\ = prod_mset (image_mset id ?P)" by simp also have "image_mset id ?P =