51 text \<open>Multiset enumeration\<close> |
51 text \<open>Multiset enumeration\<close> |
52 |
52 |
53 instantiation multiset :: (type) cancel_comm_monoid_add |
53 instantiation multiset :: (type) cancel_comm_monoid_add |
54 begin |
54 begin |
55 |
55 |
56 lift_definition zero_multiset :: "'a multiset" is "\<lambda>a. 0" |
56 lift_definition zero_multiset :: \<open>'a multiset\<close> |
|
57 is \<open>\<lambda>a. 0\<close> |
57 by simp |
58 by simp |
58 |
59 |
59 abbreviation Mempty :: "'a multiset" ("{#}") where |
60 abbreviation empty_mset :: \<open>'a multiset\<close> (\<open>{#}\<close>) |
60 "Mempty \<equiv> 0" |
61 where \<open>empty_mset \<equiv> 0\<close> |
61 |
62 |
62 lift_definition plus_multiset :: "'a multiset \<Rightarrow> 'a multiset \<Rightarrow> 'a multiset" is "\<lambda>M N. (\<lambda>a. M a + N a)" |
63 lift_definition plus_multiset :: \<open>'a multiset \<Rightarrow> 'a multiset \<Rightarrow> 'a multiset\<close> |
|
64 is \<open>\<lambda>M N a. M a + N a\<close> |
63 by simp |
65 by simp |
64 |
66 |
65 lift_definition minus_multiset :: "'a multiset \<Rightarrow> 'a multiset \<Rightarrow> 'a multiset" is "\<lambda> M N. \<lambda>a. M a - N a" |
67 lift_definition minus_multiset :: \<open>'a multiset \<Rightarrow> 'a multiset \<Rightarrow> 'a multiset\<close> |
|
68 is \<open>\<lambda>M N a. M a - N a\<close> |
66 by (rule diff_preserves_multiset) |
69 by (rule diff_preserves_multiset) |
67 |
70 |
68 instance |
71 instance |
69 by (standard; transfer) (simp_all add: fun_eq_iff) |
72 by (standard; transfer) (simp_all add: fun_eq_iff) |
70 |
73 |
119 |
122 |
120 subsection \<open>Basic operations\<close> |
123 subsection \<open>Basic operations\<close> |
121 |
124 |
122 subsubsection \<open>Conversion to set and membership\<close> |
125 subsubsection \<open>Conversion to set and membership\<close> |
123 |
126 |
124 definition set_mset :: "'a multiset \<Rightarrow> 'a set" |
127 definition set_mset :: \<open>'a multiset \<Rightarrow> 'a set\<close> |
125 where "set_mset M = {x. count M x > 0}" |
128 where \<open>set_mset M = {x. count M x > 0}\<close> |
126 |
129 |
127 abbreviation Melem :: "'a \<Rightarrow> 'a multiset \<Rightarrow> bool" |
130 abbreviation member_mset :: \<open>'a \<Rightarrow> 'a multiset \<Rightarrow> bool\<close> |
128 where "Melem a M \<equiv> a \<in> set_mset M" |
131 where \<open>member_mset a M \<equiv> a \<in> set_mset M\<close> |
129 |
132 |
130 notation |
133 notation |
131 Melem ("'(\<in>#')") and |
134 member_mset (\<open>'(\<in>#')\<close>) and |
132 Melem ("(_/ \<in># _)" [51, 51] 50) |
135 member_mset (\<open>(_/ \<in># _)\<close> [51, 51] 50) |
133 |
136 |
134 notation (ASCII) |
137 notation (ASCII) |
135 Melem ("'(:#')") and |
138 member_mset (\<open>'(:#')\<close>) and |
136 Melem ("(_/ :# _)" [51, 51] 50) |
139 member_mset (\<open>(_/ :# _)\<close> [51, 51] 50) |
137 |
140 |
138 abbreviation not_Melem :: "'a \<Rightarrow> 'a multiset \<Rightarrow> bool" |
141 abbreviation not_member_mset :: \<open>'a \<Rightarrow> 'a multiset \<Rightarrow> bool\<close> |
139 where "not_Melem a M \<equiv> a \<notin> set_mset M" |
142 where \<open>not_member_mset a M \<equiv> a \<notin> set_mset M\<close> |
140 |
143 |
141 notation |
144 notation |
142 not_Melem ("'(\<notin>#')") and |
145 not_member_mset (\<open>'(\<notin>#')\<close>) and |
143 not_Melem ("(_/ \<notin># _)" [51, 51] 50) |
146 not_member_mset (\<open>(_/ \<notin># _)\<close> [51, 51] 50) |
144 |
147 |
145 notation (ASCII) |
148 notation (ASCII) |
146 not_Melem ("'(~:#')") and |
149 not_member_mset (\<open>'(~:#')\<close>) and |
147 not_Melem ("(_/ ~:# _)" [51, 51] 50) |
150 not_member_mset (\<open>(_/ ~:# _)\<close> [51, 51] 50) |
148 |
151 |
149 context |
152 context |
150 begin |
153 begin |
151 |
154 |
152 qualified abbreviation Ball :: "'a multiset \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> bool" |
155 qualified abbreviation Ball :: "'a multiset \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> bool" |
669 qed simp |
672 qed simp |
670 |
673 |
671 |
674 |
672 subsubsection \<open>Intersection and bounded union\<close> |
675 subsubsection \<open>Intersection and bounded union\<close> |
673 |
676 |
674 definition inf_subset_mset :: "'a multiset \<Rightarrow> 'a multiset \<Rightarrow> 'a multiset" (infixl "\<inter>#" 70) where |
677 definition inter_mset :: \<open>'a multiset \<Rightarrow> 'a multiset \<Rightarrow> 'a multiset\<close> (infixl \<open>\<inter>#\<close> 70) |
675 multiset_inter_def: "inf_subset_mset A B = A - (A - B)" |
678 where \<open>A \<inter># B = A - (A - B)\<close> |
676 |
679 |
677 interpretation subset_mset: semilattice_inf inf_subset_mset "(\<subseteq>#)" "(\<subset>#)" |
680 interpretation subset_mset: semilattice_inf \<open>(\<inter>#)\<close> \<open>(\<subseteq>#)\<close> \<open>(\<subset>#)\<close> |
678 proof - |
681 proof - |
679 have [simp]: "m \<le> n \<Longrightarrow> m \<le> q \<Longrightarrow> m \<le> n - (n - q)" for m n q :: nat |
682 have [simp]: "m \<le> n \<Longrightarrow> m \<le> q \<Longrightarrow> m \<le> n - (n - q)" for m n q :: nat |
680 by arith |
683 by arith |
681 show "class.semilattice_inf (\<inter>#) (\<subseteq>#) (\<subset>#)" |
684 show "class.semilattice_inf (\<inter>#) (\<subseteq>#) (\<subset>#)" |
682 by standard (auto simp add: multiset_inter_def subseteq_mset_def) |
685 by standard (auto simp add: inter_mset_def subseteq_mset_def) |
683 qed \<comment> \<open>FIXME: avoid junk stemming from type class interpretation\<close> |
686 qed \<comment> \<open>FIXME: avoid junk stemming from type class interpretation\<close> |
684 |
687 |
685 definition sup_subset_mset :: "'a multiset \<Rightarrow> 'a multiset \<Rightarrow> 'a multiset"(infixl "\<union>#" 70) |
688 definition union_mset :: \<open>'a multiset \<Rightarrow> 'a multiset \<Rightarrow> 'a multiset\<close> (infixl \<open>\<union>#\<close> 70) |
686 where "sup_subset_mset A B = A + (B - A)" \<comment> \<open>FIXME irregular fact name\<close> |
689 where \<open>A \<union># B = A + (B - A)\<close> |
687 |
690 |
688 interpretation subset_mset: semilattice_sup sup_subset_mset "(\<subseteq>#)" "(\<subset>#)" |
691 interpretation subset_mset: semilattice_sup \<open>(\<union>#)\<close> \<open>(\<subseteq>#)\<close> \<open>(\<subset>#)\<close> |
689 proof - |
692 proof - |
690 have [simp]: "m \<le> n \<Longrightarrow> q \<le> n \<Longrightarrow> m + (q - m) \<le> n" for m n q :: nat |
693 have [simp]: "m \<le> n \<Longrightarrow> q \<le> n \<Longrightarrow> m + (q - m) \<le> n" for m n q :: nat |
691 by arith |
694 by arith |
692 show "class.semilattice_sup (\<union>#) (\<subseteq>#) (\<subset>#)" |
695 show "class.semilattice_sup (\<union>#) (\<subseteq>#) (\<subset>#)" |
693 by standard (auto simp add: sup_subset_mset_def subseteq_mset_def) |
696 by standard (auto simp add: union_mset_def subseteq_mset_def) |
694 qed \<comment> \<open>FIXME: avoid junk stemming from type class interpretation\<close> |
697 qed \<comment> \<open>FIXME: avoid junk stemming from type class interpretation\<close> |
695 |
698 |
696 interpretation subset_mset: bounded_lattice_bot "(\<inter>#)" "(\<subseteq>#)" "(\<subset>#)" |
699 interpretation subset_mset: bounded_lattice_bot "(\<inter>#)" "(\<subseteq>#)" "(\<subset>#)" |
697 "(\<union>#)" "{#}" |
700 "(\<union>#)" "{#}" |
698 by standard auto |
701 by standard auto |
699 \<comment> \<open>FIXME: avoid junk stemming from type class interpretation\<close> |
702 \<comment> \<open>FIXME: avoid junk stemming from type class interpretation\<close> |
700 |
703 |
701 |
704 |
702 subsubsection \<open>Additional intersection facts\<close> |
705 subsubsection \<open>Additional intersection facts\<close> |
703 |
706 |
704 lemma multiset_inter_count [simp]: |
707 lemma count_inter_mset [simp]: |
705 fixes A B :: "'a multiset" |
708 \<open>count (A \<inter># B) x = min (count A x) (count B x)\<close> |
706 shows "count (A \<inter># B) x = min (count A x) (count B x)" |
709 by (simp add: inter_mset_def) |
707 by (simp add: multiset_inter_def) |
|
708 |
710 |
709 lemma set_mset_inter [simp]: |
711 lemma set_mset_inter [simp]: |
710 "set_mset (A \<inter># B) = set_mset A \<inter> set_mset B" |
712 "set_mset (A \<inter># B) = set_mset A \<inter> set_mset B" |
711 by (simp only: set_eq_iff count_greater_zero_iff [symmetric] multiset_inter_count) simp |
713 by (simp only: set_mset_def) auto |
712 |
714 |
713 lemma diff_intersect_left_idem [simp]: |
715 lemma diff_intersect_left_idem [simp]: |
714 "M - M \<inter># N = M - N" |
716 "M - M \<inter># N = M - N" |
715 by (simp add: multiset_eq_iff min_def) |
717 by (simp add: multiset_eq_iff min_def) |
716 |
718 |
764 by (meson disjunct_not_in union_iff) |
766 by (meson disjunct_not_in union_iff) |
765 |
767 |
766 lemma inter_mset_empty_distrib_left: "(A + B) \<inter># C = {#} \<longleftrightarrow> A \<inter># C = {#} \<and> B \<inter># C = {#}" |
768 lemma inter_mset_empty_distrib_left: "(A + B) \<inter># C = {#} \<longleftrightarrow> A \<inter># C = {#} \<and> B \<inter># C = {#}" |
767 by (meson disjunct_not_in union_iff) |
769 by (meson disjunct_not_in union_iff) |
768 |
770 |
769 lemma add_mset_inter_add_mset[simp]: |
771 lemma add_mset_inter_add_mset [simp]: |
770 "add_mset a A \<inter># add_mset a B = add_mset a (A \<inter># B)" |
772 "add_mset a A \<inter># add_mset a B = add_mset a (A \<inter># B)" |
771 by (metis add_mset_add_single add_mset_diff_bothsides diff_subset_eq_self multiset_inter_def |
773 by (rule multiset_eqI) simp |
772 subset_mset.diff_add_assoc2) |
|
773 |
774 |
774 lemma add_mset_disjoint [simp]: |
775 lemma add_mset_disjoint [simp]: |
775 "add_mset a A \<inter># B = {#} \<longleftrightarrow> a \<notin># B \<and> A \<inter># B = {#}" |
776 "add_mset a A \<inter># B = {#} \<longleftrightarrow> a \<notin># B \<and> A \<inter># B = {#}" |
776 "{#} = add_mset a A \<inter># B \<longleftrightarrow> a \<notin># B \<and> {#} = A \<inter># B" |
777 "{#} = add_mset a A \<inter># B \<longleftrightarrow> a \<notin># B \<and> {#} = A \<inter># B" |
777 by (auto simp: disjunct_not_in) |
778 by (auto simp: disjunct_not_in) |
836 by (auto simp add: subseteq_mset_def) |
837 by (auto simp add: subseteq_mset_def) |
837 |
838 |
838 |
839 |
839 subsubsection \<open>Additional bounded union facts\<close> |
840 subsubsection \<open>Additional bounded union facts\<close> |
840 |
841 |
841 lemma sup_subset_mset_count [simp]: \<comment> \<open>FIXME irregular fact name\<close> |
842 lemma count_union_mset [simp]: |
842 "count (A \<union># B) x = max (count A x) (count B x)" |
843 \<open>count (A \<union># B) x = max (count A x) (count B x)\<close> |
843 by (simp add: sup_subset_mset_def) |
844 by (simp add: union_mset_def) |
844 |
845 |
845 lemma set_mset_sup [simp]: |
846 lemma set_mset_sup [simp]: |
846 "set_mset (A \<union># B) = set_mset A \<union> set_mset B" |
847 \<open>set_mset (A \<union># B) = set_mset A \<union> set_mset B\<close> |
847 by (simp only: set_eq_iff count_greater_zero_iff [symmetric] sup_subset_mset_count) |
848 by (simp only: set_mset_def) (auto simp add: less_max_iff_disj) |
848 (auto simp add: not_in_iff elim: mset_add) |
|
849 |
849 |
850 lemma sup_union_left1 [simp]: "\<not> x \<in># N \<Longrightarrow> (add_mset x M) \<union># N = add_mset x (M \<union># N)" |
850 lemma sup_union_left1 [simp]: "\<not> x \<in># N \<Longrightarrow> (add_mset x M) \<union># N = add_mset x (M \<union># N)" |
851 by (simp add: multiset_eq_iff not_in_iff) |
851 by (simp add: multiset_eq_iff not_in_iff) |
852 |
852 |
853 lemma sup_union_left2: "x \<in># N \<Longrightarrow> (add_mset x M) \<union># N = add_mset x (M \<union># (N - {#x#}))" |
853 lemma sup_union_left2: "x \<in># N \<Longrightarrow> (add_mset x M) \<union># N = add_mset x (M \<union># (N - {#x#}))" |
892 unfolding replicate_mset_def by (induct n) (auto intro: add.commute) |
892 unfolding replicate_mset_def by (induct n) (auto intro: add.commute) |
893 |
893 |
894 lemma count_replicate_mset[simp]: "count (replicate_mset n x) y = (if y = x then n else 0)" |
894 lemma count_replicate_mset[simp]: "count (replicate_mset n x) y = (if y = x then n else 0)" |
895 unfolding replicate_mset_def by (induct n) auto |
895 unfolding replicate_mset_def by (induct n) auto |
896 |
896 |
897 fun repeat_mset :: "nat \<Rightarrow> 'a multiset \<Rightarrow> 'a multiset" where |
897 lift_definition repeat_mset :: \<open>nat \<Rightarrow> 'a multiset \<Rightarrow> 'a multiset\<close> |
898 "repeat_mset 0 _ = {#}" | |
898 is \<open>\<lambda>n M a. n * M a\<close> by simp |
899 "repeat_mset (Suc n) A = A + repeat_mset n A" |
|
900 |
899 |
901 lemma count_repeat_mset [simp]: "count (repeat_mset i A) a = i * count A a" |
900 lemma count_repeat_mset [simp]: "count (repeat_mset i A) a = i * count A a" |
902 by (induction i) auto |
901 by transfer rule |
|
902 |
|
903 lemma repeat_mset_0 [simp]: |
|
904 \<open>repeat_mset 0 M = {#}\<close> |
|
905 by transfer simp |
|
906 |
|
907 lemma repeat_mset_Suc [simp]: |
|
908 \<open>repeat_mset (Suc n) M = M + repeat_mset n M\<close> |
|
909 by transfer simp |
903 |
910 |
904 lemma repeat_mset_right [simp]: "repeat_mset a (repeat_mset b A) = repeat_mset (a * b) A" |
911 lemma repeat_mset_right [simp]: "repeat_mset a (repeat_mset b A) = repeat_mset (a * b) A" |
905 by (auto simp: multiset_eq_iff left_diff_distrib') |
912 by (auto simp: multiset_eq_iff left_diff_distrib') |
906 |
913 |
907 lemma left_diff_repeat_mset_distrib': \<open>repeat_mset (i - j) u = repeat_mset i u - repeat_mset j u\<close> |
914 lemma left_diff_repeat_mset_distrib': \<open>repeat_mset (i - j) u = repeat_mset i u - repeat_mset j u\<close> |
926 lemma repeat_mset_distrib_add_mset[simp]: |
933 lemma repeat_mset_distrib_add_mset[simp]: |
927 "repeat_mset n (add_mset a A) = replicate_mset n a + repeat_mset n A" |
934 "repeat_mset n (add_mset a A) = replicate_mset n a + repeat_mset n A" |
928 by (auto simp: multiset_eq_iff) |
935 by (auto simp: multiset_eq_iff) |
929 |
936 |
930 lemma repeat_mset_empty[simp]: "repeat_mset n {#} = {#}" |
937 lemma repeat_mset_empty[simp]: "repeat_mset n {#} = {#}" |
931 by (induction n) simp_all |
938 by transfer simp |
932 |
939 |
933 |
940 |
934 subsubsection \<open>Simprocs\<close> |
941 subsubsection \<open>Simprocs\<close> |
935 |
942 |
936 lemma repeat_mset_iterate_add: \<open>repeat_mset n M = iterate_add n M\<close> |
943 lemma repeat_mset_iterate_add: \<open>repeat_mset n M = iterate_add n M\<close> |
3252 |
3259 |
3253 setup \<open> |
3260 setup \<open> |
3254 let |
3261 let |
3255 fun msetT T = Type (\<^type_name>\<open>multiset\<close>, [T]); |
3262 fun msetT T = Type (\<^type_name>\<open>multiset\<close>, [T]); |
3256 |
3263 |
3257 fun mk_mset T [] = Const (\<^const_abbrev>\<open>Mempty\<close>, msetT T) |
3264 fun mk_mset T [] = Const (\<^const_abbrev>\<open>empty_mset\<close>, msetT T) |
3258 | mk_mset T [x] = |
3265 | mk_mset T [x] = |
3259 Const (\<^const_name>\<open>add_mset\<close>, T --> msetT T --> msetT T) $ x $ |
3266 Const (\<^const_name>\<open>add_mset\<close>, T --> msetT T --> msetT T) $ x $ |
3260 Const (\<^const_abbrev>\<open>Mempty\<close>, msetT T) |
3267 Const (\<^const_abbrev>\<open>empty_mset\<close>, msetT T) |
3261 | mk_mset T (x :: xs) = |
3268 | mk_mset T (x :: xs) = |
3262 Const (\<^const_name>\<open>plus\<close>, msetT T --> msetT T --> msetT T) $ |
3269 Const (\<^const_name>\<open>plus\<close>, msetT T --> msetT T --> msetT T) $ |
3263 mk_mset T [x] $ mk_mset T xs |
3270 mk_mset T [x] $ mk_mset T xs |
3264 |
3271 |
3265 fun mset_member_tac ctxt m i = |
3272 fun mset_member_tac ctxt m i = |
3272 fun mset_nonempty_tac ctxt = |
3279 fun mset_nonempty_tac ctxt = |
3273 resolve_tac ctxt @{thms nonempty_plus} ORELSE' |
3280 resolve_tac ctxt @{thms nonempty_plus} ORELSE' |
3274 resolve_tac ctxt @{thms nonempty_single} |
3281 resolve_tac ctxt @{thms nonempty_single} |
3275 |
3282 |
3276 fun regroup_munion_conv ctxt = |
3283 fun regroup_munion_conv ctxt = |
3277 Function_Lib.regroup_conv ctxt \<^const_abbrev>\<open>Mempty\<close> \<^const_name>\<open>plus\<close> |
3284 Function_Lib.regroup_conv ctxt \<^const_abbrev>\<open>empty_mset\<close> \<^const_name>\<open>plus\<close> |
3278 (map (fn t => t RS eq_reflection) (@{thms ac_simps} @ @{thms empty_neutral})) |
3285 (map (fn t => t RS eq_reflection) (@{thms ac_simps} @ @{thms empty_neutral})) |
3279 |
3286 |
3280 fun unfold_pwleq_tac ctxt i = |
3287 fun unfold_pwleq_tac ctxt i = |
3281 (resolve_tac ctxt @{thms pw_leq_step} i THEN (fn st => unfold_pwleq_tac ctxt (i + 1) st)) |
3288 (resolve_tac ctxt @{thms pw_leq_step} i THEN (fn st => unfold_pwleq_tac ctxt (i + 1) st)) |
3282 ORELSE (resolve_tac ctxt @{thms pw_leq_lstep} i) |
3289 ORELSE (resolve_tac ctxt @{thms pw_leq_lstep} i) |