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 |