src/HOL/Number_Theory/Polynomial_Factorial.thy
changeset 63633 2accfb71e33b
parent 63539 70d4d9e5707b
equal deleted inserted replaced
63627:6ddb43c6b711 63633:2accfb71e33b
   810 
   810 
   811 
   811 
   812 subsection \<open>More properties of content and primitive part\<close>
   812 subsection \<open>More properties of content and primitive part\<close>
   813 
   813 
   814 lemma lift_prime_elem_poly:
   814 lemma lift_prime_elem_poly:
   815   assumes "is_prime_elem (c :: 'a :: semidom)"
   815   assumes "prime_elem (c :: 'a :: semidom)"
   816   shows   "is_prime_elem [:c:]"
   816   shows   "prime_elem [:c:]"
   817 proof (rule is_prime_elemI)
   817 proof (rule prime_elemI)
   818   fix a b assume *: "[:c:] dvd a * b"
   818   fix a b assume *: "[:c:] dvd a * b"
   819   from * have dvd: "c dvd coeff (a * b) n" for n
   819   from * have dvd: "c dvd coeff (a * b) n" for n
   820     by (subst (asm) const_poly_dvd_iff) blast
   820     by (subst (asm) const_poly_dvd_iff) blast
   821   {
   821   {
   822     define m where "m = (GREATEST m. \<not>c dvd coeff b m)"
   822     define m where "m = (GREATEST m. \<not>c dvd coeff b m)"
   860         qed
   860         qed
   861       qed
   861       qed
   862       ultimately have "c dvd coeff a i * coeff b m"
   862       ultimately have "c dvd coeff a i * coeff b m"
   863         by (simp add: dvd_add_left_iff)
   863         by (simp add: dvd_add_left_iff)
   864       with assms coeff_m show "c dvd coeff a i"
   864       with assms coeff_m show "c dvd coeff a i"
   865         by (simp add: prime_dvd_mult_iff)
   865         by (simp add: prime_elem_dvd_mult_iff)
   866     qed
   866     qed
   867     hence "[:c:] dvd a" by (subst const_poly_dvd_iff) blast
   867     hence "[:c:] dvd a" by (subst const_poly_dvd_iff) blast
   868   }
   868   }
   869   thus "[:c:] dvd a \<or> [:c:] dvd b" by blast
   869   thus "[:c:] dvd a \<or> [:c:] dvd b" by blast
   870 qed (insert assms, simp_all add: is_prime_elem_def one_poly_def)
   870 qed (insert assms, simp_all add: prime_elem_def one_poly_def)
   871 
   871 
   872 lemma prime_elem_const_poly_iff:
   872 lemma prime_elem_const_poly_iff:
   873   fixes c :: "'a :: semidom"
   873   fixes c :: "'a :: semidom"
   874   shows   "is_prime_elem [:c:] \<longleftrightarrow> is_prime_elem c"
   874   shows   "prime_elem [:c:] \<longleftrightarrow> prime_elem c"
   875 proof
   875 proof
   876   assume A: "is_prime_elem [:c:]"
   876   assume A: "prime_elem [:c:]"
   877   show "is_prime_elem c"
   877   show "prime_elem c"
   878   proof (rule is_prime_elemI)
   878   proof (rule prime_elemI)
   879     fix a b assume "c dvd a * b"
   879     fix a b assume "c dvd a * b"
   880     hence "[:c:] dvd [:a:] * [:b:]" by (simp add: mult_ac)
   880     hence "[:c:] dvd [:a:] * [:b:]" by (simp add: mult_ac)
   881     from A and this have "[:c:] dvd [:a:] \<or> [:c:] dvd [:b:]" by (rule prime_divides_productD)
   881     from A and this have "[:c:] dvd [:a:] \<or> [:c:] dvd [:b:]" by (rule prime_elem_dvd_multD)
   882     thus "c dvd a \<or> c dvd b" by simp
   882     thus "c dvd a \<or> c dvd b" by simp
   883   qed (insert A, auto simp: is_prime_elem_def is_unit_poly_iff)
   883   qed (insert A, auto simp: prime_elem_def is_unit_poly_iff)
   884 qed (auto intro: lift_prime_elem_poly)
   884 qed (auto intro: lift_prime_elem_poly)
   885 
   885 
   886 context
   886 context
   887 begin
   887 begin
   888 
   888 
   895   from assms have "f \<noteq> 0" "g \<noteq> 0" by auto
   895   from assms have "f \<noteq> 0" "g \<noteq> 0" by auto
   896 
   896 
   897   hence "f * g \<noteq> 0" by auto
   897   hence "f * g \<noteq> 0" by auto
   898   {
   898   {
   899     assume "\<not>is_unit (content (f * g))"
   899     assume "\<not>is_unit (content (f * g))"
   900     with False have "\<exists>p. p dvd content (f * g) \<and> is_prime p"
   900     with False have "\<exists>p. p dvd content (f * g) \<and> prime p"
   901       by (intro prime_divisor_exists) simp_all
   901       by (intro prime_divisor_exists) simp_all
   902     then obtain p where "p dvd content (f * g)" "is_prime p" by blast
   902     then obtain p where "p dvd content (f * g)" "prime p" by blast
   903     from \<open>p dvd content (f * g)\<close> have "[:p:] dvd f * g"
   903     from \<open>p dvd content (f * g)\<close> have "[:p:] dvd f * g"
   904       by (simp add: const_poly_dvd_iff_dvd_content)
   904       by (simp add: const_poly_dvd_iff_dvd_content)
   905     moreover from \<open>is_prime p\<close> have "is_prime_elem [:p:]" by (simp add: lift_prime_elem_poly)
   905     moreover from \<open>prime p\<close> have "prime_elem [:p:]" by (simp add: lift_prime_elem_poly)
   906     ultimately have "[:p:] dvd f \<or> [:p:] dvd g"
   906     ultimately have "[:p:] dvd f \<or> [:p:] dvd g"
   907       by (simp add: prime_dvd_mult_iff)
   907       by (simp add: prime_elem_dvd_mult_iff)
   908     with assms have "is_unit p" by (simp add: const_poly_dvd_iff_dvd_content)
   908     with assms have "is_unit p" by (simp add: const_poly_dvd_iff_dvd_content)
   909     with \<open>is_prime p\<close> have False by simp
   909     with \<open>prime p\<close> have False by simp
   910   }
   910   }
   911   hence "is_unit (content (f * g))" by blast
   911   hence "is_unit (content (f * g))" by blast
   912   hence "normalize (content (f * g)) = 1" by (simp add: is_unit_normalize del: normalize_content)
   912   hence "normalize (content (f * g)) = 1" by (simp add: is_unit_normalize del: normalize_content)
   913   thus ?thesis by simp
   913   thus ?thesis by simp
   914 qed (insert assms, auto)
   914 qed (insert assms, auto)
  1031 qed (auto simp: unit_factor_field_poly_def normalize_field_poly_def lead_coeff_mult 
  1031 qed (auto simp: unit_factor_field_poly_def normalize_field_poly_def lead_coeff_mult 
  1032        euclidean_size_field_poly_def intro!: degree_mod_less' degree_mult_right_le)
  1032        euclidean_size_field_poly_def intro!: degree_mod_less' degree_mult_right_le)
  1033 
  1033 
  1034 private lemma field_poly_irreducible_imp_prime:
  1034 private lemma field_poly_irreducible_imp_prime:
  1035   assumes "irreducible (p :: 'a :: field poly)"
  1035   assumes "irreducible (p :: 'a :: field poly)"
  1036   shows   "is_prime_elem p"
  1036   shows   "prime_elem p"
  1037 proof -
  1037 proof -
  1038   have A: "class.comm_semiring_1 op * 1 op + (0 :: 'a poly)" ..
  1038   have A: "class.comm_semiring_1 op * 1 op + (0 :: 'a poly)" ..
  1039   from field_poly.irreducible_imp_prime[of p] assms
  1039   from field_poly.irreducible_imp_prime_elem[of p] assms
  1040     show ?thesis unfolding irreducible_def is_prime_elem_def dvd_field_poly
  1040     show ?thesis unfolding irreducible_def prime_elem_def dvd_field_poly
  1041       comm_semiring_1.irreducible_def[OF A] comm_semiring_1.is_prime_elem_def[OF A] by blast
  1041       comm_semiring_1.irreducible_def[OF A] comm_semiring_1.prime_elem_def[OF A] by blast
  1042 qed
  1042 qed
  1043 
  1043 
  1044 private lemma field_poly_msetprod_prime_factorization:
  1044 private lemma field_poly_msetprod_prime_factorization:
  1045   assumes "(x :: 'a :: field poly) \<noteq> 0"
  1045   assumes "(x :: 'a :: field poly) \<noteq> 0"
  1046   shows   "msetprod (field_poly.prime_factorization x) = normalize_field_poly x"
  1046   shows   "msetprod (field_poly.prime_factorization x) = normalize_field_poly x"
  1051   with field_poly.msetprod_prime_factorization[OF assms] show ?thesis by simp
  1051   with field_poly.msetprod_prime_factorization[OF assms] show ?thesis by simp
  1052 qed
  1052 qed
  1053 
  1053 
  1054 private lemma field_poly_in_prime_factorization_imp_prime:
  1054 private lemma field_poly_in_prime_factorization_imp_prime:
  1055   assumes "(p :: 'a :: field poly) \<in># field_poly.prime_factorization x"
  1055   assumes "(p :: 'a :: field poly) \<in># field_poly.prime_factorization x"
  1056   shows   "is_prime_elem p"
  1056   shows   "prime_elem p"
  1057 proof -
  1057 proof -
  1058   have A: "class.comm_semiring_1 op * 1 op + (0 :: 'a poly)" ..
  1058   have A: "class.comm_semiring_1 op * 1 op + (0 :: 'a poly)" ..
  1059   have B: "class.normalization_semidom op div op + op - (0 :: 'a poly) op * 1 
  1059   have B: "class.normalization_semidom op div op + op - (0 :: 'a poly) op * 1 
  1060              normalize_field_poly unit_factor_field_poly" ..
  1060              normalize_field_poly unit_factor_field_poly" ..
  1061   from field_poly.in_prime_factorization_imp_prime[of p x] assms
  1061   from field_poly.in_prime_factorization_imp_prime[of p x] assms
  1062     show ?thesis unfolding is_prime_elem_def dvd_field_poly
  1062     show ?thesis unfolding prime_elem_def dvd_field_poly
  1063       comm_semiring_1.is_prime_elem_def[OF A] normalization_semidom.is_prime_def[OF B] by blast
  1063       comm_semiring_1.prime_elem_def[OF A] normalization_semidom.prime_def[OF B] by blast
  1064 qed
  1064 qed
  1065 
  1065 
  1066 
  1066 
  1067 subsection \<open>Primality and irreducibility in polynomial rings\<close>
  1067 subsection \<open>Primality and irreducibility in polynomial rings\<close>
  1068 
  1068 
  1142 qed
  1142 qed
  1143 
  1143 
  1144 private lemma irreducible_imp_prime_poly:
  1144 private lemma irreducible_imp_prime_poly:
  1145   fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly"
  1145   fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly"
  1146   assumes "irreducible p"
  1146   assumes "irreducible p"
  1147   shows   "is_prime_elem p"
  1147   shows   "prime_elem p"
  1148 proof (cases "degree p = 0")
  1148 proof (cases "degree p = 0")
  1149   case True
  1149   case True
  1150   with assms show ?thesis
  1150   with assms show ?thesis
  1151     by (auto simp: prime_elem_const_poly_iff irreducible_const_poly_iff
  1151     by (auto simp: prime_elem_const_poly_iff irreducible_const_poly_iff
  1152              intro!: irreducible_imp_prime elim!: degree_eq_zeroE)
  1152              intro!: irreducible_imp_prime_elem elim!: degree_eq_zeroE)
  1153 next
  1153 next
  1154   case False
  1154   case False
  1155   from assms False have irred: "irreducible (fract_poly p)" and primitive: "content p = 1"
  1155   from assms False have irred: "irreducible (fract_poly p)" and primitive: "content p = 1"
  1156     by (simp_all add: nonconst_poly_irreducible_iff)
  1156     by (simp_all add: nonconst_poly_irreducible_iff)
  1157   from irred have prime: "is_prime_elem (fract_poly p)" by (rule field_poly_irreducible_imp_prime)
  1157   from irred have prime: "prime_elem (fract_poly p)" by (rule field_poly_irreducible_imp_prime)
  1158   show ?thesis
  1158   show ?thesis
  1159   proof (rule is_prime_elemI)
  1159   proof (rule prime_elemI)
  1160     fix q r assume "p dvd q * r"
  1160     fix q r assume "p dvd q * r"
  1161     hence "fract_poly p dvd fract_poly (q * r)" by (rule fract_poly_dvd)
  1161     hence "fract_poly p dvd fract_poly (q * r)" by (rule fract_poly_dvd)
  1162     hence "fract_poly p dvd fract_poly q * fract_poly r" by simp
  1162     hence "fract_poly p dvd fract_poly q * fract_poly r" by simp
  1163     from prime and this have "fract_poly p dvd fract_poly q \<or> fract_poly p dvd fract_poly r"
  1163     from prime and this have "fract_poly p dvd fract_poly q \<or> fract_poly p dvd fract_poly r"
  1164       by (rule prime_divides_productD)
  1164       by (rule prime_elem_dvd_multD)
  1165     with primitive show "p dvd q \<or> p dvd r" by (auto dest: fract_poly_dvdD)
  1165     with primitive show "p dvd q \<or> p dvd r" by (auto dest: fract_poly_dvdD)
  1166   qed (insert assms, auto simp: irreducible_def)
  1166   qed (insert assms, auto simp: irreducible_def)
  1167 qed
  1167 qed
  1168 
  1168 
  1169 
  1169 
  1194     by (intro irreducible_mult_unit_left) (simp_all add: is_unit_poly_iff dvd_field_iff)
  1194     by (intro irreducible_mult_unit_left) (simp_all add: is_unit_poly_iff dvd_field_iff)
  1195   finally show ?thesis using deg
  1195   finally show ?thesis using deg
  1196     by (simp add: nonconst_poly_irreducible_iff)
  1196     by (simp add: nonconst_poly_irreducible_iff)
  1197 qed
  1197 qed
  1198 
  1198 
  1199 lemma is_prime_elem_primitive_part_fract:
  1199 lemma prime_elem_primitive_part_fract:
  1200   fixes p :: "'a :: {idom_divide, ring_gcd, factorial_semiring, semiring_Gcd} fract poly"
  1200   fixes p :: "'a :: {idom_divide, ring_gcd, factorial_semiring, semiring_Gcd} fract poly"
  1201   shows "irreducible p \<Longrightarrow> is_prime_elem (primitive_part_fract p)"
  1201   shows "irreducible p \<Longrightarrow> prime_elem (primitive_part_fract p)"
  1202   by (intro irreducible_imp_prime_poly irreducible_primitive_part_fract)
  1202   by (intro irreducible_imp_prime_poly irreducible_primitive_part_fract)
  1203 
  1203 
  1204 lemma irreducible_linear_field_poly:
  1204 lemma irreducible_linear_field_poly:
  1205   fixes a b :: "'a::field"
  1205   fixes a b :: "'a::field"
  1206   assumes "b \<noteq> 0"
  1206   assumes "b \<noteq> 0"
  1212   finally have "degree p = 0 \<or> degree q = 0" using assms by auto
  1212   finally have "degree p = 0 \<or> degree q = 0" using assms by auto
  1213   with assms pq show "is_unit p \<or> is_unit q"
  1213   with assms pq show "is_unit p \<or> is_unit q"
  1214     by (auto simp: is_unit_const_poly_iff dvd_field_iff elim!: degree_eq_zeroE)
  1214     by (auto simp: is_unit_const_poly_iff dvd_field_iff elim!: degree_eq_zeroE)
  1215 qed (insert assms, auto simp: is_unit_poly_iff)
  1215 qed (insert assms, auto simp: is_unit_poly_iff)
  1216 
  1216 
  1217 lemma is_prime_elem_linear_field_poly:
  1217 lemma prime_elem_linear_field_poly:
  1218   "(b :: 'a :: field) \<noteq> 0 \<Longrightarrow> is_prime_elem [:a,b:]"
  1218   "(b :: 'a :: field) \<noteq> 0 \<Longrightarrow> prime_elem [:a,b:]"
  1219   by (rule field_poly_irreducible_imp_prime, rule irreducible_linear_field_poly)
  1219   by (rule field_poly_irreducible_imp_prime, rule irreducible_linear_field_poly)
  1220 
  1220 
  1221 lemma irreducible_linear_poly:
  1221 lemma irreducible_linear_poly:
  1222   fixes a b :: "'a::{idom_divide,ring_gcd,factorial_semiring,semiring_Gcd}"
  1222   fixes a b :: "'a::{idom_divide,ring_gcd,factorial_semiring,semiring_Gcd}"
  1223   shows "b \<noteq> 0 \<Longrightarrow> coprime a b \<Longrightarrow> irreducible [:a,b:]"
  1223   shows "b \<noteq> 0 \<Longrightarrow> coprime a b \<Longrightarrow> irreducible [:a,b:]"
  1224   by (auto intro!: irreducible_linear_field_poly 
  1224   by (auto intro!: irreducible_linear_field_poly 
  1225            simp:   nonconst_poly_irreducible_iff content_def map_poly_pCons)
  1225            simp:   nonconst_poly_irreducible_iff content_def map_poly_pCons)
  1226 
  1226 
  1227 lemma is_prime_elem_linear_poly:
  1227 lemma prime_elem_linear_poly:
  1228   fixes a b :: "'a::{idom_divide,ring_gcd,factorial_semiring,semiring_Gcd}"
  1228   fixes a b :: "'a::{idom_divide,ring_gcd,factorial_semiring,semiring_Gcd}"
  1229   shows "b \<noteq> 0 \<Longrightarrow> coprime a b \<Longrightarrow> is_prime_elem [:a,b:]"
  1229   shows "b \<noteq> 0 \<Longrightarrow> coprime a b \<Longrightarrow> prime_elem [:a,b:]"
  1230   by (rule irreducible_imp_prime_poly, rule irreducible_linear_poly)
  1230   by (rule irreducible_imp_prime_poly, rule irreducible_linear_poly)
  1231 
  1231 
  1232   
  1232   
  1233 subsection \<open>Prime factorisation of polynomials\<close>   
  1233 subsection \<open>Prime factorisation of polynomials\<close>   
  1234 
  1234 
  1235 private lemma poly_prime_factorization_exists_content_1:
  1235 private lemma poly_prime_factorization_exists_content_1:
  1236   fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly"
  1236   fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly"
  1237   assumes "p \<noteq> 0" "content p = 1"
  1237   assumes "p \<noteq> 0" "content p = 1"
  1238   shows   "\<exists>A. (\<forall>p. p \<in># A \<longrightarrow> is_prime_elem p) \<and> msetprod A = normalize p"
  1238   shows   "\<exists>A. (\<forall>p. p \<in># A \<longrightarrow> prime_elem p) \<and> msetprod A = normalize p"
  1239 proof -
  1239 proof -
  1240   let ?P = "field_poly.prime_factorization (fract_poly p)"
  1240   let ?P = "field_poly.prime_factorization (fract_poly p)"
  1241   define c where "c = msetprod (image_mset fract_content ?P)"
  1241   define c where "c = msetprod (image_mset fract_content ?P)"
  1242   define c' where "c' = c * to_fract (lead_coeff p)"
  1242   define c' where "c' = c * to_fract (lead_coeff p)"
  1243   define e where "e = msetprod (image_mset primitive_part_fract ?P)"
  1243   define e where "e = msetprod (image_mset primitive_part_fract ?P)"
  1280     by (simp only: normalize_mult) (simp add: is_unit_normalize is_unit_poly_iff)
  1280     by (simp only: normalize_mult) (simp add: is_unit_normalize is_unit_poly_iff)
  1281   also have "normalize e = msetprod A"
  1281   also have "normalize e = msetprod A"
  1282     by (simp add: multiset.map_comp e_def A_def normalize_msetprod)
  1282     by (simp add: multiset.map_comp e_def A_def normalize_msetprod)
  1283   finally have "msetprod A = normalize p" ..
  1283   finally have "msetprod A = normalize p" ..
  1284   
  1284   
  1285   have "is_prime_elem p" if "p \<in># A" for p
  1285   have "prime_elem p" if "p \<in># A" for p
  1286     using that by (auto simp: A_def is_prime_elem_primitive_part_fract prime_imp_irreducible 
  1286     using that by (auto simp: A_def prime_elem_primitive_part_fract prime_elem_imp_irreducible 
  1287                         dest!: field_poly_in_prime_factorization_imp_prime )
  1287                         dest!: field_poly_in_prime_factorization_imp_prime )
  1288   from this and \<open>msetprod A = normalize p\<close> show ?thesis
  1288   from this and \<open>msetprod A = normalize p\<close> show ?thesis
  1289     by (intro exI[of _ A]) blast
  1289     by (intro exI[of _ A]) blast
  1290 qed
  1290 qed
  1291 
  1291 
  1292 lemma poly_prime_factorization_exists:
  1292 lemma poly_prime_factorization_exists:
  1293   fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly"
  1293   fixes p :: "'a :: {factorial_semiring,semiring_Gcd,ring_gcd,idom_divide} poly"
  1294   assumes "p \<noteq> 0"
  1294   assumes "p \<noteq> 0"
  1295   shows   "\<exists>A. (\<forall>p. p \<in># A \<longrightarrow> is_prime_elem p) \<and> msetprod A = normalize p"
  1295   shows   "\<exists>A. (\<forall>p. p \<in># A \<longrightarrow> prime_elem p) \<and> msetprod A = normalize p"
  1296 proof -
  1296 proof -
  1297   define B where "B = image_mset (\<lambda>x. [:x:]) (prime_factorization (content p))"
  1297   define B where "B = image_mset (\<lambda>x. [:x:]) (prime_factorization (content p))"
  1298   have "\<exists>A. (\<forall>p. p \<in># A \<longrightarrow> is_prime_elem p) \<and> msetprod A = normalize (primitive_part p)"
  1298   have "\<exists>A. (\<forall>p. p \<in># A \<longrightarrow> prime_elem p) \<and> msetprod A = normalize (primitive_part p)"
  1299     by (rule poly_prime_factorization_exists_content_1) (insert assms, simp_all)
  1299     by (rule poly_prime_factorization_exists_content_1) (insert assms, simp_all)
  1300   then guess A by (elim exE conjE) note A = this
  1300   then guess A by (elim exE conjE) note A = this
  1301   moreover from assms have "msetprod B = [:content p:]"
  1301   moreover from assms have "msetprod B = [:content p:]"
  1302     by (simp add: B_def msetprod_const_poly msetprod_prime_factorization)
  1302     by (simp add: B_def msetprod_const_poly msetprod_prime_factorization)
  1303   moreover have "\<forall>p. p \<in># B \<longrightarrow> is_prime_elem p"
  1303   moreover have "\<forall>p. p \<in># B \<longrightarrow> prime_elem p"
  1304     by (auto simp: B_def intro: lift_prime_elem_poly dest: in_prime_factorization_imp_prime)
  1304     by (auto simp: B_def intro: lift_prime_elem_poly dest: in_prime_factorization_imp_prime)
  1305   ultimately show ?thesis by (intro exI[of _ "B + A"]) auto
  1305   ultimately show ?thesis by (intro exI[of _ "B + A"]) auto
  1306 qed
  1306 qed
  1307 
  1307 
  1308 end
  1308 end