576 assume "x = a" with insertI show ?case by auto |
576 assume "x = a" with insertI show ?case by auto |
577 next |
577 next |
578 assume "x \<noteq> a" |
578 assume "x \<noteq> a" |
579 then obtain y' where y: "y = f a y'" and y': "fold_graph f z (A - {a}) y'" |
579 then obtain y' where y: "y = f a y'" and y': "fold_graph f z (A - {a}) y'" |
580 using insertI by auto |
580 using insertI by auto |
581 have 1: "f x y = f a (f x y')" |
581 have "f x y = f a (f x y')" |
582 unfolding y by (rule fun_left_comm) |
582 unfolding y by (rule fun_left_comm) |
583 have 2: "fold_graph f z (insert x A - {a}) (f x y')" |
583 moreover have "fold_graph f z (insert x A - {a}) (f x y')" |
584 using y' and `x \<noteq> a` and `x \<notin> A` |
584 using y' and `x \<noteq> a` and `x \<notin> A` |
585 by (simp add: insert_Diff_if fold_graph.insertI) |
585 by (simp add: insert_Diff_if fold_graph.insertI) |
586 from 1 2 show ?case by fast |
586 ultimately show ?case by fast |
587 qed |
587 qed |
588 qed simp |
588 qed simp |
589 |
589 |
590 lemma fold_graph_insertE: |
590 lemma fold_graph_insertE: |
591 assumes "fold_graph f z (insert x A) v" and "x \<notin> A" |
591 assumes "fold_graph f z (insert x A) v" and "x \<notin> A" |
624 by (unfold fold_def) blast |
624 by (unfold fold_def) blast |
625 |
625 |
626 text{* The various recursion equations for @{const fold}: *} |
626 text{* The various recursion equations for @{const fold}: *} |
627 |
627 |
628 lemma fold_insert [simp]: |
628 lemma fold_insert [simp]: |
629 "finite A ==> x \<notin> A ==> fold f z (insert x A) = f x (fold f z A)" |
629 assumes "finite A" and "x \<notin> A" |
630 apply (rule fold_equality) |
630 shows "fold f z (insert x A) = f x (fold f z A)" |
631 apply (erule fold_graph.insertI) |
631 proof (rule fold_equality) |
632 apply (erule fold_graph_fold) |
632 from `finite A` have "fold_graph f z A (fold f z A)" by (rule fold_graph_fold) |
633 done |
633 with `x \<notin> A`show "fold_graph f z (insert x A) (f x (fold f z A))" by (rule fold_graph.insertI) |
|
634 qed |
634 |
635 |
635 lemma fold_fun_comm: |
636 lemma fold_fun_comm: |
636 "finite A \<Longrightarrow> f x (fold f z A) = fold f (f x z) A" |
637 "finite A \<Longrightarrow> f x (fold f z A) = fold f (f x z) A" |
637 proof (induct rule: finite_induct) |
638 proof (induct rule: finite_induct) |
638 case empty then show ?case by simp |
639 case empty then show ?case by simp |
644 lemma fold_insert2: |
645 lemma fold_insert2: |
645 "finite A \<Longrightarrow> x \<notin> A \<Longrightarrow> fold f z (insert x A) = fold f (f x z) A" |
646 "finite A \<Longrightarrow> x \<notin> A \<Longrightarrow> fold f z (insert x A) = fold f (f x z) A" |
646 by (simp add: fold_fun_comm) |
647 by (simp add: fold_fun_comm) |
647 |
648 |
648 lemma fold_rec: |
649 lemma fold_rec: |
649 assumes "finite A" and "x \<in> A" |
650 assumes "finite A" and "x \<in> A" |
650 shows "fold f z A = f x (fold f z (A - {x}))" |
651 shows "fold f z A = f x (fold f z (A - {x}))" |
651 proof - |
652 proof - |
652 have A: "A = insert x (A - {x})" using `x \<in> A` by blast |
653 have A: "A = insert x (A - {x})" using `x \<in> A` by blast |
653 then have "fold f z A = fold f z (insert x (A - {x}))" by simp |
654 then have "fold f z A = fold f z (insert x (A - {x}))" by simp |
654 also have "\<dots> = f x (fold f z (A - {x}))" |
655 also have "\<dots> = f x (fold f z (A - {x}))" |
655 by (rule fold_insert) (simp add: `finite A`)+ |
656 by (rule fold_insert) (simp add: `finite A`)+ |
813 |
814 |
814 |
815 |
815 subsection {* The derived combinator @{text fold_image} *} |
816 subsection {* The derived combinator @{text fold_image} *} |
816 |
817 |
817 definition fold_image :: "('b \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> 'b \<Rightarrow> 'a set \<Rightarrow> 'b" |
818 definition fold_image :: "('b \<Rightarrow> 'b \<Rightarrow> 'b) \<Rightarrow> ('a \<Rightarrow> 'b) \<Rightarrow> 'b \<Rightarrow> 'a set \<Rightarrow> 'b" |
818 where "fold_image f g = fold (%x y. f (g x) y)" |
819 where "fold_image f g = fold (\<lambda>x y. f (g x) y)" |
819 |
820 |
820 lemma fold_image_empty[simp]: "fold_image f g z {} = z" |
821 lemma fold_image_empty[simp]: "fold_image f g z {} = z" |
821 by(simp add:fold_image_def) |
822 by (simp add:fold_image_def) |
822 |
823 |
823 context ab_semigroup_mult |
824 context ab_semigroup_mult |
824 begin |
825 begin |
825 |
826 |
826 lemma fold_image_insert[simp]: |
827 lemma fold_image_insert[simp]: |
827 assumes "finite A" and "a \<notin> A" |
828 assumes "finite A" and "a \<notin> A" |
828 shows "fold_image times g z (insert a A) = g a * (fold_image times g z A)" |
829 shows "fold_image times g z (insert a A) = g a * (fold_image times g z A)" |
829 proof - |
830 proof - |
830 interpret I: comp_fun_commute "%x y. (g x) * y" proof |
831 interpret comp_fun_commute "%x y. (g x) * y" proof |
831 qed (simp add: fun_eq_iff mult_ac) |
832 qed (simp add: fun_eq_iff mult_ac) |
832 show ?thesis using assms by (simp add: fold_image_def) |
833 show ?thesis using assms by (simp add: fold_image_def) |
833 qed |
834 qed |
834 |
835 |
835 (* |
|
836 lemma fold_commute: |
|
837 "finite A ==> (!!z. x * (fold times g z A) = fold times g (x * z) A)" |
|
838 apply (induct set: finite) |
|
839 apply simp |
|
840 apply (simp add: mult_left_commute [of x]) |
|
841 done |
|
842 |
|
843 lemma fold_nest_Un_Int: |
|
844 "finite A ==> finite B |
|
845 ==> fold times g (fold times g z B) A = fold times g (fold times g z (A Int B)) (A Un B)" |
|
846 apply (induct set: finite) |
|
847 apply simp |
|
848 apply (simp add: fold_commute Int_insert_left insert_absorb) |
|
849 done |
|
850 |
|
851 lemma fold_nest_Un_disjoint: |
|
852 "finite A ==> finite B ==> A Int B = {} |
|
853 ==> fold times g z (A Un B) = fold times g (fold times g z B) A" |
|
854 by (simp add: fold_nest_Un_Int) |
|
855 *) |
|
856 |
|
857 lemma fold_image_reindex: |
836 lemma fold_image_reindex: |
858 assumes fin: "finite A" |
837 assumes "finite A" |
859 shows "inj_on h A \<Longrightarrow> fold_image times g z (h`A) = fold_image times (g\<circ>h) z A" |
838 shows "inj_on h A \<Longrightarrow> fold_image times g z (h ` A) = fold_image times (g \<circ> h) z A" |
860 using fin by induct auto |
839 using assms by induct auto |
861 |
|
862 (* |
|
863 text{* |
|
864 Fusion theorem, as described in Graham Hutton's paper, |
|
865 A Tutorial on the Universality and Expressiveness of Fold, |
|
866 JFP 9:4 (355-372), 1999. |
|
867 *} |
|
868 |
|
869 lemma fold_fusion: |
|
870 assumes "ab_semigroup_mult g" |
|
871 assumes fin: "finite A" |
|
872 and hyp: "\<And>x y. h (g x y) = times x (h y)" |
|
873 shows "h (fold g j w A) = fold times j (h w) A" |
|
874 proof - |
|
875 class_interpret ab_semigroup_mult [g] by fact |
|
876 show ?thesis using fin hyp by (induct set: finite) simp_all |
|
877 qed |
|
878 *) |
|
879 |
840 |
880 lemma fold_image_cong: |
841 lemma fold_image_cong: |
881 "finite A \<Longrightarrow> |
842 assumes "finite A" and g_h: "\<And>x. x\<in>A \<Longrightarrow> g x = h x" |
882 (!!x. x:A ==> g x = h x) ==> fold_image times g z A = fold_image times h z A" |
843 shows "fold_image times g z A = fold_image times h z A" |
883 apply (subgoal_tac "ALL C. C <= A --> (ALL x:C. g x = h x) --> fold_image times g z C = fold_image times h z C") |
844 proof - |
884 apply simp |
845 from `finite A` |
885 apply (erule finite_induct, simp) |
846 have "\<And>C. C <= A --> (ALL x:C. g x = h x) --> fold_image times g z C = fold_image times h z C" |
886 apply (simp add: subset_insert_iff, clarify) |
847 proof (induct arbitrary: C) |
887 apply (subgoal_tac "finite C") |
848 case empty then show ?case by simp |
888 prefer 2 apply (blast dest: finite_subset [COMP swap_prems_rl]) |
849 next |
889 apply (subgoal_tac "C = insert x (C - {x})") |
850 case (insert x F) then show ?case apply - |
890 prefer 2 apply blast |
851 apply (simp add: subset_insert_iff, clarify) |
891 apply (erule ssubst) |
852 apply (subgoal_tac "finite C") |
892 apply (drule spec) |
853 prefer 2 apply (blast dest: finite_subset [COMP swap_prems_rl]) |
893 apply (erule (1) notE impE) |
854 apply (subgoal_tac "C = insert x (C - {x})") |
894 apply (simp add: Ball_def del: insert_Diff_single) |
855 prefer 2 apply blast |
895 done |
856 apply (erule ssubst) |
|
857 apply (simp add: Ball_def del: insert_Diff_single) |
|
858 done |
|
859 qed |
|
860 with g_h show ?thesis by simp |
|
861 qed |
896 |
862 |
897 end |
863 end |
898 |
864 |
899 context comm_monoid_mult |
865 context comm_monoid_mult |
900 begin |
866 begin |