469 and fin2: "finite {q. f2 q \<noteq> 0}" |
469 and fin2: "finite {q. f2 q \<noteq> 0}" |
470 shows "finite {k. prod_fun f1 f2 k \<noteq> 0}" |
470 shows "finite {k. prod_fun f1 f2 k \<noteq> 0}" |
471 proof - |
471 proof - |
472 have *: "finite {k. (\<exists>l. f1 l \<noteq> 0 \<and> (\<exists>q. f2 q \<noteq> 0 \<and> k = l + q))}" |
472 have *: "finite {k. (\<exists>l. f1 l \<noteq> 0 \<and> (\<exists>q. f2 q \<noteq> 0 \<and> k = l + q))}" |
473 using assms by simp |
473 using assms by simp |
474 { fix k l |
474 have aux: "sum f2 {q. f2 q \<noteq> 0 \<and> k = l + q} = (\<Sum>q. (f2 q when k = l + q))" for k l |
|
475 proof - |
475 have "{q. (f2 q when k = l + q) \<noteq> 0} \<subseteq> {q. f2 q \<noteq> 0 \<and> k = l + q}" by auto |
476 have "{q. (f2 q when k = l + q) \<noteq> 0} \<subseteq> {q. f2 q \<noteq> 0 \<and> k = l + q}" by auto |
476 with fin2 have "sum f2 {q. f2 q \<noteq> 0 \<and> k = l + q} = (\<Sum>q. (f2 q when k = l + q))" |
477 with fin2 show ?thesis |
477 by (simp add: Sum_any.expand_superset [of "{q. f2 q \<noteq> 0 \<and> k = l + q}"]) } |
478 by (simp add: Sum_any.expand_superset [of "{q. f2 q \<noteq> 0 \<and> k = l + q}"]) |
478 note aux = this |
479 qed |
479 have "{k. (\<Sum>l. f1 l * sum f2 {q. f2 q \<noteq> 0 \<and> k = l + q}) \<noteq> 0} |
480 have "{k. (\<Sum>l. f1 l * sum f2 {q. f2 q \<noteq> 0 \<and> k = l + q}) \<noteq> 0} |
480 \<subseteq> {k. (\<exists>l. f1 l * sum f2 {q. f2 q \<noteq> 0 \<and> k = l + q} \<noteq> 0)}" |
481 \<subseteq> {k. (\<exists>l. f1 l * sum f2 {q. f2 q \<noteq> 0 \<and> k = l + q} \<noteq> 0)}" |
481 by (auto elim!: Sum_any.not_neutral_obtains_not_neutral) |
482 by (auto elim!: Sum_any.not_neutral_obtains_not_neutral) |
482 also have "\<dots> \<subseteq> {k. (\<exists>l. f1 l \<noteq> 0 \<and> sum f2 {q. f2 q \<noteq> 0 \<and> k = l + q} \<noteq> 0)}" |
483 also have "\<dots> \<subseteq> {k. (\<exists>l. f1 l \<noteq> 0 \<and> sum f2 {q. f2 q \<noteq> 0 \<and> k = l + q} \<noteq> 0)}" |
483 by (auto dest: mult_not_zero) |
484 by (auto dest: mult_not_zero) |
524 fix k |
525 fix k |
525 from fin_f fin_g fin_h fin_fg'' |
526 from fin_f fin_g fin_h fin_fg'' |
526 have "?lhs k = (\<Sum>(ab, c). (\<Sum>(a, b). f a * g b when ab = a + b) * h c when k = ab + c)" |
527 have "?lhs k = (\<Sum>(ab, c). (\<Sum>(a, b). f a * g b when ab = a + b) * h c when k = ab + c)" |
527 by (simp add: prod_fun_unfold_prod) |
528 by (simp add: prod_fun_unfold_prod) |
528 also have "\<dots> = (\<Sum>(ab, c). (\<Sum>(a, b). f a * g b * h c when k = ab + c when ab = a + b))" |
529 also have "\<dots> = (\<Sum>(ab, c). (\<Sum>(a, b). f a * g b * h c when k = ab + c when ab = a + b))" |
529 using fin_fg |
530 using fin_fg |
530 apply (simp add: Sum_any_left_distrib split_def flip: Sum_any_when_independent) |
531 apply (simp add: Sum_any_left_distrib split_def flip: Sum_any_when_independent) |
531 apply (simp add: when_when when_mult mult_when conj_commute) |
532 apply (simp add: when_when when_mult mult_when conj_commute) |
532 done |
533 done |
533 also have "\<dots> = (\<Sum>(ab, c, a, b). f a * g b * h c when k = ab + c when ab = a + b)" |
534 also have "\<dots> = (\<Sum>(ab, c, a, b). f a * g b * h c when k = ab + c when ab = a + b)" |
534 apply (subst Sum_any.cartesian_product2 [of "(?FG' \<times> ?H) \<times> ?FG"]) |
535 apply (subst Sum_any.cartesian_product2 [of "(?FG' \<times> ?H) \<times> ?FG"]) |
633 fix f g h :: "'a \<Rightarrow> 'b" |
634 fix f g h :: "'a \<Rightarrow> 'b" |
634 assume fin_f: "finite {k. f k \<noteq> 0}" |
635 assume fin_f: "finite {k. f k \<noteq> 0}" |
635 assume fin_g: "finite {k. g k \<noteq> 0}" |
636 assume fin_g: "finite {k. g k \<noteq> 0}" |
636 assume fin_h: "finite {k. h k \<noteq> 0}" |
637 assume fin_h: "finite {k. h k \<noteq> 0}" |
637 show "prod_fun (\<lambda>k. f k + g k) h = (\<lambda>k. prod_fun f h k + prod_fun g h k)" |
638 show "prod_fun (\<lambda>k. f k + g k) h = (\<lambda>k. prod_fun f h k + prod_fun g h k)" |
638 by (auto simp: prod_fun_def fun_eq_iff algebra_simps |
639 by (auto simp: prod_fun_def fun_eq_iff algebra_simps |
639 Sum_any.distrib fin_f fin_g finite_mult_not_eq_zero_rightI) |
640 Sum_any.distrib fin_f fin_g finite_mult_not_eq_zero_rightI) |
640 qed |
641 qed |
641 qed |
642 qed |
642 |
643 |
643 instance poly_mapping :: (monoid_add, semiring_0_cancel) semiring_0_cancel |
644 instance poly_mapping :: (monoid_add, semiring_0_cancel) semiring_0_cancel |
919 |
920 |
920 instance poly_mapping :: (linorder, "{ordered_comm_monoid_add, ordered_ab_semigroup_add_imp_le, linorder}") ordered_ab_semigroup_add |
921 instance poly_mapping :: (linorder, "{ordered_comm_monoid_add, ordered_ab_semigroup_add_imp_le, linorder}") ordered_ab_semigroup_add |
921 proof (intro_classes, transfer) |
922 proof (intro_classes, transfer) |
922 fix f g h :: "'a \<Rightarrow> 'b" |
923 fix f g h :: "'a \<Rightarrow> 'b" |
923 assume *: "less_fun f g \<or> f = g" |
924 assume *: "less_fun f g \<or> f = g" |
924 { assume "less_fun f g" |
925 have "less_fun (\<lambda>k. h k + f k) (\<lambda>k. h k + g k)" if "less_fun f g" |
925 then obtain k where "f k < g k" "(\<And>k'. k' < k \<Longrightarrow> f k' = g k')" |
926 proof - |
|
927 from that obtain k where "f k < g k" "(\<And>k'. k' < k \<Longrightarrow> f k' = g k')" |
926 by (blast elim!: less_funE) |
928 by (blast elim!: less_funE) |
927 then have "h k + f k < h k + g k" "(\<And>k'. k' < k \<Longrightarrow> h k' + f k' = h k' + g k')" |
929 then have "h k + f k < h k + g k" "(\<And>k'. k' < k \<Longrightarrow> h k' + f k' = h k' + g k')" |
928 by simp_all |
930 by simp_all |
929 then have "less_fun (\<lambda>k. h k + f k) (\<lambda>k. h k + g k)" |
931 then show ?thesis |
930 by (blast intro: less_funI) |
932 by (blast intro: less_funI) |
931 } |
933 qed |
932 with * show "less_fun (\<lambda>k. h k + f k) (\<lambda>k. h k + g k) \<or> (\<lambda>k. h k + f k) = (\<lambda>k. h k + g k)" |
934 with * show "less_fun (\<lambda>k. h k + f k) (\<lambda>k. h k + g k) \<or> (\<lambda>k. h k + f k) = (\<lambda>k. h k + g k)" |
933 by (auto simp: fun_eq_iff) |
935 by (auto simp: fun_eq_iff) |
934 qed |
936 qed |
935 |
937 |
936 instance poly_mapping :: (linorder, "{ordered_comm_monoid_add, ordered_ab_semigroup_add_imp_le, cancel_comm_monoid_add, linorder}") linordered_cancel_ab_semigroup_add |
938 instance poly_mapping :: (linorder, "{ordered_comm_monoid_add, ordered_ab_semigroup_add_imp_le, cancel_comm_monoid_add, linorder}") linordered_cancel_ab_semigroup_add |
1271 |
1273 |
1272 lemma mult_map_scale_conv_mult: "map ((*) s) p = single 0 s * p" |
1274 lemma mult_map_scale_conv_mult: "map ((*) s) p = single 0 s * p" |
1273 proof(transfer fixing: s) |
1275 proof(transfer fixing: s) |
1274 fix p :: "'a \<Rightarrow> 'b" |
1276 fix p :: "'a \<Rightarrow> 'b" |
1275 assume *: "finite {x. p x \<noteq> 0}" |
1277 assume *: "finite {x. p x \<noteq> 0}" |
1276 { fix x |
1278 have "prod_fun (\<lambda>k'. s when 0 = k') p x = (\<lambda>k. s * p k when p k \<noteq> 0) x" (is "?lhs = ?rhs") for x |
1277 have "prod_fun (\<lambda>k'. s when 0 = k') p x = |
1279 proof - |
1278 (\<Sum>l :: 'a. if l = 0 then s * (\<Sum>q. p q when x = q) else 0)" |
1280 have "?lhs = (\<Sum>l :: 'a. if l = 0 then s * (\<Sum>q. p q when x = q) else 0)" |
1279 by(auto simp: prod_fun_def when_def intro: Sum_any.cong simp del: Sum_any.delta) |
1281 by (auto simp: prod_fun_def when_def intro: Sum_any.cong simp del: Sum_any.delta) |
1280 also have "\<dots> = (\<lambda>k. s * p k when p k \<noteq> 0) x" by(simp add: when_def) |
1282 also have "\<dots> = ?rhs" |
1281 also note calculation } |
1283 by (simp add: when_def) |
|
1284 finally show ?thesis . |
|
1285 qed |
1282 then show "(\<lambda>k. s * p k when p k \<noteq> 0) = prod_fun (\<lambda>k'. s when 0 = k') p" |
1286 then show "(\<lambda>k. s * p k when p k \<noteq> 0) = prod_fun (\<lambda>k'. s when 0 = k') p" |
1283 by(simp add: fun_eq_iff) |
1287 by(simp add: fun_eq_iff) |
1284 qed |
1288 qed |
1285 |
1289 |
1286 lemma map_single [simp]: |
1290 lemma map_single [simp]: |
1343 |
1347 |
1344 lemma keys_nth [simp]: |
1348 lemma keys_nth [simp]: |
1345 "keys (nth xs) = fst ` {(n, v) \<in> set (enumerate 0 xs). v \<noteq> 0}" |
1349 "keys (nth xs) = fst ` {(n, v) \<in> set (enumerate 0 xs). v \<noteq> 0}" |
1346 proof transfer |
1350 proof transfer |
1347 fix xs :: "'a list" |
1351 fix xs :: "'a list" |
1348 { fix n |
1352 have "n \<in> fst ` {(n, v). (n, v) \<in> set (enumerate 0 xs) \<and> v \<noteq> 0}" |
1349 assume "nth_default 0 xs n \<noteq> 0" |
1353 if "nth_default 0 xs n \<noteq> 0" for n |
1350 then have "n < length xs" and "xs ! n \<noteq> 0" |
1354 proof - |
|
1355 from that have "n < length xs" and "xs ! n \<noteq> 0" |
1351 by (auto simp: nth_default_def split: if_splits) |
1356 by (auto simp: nth_default_def split: if_splits) |
1352 then have "(n, xs ! n) \<in> {(n, v). (n, v) \<in> set (enumerate 0 xs) \<and> v \<noteq> 0}" (is "?x \<in> ?A") |
1357 then have "(n, xs ! n) \<in> {(n, v). (n, v) \<in> set (enumerate 0 xs) \<and> v \<noteq> 0}" (is "?x \<in> ?A") |
1353 by (auto simp: in_set_conv_nth enumerate_eq_zip) |
1358 by (auto simp: in_set_conv_nth enumerate_eq_zip) |
1354 then have "fst ?x \<in> fst ` ?A" |
1359 then have "fst ?x \<in> fst ` ?A" |
1355 by blast |
1360 by blast |
1356 then have "n \<in> fst ` {(n, v). (n, v) \<in> set (enumerate 0 xs) \<and> v \<noteq> 0}" |
1361 then show ?thesis |
1357 by simp |
1362 by simp |
1358 } |
1363 qed |
1359 then show "{k. nth_default 0 xs k \<noteq> 0} = fst ` {(n, v). (n, v) \<in> set (enumerate 0 xs) \<and> v \<noteq> 0}" |
1364 then show "{k. nth_default 0 xs k \<noteq> 0} = fst ` {(n, v). (n, v) \<in> set (enumerate 0 xs) \<and> v \<noteq> 0}" |
1360 by (auto simp: in_enumerate_iff_nth_default_eq) |
1365 by (auto simp: in_enumerate_iff_nth_default_eq) |
1361 qed |
1366 qed |
1362 |
1367 |
1363 lemma range_nth [simp]: |
1368 lemma range_nth [simp]: |
1533 show ?thesis by simp |
1538 show ?thesis by simp |
1534 next |
1539 next |
1535 case False |
1540 case False |
1536 then show ?thesis |
1541 then show ?thesis |
1537 by (simp add: Poly_Mapping.poly_mapping_size_def in_keys_iff) |
1542 by (simp add: Poly_Mapping.poly_mapping_size_def in_keys_iff) |
1538 qed |
1543 qed |
1539 |
1544 |
1540 lemma poly_mapping_size_estimation: |
1545 lemma poly_mapping_size_estimation: |
1541 "k \<in> keys m \<Longrightarrow> y \<le> f k + g (lookup m k) \<Longrightarrow> y < poly_mapping_size m" |
1546 "k \<in> keys m \<Longrightarrow> y \<le> f k + g (lookup m k) \<Longrightarrow> y < poly_mapping_size m" |
1542 using keys_less_poly_mapping_size by (auto intro: le_less_trans) |
1547 using keys_less_poly_mapping_size by (auto intro: le_less_trans) |
1543 |
1548 |
1652 by simp |
1657 by simp |
1653 |
1658 |
1654 lemma keys_cmul: "Poly_Mapping.keys(frag_cmul c a) \<subseteq> Poly_Mapping.keys a" |
1659 lemma keys_cmul: "Poly_Mapping.keys(frag_cmul c a) \<subseteq> Poly_Mapping.keys a" |
1655 using finite_cmul_nonzero [of c a] |
1660 using finite_cmul_nonzero [of c a] |
1656 by (metis lookup_frag_cmul mult_zero_right not_in_keys_iff_lookup_eq_zero subsetI) |
1661 by (metis lookup_frag_cmul mult_zero_right not_in_keys_iff_lookup_eq_zero subsetI) |
1657 |
1662 |
1658 |
1663 |
1659 lemma keys_cmul_iff [iff]: "i \<in> Poly_Mapping.keys (frag_cmul c x) \<longleftrightarrow> i \<in> Poly_Mapping.keys x \<and> c \<noteq> 0" |
1664 lemma keys_cmul_iff [iff]: "i \<in> Poly_Mapping.keys (frag_cmul c x) \<longleftrightarrow> i \<in> Poly_Mapping.keys x \<and> c \<noteq> 0" |
1660 by (metis in_keys_iff lookup_frag_cmul mult_eq_0_iff) |
1665 by (metis in_keys_iff lookup_frag_cmul mult_eq_0_iff) |
1661 |
1666 |
1662 lemma keys_minus [simp]: "Poly_Mapping.keys(-a) = Poly_Mapping.keys a" |
1667 lemma keys_minus [simp]: "Poly_Mapping.keys(-a) = Poly_Mapping.keys a" |
1663 by (metis (no_types, opaque_lifting) in_keys_iff lookup_uminus neg_equal_0_iff_equal subsetI subset_antisym) |
1668 by (metis (no_types, opaque_lifting) in_keys_iff lookup_uminus neg_equal_0_iff_equal subsetI subset_antisym) |
1664 |
1669 |
1665 lemma keys_diff: |
1670 lemma keys_diff: |
1666 "Poly_Mapping.keys(a - b) \<subseteq> Poly_Mapping.keys a \<union> Poly_Mapping.keys b" |
1671 "Poly_Mapping.keys(a - b) \<subseteq> Poly_Mapping.keys a \<union> Poly_Mapping.keys b" |
1667 by (auto simp: in_keys_iff lookup_minus) |
1672 by (auto simp: in_keys_iff lookup_minus) |
1668 |
1673 |
1669 lemma keys_eq_empty [simp]: "Poly_Mapping.keys c = {} \<longleftrightarrow> c = 0" |
1674 lemma keys_eq_empty [simp]: "Poly_Mapping.keys c = {} \<longleftrightarrow> c = 0" |
1670 by (metis in_keys_iff keys_zero lookup_zero poly_mapping_eqI) |
1675 by (metis in_keys_iff keys_zero lookup_zero poly_mapping_eqI) |
1724 using frag_extend_cmul [of f "-1"] by simp |
1729 using frag_extend_cmul [of f "-1"] by simp |
1725 |
1730 |
1726 lemma frag_extend_add: |
1731 lemma frag_extend_add: |
1727 "frag_extend f (a+b) = (frag_extend f a) + (frag_extend f b)" |
1732 "frag_extend f (a+b) = (frag_extend f a) + (frag_extend f b)" |
1728 proof - |
1733 proof - |
1729 have *: "(\<Sum>i\<in>Poly_Mapping.keys a. frag_cmul (poly_mapping.lookup a i) (f i)) |
1734 have *: "(\<Sum>i\<in>Poly_Mapping.keys a. frag_cmul (poly_mapping.lookup a i) (f i)) |
1730 = (\<Sum>i\<in>Poly_Mapping.keys a \<union> Poly_Mapping.keys b. frag_cmul (poly_mapping.lookup a i) (f i))" |
1735 = (\<Sum>i\<in>Poly_Mapping.keys a \<union> Poly_Mapping.keys b. frag_cmul (poly_mapping.lookup a i) (f i))" |
1731 "(\<Sum>i\<in>Poly_Mapping.keys b. frag_cmul (poly_mapping.lookup b i) (f i)) |
1736 "(\<Sum>i\<in>Poly_Mapping.keys b. frag_cmul (poly_mapping.lookup b i) (f i)) |
1732 = (\<Sum>i\<in>Poly_Mapping.keys a \<union> Poly_Mapping.keys b. frag_cmul (poly_mapping.lookup b i) (f i))" |
1737 = (\<Sum>i\<in>Poly_Mapping.keys a \<union> Poly_Mapping.keys b. frag_cmul (poly_mapping.lookup b i) (f i))" |
1733 by (auto simp: in_keys_iff intro: sum.mono_neutral_cong_left) |
1738 by (auto simp: in_keys_iff intro: sum.mono_neutral_cong_left) |
1734 have "frag_extend f (a+b) = (\<Sum>i\<in>Poly_Mapping.keys (a + b). |
1739 have "frag_extend f (a+b) = (\<Sum>i\<in>Poly_Mapping.keys (a + b). |
1735 frag_cmul (poly_mapping.lookup a i) (f i) + frag_cmul (poly_mapping.lookup b i) (f i)) " |
1740 frag_cmul (poly_mapping.lookup a i) (f i) + frag_cmul (poly_mapping.lookup b i) (f i)) " |
1736 by (auto simp: frag_extend_def Poly_Mapping.lookup_add frag_cmul_distrib) |
1741 by (auto simp: frag_extend_def Poly_Mapping.lookup_add frag_cmul_distrib) |
1737 also have "... = (\<Sum>i \<in> Poly_Mapping.keys a \<union> Poly_Mapping.keys b. frag_cmul (poly_mapping.lookup a i) (f i) |
1742 also have "... = (\<Sum>i \<in> Poly_Mapping.keys a \<union> Poly_Mapping.keys b. frag_cmul (poly_mapping.lookup a i) (f i) |
1738 + frag_cmul (poly_mapping.lookup b i) (f i))" |
1743 + frag_cmul (poly_mapping.lookup b i) (f i))" |
1739 proof (rule sum.mono_neutral_cong_left) |
1744 proof (rule sum.mono_neutral_cong_left) |
1740 show "\<forall>i\<in>keys a \<union> keys b - keys (a + b). |
1745 show "\<forall>i\<in>keys a \<union> keys b - keys (a + b). |
1741 frag_cmul (lookup a i) (f i) + frag_cmul (lookup b i) (f i) = 0" |
1746 frag_cmul (lookup a i) (f i) + frag_cmul (lookup b i) (f i) = 0" |
1742 by (metis DiffD2 frag_cmul_distrib frag_cmul_zero in_keys_iff lookup_add) |
1747 by (metis DiffD2 frag_cmul_distrib frag_cmul_zero in_keys_iff lookup_add) |
1828 |
1833 |
1829 lemma frag_split: |
1834 lemma frag_split: |
1830 fixes c :: "'a \<Rightarrow>\<^sub>0 int" |
1835 fixes c :: "'a \<Rightarrow>\<^sub>0 int" |
1831 assumes "Poly_Mapping.keys c \<subseteq> S \<union> T" |
1836 assumes "Poly_Mapping.keys c \<subseteq> S \<union> T" |
1832 obtains d e where "Poly_Mapping.keys d \<subseteq> S" "Poly_Mapping.keys e \<subseteq> T" "d + e = c" |
1837 obtains d e where "Poly_Mapping.keys d \<subseteq> S" "Poly_Mapping.keys e \<subseteq> T" "d + e = c" |
1833 proof |
1838 proof |
1834 let ?d = "frag_extend (\<lambda>f. if f \<in> S then frag_of f else 0) c" |
1839 let ?d = "frag_extend (\<lambda>f. if f \<in> S then frag_of f else 0) c" |
1835 let ?e = "frag_extend (\<lambda>f. if f \<in> S then 0 else frag_of f) c" |
1840 let ?e = "frag_extend (\<lambda>f. if f \<in> S then 0 else frag_of f) c" |
1836 show "Poly_Mapping.keys ?d \<subseteq> S" "Poly_Mapping.keys ?e \<subseteq> T" |
1841 show "Poly_Mapping.keys ?d \<subseteq> S" "Poly_Mapping.keys ?e \<subseteq> T" |
1837 using assms by (auto intro!: order_trans [OF keys_frag_extend] split: if_split_asm) |
1842 using assms by (auto intro!: order_trans [OF keys_frag_extend] split: if_split_asm) |
1838 show "?d + ?e = c" |
1843 show "?d + ?e = c" |