src/HOL/Library/Polynomial_Factorial.thy
changeset 63830 2ea3725a34bd
parent 63764 f3ad26c4b2d9
child 63905 1c3dcb5fe6cb
equal deleted inserted replaced
63829:6a05c8cbf7de 63830:2ea3725a34bd
    14   "~~/src/HOL/Library/Normalized_Fraction"
    14   "~~/src/HOL/Library/Normalized_Fraction"
    15 begin
    15 begin
    16 
    16 
    17 subsection \<open>Prelude\<close>
    17 subsection \<open>Prelude\<close>
    18 
    18 
    19 lemma msetprod_mult: 
    19 lemma prod_mset_mult: 
    20   "msetprod (image_mset (\<lambda>x. f x * g x) A) = msetprod (image_mset f A) * msetprod (image_mset g A)"
    20   "prod_mset (image_mset (\<lambda>x. f x * g x) A) = prod_mset (image_mset f A) * prod_mset (image_mset g A)"
    21   by (induction A) (simp_all add: mult_ac)
    21   by (induction A) (simp_all add: mult_ac)
    22   
    22   
    23 lemma msetprod_const: "msetprod (image_mset (\<lambda>_. c) A) = c ^ size A"
    23 lemma prod_mset_const: "prod_mset (image_mset (\<lambda>_. c) A) = c ^ size A"
    24   by (induction A) (simp_all add: mult_ac)
    24   by (induction A) (simp_all add: mult_ac)
    25   
    25   
    26 lemma dvd_field_iff: "x dvd y \<longleftrightarrow> (x = 0 \<longrightarrow> y = (0::'a::field))"
    26 lemma dvd_field_iff: "x dvd y \<longleftrightarrow> (x = 0 \<longrightarrow> y = (0::'a::field))"
    27 proof safe
    27 proof safe
    28   assume "x \<noteq> 0"
    28   assume "x \<noteq> 0"
   339 
   339 
   340 
   340 
   341 
   341 
   342 subsection \<open>Various facts about polynomials\<close>
   342 subsection \<open>Various facts about polynomials\<close>
   343 
   343 
   344 lemma msetprod_const_poly: "msetprod (image_mset (\<lambda>x. [:f x:]) A) = [:msetprod (image_mset f A):]"
   344 lemma prod_mset_const_poly: "prod_mset (image_mset (\<lambda>x. [:f x:]) A) = [:prod_mset (image_mset f A):]"
   345   by (induction A) (simp_all add: one_poly_def mult_ac)
   345   by (induction A) (simp_all add: one_poly_def mult_ac)
   346 
   346 
   347 lemma degree_mod_less': "b \<noteq> 0 \<Longrightarrow> a mod b \<noteq> 0 \<Longrightarrow> degree (a mod b) < degree b"
   347 lemma degree_mod_less': "b \<noteq> 0 \<Longrightarrow> a mod b \<noteq> 0 \<Longrightarrow> degree (a mod b) < degree b"
   348   using degree_mod_less[of b a] by auto
   348   using degree_mod_less[of b a] by auto
   349   
   349   
   677   using fract_poly_eq_iff[of p 0] by (simp del: fract_poly_eq_iff)
   677   using fract_poly_eq_iff[of p 0] by (simp del: fract_poly_eq_iff)
   678 
   678 
   679 lemma fract_poly_dvd: "p dvd q \<Longrightarrow> fract_poly p dvd fract_poly q"
   679 lemma fract_poly_dvd: "p dvd q \<Longrightarrow> fract_poly p dvd fract_poly q"
   680   by (auto elim!: dvdE)
   680   by (auto elim!: dvdE)
   681 
   681 
   682 lemma msetprod_fract_poly: 
   682 lemma prod_mset_fract_poly: 
   683   "msetprod (image_mset (\<lambda>x. fract_poly (f x)) A) = fract_poly (msetprod (image_mset f A))"
   683   "prod_mset (image_mset (\<lambda>x. fract_poly (f x)) A) = fract_poly (prod_mset (image_mset f A))"
   684   by (induction A) (simp_all add: mult_ac)
   684   by (induction A) (simp_all add: mult_ac)
   685   
   685   
   686 lemma is_unit_fract_poly_iff:
   686 lemma is_unit_fract_poly_iff:
   687   "p dvd 1 \<longleftrightarrow> fract_poly p dvd 1 \<and> content p = 1"
   687   "p dvd 1 \<longleftrightarrow> fract_poly p dvd 1 \<and> content p = 1"
   688 proof safe
   688 proof safe
   959 lemma primitive_part_dvd_primitive_partI [intro]:
   959 lemma primitive_part_dvd_primitive_partI [intro]:
   960   fixes p q :: "'a :: {factorial_semiring, semiring_Gcd, ring_gcd, idom_divide} poly"
   960   fixes p q :: "'a :: {factorial_semiring, semiring_Gcd, ring_gcd, idom_divide} poly"
   961   shows "p dvd q \<Longrightarrow> primitive_part p dvd primitive_part q"
   961   shows "p dvd q \<Longrightarrow> primitive_part p dvd primitive_part q"
   962   by (auto elim!: dvdE simp: primitive_part_mult)
   962   by (auto elim!: dvdE simp: primitive_part_mult)
   963 
   963 
   964 lemma content_msetprod: 
   964 lemma content_prod_mset: 
   965   fixes A :: "'a :: {factorial_semiring, semiring_Gcd} poly multiset"
   965   fixes A :: "'a :: {factorial_semiring, semiring_Gcd} poly multiset"
   966   shows "content (msetprod A) = msetprod (image_mset content A)"
   966   shows "content (prod_mset A) = prod_mset (image_mset content A)"
   967   by (induction A) (simp_all add: content_mult mult_ac)
   967   by (induction A) (simp_all add: content_mult mult_ac)
   968 
   968 
   969 lemma fract_poly_dvdD:
   969 lemma fract_poly_dvdD:
   970   fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly"
   970   fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly"
   971   assumes "fract_poly p dvd fract_poly q" "content p = 1"
   971   assumes "fract_poly p dvd fract_poly q" "content p = 1"
  1044   from field_poly.irreducible_imp_prime_elem[of p] assms
  1044   from field_poly.irreducible_imp_prime_elem[of p] assms
  1045     show ?thesis unfolding irreducible_def prime_elem_def dvd_field_poly
  1045     show ?thesis unfolding irreducible_def prime_elem_def dvd_field_poly
  1046       comm_semiring_1.irreducible_def[OF A] comm_semiring_1.prime_elem_def[OF A] by blast
  1046       comm_semiring_1.irreducible_def[OF A] comm_semiring_1.prime_elem_def[OF A] by blast
  1047 qed
  1047 qed
  1048 
  1048 
  1049 lemma field_poly_msetprod_prime_factorization:
  1049 lemma field_poly_prod_mset_prime_factorization:
  1050   assumes "(x :: 'a :: field poly) \<noteq> 0"
  1050   assumes "(x :: 'a :: field poly) \<noteq> 0"
  1051   shows   "msetprod (field_poly.prime_factorization x) = normalize_field_poly x"
  1051   shows   "prod_mset (field_poly.prime_factorization x) = normalize_field_poly x"
  1052 proof -
  1052 proof -
  1053   have A: "class.comm_monoid_mult op * (1 :: 'a poly)" ..
  1053   have A: "class.comm_monoid_mult op * (1 :: 'a poly)" ..
  1054   have "comm_monoid_mult.msetprod op * (1 :: 'a poly) = msetprod"
  1054   have "comm_monoid_mult.prod_mset op * (1 :: 'a poly) = prod_mset"
  1055     by (intro ext) (simp add: comm_monoid_mult.msetprod_def[OF A] msetprod_def)
  1055     by (intro ext) (simp add: comm_monoid_mult.prod_mset_def[OF A] prod_mset_def)
  1056   with field_poly.msetprod_prime_factorization[OF assms] show ?thesis by simp
  1056   with field_poly.prod_mset_prime_factorization[OF assms] show ?thesis by simp
  1057 qed
  1057 qed
  1058 
  1058 
  1059 lemma field_poly_in_prime_factorization_imp_prime:
  1059 lemma field_poly_in_prime_factorization_imp_prime:
  1060   assumes "(p :: 'a :: field poly) \<in># field_poly.prime_factorization x"
  1060   assumes "(p :: 'a :: field poly) \<in># field_poly.prime_factorization x"
  1061   shows   "prime_elem p"
  1061   shows   "prime_elem p"
  1246 begin 
  1246 begin 
  1247 
  1247 
  1248 private lemma poly_prime_factorization_exists_content_1:
  1248 private lemma poly_prime_factorization_exists_content_1:
  1249   fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly"
  1249   fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly"
  1250   assumes "p \<noteq> 0" "content p = 1"
  1250   assumes "p \<noteq> 0" "content p = 1"
  1251   shows   "\<exists>A. (\<forall>p. p \<in># A \<longrightarrow> prime_elem p) \<and> msetprod A = normalize p"
  1251   shows   "\<exists>A. (\<forall>p. p \<in># A \<longrightarrow> prime_elem p) \<and> prod_mset A = normalize p"
  1252 proof -
  1252 proof -
  1253   let ?P = "field_poly.prime_factorization (fract_poly p)"
  1253   let ?P = "field_poly.prime_factorization (fract_poly p)"
  1254   define c where "c = msetprod (image_mset fract_content ?P)"
  1254   define c where "c = prod_mset (image_mset fract_content ?P)"
  1255   define c' where "c' = c * to_fract (lead_coeff p)"
  1255   define c' where "c' = c * to_fract (lead_coeff p)"
  1256   define e where "e = msetprod (image_mset primitive_part_fract ?P)"
  1256   define e where "e = prod_mset (image_mset primitive_part_fract ?P)"
  1257   define A where "A = image_mset (normalize \<circ> primitive_part_fract) ?P"
  1257   define A where "A = image_mset (normalize \<circ> primitive_part_fract) ?P"
  1258   have "content e = (\<Prod>x\<in>#field_poly.prime_factorization (map_poly to_fract p). 
  1258   have "content e = (\<Prod>x\<in>#field_poly.prime_factorization (map_poly to_fract p). 
  1259                       content (primitive_part_fract x))"
  1259                       content (primitive_part_fract x))"
  1260     by (simp add: e_def content_msetprod multiset.map_comp o_def)
  1260     by (simp add: e_def content_prod_mset multiset.map_comp o_def)
  1261   also have "image_mset (\<lambda>x. content (primitive_part_fract x)) ?P = image_mset (\<lambda>_. 1) ?P"
  1261   also have "image_mset (\<lambda>x. content (primitive_part_fract x)) ?P = image_mset (\<lambda>_. 1) ?P"
  1262     by (intro image_mset_cong content_primitive_part_fract) auto
  1262     by (intro image_mset_cong content_primitive_part_fract) auto
  1263   finally have content_e: "content e = 1" by (simp add: msetprod_const)    
  1263   finally have content_e: "content e = 1" by (simp add: prod_mset_const)    
  1264   
  1264   
  1265   have "fract_poly p = unit_factor_field_poly (fract_poly p) * 
  1265   have "fract_poly p = unit_factor_field_poly (fract_poly p) * 
  1266           normalize_field_poly (fract_poly p)" by simp
  1266           normalize_field_poly (fract_poly p)" by simp
  1267   also have "unit_factor_field_poly (fract_poly p) = [:to_fract (lead_coeff p):]" 
  1267   also have "unit_factor_field_poly (fract_poly p) = [:to_fract (lead_coeff p):]" 
  1268     by (simp add: unit_factor_field_poly_def lead_coeff_def monom_0 degree_map_poly coeff_map_poly)
  1268     by (simp add: unit_factor_field_poly_def lead_coeff_def monom_0 degree_map_poly coeff_map_poly)
  1269   also from assms have "normalize_field_poly (fract_poly p) = msetprod ?P" 
  1269   also from assms have "normalize_field_poly (fract_poly p) = prod_mset ?P" 
  1270     by (subst field_poly_msetprod_prime_factorization) simp_all
  1270     by (subst field_poly_prod_mset_prime_factorization) simp_all
  1271   also have "\<dots> = msetprod (image_mset id ?P)" by simp
  1271   also have "\<dots> = prod_mset (image_mset id ?P)" by simp
  1272   also have "image_mset id ?P = 
  1272   also have "image_mset id ?P = 
  1273                image_mset (\<lambda>x. [:fract_content x:] * fract_poly (primitive_part_fract x)) ?P"
  1273                image_mset (\<lambda>x. [:fract_content x:] * fract_poly (primitive_part_fract x)) ?P"
  1274     by (intro image_mset_cong) (auto simp: content_times_primitive_part_fract)
  1274     by (intro image_mset_cong) (auto simp: content_times_primitive_part_fract)
  1275   also have "msetprod \<dots> = smult c (fract_poly e)"
  1275   also have "prod_mset \<dots> = smult c (fract_poly e)"
  1276     by (subst msetprod_mult) (simp_all add: msetprod_fract_poly msetprod_const_poly c_def e_def)
  1276     by (subst prod_mset_mult) (simp_all add: prod_mset_fract_poly prod_mset_const_poly c_def e_def)
  1277   also have "[:to_fract (lead_coeff p):] * \<dots> = smult c' (fract_poly e)"
  1277   also have "[:to_fract (lead_coeff p):] * \<dots> = smult c' (fract_poly e)"
  1278     by (simp add: c'_def)
  1278     by (simp add: c'_def)
  1279   finally have eq: "fract_poly p = smult c' (fract_poly e)" .
  1279   finally have eq: "fract_poly p = smult c' (fract_poly e)" .
  1280   also obtain b where b: "c' = to_fract b" "is_unit b"
  1280   also obtain b where b: "c' = to_fract b" "is_unit b"
  1281   proof -
  1281   proof -
  1289   hence "smult c' (fract_poly e) = fract_poly (smult b e)" by simp
  1289   hence "smult c' (fract_poly e) = fract_poly (smult b e)" by simp
  1290   finally have "p = smult b e" by (simp only: fract_poly_eq_iff)
  1290   finally have "p = smult b e" by (simp only: fract_poly_eq_iff)
  1291   hence "p = [:b:] * e" by simp
  1291   hence "p = [:b:] * e" by simp
  1292   with b have "normalize p = normalize e" 
  1292   with b have "normalize p = normalize e" 
  1293     by (simp only: normalize_mult) (simp add: is_unit_normalize is_unit_poly_iff)
  1293     by (simp only: normalize_mult) (simp add: is_unit_normalize is_unit_poly_iff)
  1294   also have "normalize e = msetprod A"
  1294   also have "normalize e = prod_mset A"
  1295     by (simp add: multiset.map_comp e_def A_def normalize_msetprod)
  1295     by (simp add: multiset.map_comp e_def A_def normalize_prod_mset)
  1296   finally have "msetprod A = normalize p" ..
  1296   finally have "prod_mset A = normalize p" ..
  1297   
  1297   
  1298   have "prime_elem p" if "p \<in># A" for p
  1298   have "prime_elem p" if "p \<in># A" for p
  1299     using that by (auto simp: A_def prime_elem_primitive_part_fract prime_elem_imp_irreducible 
  1299     using that by (auto simp: A_def prime_elem_primitive_part_fract prime_elem_imp_irreducible 
  1300                         dest!: field_poly_in_prime_factorization_imp_prime )
  1300                         dest!: field_poly_in_prime_factorization_imp_prime )
  1301   from this and \<open>msetprod A = normalize p\<close> show ?thesis
  1301   from this and \<open>prod_mset A = normalize p\<close> show ?thesis
  1302     by (intro exI[of _ A]) blast
  1302     by (intro exI[of _ A]) blast
  1303 qed
  1303 qed
  1304 
  1304 
  1305 lemma poly_prime_factorization_exists:
  1305 lemma poly_prime_factorization_exists:
  1306   fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly"
  1306   fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly"
  1307   assumes "p \<noteq> 0"
  1307   assumes "p \<noteq> 0"
  1308   shows   "\<exists>A. (\<forall>p. p \<in># A \<longrightarrow> prime_elem p) \<and> msetprod A = normalize p"
  1308   shows   "\<exists>A. (\<forall>p. p \<in># A \<longrightarrow> prime_elem p) \<and> prod_mset A = normalize p"
  1309 proof -
  1309 proof -
  1310   define B where "B = image_mset (\<lambda>x. [:x:]) (prime_factorization (content p))"
  1310   define B where "B = image_mset (\<lambda>x. [:x:]) (prime_factorization (content p))"
  1311   have "\<exists>A. (\<forall>p. p \<in># A \<longrightarrow> prime_elem p) \<and> msetprod A = normalize (primitive_part p)"
  1311   have "\<exists>A. (\<forall>p. p \<in># A \<longrightarrow> prime_elem p) \<and> prod_mset A = normalize (primitive_part p)"
  1312     by (rule poly_prime_factorization_exists_content_1) (insert assms, simp_all)
  1312     by (rule poly_prime_factorization_exists_content_1) (insert assms, simp_all)
  1313   then guess A by (elim exE conjE) note A = this
  1313   then guess A by (elim exE conjE) note A = this
  1314   moreover from assms have "msetprod B = [:content p:]"
  1314   moreover from assms have "prod_mset B = [:content p:]"
  1315     by (simp add: B_def msetprod_const_poly msetprod_prime_factorization)
  1315     by (simp add: B_def prod_mset_const_poly prod_mset_prime_factorization)
  1316   moreover have "\<forall>p. p \<in># B \<longrightarrow> prime_elem p"
  1316   moreover have "\<forall>p. p \<in># B \<longrightarrow> prime_elem p"
  1317     by (auto simp: B_def intro: lift_prime_elem_poly dest: in_prime_factorization_imp_prime)
  1317     by (auto simp: B_def intro: lift_prime_elem_poly dest: in_prime_factorization_imp_prime)
  1318   ultimately show ?thesis by (intro exI[of _ "B + A"]) auto
  1318   ultimately show ?thesis by (intro exI[of _ "B + A"]) auto
  1319 qed
  1319 qed
  1320 
  1320