haftmann@58197: (* Author: Florian Haftmann, TU Muenchen *) haftmann@58197: haftmann@58197: header \Big sum and product over function bodies\ haftmann@58197: haftmann@58197: theory Groups_Big_Fun haftmann@58197: imports haftmann@58197: Main haftmann@58197: "~~/src/Tools/Permanent_Interpretation" haftmann@58197: begin haftmann@58197: haftmann@58197: subsection \Abstract product\ haftmann@58197: haftmann@58197: no_notation times (infixl "*" 70) haftmann@58197: no_notation Groups.one ("1") haftmann@58197: haftmann@58197: locale comm_monoid_fun = comm_monoid haftmann@58197: begin haftmann@58197: haftmann@58197: definition G :: "('b \ 'a) \ 'a" haftmann@58197: where haftmann@58197: expand_set: "G g = comm_monoid_set.F f 1 g {a. g a \ 1}" haftmann@58197: haftmann@58197: interpretation F!: comm_monoid_set f 1 haftmann@58197: .. haftmann@58197: haftmann@58197: lemma expand_superset: haftmann@58197: assumes "finite A" and "{a. g a \ 1} \ A" haftmann@58197: shows "G g = F.F g A" haftmann@58197: apply (simp add: expand_set) haftmann@58197: apply (rule F.same_carrierI [of A]) haftmann@58197: apply (simp_all add: assms) haftmann@58197: done haftmann@58197: haftmann@58197: lemma conditionalize: haftmann@58197: assumes "finite A" haftmann@58197: shows "F.F g A = G (\a. if a \ A then g a else 1)" haftmann@58197: using assms haftmann@58197: apply (simp add: expand_set) haftmann@58197: apply (rule F.same_carrierI [of A]) haftmann@58197: apply auto haftmann@58197: done haftmann@58197: haftmann@58197: lemma neutral [simp]: haftmann@58197: "G (\a. 1) = 1" haftmann@58197: by (simp add: expand_set) haftmann@58197: haftmann@58197: lemma update [simp]: haftmann@58197: assumes "finite {a. g a \ 1}" haftmann@58197: assumes "g a = 1" haftmann@58197: shows "G (g(a := b)) = b * G g" haftmann@58197: proof (cases "b = 1") haftmann@58197: case True with `g a = 1` show ?thesis haftmann@58197: by (simp add: expand_set) (rule F.cong, auto) haftmann@58197: next haftmann@58197: case False haftmann@58197: moreover have "{a'. a' \ a \ g a' \ 1} = insert a {a. g a \ 1}" haftmann@58197: by auto haftmann@58197: moreover from `g a = 1` have "a \ {a. g a \ 1}" haftmann@58197: by simp haftmann@58197: moreover have "F.F (\a'. if a' = a then b else g a') {a. g a \ 1} = F.F g {a. g a \ 1}" haftmann@58197: by (rule F.cong) (auto simp add: `g a = 1`) haftmann@58197: ultimately show ?thesis using `finite {a. g a \ 1}` by (simp add: expand_set) haftmann@58197: qed haftmann@58197: haftmann@58197: lemma infinite [simp]: haftmann@58197: "\ finite {a. g a \ 1} \ G g = 1" haftmann@58197: by (simp add: expand_set) haftmann@58197: haftmann@58197: lemma cong: haftmann@58197: assumes "\a. g a = h a" haftmann@58197: shows "G g = G h" haftmann@58197: using assms by (simp add: expand_set) haftmann@58197: haftmann@58197: lemma strong_cong [cong]: haftmann@58197: assumes "\a. g a = h a" haftmann@58197: shows "G (\a. g a) = G (\a. h a)" haftmann@58197: using assms by (fact cong) haftmann@58197: haftmann@58197: lemma not_neutral_obtains_not_neutral: haftmann@58197: assumes "G g \ 1" haftmann@58197: obtains a where "g a \ 1" haftmann@58197: using assms by (auto elim: F.not_neutral_contains_not_neutral simp add: expand_set) haftmann@58197: haftmann@58197: lemma reindex_cong: haftmann@58197: assumes "bij l" haftmann@58197: assumes "g \ l = h" haftmann@58197: shows "G g = G h" haftmann@58197: proof - haftmann@58197: from assms have unfold: "h = g \ l" by simp haftmann@58197: from `bij l` have "inj l" by (rule bij_is_inj) haftmann@58197: then have "inj_on l {a. h a \ 1}" by (rule subset_inj_on) simp haftmann@58197: moreover from `bij l` have "{a. g a \ 1} = l ` {a. h a \ 1}" haftmann@58197: by (auto simp add: image_Collect unfold elim: bij_pointE) haftmann@58197: moreover have "\x. x \ {a. h a \ 1} \ g (l x) = h x" haftmann@58197: by (simp add: unfold) haftmann@58197: ultimately have "F.F g {a. g a \ 1} = F.F h {a. h a \ 1}" haftmann@58197: by (rule F.reindex_cong) haftmann@58197: then show ?thesis by (simp add: expand_set) haftmann@58197: qed haftmann@58197: haftmann@58197: lemma distrib: haftmann@58197: assumes "finite {a. g a \ 1}" and "finite {a. h a \ 1}" haftmann@58197: shows "G (\a. g a * h a) = G g * G h" haftmann@58197: proof - haftmann@58197: from assms have "finite ({a. g a \ 1} \ {a. h a \ 1})" by simp haftmann@58197: moreover have "{a. g a * h a \ 1} \ {a. g a \ 1} \ {a. h a \ 1}" haftmann@58197: by auto (drule sym, simp) haftmann@58197: ultimately show ?thesis haftmann@58197: using assms haftmann@58197: by (simp add: expand_superset [of "{a. g a \ 1} \ {a. h a \ 1}"] F.distrib) haftmann@58197: qed haftmann@58197: haftmann@58197: lemma commute: haftmann@58197: assumes "finite C" haftmann@58197: assumes subset: "{a. \b. g a b \ 1} \ {b. \a. g a b \ 1} \ C" (is "?A \ ?B \ C") haftmann@58197: shows "G (\a. G (g a)) = G (\b. G (\a. g a b))" haftmann@58197: proof - haftmann@58197: from `finite C` subset haftmann@58197: have "finite ({a. \b. g a b \ 1} \ {b. \a. g a b \ 1})" haftmann@58197: by (rule rev_finite_subset) haftmann@58197: then have fins: haftmann@58197: "finite {b. \a. g a b \ 1}" "finite {a. \b. g a b \ 1}" haftmann@58197: by (auto simp add: finite_cartesian_product_iff) haftmann@58197: have subsets: "\a. {b. g a b \ 1} \ {b. \a. g a b \ 1}" haftmann@58197: "\b. {a. g a b \ 1} \ {a. \b. g a b \ 1}" haftmann@58197: "{a. F.F (g a) {b. \a. g a b \ 1} \ 1} \ {a. \b. g a b \ 1}" haftmann@58197: "{a. F.F (\aa. g aa a) {a. \b. g a b \ 1} \ 1} \ {b. \a. g a b \ 1}" haftmann@58197: by (auto elim: F.not_neutral_contains_not_neutral) haftmann@58197: from F.commute have haftmann@58197: "F.F (\a. F.F (g a) {b. \a. g a b \ 1}) {a. \b. g a b \ 1} = haftmann@58197: F.F (\b. F.F (\a. g a b) {a. \b. g a b \ 1}) {b. \a. g a b \ 1}" . haftmann@58197: with subsets fins have "G (\a. F.F (g a) {b. \a. g a b \ 1}) = haftmann@58197: G (\b. F.F (\a. g a b) {a. \b. g a b \ 1})" haftmann@58197: by (auto simp add: expand_superset [of "{b. \a. g a b \ 1}"] haftmann@58197: expand_superset [of "{a. \b. g a b \ 1}"]) haftmann@58197: with subsets fins show ?thesis haftmann@58197: by (auto simp add: expand_superset [of "{b. \a. g a b \ 1}"] haftmann@58197: expand_superset [of "{a. \b. g a b \ 1}"]) haftmann@58197: qed haftmann@58197: haftmann@58197: lemma cartesian_product: haftmann@58197: assumes "finite C" haftmann@58197: assumes subset: "{a. \b. g a b \ 1} \ {b. \a. g a b \ 1} \ C" (is "?A \ ?B \ C") haftmann@58197: shows "G (\a. G (g a)) = G (\(a, b). g a b)" haftmann@58197: proof - haftmann@58197: from subset `finite C` have fin_prod: "finite (?A \ ?B)" haftmann@58197: by (rule finite_subset) haftmann@58197: from fin_prod have "finite ?A" and "finite ?B" haftmann@58197: by (auto simp add: finite_cartesian_product_iff) haftmann@58197: have *: "G (\a. G (g a)) = haftmann@58197: (F.F (\a. F.F (g a) {b. \a. g a b \ 1}) {a. \b. g a b \ 1})" haftmann@58197: apply (subst expand_superset [of "?B"]) haftmann@58197: apply (rule `finite ?B`) haftmann@58197: apply auto haftmann@58197: apply (subst expand_superset [of "?A"]) haftmann@58197: apply (rule `finite ?A`) haftmann@58197: apply auto haftmann@58197: apply (erule F.not_neutral_contains_not_neutral) haftmann@58197: apply auto haftmann@58197: done haftmann@58197: have "{p. (case p of (a, b) \ g a b) \ 1} \ ?A \ ?B" haftmann@58197: by auto haftmann@58197: with subset have **: "{p. (case p of (a, b) \ g a b) \ 1} \ C" haftmann@58197: by blast haftmann@58197: show ?thesis haftmann@58197: apply (simp add: *) haftmann@58197: apply (simp add: F.cartesian_product) haftmann@58197: apply (subst expand_superset [of C]) haftmann@58197: apply (rule `finite C`) haftmann@58197: apply (simp_all add: **) haftmann@58197: apply (rule F.same_carrierI [of C]) haftmann@58197: apply (rule `finite C`) haftmann@58197: apply (simp_all add: subset) haftmann@58197: apply auto haftmann@58197: done haftmann@58197: qed haftmann@58197: haftmann@58197: lemma cartesian_product2: haftmann@58197: assumes fin: "finite D" haftmann@58197: assumes subset: "{(a, b). \c. g a b c \ 1} \ {c. \a b. g a b c \ 1} \ D" (is "?AB \ ?C \ D") haftmann@58197: shows "G (\(a, b). G (g a b)) = G (\(a, b, c). g a b c)" haftmann@58197: proof - haftmann@58197: have bij: "bij (\(a, b, c). ((a, b), c))" haftmann@58197: by (auto intro!: bijI injI simp add: image_def) haftmann@58197: have "{p. \c. g (fst p) (snd p) c \ 1} \ {c. \p. g (fst p) (snd p) c \ 1} \ D" haftmann@58197: by auto (insert subset, auto) haftmann@58197: with fin have "G (\p. G (g (fst p) (snd p))) = G (\(p, c). g (fst p) (snd p) c)" haftmann@58197: by (rule cartesian_product) haftmann@58197: then have "G (\(a, b). G (g a b)) = G (\((a, b), c). g a b c)" haftmann@58197: by (auto simp add: split_def) haftmann@58197: also have "G (\((a, b), c). g a b c) = G (\(a, b, c). g a b c)" haftmann@58197: using bij by (rule reindex_cong [of "\(a, b, c). ((a, b), c)"]) (simp add: fun_eq_iff) haftmann@58197: finally show ?thesis . haftmann@58197: qed haftmann@58197: haftmann@58197: lemma delta [simp]: haftmann@58197: "G (\b. if b = a then g b else 1) = g a" haftmann@58197: proof - haftmann@58197: have "{b. (if b = a then g b else 1) \ 1} \ {a}" by auto haftmann@58197: then show ?thesis by (simp add: expand_superset [of "{a}"]) haftmann@58197: qed haftmann@58197: haftmann@58197: lemma delta' [simp]: haftmann@58197: "G (\b. if a = b then g b else 1) = g a" haftmann@58197: proof - haftmann@58197: have "(\b. if a = b then g b else 1) = (\b. if b = a then g b else 1)" haftmann@58197: by (simp add: fun_eq_iff) haftmann@58197: then have "G (\b. if a = b then g b else 1) = G (\b. if b = a then g b else 1)" haftmann@58197: by (simp cong del: strong_cong) haftmann@58197: then show ?thesis by simp haftmann@58197: qed haftmann@58197: haftmann@58197: end haftmann@58197: haftmann@58197: notation times (infixl "*" 70) haftmann@58197: notation Groups.one ("1") haftmann@58197: haftmann@58197: haftmann@58197: subsection \Concrete sum\ haftmann@58197: haftmann@58197: context comm_monoid_add haftmann@58197: begin haftmann@58197: haftmann@58197: definition Sum_any :: "('b \ 'a) \ 'a" haftmann@58197: where haftmann@58197: "Sum_any = comm_monoid_fun.G plus 0" haftmann@58197: haftmann@58197: permanent_interpretation Sum_any!: comm_monoid_fun plus 0 haftmann@58197: where haftmann@58197: "comm_monoid_fun.G plus 0 = Sum_any" and haftmann@58197: "comm_monoid_set.F plus 0 = setsum" haftmann@58197: proof - haftmann@58197: show "comm_monoid_fun plus 0" .. haftmann@58197: then interpret Sum_any!: comm_monoid_fun plus 0 . haftmann@58197: from Sum_any_def show "comm_monoid_fun.G plus 0 = Sum_any" by rule haftmann@58197: from setsum_def show "comm_monoid_set.F plus 0 = setsum" by rule haftmann@58197: qed haftmann@58197: haftmann@58197: end haftmann@58197: haftmann@58197: syntax haftmann@58197: "_Sum_any" :: "pttrn \ 'a \ 'a::comm_monoid_add" ("(3SUM _. _)" [0, 10] 10) haftmann@58197: syntax (xsymbols) haftmann@58197: "_Sum_any" :: "pttrn \ 'a \ 'a::comm_monoid_add" ("(3\_. _)" [0, 10] 10) haftmann@58197: syntax (HTML output) haftmann@58197: "_Sum_any" :: "pttrn \ 'a \ 'a::comm_monoid_add" ("(3\_. _)" [0, 10] 10) haftmann@58197: haftmann@58197: translations haftmann@58197: "\a. b" == "CONST Sum_any (\a. b)" haftmann@58197: haftmann@58197: lemma Sum_any_left_distrib: haftmann@58197: fixes r :: "'a :: semiring_0" haftmann@58197: assumes "finite {a. g a \ 0}" haftmann@58197: shows "Sum_any g * r = (\n. g n * r)" haftmann@58197: proof - haftmann@58197: note assms haftmann@58197: moreover have "{a. g a * r \ 0} \ {a. g a \ 0}" by auto haftmann@58197: ultimately show ?thesis haftmann@58197: by (simp add: setsum_left_distrib Sum_any.expand_superset [of "{a. g a \ 0}"]) haftmann@58197: qed haftmann@58197: haftmann@58197: lemma Sum_any_right_distrib: haftmann@58197: fixes r :: "'a :: semiring_0" haftmann@58197: assumes "finite {a. g a \ 0}" haftmann@58197: shows "r * Sum_any g = (\n. r * g n)" haftmann@58197: proof - haftmann@58197: note assms haftmann@58197: moreover have "{a. r * g a \ 0} \ {a. g a \ 0}" by auto haftmann@58197: ultimately show ?thesis haftmann@58197: by (simp add: setsum_right_distrib Sum_any.expand_superset [of "{a. g a \ 0}"]) haftmann@58197: qed haftmann@58197: haftmann@58197: lemma Sum_any_product: haftmann@58197: fixes f g :: "'b \ 'a::semiring_0" haftmann@58197: assumes "finite {a. f a \ 0}" and "finite {b. g b \ 0}" haftmann@58197: shows "Sum_any f * Sum_any g = (\a. \b. f a * g b)" haftmann@58197: proof - haftmann@58197: have subset_f: "{a. (\b. f a * g b) \ 0} \ {a. f a \ 0}" haftmann@58197: by rule (simp, rule, auto) haftmann@58197: moreover have subset_g: "\a. {b. f a * g b \ 0} \ {b. g b \ 0}" haftmann@58197: by rule (simp, rule, auto) haftmann@58197: ultimately show ?thesis using assms haftmann@58197: by (auto simp add: Sum_any.expand_set [of f] Sum_any.expand_set [of g] haftmann@58197: Sum_any.expand_superset [of "{a. f a \ 0}"] Sum_any.expand_superset [of "{b. g b \ 0}"] haftmann@58197: setsum_product) haftmann@58197: qed haftmann@58197: haftmann@58197: haftmann@58197: subsection \Concrete product\ haftmann@58197: haftmann@58197: context comm_monoid_mult haftmann@58197: begin haftmann@58197: haftmann@58197: definition Prod_any :: "('b \ 'a) \ 'a" haftmann@58197: where haftmann@58197: "Prod_any = comm_monoid_fun.G times 1" haftmann@58197: haftmann@58197: permanent_interpretation Prod_any!: comm_monoid_fun times 1 haftmann@58197: where haftmann@58197: "comm_monoid_fun.G times 1 = Prod_any" and haftmann@58197: "comm_monoid_set.F times 1 = setprod" haftmann@58197: proof - haftmann@58197: show "comm_monoid_fun times 1" .. haftmann@58197: then interpret Prod_any!: comm_monoid_fun times 1 . haftmann@58197: from Prod_any_def show "comm_monoid_fun.G times 1 = Prod_any" by rule haftmann@58197: from setprod_def show "comm_monoid_set.F times 1 = setprod" by rule haftmann@58197: qed haftmann@58197: haftmann@58197: end haftmann@58197: haftmann@58197: syntax haftmann@58197: "_Prod_any" :: "pttrn \ 'a \ 'a::comm_monoid_mult" ("(3PROD _. _)" [0, 10] 10) haftmann@58197: syntax (xsymbols) haftmann@58197: "_Prod_any" :: "pttrn \ 'a \ 'a::comm_monoid_mult" ("(3\_. _)" [0, 10] 10) haftmann@58197: syntax (HTML output) haftmann@58197: "_Prod_any" :: "pttrn \ 'a \ 'a::comm_monoid_mult" ("(3\_. _)" [0, 10] 10) haftmann@58197: haftmann@58197: translations haftmann@58197: "\a. b" == "CONST Prod_any (\a. b)" haftmann@58197: haftmann@58197: lemma Prod_any_zero: haftmann@58197: fixes f :: "'b \ 'a :: comm_semiring_1" haftmann@58197: assumes "finite {a. f a \ 1}" haftmann@58197: assumes "f a = 0" haftmann@58197: shows "(\a. f a) = 0" haftmann@58197: proof - haftmann@58197: from `f a = 0` have "f a \ 1" by simp haftmann@58197: with `f a = 0` have "\a. f a \ 1 \ f a = 0" by blast haftmann@58197: with `finite {a. f a \ 1}` show ?thesis haftmann@58197: by (simp add: Prod_any.expand_set setprod_zero) haftmann@58197: qed haftmann@58197: haftmann@58197: lemma Prod_any_not_zero: haftmann@58197: fixes f :: "'b \ 'a :: comm_semiring_1" haftmann@58197: assumes "finite {a. f a \ 1}" haftmann@58197: assumes "(\a. f a) \ 0" haftmann@58197: shows "f a \ 0" haftmann@58197: using assms Prod_any_zero [of f] by blast haftmann@58197: haftmann@58197: end