src/HOL/Library/Poly_Mapping.thy
changeset 81332 f94b30fa2b6c
parent 80914 d97fdabd9e2b
equal deleted inserted replaced
81331:405f7fd15f4e 81332:f94b30fa2b6c
   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"