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" |
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 |