haftmann@58101: (* Author: Tobias Nipkow, TU Muenchen *) haftmann@58101: wenzelm@58889: section {* Sum and product over lists *} haftmann@58101: haftmann@58101: theory Groups_List haftmann@58101: imports List haftmann@58101: begin haftmann@58101: haftmann@58320: no_notation times (infixl "*" 70) haftmann@58320: no_notation Groups.one ("1") haftmann@58320: haftmann@58320: locale monoid_list = monoid haftmann@58320: begin haftmann@58320: haftmann@58320: definition F :: "'a list \ 'a" haftmann@58320: where haftmann@58320: eq_foldr [code]: "F xs = foldr f xs 1" haftmann@58320: haftmann@58320: lemma Nil [simp]: haftmann@58320: "F [] = 1" haftmann@58320: by (simp add: eq_foldr) haftmann@58320: haftmann@58320: lemma Cons [simp]: haftmann@58320: "F (x # xs) = x * F xs" haftmann@58320: by (simp add: eq_foldr) haftmann@58320: haftmann@58320: lemma append [simp]: haftmann@58320: "F (xs @ ys) = F xs * F ys" haftmann@58320: by (induct xs) (simp_all add: assoc) haftmann@58320: haftmann@58320: end haftmann@58101: haftmann@58320: locale comm_monoid_list = comm_monoid + monoid_list haftmann@58320: begin haftmann@58320: haftmann@58320: lemma rev [simp]: haftmann@58320: "F (rev xs) = F xs" haftmann@58320: by (simp add: eq_foldr foldr_fold fold_rev fun_eq_iff assoc left_commute) haftmann@58320: haftmann@58320: end haftmann@58320: haftmann@58320: locale comm_monoid_list_set = list: comm_monoid_list + set: comm_monoid_set haftmann@58320: begin haftmann@58101: haftmann@58320: lemma distinct_set_conv_list: haftmann@58320: "distinct xs \ set.F g (set xs) = list.F (map g xs)" haftmann@58320: by (induct xs) simp_all haftmann@58101: haftmann@58320: lemma set_conv_list [code]: haftmann@58320: "set.F g (set xs) = list.F (map g (remdups xs))" haftmann@58320: by (simp add: distinct_set_conv_list [symmetric]) haftmann@58320: haftmann@58320: end haftmann@58320: haftmann@58320: notation times (infixl "*" 70) haftmann@58320: notation Groups.one ("1") haftmann@58320: haftmann@58320: haftmann@58320: subsection {* List summation *} haftmann@58320: haftmann@58320: context monoid_add haftmann@58320: begin haftmann@58320: haftmann@58320: definition listsum :: "'a list \ 'a" haftmann@58320: where haftmann@58320: "listsum = monoid_list.F plus 0" haftmann@58101: haftmann@58320: sublocale listsum!: monoid_list plus 0 haftmann@58320: where haftmann@58320: "monoid_list.F plus 0 = listsum" haftmann@58320: proof - haftmann@58320: show "monoid_list plus 0" .. haftmann@58320: then interpret listsum!: monoid_list plus 0 . haftmann@58320: from listsum_def show "monoid_list.F plus 0 = listsum" by rule haftmann@58320: qed haftmann@58320: haftmann@58320: end haftmann@58320: haftmann@58320: context comm_monoid_add haftmann@58320: begin haftmann@58320: haftmann@58320: sublocale listsum!: comm_monoid_list plus 0 haftmann@58320: where haftmann@58320: "monoid_list.F plus 0 = listsum" haftmann@58320: proof - haftmann@58320: show "comm_monoid_list plus 0" .. haftmann@58320: then interpret listsum!: comm_monoid_list plus 0 . haftmann@58320: from listsum_def show "monoid_list.F plus 0 = listsum" by rule haftmann@58101: qed haftmann@58101: haftmann@58320: sublocale setsum!: comm_monoid_list_set plus 0 haftmann@58320: where haftmann@58320: "monoid_list.F plus 0 = listsum" haftmann@58320: and "comm_monoid_set.F plus 0 = setsum" haftmann@58320: proof - haftmann@58320: show "comm_monoid_list_set plus 0" .. haftmann@58320: then interpret setsum!: comm_monoid_list_set plus 0 . haftmann@58320: from listsum_def show "monoid_list.F plus 0 = listsum" by rule haftmann@58320: from setsum_def show "comm_monoid_set.F plus 0 = setsum" by rule haftmann@58320: qed haftmann@58320: haftmann@58320: end haftmann@58320: haftmann@58320: text {* Some syntactic sugar for summing a function over a list: *} haftmann@58101: haftmann@58101: syntax haftmann@58101: "_listsum" :: "pttrn => 'a list => 'b => 'b" ("(3SUM _<-_. _)" [0, 51, 10] 10) haftmann@58101: syntax (xsymbols) haftmann@58101: "_listsum" :: "pttrn => 'a list => 'b => 'b" ("(3\_\_. _)" [0, 51, 10] 10) haftmann@58101: syntax (HTML output) haftmann@58101: "_listsum" :: "pttrn => 'a list => 'b => 'b" ("(3\_\_. _)" [0, 51, 10] 10) haftmann@58101: haftmann@58101: translations -- {* Beware of argument permutation! *} haftmann@58101: "SUM x<-xs. b" == "CONST listsum (CONST map (%x. b) xs)" haftmann@58101: "\x\xs. b" == "CONST listsum (CONST map (%x. b) xs)" haftmann@58101: haftmann@58320: text {* TODO duplicates *} haftmann@58320: lemmas listsum_simps = listsum.Nil listsum.Cons haftmann@58320: lemmas listsum_append = listsum.append haftmann@58320: lemmas listsum_rev = listsum.rev haftmann@58320: haftmann@58320: lemma (in monoid_add) fold_plus_listsum_rev: haftmann@58320: "fold plus xs = plus (listsum (rev xs))" haftmann@58320: proof haftmann@58320: fix x haftmann@58320: have "fold plus xs x = listsum (rev xs @ [x])" haftmann@58320: by (simp add: foldr_conv_fold listsum.eq_foldr) haftmann@58320: also have "\ = listsum (rev xs) + x" haftmann@58320: by simp haftmann@58320: finally show "fold plus xs x = listsum (rev xs) + x" haftmann@58320: . haftmann@58320: qed haftmann@58320: haftmann@58101: lemma (in comm_monoid_add) listsum_map_remove1: haftmann@58101: "x \ set xs \ listsum (map f xs) = f x + listsum (map f (remove1 x xs))" haftmann@58101: by (induct xs) (auto simp add: ac_simps) haftmann@58101: haftmann@58101: lemma (in monoid_add) size_list_conv_listsum: haftmann@58101: "size_list f xs = listsum (map f xs) + size xs" haftmann@58101: by (induct xs) auto haftmann@58101: haftmann@58101: lemma (in monoid_add) length_concat: haftmann@58101: "length (concat xss) = listsum (map length xss)" haftmann@58101: by (induct xss) simp_all haftmann@58101: haftmann@58101: lemma (in monoid_add) length_product_lists: haftmann@58101: "length (product_lists xss) = foldr op * (map length xss) 1" haftmann@58101: proof (induct xss) haftmann@58101: case (Cons xs xss) then show ?case by (induct xs) (auto simp: length_concat o_def) haftmann@58101: qed simp haftmann@58101: haftmann@58101: lemma (in monoid_add) listsum_map_filter: haftmann@58101: assumes "\x. x \ set xs \ \ P x \ f x = 0" haftmann@58101: shows "listsum (map f (filter P xs)) = listsum (map f xs)" haftmann@58101: using assms by (induct xs) auto haftmann@58101: haftmann@58101: lemma (in comm_monoid_add) distinct_listsum_conv_Setsum: haftmann@58101: "distinct xs \ listsum xs = Setsum (set xs)" haftmann@58101: by (induct xs) simp_all haftmann@58101: nipkow@58995: lemma listsum_upt[simp]: nipkow@58995: "m \ n \ listsum [m.. {m.. (\n \ set ns. n = 0)" haftmann@58101: by (induct ns) simp_all haftmann@58101: haftmann@58101: lemma member_le_listsum_nat: haftmann@58101: "(n :: nat) \ set ns \ n \ listsum ns" haftmann@58101: by (induct ns) auto haftmann@58101: haftmann@58101: lemma elem_le_listsum_nat: haftmann@58101: "k < size ns \ ns ! k \ listsum (ns::nat list)" haftmann@58101: by (rule member_le_listsum_nat) simp haftmann@58101: haftmann@58101: lemma listsum_update_nat: haftmann@58101: "k < size ns \ listsum (ns[k := (n::nat)]) = listsum ns + n - ns ! k" haftmann@58101: apply(induct ns arbitrary:k) haftmann@58101: apply (auto split:nat.split) haftmann@58101: apply(drule elem_le_listsum_nat) haftmann@58101: apply arith haftmann@58101: done haftmann@58101: haftmann@58101: lemma (in monoid_add) listsum_triv: haftmann@58101: "(\x\xs. r) = of_nat (length xs) * r" haftmann@58101: by (induct xs) (simp_all add: distrib_right) haftmann@58101: haftmann@58101: lemma (in monoid_add) listsum_0 [simp]: haftmann@58101: "(\x\xs. 0) = 0" haftmann@58101: by (induct xs) (simp_all add: distrib_right) haftmann@58101: haftmann@58101: text{* For non-Abelian groups @{text xs} needs to be reversed on one side: *} haftmann@58101: lemma (in ab_group_add) uminus_listsum_map: haftmann@58101: "- listsum (map f xs) = listsum (map (uminus \ f) xs)" haftmann@58101: by (induct xs) simp_all haftmann@58101: haftmann@58101: lemma (in comm_monoid_add) listsum_addf: haftmann@58101: "(\x\xs. f x + g x) = listsum (map f xs) + listsum (map g xs)" haftmann@58101: by (induct xs) (simp_all add: algebra_simps) haftmann@58101: haftmann@58101: lemma (in ab_group_add) listsum_subtractf: haftmann@58101: "(\x\xs. f x - g x) = listsum (map f xs) - listsum (map g xs)" haftmann@58101: by (induct xs) (simp_all add: algebra_simps) haftmann@58101: haftmann@58101: lemma (in semiring_0) listsum_const_mult: haftmann@58101: "(\x\xs. c * f x) = c * (\x\xs. f x)" haftmann@58101: by (induct xs) (simp_all add: algebra_simps) haftmann@58101: haftmann@58101: lemma (in semiring_0) listsum_mult_const: haftmann@58101: "(\x\xs. f x * c) = (\x\xs. f x) * c" haftmann@58101: by (induct xs) (simp_all add: algebra_simps) haftmann@58101: haftmann@58101: lemma (in ordered_ab_group_add_abs) listsum_abs: haftmann@58101: "\listsum xs\ \ listsum (map abs xs)" haftmann@58101: by (induct xs) (simp_all add: order_trans [OF abs_triangle_ineq]) haftmann@58101: haftmann@58101: lemma listsum_mono: haftmann@58101: fixes f g :: "'a \ 'b::{monoid_add, ordered_ab_semigroup_add}" haftmann@58101: shows "(\x. x \ set xs \ f x \ g x) \ (\x\xs. f x) \ (\x\xs. g x)" haftmann@58101: by (induct xs) (simp, simp add: add_mono) haftmann@58101: haftmann@58101: lemma (in monoid_add) listsum_distinct_conv_setsum_set: haftmann@58101: "distinct xs \ listsum (map f xs) = setsum f (set xs)" haftmann@58101: by (induct xs) simp_all haftmann@58101: haftmann@58101: lemma (in monoid_add) interv_listsum_conv_setsum_set_nat: haftmann@58101: "listsum (map f [m.. i = 0 ..< length xs. xs ! i)" haftmann@58101: using interv_listsum_conv_setsum_set_nat [of "op ! xs" 0 "length xs"] by (simp add: map_nth) haftmann@58101: haftmann@58101: haftmann@58101: subsection {* Further facts about @{const List.n_lists} *} haftmann@58101: haftmann@58101: lemma length_n_lists: "length (List.n_lists n xs) = length xs ^ n" haftmann@58101: by (induct n) (auto simp add: comp_def length_concat listsum_triv) haftmann@58101: haftmann@58101: lemma distinct_n_lists: haftmann@58101: assumes "distinct xs" haftmann@58101: shows "distinct (List.n_lists n xs)" haftmann@58101: proof (rule card_distinct) haftmann@58101: from assms have card_length: "card (set xs) = length xs" by (rule distinct_card) haftmann@58101: have "card (set (List.n_lists n xs)) = card (set xs) ^ n" haftmann@58101: proof (induct n) haftmann@58101: case 0 then show ?case by simp haftmann@58101: next haftmann@58101: case (Suc n) haftmann@58101: moreover have "card (\ys\set (List.n_lists n xs). (\y. y # ys) ` set xs) haftmann@58101: = (\ys\set (List.n_lists n xs). card ((\y. y # ys) ` set xs))" haftmann@58101: by (rule card_UN_disjoint) auto haftmann@58101: moreover have "\ys. card ((\y. y # ys) ` set xs) = card (set xs)" haftmann@58101: by (rule card_image) (simp add: inj_on_def) haftmann@58101: ultimately show ?case by auto haftmann@58101: qed haftmann@58101: also have "\ = length xs ^ n" by (simp add: card_length) haftmann@58101: finally show "card (set (List.n_lists n xs)) = length (List.n_lists n xs)" haftmann@58101: by (simp add: length_n_lists) haftmann@58101: qed haftmann@58101: haftmann@58101: haftmann@58101: subsection {* Tools setup *} haftmann@58101: haftmann@58320: lemmas setsum_code = setsum.set_conv_list haftmann@58320: haftmann@58101: lemma setsum_set_upto_conv_listsum_int [code_unfold]: haftmann@58101: "setsum f (set [i..j::int]) = listsum (map f [i..j])" haftmann@58101: by (simp add: interv_listsum_conv_setsum_set_int) haftmann@58101: haftmann@58101: lemma setsum_set_upt_conv_listsum_nat [code_unfold]: haftmann@58101: "setsum f (set [m.. A ===> A) op + op +" haftmann@58101: shows "(list_all2 A ===> A) listsum listsum" haftmann@58320: unfolding listsum.eq_foldr [abs_def] haftmann@58101: by transfer_prover haftmann@58101: haftmann@58101: end haftmann@58101: haftmann@58368: haftmann@58368: subsection {* List product *} haftmann@58368: haftmann@58368: context monoid_mult haftmann@58368: begin haftmann@58368: haftmann@58368: definition listprod :: "'a list \ 'a" haftmann@58368: where haftmann@58368: "listprod = monoid_list.F times 1" haftmann@58368: haftmann@58368: sublocale listprod!: monoid_list times 1 haftmann@58368: where haftmann@58368: "monoid_list.F times 1 = listprod" haftmann@58368: proof - haftmann@58368: show "monoid_list times 1" .. haftmann@58368: then interpret listprod!: monoid_list times 1 . haftmann@58368: from listprod_def show "monoid_list.F times 1 = listprod" by rule haftmann@58368: qed haftmann@58368: haftmann@58320: end haftmann@58368: haftmann@58368: context comm_monoid_mult haftmann@58368: begin haftmann@58368: haftmann@58368: sublocale listprod!: comm_monoid_list times 1 haftmann@58368: where haftmann@58368: "monoid_list.F times 1 = listprod" haftmann@58368: proof - haftmann@58368: show "comm_monoid_list times 1" .. haftmann@58368: then interpret listprod!: comm_monoid_list times 1 . haftmann@58368: from listprod_def show "monoid_list.F times 1 = listprod" by rule haftmann@58368: qed haftmann@58368: haftmann@58368: sublocale setprod!: comm_monoid_list_set times 1 haftmann@58368: where haftmann@58368: "monoid_list.F times 1 = listprod" haftmann@58368: and "comm_monoid_set.F times 1 = setprod" haftmann@58368: proof - haftmann@58368: show "comm_monoid_list_set times 1" .. haftmann@58368: then interpret setprod!: comm_monoid_list_set times 1 . haftmann@58368: from listprod_def show "monoid_list.F times 1 = listprod" by rule haftmann@58368: from setprod_def show "comm_monoid_set.F times 1 = setprod" by rule haftmann@58368: qed haftmann@58368: haftmann@58368: end haftmann@58368: haftmann@58368: text {* Some syntactic sugar: *} haftmann@58368: haftmann@58368: syntax haftmann@58368: "_listprod" :: "pttrn => 'a list => 'b => 'b" ("(3PROD _<-_. _)" [0, 51, 10] 10) haftmann@58368: syntax (xsymbols) haftmann@58368: "_listprod" :: "pttrn => 'a list => 'b => 'b" ("(3\_\_. _)" [0, 51, 10] 10) haftmann@58368: syntax (HTML output) haftmann@58368: "_listprod" :: "pttrn => 'a list => 'b => 'b" ("(3\_\_. _)" [0, 51, 10] 10) haftmann@58368: haftmann@58368: translations -- {* Beware of argument permutation! *} haftmann@58368: "PROD x<-xs. b" == "CONST listprod (CONST map (%x. b) xs)" haftmann@58368: "\x\xs. b" == "CONST listprod (CONST map (%x. b) xs)" haftmann@58368: haftmann@58368: end