| author | urbanc | 
| Thu, 22 Mar 2007 11:17:32 +0100 | |
| changeset 22495 | c54748fd1f43 | 
| parent 22316 | f662831459de | 
| child 23281 | e26ec695c9b3 | 
| permissions | -rw-r--r-- | 
| 10249 | 1 | (* Title: HOL/Library/Multiset.thy | 
| 2 | ID: $Id$ | |
| 15072 | 3 | Author: Tobias Nipkow, Markus Wenzel, Lawrence C Paulson, Norbert Voelker | 
| 10249 | 4 | *) | 
| 5 | ||
| 14706 | 6 | header {* Multisets *}
 | 
| 10249 | 7 | |
| 15131 | 8 | theory Multiset | 
| 19564 
d3e2f532459a
First usable version of the new function definition package (HOL/function_packake/...).
 krauss parents: 
19363diff
changeset | 9 | imports Main | 
| 15131 | 10 | begin | 
| 10249 | 11 | |
| 12 | subsection {* The type of multisets *}
 | |
| 13 | ||
| 14 | typedef 'a multiset = "{f::'a => nat. finite {x . 0 < f x}}"
 | |
| 15 | proof | |
| 11464 | 16 | show "(\<lambda>x. 0::nat) \<in> ?multiset" by simp | 
| 10249 | 17 | qed | 
| 18 | ||
| 19 | lemmas multiset_typedef [simp] = | |
| 10277 | 20 | Abs_multiset_inverse Rep_multiset_inverse Rep_multiset | 
| 21 | and [simp] = Rep_multiset_inject [symmetric] | |
| 10249 | 22 | |
| 19086 | 23 | definition | 
| 21404 
eb85850d3eb7
more robust syntax for definition/abbreviation/notation;
 wenzelm parents: 
21214diff
changeset | 24 |   Mempty :: "'a multiset"  ("{#}") where
 | 
| 19086 | 25 |   "{#} = Abs_multiset (\<lambda>a. 0)"
 | 
| 10249 | 26 | |
| 21404 
eb85850d3eb7
more robust syntax for definition/abbreviation/notation;
 wenzelm parents: 
21214diff
changeset | 27 | definition | 
| 
eb85850d3eb7
more robust syntax for definition/abbreviation/notation;
 wenzelm parents: 
21214diff
changeset | 28 |   single :: "'a => 'a multiset"  ("{#_#}") where
 | 
| 19086 | 29 |   "{#a#} = Abs_multiset (\<lambda>b. if b = a then 1 else 0)"
 | 
| 10249 | 30 | |
| 21404 
eb85850d3eb7
more robust syntax for definition/abbreviation/notation;
 wenzelm parents: 
21214diff
changeset | 31 | definition | 
| 
eb85850d3eb7
more robust syntax for definition/abbreviation/notation;
 wenzelm parents: 
21214diff
changeset | 32 | count :: "'a multiset => 'a => nat" where | 
| 19086 | 33 | "count = Rep_multiset" | 
| 10249 | 34 | |
| 21404 
eb85850d3eb7
more robust syntax for definition/abbreviation/notation;
 wenzelm parents: 
21214diff
changeset | 35 | definition | 
| 
eb85850d3eb7
more robust syntax for definition/abbreviation/notation;
 wenzelm parents: 
21214diff
changeset | 36 |   MCollect :: "'a multiset => ('a => bool) => 'a multiset" where
 | 
| 19086 | 37 | "MCollect M P = Abs_multiset (\<lambda>x. if P x then Rep_multiset M x else 0)" | 
| 38 | ||
| 19363 | 39 | abbreviation | 
| 21404 
eb85850d3eb7
more robust syntax for definition/abbreviation/notation;
 wenzelm parents: 
21214diff
changeset | 40 |   Melem :: "'a => 'a multiset => bool"  ("(_/ :# _)" [50, 51] 50) where
 | 
| 19363 | 41 | "a :# M == 0 < count M a" | 
| 10249 | 42 | |
| 43 | syntax | |
| 44 |   "_MCollect" :: "pttrn => 'a multiset => bool => 'a multiset"    ("(1{# _ : _./ _#})")
 | |
| 45 | translations | |
| 20770 | 46 |   "{#x:M. P#}" == "CONST MCollect M (\<lambda>x. P)"
 | 
| 10249 | 47 | |
| 19086 | 48 | definition | 
| 21404 
eb85850d3eb7
more robust syntax for definition/abbreviation/notation;
 wenzelm parents: 
21214diff
changeset | 49 | set_of :: "'a multiset => 'a set" where | 
| 19086 | 50 |   "set_of M = {x. x :# M}"
 | 
| 10249 | 51 | |
| 21417 | 52 | instance multiset :: (type) "{plus, minus, zero, size}" 
 | 
| 11464 | 53 | union_def: "M + N == Abs_multiset (\<lambda>a. Rep_multiset M a + Rep_multiset N a)" | 
| 54 | diff_def: "M - N == Abs_multiset (\<lambda>a. Rep_multiset M a - Rep_multiset N a)" | |
| 11701 
3d51fbf81c17
sane numerals (stage 1): added generic 1, removed 1' and 2 on nat,
 wenzelm parents: 
11655diff
changeset | 55 |   Zero_multiset_def [simp]: "0 == {#}"
 | 
| 21417 | 56 | size_def: "size M == setsum (count M) (set_of M)" .. | 
| 10249 | 57 | |
| 19086 | 58 | definition | 
| 21404 
eb85850d3eb7
more robust syntax for definition/abbreviation/notation;
 wenzelm parents: 
21214diff
changeset | 59 | multiset_inter :: "'a multiset \<Rightarrow> 'a multiset \<Rightarrow> 'a multiset" (infixl "#\<inter>" 70) where | 
| 19086 | 60 | "multiset_inter A B = A - (A - B)" | 
| 15869 | 61 | |
| 10249 | 62 | |
| 63 | text {*
 | |
| 64 |  \medskip Preservation of the representing set @{term multiset}.
 | |
| 65 | *} | |
| 66 | ||
| 11464 | 67 | lemma const0_in_multiset [simp]: "(\<lambda>a. 0) \<in> multiset" | 
| 17161 | 68 | by (simp add: multiset_def) | 
| 10249 | 69 | |
| 11701 
3d51fbf81c17
sane numerals (stage 1): added generic 1, removed 1' and 2 on nat,
 wenzelm parents: 
11655diff
changeset | 70 | lemma only1_in_multiset [simp]: "(\<lambda>b. if b = a then 1 else 0) \<in> multiset" | 
| 17161 | 71 | by (simp add: multiset_def) | 
| 10249 | 72 | |
| 73 | lemma union_preserves_multiset [simp]: | |
| 11464 | 74 | "M \<in> multiset ==> N \<in> multiset ==> (\<lambda>a. M a + N a) \<in> multiset" | 
| 17161 | 75 | apply (simp add: multiset_def) | 
| 76 | apply (drule (1) finite_UnI) | |
| 10249 | 77 | apply (simp del: finite_Un add: Un_def) | 
| 78 | done | |
| 79 | ||
| 80 | lemma diff_preserves_multiset [simp]: | |
| 11464 | 81 | "M \<in> multiset ==> (\<lambda>a. M a - N a) \<in> multiset" | 
| 17161 | 82 | apply (simp add: multiset_def) | 
| 10249 | 83 | apply (rule finite_subset) | 
| 17161 | 84 | apply auto | 
| 10249 | 85 | done | 
| 86 | ||
| 87 | ||
| 88 | subsection {* Algebraic properties of multisets *}
 | |
| 89 | ||
| 90 | subsubsection {* Union *}
 | |
| 91 | ||
| 17161 | 92 | lemma union_empty [simp]: "M + {#} = M \<and> {#} + M = M"
 | 
| 93 | by (simp add: union_def Mempty_def) | |
| 10249 | 94 | |
| 17161 | 95 | lemma union_commute: "M + N = N + (M::'a multiset)" | 
| 96 | by (simp add: union_def add_ac) | |
| 97 | ||
| 98 | lemma union_assoc: "(M + N) + K = M + (N + (K::'a multiset))" | |
| 99 | by (simp add: union_def add_ac) | |
| 10249 | 100 | |
| 17161 | 101 | lemma union_lcomm: "M + (N + K) = N + (M + (K::'a multiset))" | 
| 102 | proof - | |
| 103 | have "M + (N + K) = (N + K) + M" | |
| 104 | by (rule union_commute) | |
| 105 | also have "\<dots> = N + (K + M)" | |
| 106 | by (rule union_assoc) | |
| 107 | also have "K + M = M + K" | |
| 108 | by (rule union_commute) | |
| 109 | finally show ?thesis . | |
| 110 | qed | |
| 10249 | 111 | |
| 17161 | 112 | lemmas union_ac = union_assoc union_commute union_lcomm | 
| 10249 | 113 | |
| 14738 | 114 | instance multiset :: (type) comm_monoid_add | 
| 17200 | 115 | proof | 
| 14722 
8e739a6eaf11
replaced apply-style proof for instance Multiset :: plus_ac0 by recommended Isar proof style
 obua parents: 
14706diff
changeset | 116 | fix a b c :: "'a multiset" | 
| 
8e739a6eaf11
replaced apply-style proof for instance Multiset :: plus_ac0 by recommended Isar proof style
 obua parents: 
14706diff
changeset | 117 | show "(a + b) + c = a + (b + c)" by (rule union_assoc) | 
| 
8e739a6eaf11
replaced apply-style proof for instance Multiset :: plus_ac0 by recommended Isar proof style
 obua parents: 
14706diff
changeset | 118 | show "a + b = b + a" by (rule union_commute) | 
| 
8e739a6eaf11
replaced apply-style proof for instance Multiset :: plus_ac0 by recommended Isar proof style
 obua parents: 
14706diff
changeset | 119 | show "0 + a = a" by simp | 
| 
8e739a6eaf11
replaced apply-style proof for instance Multiset :: plus_ac0 by recommended Isar proof style
 obua parents: 
14706diff
changeset | 120 | qed | 
| 10277 | 121 | |
| 10249 | 122 | |
| 123 | subsubsection {* Difference *}
 | |
| 124 | ||
| 17161 | 125 | lemma diff_empty [simp]: "M - {#} = M \<and> {#} - M = {#}"
 | 
| 126 | by (simp add: Mempty_def diff_def) | |
| 10249 | 127 | |
| 17161 | 128 | lemma diff_union_inverse2 [simp]: "M + {#a#} - {#a#} = M"
 | 
| 129 | by (simp add: union_def diff_def) | |
| 10249 | 130 | |
| 131 | ||
| 132 | subsubsection {* Count of elements *}
 | |
| 133 | ||
| 17161 | 134 | lemma count_empty [simp]: "count {#} a = 0"
 | 
| 135 | by (simp add: count_def Mempty_def) | |
| 10249 | 136 | |
| 17161 | 137 | lemma count_single [simp]: "count {#b#} a = (if b = a then 1 else 0)"
 | 
| 138 | by (simp add: count_def single_def) | |
| 10249 | 139 | |
| 17161 | 140 | lemma count_union [simp]: "count (M + N) a = count M a + count N a" | 
| 141 | by (simp add: count_def union_def) | |
| 10249 | 142 | |
| 17161 | 143 | lemma count_diff [simp]: "count (M - N) a = count M a - count N a" | 
| 144 | by (simp add: count_def diff_def) | |
| 10249 | 145 | |
| 146 | ||
| 147 | subsubsection {* Set of elements *}
 | |
| 148 | ||
| 17161 | 149 | lemma set_of_empty [simp]: "set_of {#} = {}"
 | 
| 150 | by (simp add: set_of_def) | |
| 10249 | 151 | |
| 17161 | 152 | lemma set_of_single [simp]: "set_of {#b#} = {b}"
 | 
| 153 | by (simp add: set_of_def) | |
| 10249 | 154 | |
| 17161 | 155 | lemma set_of_union [simp]: "set_of (M + N) = set_of M \<union> set_of N" | 
| 156 | by (auto simp add: set_of_def) | |
| 10249 | 157 | |
| 17161 | 158 | lemma set_of_eq_empty_iff [simp]: "(set_of M = {}) = (M = {#})"
 | 
| 159 | by (auto simp add: set_of_def Mempty_def count_def expand_fun_eq) | |
| 10249 | 160 | |
| 17161 | 161 | lemma mem_set_of_iff [simp]: "(x \<in> set_of M) = (x :# M)" | 
| 162 | by (auto simp add: set_of_def) | |
| 10249 | 163 | |
| 164 | ||
| 165 | subsubsection {* Size *}
 | |
| 166 | ||
| 17161 | 167 | lemma size_empty [simp]: "size {#} = 0"
 | 
| 168 | by (simp add: size_def) | |
| 10249 | 169 | |
| 17161 | 170 | lemma size_single [simp]: "size {#b#} = 1"
 | 
| 171 | by (simp add: size_def) | |
| 10249 | 172 | |
| 17161 | 173 | lemma finite_set_of [iff]: "finite (set_of M)" | 
| 174 | using Rep_multiset [of M] | |
| 175 | by (simp add: multiset_def set_of_def count_def) | |
| 10249 | 176 | |
| 17161 | 177 | lemma setsum_count_Int: | 
| 11464 | 178 | "finite A ==> setsum (count N) (A \<inter> set_of N) = setsum (count N) A" | 
| 18258 | 179 | apply (induct rule: finite_induct) | 
| 17161 | 180 | apply simp | 
| 10249 | 181 | apply (simp add: Int_insert_left set_of_def) | 
| 182 | done | |
| 183 | ||
| 17161 | 184 | lemma size_union [simp]: "size (M + N::'a multiset) = size M + size N" | 
| 10249 | 185 | apply (unfold size_def) | 
| 11464 | 186 | apply (subgoal_tac "count (M + N) = (\<lambda>a. count M a + count N a)") | 
| 10249 | 187 | prefer 2 | 
| 15072 | 188 | apply (rule ext, simp) | 
| 15402 | 189 | apply (simp (no_asm_simp) add: setsum_Un_nat setsum_addf setsum_count_Int) | 
| 10249 | 190 | apply (subst Int_commute) | 
| 191 | apply (simp (no_asm_simp) add: setsum_count_Int) | |
| 192 | done | |
| 193 | ||
| 17161 | 194 | lemma size_eq_0_iff_empty [iff]: "(size M = 0) = (M = {#})"
 | 
| 15072 | 195 | apply (unfold size_def Mempty_def count_def, auto) | 
| 10249 | 196 | apply (simp add: set_of_def count_def expand_fun_eq) | 
| 197 | done | |
| 198 | ||
| 17161 | 199 | lemma size_eq_Suc_imp_elem: "size M = Suc n ==> \<exists>a. a :# M" | 
| 10249 | 200 | apply (unfold size_def) | 
| 15072 | 201 | apply (drule setsum_SucD, auto) | 
| 10249 | 202 | done | 
| 203 | ||
| 204 | ||
| 205 | subsubsection {* Equality of multisets *}
 | |
| 206 | ||
| 17161 | 207 | lemma multiset_eq_conv_count_eq: "(M = N) = (\<forall>a. count M a = count N a)" | 
| 208 | by (simp add: count_def expand_fun_eq) | |
| 10249 | 209 | |
| 17161 | 210 | lemma single_not_empty [simp]: "{#a#} \<noteq> {#} \<and> {#} \<noteq> {#a#}"
 | 
| 211 | by (simp add: single_def Mempty_def expand_fun_eq) | |
| 10249 | 212 | |
| 17161 | 213 | lemma single_eq_single [simp]: "({#a#} = {#b#}) = (a = b)"
 | 
| 214 | by (auto simp add: single_def expand_fun_eq) | |
| 10249 | 215 | |
| 17161 | 216 | lemma union_eq_empty [iff]: "(M + N = {#}) = (M = {#} \<and> N = {#})"
 | 
| 217 | by (auto simp add: union_def Mempty_def expand_fun_eq) | |
| 10249 | 218 | |
| 17161 | 219 | lemma empty_eq_union [iff]: "({#} = M + N) = (M = {#} \<and> N = {#})"
 | 
| 220 | by (auto simp add: union_def Mempty_def expand_fun_eq) | |
| 10249 | 221 | |
| 17161 | 222 | lemma union_right_cancel [simp]: "(M + K = N + K) = (M = (N::'a multiset))" | 
| 223 | by (simp add: union_def expand_fun_eq) | |
| 10249 | 224 | |
| 17161 | 225 | lemma union_left_cancel [simp]: "(K + M = K + N) = (M = (N::'a multiset))" | 
| 226 | by (simp add: union_def expand_fun_eq) | |
| 10249 | 227 | |
| 17161 | 228 | lemma union_is_single: | 
| 11464 | 229 |     "(M + N = {#a#}) = (M = {#a#} \<and> N={#} \<or> M = {#} \<and> N = {#a#})"
 | 
| 15072 | 230 | apply (simp add: Mempty_def single_def union_def add_is_1 expand_fun_eq) | 
| 10249 | 231 | apply blast | 
| 232 | done | |
| 233 | ||
| 17161 | 234 | lemma single_is_union: | 
| 15072 | 235 |      "({#a#} = M + N) = ({#a#} = M \<and> N = {#} \<or> M = {#} \<and> {#a#} = N)"
 | 
| 10249 | 236 | apply (unfold Mempty_def single_def union_def) | 
| 11464 | 237 | apply (simp add: add_is_1 one_is_add expand_fun_eq) | 
| 10249 | 238 | apply (blast dest: sym) | 
| 239 | done | |
| 240 | ||
| 17778 | 241 | ML"reset use_neq_simproc" | 
| 17161 | 242 | lemma add_eq_conv_diff: | 
| 10249 | 243 |   "(M + {#a#} = N + {#b#}) =
 | 
| 15072 | 244 |    (M = N \<and> a = b \<or> M = N - {#a#} + {#b#} \<and> N = M - {#b#} + {#a#})"
 | 
| 10249 | 245 | apply (unfold single_def union_def diff_def) | 
| 246 | apply (simp (no_asm) add: expand_fun_eq) | |
| 15072 | 247 | apply (rule conjI, force, safe, simp_all) | 
| 13601 | 248 | apply (simp add: eq_sym_conv) | 
| 10249 | 249 | done | 
| 17778 | 250 | ML"set use_neq_simproc" | 
| 10249 | 251 | |
| 15869 | 252 | declare Rep_multiset_inject [symmetric, simp del] | 
| 253 | ||
| 254 | ||
| 255 | subsubsection {* Intersection *}
 | |
| 256 | ||
| 257 | lemma multiset_inter_count: | |
| 17161 | 258 | "count (A #\<inter> B) x = min (count A x) (count B x)" | 
| 259 | by (simp add: multiset_inter_def min_def) | |
| 15869 | 260 | |
| 261 | lemma multiset_inter_commute: "A #\<inter> B = B #\<inter> A" | |
| 17200 | 262 | by (simp add: multiset_eq_conv_count_eq multiset_inter_count | 
| 21214 
a91bab12b2bd
adjusted two lemma names due to name change in interpretation
 haftmann parents: 
20770diff
changeset | 263 | min_max.inf_commute) | 
| 15869 | 264 | |
| 265 | lemma multiset_inter_assoc: "A #\<inter> (B #\<inter> C) = A #\<inter> B #\<inter> C" | |
| 17200 | 266 | by (simp add: multiset_eq_conv_count_eq multiset_inter_count | 
| 21214 
a91bab12b2bd
adjusted two lemma names due to name change in interpretation
 haftmann parents: 
20770diff
changeset | 267 | min_max.inf_assoc) | 
| 15869 | 268 | |
| 269 | lemma multiset_inter_left_commute: "A #\<inter> (B #\<inter> C) = B #\<inter> (A #\<inter> C)" | |
| 270 | by (simp add: multiset_eq_conv_count_eq multiset_inter_count min_def) | |
| 271 | ||
| 17161 | 272 | lemmas multiset_inter_ac = | 
| 273 | multiset_inter_commute | |
| 274 | multiset_inter_assoc | |
| 275 | multiset_inter_left_commute | |
| 15869 | 276 | |
| 277 | lemma multiset_union_diff_commute: "B #\<inter> C = {#} \<Longrightarrow> A + B - C = A - C + B"
 | |
| 17200 | 278 | apply (simp add: multiset_eq_conv_count_eq multiset_inter_count min_def | 
| 17161 | 279 | split: split_if_asm) | 
| 15869 | 280 | apply clarsimp | 
| 17161 | 281 | apply (erule_tac x = a in allE) | 
| 15869 | 282 | apply auto | 
| 283 | done | |
| 284 | ||
| 10249 | 285 | |
| 286 | subsection {* Induction over multisets *}
 | |
| 287 | ||
| 288 | lemma setsum_decr: | |
| 11701 
3d51fbf81c17
sane numerals (stage 1): added generic 1, removed 1' and 2 on nat,
 wenzelm parents: 
11655diff
changeset | 289 | "finite F ==> (0::nat) < f a ==> | 
| 15072 | 290 | setsum (f (a := f a - 1)) F = (if a\<in>F then setsum f F - 1 else setsum f F)" | 
| 18258 | 291 | apply (induct rule: finite_induct) | 
| 292 | apply auto | |
| 15072 | 293 | apply (drule_tac a = a in mk_disjoint_insert, auto) | 
| 10249 | 294 | done | 
| 295 | ||
| 10313 | 296 | lemma rep_multiset_induct_aux: | 
| 18730 | 297 | assumes 1: "P (\<lambda>a. (0::nat))" | 
| 298 | and 2: "!!f b. f \<in> multiset ==> P f ==> P (f (b := f b + 1))" | |
| 17161 | 299 |   shows "\<forall>f. f \<in> multiset --> setsum f {x. 0 < f x} = n --> P f"
 | 
| 18730 | 300 | apply (unfold multiset_def) | 
| 301 | apply (induct_tac n, simp, clarify) | |
| 302 | apply (subgoal_tac "f = (\<lambda>a.0)") | |
| 303 | apply simp | |
| 304 | apply (rule 1) | |
| 305 | apply (rule ext, force, clarify) | |
| 306 | apply (frule setsum_SucD, clarify) | |
| 307 | apply (rename_tac a) | |
| 308 |   apply (subgoal_tac "finite {x. 0 < (f (a := f a - 1)) x}")
 | |
| 309 | prefer 2 | |
| 310 | apply (rule finite_subset) | |
| 311 | prefer 2 | |
| 312 | apply assumption | |
| 313 | apply simp | |
| 314 | apply blast | |
| 315 | apply (subgoal_tac "f = (f (a := f a - 1))(a := (f (a := f a - 1)) a + 1)") | |
| 316 | prefer 2 | |
| 317 | apply (rule ext) | |
| 318 | apply (simp (no_asm_simp)) | |
| 319 | apply (erule ssubst, rule 2 [unfolded multiset_def], blast) | |
| 320 | apply (erule allE, erule impE, erule_tac [2] mp, blast) | |
| 321 | apply (simp (no_asm_simp) add: setsum_decr del: fun_upd_apply One_nat_def) | |
| 322 |   apply (subgoal_tac "{x. x \<noteq> a --> 0 < f x} = {x. 0 < f x}")
 | |
| 323 | prefer 2 | |
| 324 | apply blast | |
| 325 |   apply (subgoal_tac "{x. x \<noteq> a \<and> 0 < f x} = {x. 0 < f x} - {a}")
 | |
| 326 | prefer 2 | |
| 327 | apply blast | |
| 328 | apply (simp add: le_imp_diff_is_add setsum_diff1_nat cong: conj_cong) | |
| 329 | done | |
| 10249 | 330 | |
| 10313 | 331 | theorem rep_multiset_induct: | 
| 11464 | 332 | "f \<in> multiset ==> P (\<lambda>a. 0) ==> | 
| 11701 
3d51fbf81c17
sane numerals (stage 1): added generic 1, removed 1' and 2 on nat,
 wenzelm parents: 
11655diff
changeset | 333 | (!!f b. f \<in> multiset ==> P f ==> P (f (b := f b + 1))) ==> P f" | 
| 17161 | 334 | using rep_multiset_induct_aux by blast | 
| 10249 | 335 | |
| 18258 | 336 | theorem multiset_induct [case_names empty add, induct type: multiset]: | 
| 337 |   assumes empty: "P {#}"
 | |
| 338 |     and add: "!!M x. P M ==> P (M + {#x#})"
 | |
| 17161 | 339 | shows "P M" | 
| 10249 | 340 | proof - | 
| 341 | note defns = union_def single_def Mempty_def | |
| 342 | show ?thesis | |
| 343 | apply (rule Rep_multiset_inverse [THEN subst]) | |
| 10313 | 344 | apply (rule Rep_multiset [THEN rep_multiset_induct]) | 
| 18258 | 345 | apply (rule empty [unfolded defns]) | 
| 15072 | 346 | apply (subgoal_tac "f(b := f b + 1) = (\<lambda>a. f a + (if a=b then 1 else 0))") | 
| 10249 | 347 | prefer 2 | 
| 348 | apply (simp add: expand_fun_eq) | |
| 349 | apply (erule ssubst) | |
| 17200 | 350 | apply (erule Abs_multiset_inverse [THEN subst]) | 
| 18258 | 351 | apply (erule add [unfolded defns, simplified]) | 
| 10249 | 352 | done | 
| 353 | qed | |
| 354 | ||
| 355 | lemma MCollect_preserves_multiset: | |
| 11464 | 356 | "M \<in> multiset ==> (\<lambda>x. if P x then M x else 0) \<in> multiset" | 
| 10249 | 357 | apply (simp add: multiset_def) | 
| 15072 | 358 | apply (rule finite_subset, auto) | 
| 10249 | 359 | done | 
| 360 | ||
| 17161 | 361 | lemma count_MCollect [simp]: | 
| 10249 | 362 |     "count {# x:M. P x #} a = (if P a then count M a else 0)"
 | 
| 15072 | 363 | by (simp add: count_def MCollect_def MCollect_preserves_multiset) | 
| 10249 | 364 | |
| 17161 | 365 | lemma set_of_MCollect [simp]: "set_of {# x:M. P x #} = set_of M \<inter> {x. P x}"
 | 
| 366 | by (auto simp add: set_of_def) | |
| 10249 | 367 | |
| 17161 | 368 | lemma multiset_partition: "M = {# x:M. P x #} + {# x:M. \<not> P x #}"
 | 
| 369 | by (subst multiset_eq_conv_count_eq, auto) | |
| 10249 | 370 | |
| 17161 | 371 | lemma add_eq_conv_ex: | 
| 372 |   "(M + {#a#} = N + {#b#}) =
 | |
| 373 |     (M = N \<and> a = b \<or> (\<exists>K. M = K + {#b#} \<and> N = K + {#a#}))"
 | |
| 15072 | 374 | by (auto simp add: add_eq_conv_diff) | 
| 10249 | 375 | |
| 15869 | 376 | declare multiset_typedef [simp del] | 
| 10249 | 377 | |
| 17161 | 378 | |
| 10249 | 379 | subsection {* Multiset orderings *}
 | 
| 380 | ||
| 381 | subsubsection {* Well-foundedness *}
 | |
| 382 | ||
| 19086 | 383 | definition | 
| 22270 | 384 |   mult1 :: "('a => 'a => bool) => 'a multiset => 'a multiset => bool" where
 | 
| 19086 | 385 | "mult1 r = | 
| 22270 | 386 |     (%N M. \<exists>a M0 K. M = M0 + {#a#} \<and> N = M0 + K \<and>
 | 
| 387 | (\<forall>b. b :# K --> r b a))" | |
| 10249 | 388 | |
| 21404 
eb85850d3eb7
more robust syntax for definition/abbreviation/notation;
 wenzelm parents: 
21214diff
changeset | 389 | definition | 
| 22270 | 390 |   mult :: "('a => 'a => bool) => 'a multiset => 'a multiset => bool" where
 | 
| 391 | "mult r = (mult1 r)\<^sup>+\<^sup>+" | |
| 10249 | 392 | |
| 22270 | 393 | lemma not_less_empty [iff]: "\<not> mult1 r M {#}"
 | 
| 10277 | 394 | by (simp add: mult1_def) | 
| 10249 | 395 | |
| 22270 | 396 | lemma less_add: "mult1 r N (M0 + {#a#})==>
 | 
| 397 |     (\<exists>M. mult1 r M M0 \<and> N = M + {#a#}) \<or>
 | |
| 398 | (\<exists>K. (\<forall>b. b :# K --> r b a) \<and> N = M0 + K)" | |
| 19582 | 399 | (is "_ \<Longrightarrow> ?case1 (mult1 r) \<or> ?case2") | 
| 10249 | 400 | proof (unfold mult1_def) | 
| 22270 | 401 | let ?r = "\<lambda>K a. \<forall>b. b :# K --> r b a" | 
| 11464 | 402 |   let ?R = "\<lambda>N M. \<exists>a M0 K. M = M0 + {#a#} \<and> N = M0 + K \<and> ?r K a"
 | 
| 22270 | 403 | let ?case1 = "?case1 ?R" | 
| 10249 | 404 | |
| 22270 | 405 |   assume "?R N (M0 + {#a#})"
 | 
| 18258 | 406 | then have "\<exists>a' M0' K. | 
| 11464 | 407 |       M0 + {#a#} = M0' + {#a'#} \<and> N = M0' + K \<and> ?r K a'" by simp
 | 
| 18258 | 408 | then show "?case1 \<or> ?case2" | 
| 10249 | 409 | proof (elim exE conjE) | 
| 410 | fix a' M0' K | |
| 411 | assume N: "N = M0' + K" and r: "?r K a'" | |
| 412 |     assume "M0 + {#a#} = M0' + {#a'#}"
 | |
| 18258 | 413 | then have "M0 = M0' \<and> a = a' \<or> | 
| 11464 | 414 |         (\<exists>K'. M0 = K' + {#a'#} \<and> M0' = K' + {#a#})"
 | 
| 10249 | 415 | by (simp only: add_eq_conv_ex) | 
| 18258 | 416 | then show ?thesis | 
| 10249 | 417 | proof (elim disjE conjE exE) | 
| 418 | assume "M0 = M0'" "a = a'" | |
| 11464 | 419 | with N r have "?r K a \<and> N = M0 + K" by simp | 
| 18258 | 420 | then have ?case2 .. then show ?thesis .. | 
| 10249 | 421 | next | 
| 422 | fix K' | |
| 423 |       assume "M0' = K' + {#a#}"
 | |
| 424 |       with N have n: "N = K' + K + {#a#}" by (simp add: union_ac)
 | |
| 425 | ||
| 426 |       assume "M0 = K' + {#a'#}"
 | |
| 427 | with r have "?R (K' + K) M0" by blast | |
| 18258 | 428 | with n have ?case1 by simp then show ?thesis .. | 
| 10249 | 429 | qed | 
| 430 | qed | |
| 431 | qed | |
| 432 | ||
| 22270 | 433 | lemma all_accessible: "wfP r ==> \<forall>M. acc (mult1 r) M" | 
| 10249 | 434 | proof | 
| 435 | let ?R = "mult1 r" | |
| 436 | let ?W = "acc ?R" | |
| 437 |   {
 | |
| 438 | fix M M0 a | |
| 22270 | 439 | assume M0: "?W M0" | 
| 440 |       and wf_hyp: "!!b. r b a ==> \<forall>M \<triangleright> ?W. ?W (M + {#b#})"
 | |
| 441 |       and acc_hyp: "\<forall>M. ?R M M0 --> ?W (M + {#a#})"
 | |
| 442 |     have "?W (M0 + {#a#})"
 | |
| 443 |     proof (rule accI [of _ "M0 + {#a#}"])
 | |
| 10249 | 444 | fix N | 
| 22270 | 445 |       assume "?R N (M0 + {#a#})"
 | 
| 446 |       then have "((\<exists>M. ?R M M0 \<and> N = M + {#a#}) \<or>
 | |
| 447 | (\<exists>K. (\<forall>b. b :# K --> r b a) \<and> N = M0 + K))" | |
| 10249 | 448 | by (rule less_add) | 
| 22270 | 449 | then show "?W N" | 
| 10249 | 450 | proof (elim exE disjE conjE) | 
| 22270 | 451 |         fix M assume "?R M M0" and N: "N = M + {#a#}"
 | 
| 452 |         from acc_hyp have "?R M M0 --> ?W (M + {#a#})" ..
 | |
| 453 |         then have "?W (M + {#a#})" ..
 | |
| 454 | then show "?W N" by (simp only: N) | |
| 10249 | 455 | next | 
| 456 | fix K | |
| 457 | assume N: "N = M0 + K" | |
| 22270 | 458 | assume "\<forall>b. b :# K --> r b a" | 
| 459 | then have "?W (M0 + K)" | |
| 10249 | 460 | proof (induct K) | 
| 18730 | 461 | case empty | 
| 22270 | 462 |           from M0 show "?W (M0 + {#})" by simp
 | 
| 18730 | 463 | next | 
| 464 | case (add K x) | |
| 22270 | 465 | from add.prems have "r x a" by simp | 
| 466 |           with wf_hyp have "\<forall>M \<triangleright> ?W. ?W (M + {#x#})" by blast
 | |
| 467 | moreover from add have "?W (M0 + K)" by simp | |
| 468 |           ultimately have "?W ((M0 + K) + {#x#})" ..
 | |
| 469 |           then show "?W (M0 + (K + {#x#}))" by (simp only: union_assoc)
 | |
| 10249 | 470 | qed | 
| 22270 | 471 | then show "?W N" by (simp only: N) | 
| 10249 | 472 | qed | 
| 473 | qed | |
| 474 | } note tedious_reasoning = this | |
| 475 | ||
| 22270 | 476 | assume wf: "wfP r" | 
| 10249 | 477 | fix M | 
| 22270 | 478 | show "?W M" | 
| 10249 | 479 | proof (induct M) | 
| 22270 | 480 |     show "?W {#}"
 | 
| 10249 | 481 | proof (rule accI) | 
| 22270 | 482 |       fix b assume "?R b {#}"
 | 
| 483 | with not_less_empty show "?W b" by contradiction | |
| 10249 | 484 | qed | 
| 485 | ||
| 22270 | 486 | fix M a assume "?W M" | 
| 487 |     from wf have "\<forall>M \<triangleright> ?W. ?W (M + {#a#})"
 | |
| 10249 | 488 | proof induct | 
| 489 | fix a | |
| 22270 | 490 |       assume "!!b. r b a ==> \<forall>M \<triangleright> ?W. ?W (M + {#b#})"
 | 
| 491 |       show "\<forall>M \<triangleright> ?W. ?W (M + {#a#})"
 | |
| 10249 | 492 | proof | 
| 22270 | 493 | fix M assume "?W M" | 
| 494 |         then show "?W (M + {#a#})"
 | |
| 10249 | 495 | by (rule acc_induct) (rule tedious_reasoning) | 
| 496 | qed | |
| 497 | qed | |
| 22270 | 498 |     then show "?W (M + {#a#})" ..
 | 
| 10249 | 499 | qed | 
| 500 | qed | |
| 501 | ||
| 22270 | 502 | theorem wf_mult1: "wfP r ==> wfP (mult1 r)" | 
| 10249 | 503 | by (rule acc_wfI, rule all_accessible) | 
| 504 | ||
| 22270 | 505 | theorem wf_mult: "wfP r ==> wfP (mult r)" | 
| 506 | by (unfold mult_def, rule wfP_trancl, rule wf_mult1) | |
| 10249 | 507 | |
| 508 | ||
| 509 | subsubsection {* Closure-free presentation *}
 | |
| 510 | ||
| 511 | (*Badly needed: a linear arithmetic procedure for multisets*) | |
| 512 | ||
| 513 | lemma diff_union_single_conv: "a :# J ==> I + J - {#a#} = I + (J - {#a#})"
 | |
| 15072 | 514 | by (simp add: multiset_eq_conv_count_eq) | 
| 10249 | 515 | |
| 516 | text {* One direction. *}
 | |
| 517 | ||
| 518 | lemma mult_implies_one_step: | |
| 22270 | 519 | "transP r ==> mult r M N ==> | 
| 11464 | 520 |     \<exists>I J K. N = I + J \<and> M = I + K \<and> J \<noteq> {#} \<and>
 | 
| 22270 | 521 | (\<forall>k \<in> set_of K. \<exists>j \<in> set_of J. r k j)" | 
| 10249 | 522 | apply (unfold mult_def mult1_def set_of_def) | 
| 22270 | 523 | apply (erule converse_trancl_induct', clarify) | 
| 15072 | 524 | apply (rule_tac x = M0 in exI, simp, clarify) | 
| 22270 | 525 | apply (case_tac "a :# Ka") | 
| 10249 | 526 | apply (rule_tac x = I in exI) | 
| 527 | apply (simp (no_asm)) | |
| 22270 | 528 |    apply (rule_tac x = "(Ka - {#a#}) + K" in exI)
 | 
| 10249 | 529 | apply (simp (no_asm_simp) add: union_assoc [symmetric]) | 
| 11464 | 530 |    apply (drule_tac f = "\<lambda>M. M - {#a#}" in arg_cong)
 | 
| 10249 | 531 | apply (simp add: diff_union_single_conv) | 
| 532 | apply (simp (no_asm_use) add: trans_def) | |
| 533 | apply blast | |
| 534 | apply (subgoal_tac "a :# I") | |
| 535 |    apply (rule_tac x = "I - {#a#}" in exI)
 | |
| 536 |    apply (rule_tac x = "J + {#a#}" in exI)
 | |
| 537 | apply (rule_tac x = "K + Ka" in exI) | |
| 538 | apply (rule conjI) | |
| 539 | apply (simp add: multiset_eq_conv_count_eq split: nat_diff_split) | |
| 540 | apply (rule conjI) | |
| 15072 | 541 |     apply (drule_tac f = "\<lambda>M. M - {#a#}" in arg_cong, simp)
 | 
| 10249 | 542 | apply (simp add: multiset_eq_conv_count_eq split: nat_diff_split) | 
| 543 | apply (simp (no_asm_use) add: trans_def) | |
| 544 | apply blast | |
| 10277 | 545 |   apply (subgoal_tac "a :# (M0 + {#a#})")
 | 
| 10249 | 546 | apply simp | 
| 547 | apply (simp (no_asm)) | |
| 548 | done | |
| 549 | ||
| 550 | lemma elem_imp_eq_diff_union: "a :# M ==> M = M - {#a#} + {#a#}"
 | |
| 15072 | 551 | by (simp add: multiset_eq_conv_count_eq) | 
| 10249 | 552 | |
| 11464 | 553 | lemma size_eq_Suc_imp_eq_union: "size M = Suc n ==> \<exists>a N. M = N + {#a#}"
 | 
| 10249 | 554 | apply (erule size_eq_Suc_imp_elem [THEN exE]) | 
| 15072 | 555 | apply (drule elem_imp_eq_diff_union, auto) | 
| 10249 | 556 | done | 
| 557 | ||
| 558 | lemma one_step_implies_mult_aux: | |
| 22270 | 559 |   "\<forall>I J K. (size J = n \<and> J \<noteq> {#} \<and> (\<forall>k \<in> set_of K. \<exists>j \<in> set_of J. r k j))
 | 
| 560 | --> mult r (I + K) (I + J)" | |
| 15072 | 561 | apply (induct_tac n, auto) | 
| 562 | apply (frule size_eq_Suc_imp_eq_union, clarify) | |
| 563 | apply (rename_tac "J'", simp) | |
| 564 | apply (erule notE, auto) | |
| 10249 | 565 |   apply (case_tac "J' = {#}")
 | 
| 566 | apply (simp add: mult_def) | |
| 22270 | 567 | apply (rule trancl.r_into_trancl) | 
| 15072 | 568 | apply (simp add: mult1_def set_of_def, blast) | 
| 11464 | 569 |   txt {* Now we know @{term "J' \<noteq> {#}"}. *}
 | 
| 22270 | 570 | apply (cut_tac M = K and P = "\<lambda>x. r x a" in multiset_partition) | 
| 11464 | 571 | apply (erule_tac P = "\<forall>k \<in> set_of K. ?P k" in rev_mp) | 
| 10249 | 572 | apply (erule ssubst) | 
| 15072 | 573 | apply (simp add: Ball_def, auto) | 
| 10249 | 574 | apply (subgoal_tac | 
| 22270 | 575 |     "mult r ((I + {# x : K. r x a #}) + {# x : K. \<not> r x a #})
 | 
| 576 |       ((I + {# x : K. r x a #}) + J')")
 | |
| 10249 | 577 | prefer 2 | 
| 578 | apply force | |
| 579 | apply (simp (no_asm_use) add: union_assoc [symmetric] mult_def) | |
| 22270 | 580 | apply (erule trancl_trans') | 
| 581 | apply (rule trancl.r_into_trancl) | |
| 10249 | 582 | apply (simp add: mult1_def set_of_def) | 
| 583 | apply (rule_tac x = a in exI) | |
| 584 | apply (rule_tac x = "I + J'" in exI) | |
| 585 | apply (simp add: union_ac) | |
| 586 | done | |
| 587 | ||
| 17161 | 588 | lemma one_step_implies_mult: | 
| 22270 | 589 |   "J \<noteq> {#} ==> \<forall>k \<in> set_of K. \<exists>j \<in> set_of J. r k j
 | 
| 590 | ==> mult r (I + K) (I + J)" | |
| 15072 | 591 | apply (insert one_step_implies_mult_aux, blast) | 
| 10249 | 592 | done | 
| 593 | ||
| 594 | ||
| 595 | subsubsection {* Partial-order properties *}
 | |
| 596 | ||
| 12338 
de0f4a63baa5
renamed class "term" to "type" (actually "HOL.type");
 wenzelm parents: 
11868diff
changeset | 597 | instance multiset :: (type) ord .. | 
| 10249 | 598 | |
| 599 | defs (overloaded) | |
| 22270 | 600 | less_multiset_def: "op < == mult op <" | 
| 11464 | 601 | le_multiset_def: "M' <= M == M' = M \<or> M' < (M::'a multiset)" | 
| 10249 | 602 | |
| 22270 | 603 | lemma trans_base_order: "transP (op < :: 'a::order => 'a => bool)" | 
| 18730 | 604 | unfolding trans_def by (blast intro: order_less_trans) | 
| 10249 | 605 | |
| 606 | text {*
 | |
| 607 | \medskip Irreflexivity. | |
| 608 | *} | |
| 609 | ||
| 610 | lemma mult_irrefl_aux: | |
| 18258 | 611 |     "finite A ==> (\<forall>x \<in> A. \<exists>y \<in> A. x < (y::'a::order)) \<Longrightarrow> A = {}"
 | 
| 612 | apply (induct rule: finite_induct) | |
| 10249 | 613 | apply (auto intro: order_less_trans) | 
| 614 | done | |
| 615 | ||
| 17161 | 616 | lemma mult_less_not_refl: "\<not> M < (M::'a::order multiset)" | 
| 15072 | 617 | apply (unfold less_multiset_def, auto) | 
| 618 | apply (drule trans_base_order [THEN mult_implies_one_step], auto) | |
| 10249 | 619 | apply (drule finite_set_of [THEN mult_irrefl_aux [rule_format (no_asm)]]) | 
| 620 | apply (simp add: set_of_eq_empty_iff) | |
| 621 | done | |
| 622 | ||
| 623 | lemma mult_less_irrefl [elim!]: "M < (M::'a::order multiset) ==> R" | |
| 15072 | 624 | by (insert mult_less_not_refl, fast) | 
| 10249 | 625 | |
| 626 | ||
| 627 | text {* Transitivity. *}
 | |
| 628 | ||
| 629 | theorem mult_less_trans: "K < M ==> M < N ==> K < (N::'a::order multiset)" | |
| 630 | apply (unfold less_multiset_def mult_def) | |
| 22270 | 631 | apply (blast intro: trancl_trans') | 
| 10249 | 632 | done | 
| 633 | ||
| 634 | text {* Asymmetry. *}
 | |
| 635 | ||
| 11464 | 636 | theorem mult_less_not_sym: "M < N ==> \<not> N < (M::'a::order multiset)" | 
| 10249 | 637 | apply auto | 
| 638 | apply (rule mult_less_not_refl [THEN notE]) | |
| 15072 | 639 | apply (erule mult_less_trans, assumption) | 
| 10249 | 640 | done | 
| 641 | ||
| 642 | theorem mult_less_asym: | |
| 11464 | 643 | "M < N ==> (\<not> P ==> N < (M::'a::order multiset)) ==> P" | 
| 15072 | 644 | by (insert mult_less_not_sym, blast) | 
| 10249 | 645 | |
| 646 | theorem mult_le_refl [iff]: "M <= (M::'a::order multiset)" | |
| 18730 | 647 | unfolding le_multiset_def by auto | 
| 10249 | 648 | |
| 649 | text {* Anti-symmetry. *}
 | |
| 650 | ||
| 651 | theorem mult_le_antisym: | |
| 652 | "M <= N ==> N <= M ==> M = (N::'a::order multiset)" | |
| 18730 | 653 | unfolding le_multiset_def by (blast dest: mult_less_not_sym) | 
| 10249 | 654 | |
| 655 | text {* Transitivity. *}
 | |
| 656 | ||
| 657 | theorem mult_le_trans: | |
| 658 | "K <= M ==> M <= N ==> K <= (N::'a::order multiset)" | |
| 18730 | 659 | unfolding le_multiset_def by (blast intro: mult_less_trans) | 
| 10249 | 660 | |
| 11655 | 661 | theorem mult_less_le: "(M < N) = (M <= N \<and> M \<noteq> (N::'a::order multiset))" | 
| 18730 | 662 | unfolding le_multiset_def by auto | 
| 10249 | 663 | |
| 10277 | 664 | text {* Partial order. *}
 | 
| 665 | ||
| 666 | instance multiset :: (order) order | |
| 667 | apply intro_classes | |
| 22316 | 668 | apply (rule mult_less_le) | 
| 669 | apply (rule mult_le_refl) | |
| 15072 | 670 | apply (erule mult_le_trans, assumption) | 
| 22316 | 671 | apply (erule mult_le_antisym, assumption) | 
| 10277 | 672 | done | 
| 673 | ||
| 10249 | 674 | |
| 675 | subsubsection {* Monotonicity of multiset union *}
 | |
| 676 | ||
| 17161 | 677 | lemma mult1_union: | 
| 22270 | 678 | "mult1 r B D ==> mult1 r (C + B) (C + D)" | 
| 15072 | 679 | apply (unfold mult1_def, auto) | 
| 10249 | 680 | apply (rule_tac x = a in exI) | 
| 681 | apply (rule_tac x = "C + M0" in exI) | |
| 682 | apply (simp add: union_assoc) | |
| 683 | done | |
| 684 | ||
| 685 | lemma union_less_mono2: "B < D ==> C + B < C + (D::'a::order multiset)" | |
| 686 | apply (unfold less_multiset_def mult_def) | |
| 22270 | 687 | apply (erule trancl_induct') | 
| 688 | apply (blast intro: mult1_union) | |
| 689 | apply (blast intro: mult1_union trancl.r_into_trancl trancl_trans') | |
| 10249 | 690 | done | 
| 691 | ||
| 692 | lemma union_less_mono1: "B < D ==> B + C < D + (C::'a::order multiset)" | |
| 693 | apply (subst union_commute [of B C]) | |
| 694 | apply (subst union_commute [of D C]) | |
| 695 | apply (erule union_less_mono2) | |
| 696 | done | |
| 697 | ||
| 17161 | 698 | lemma union_less_mono: | 
| 10249 | 699 | "A < C ==> B < D ==> A + B < C + (D::'a::order multiset)" | 
| 700 | apply (blast intro!: union_less_mono1 union_less_mono2 mult_less_trans) | |
| 701 | done | |
| 702 | ||
| 17161 | 703 | lemma union_le_mono: | 
| 10249 | 704 | "A <= C ==> B <= D ==> A + B <= C + (D::'a::order multiset)" | 
| 18730 | 705 | unfolding le_multiset_def | 
| 706 | by (blast intro: union_less_mono union_less_mono1 union_less_mono2) | |
| 10249 | 707 | |
| 17161 | 708 | lemma empty_leI [iff]: "{#} <= (M::'a::order multiset)"
 | 
| 10249 | 709 | apply (unfold le_multiset_def less_multiset_def) | 
| 710 |   apply (case_tac "M = {#}")
 | |
| 711 | prefer 2 | |
| 22270 | 712 |    apply (subgoal_tac "mult op < ({#} + {#}) ({#} + M)")
 | 
| 10249 | 713 | prefer 2 | 
| 714 | apply (rule one_step_implies_mult) | |
| 22270 | 715 | apply auto | 
| 10249 | 716 | done | 
| 717 | ||
| 17161 | 718 | lemma union_upper1: "A <= A + (B::'a::order multiset)" | 
| 15072 | 719 | proof - | 
| 17200 | 720 |   have "A + {#} <= A + B" by (blast intro: union_le_mono)
 | 
| 18258 | 721 | then show ?thesis by simp | 
| 15072 | 722 | qed | 
| 723 | ||
| 17161 | 724 | lemma union_upper2: "B <= A + (B::'a::order multiset)" | 
| 18258 | 725 | by (subst union_commute) (rule union_upper1) | 
| 15072 | 726 | |
| 727 | ||
| 17200 | 728 | subsection {* Link with lists *}
 | 
| 15072 | 729 | |
| 17200 | 730 | consts | 
| 15072 | 731 | multiset_of :: "'a list \<Rightarrow> 'a multiset" | 
| 732 | primrec | |
| 733 |   "multiset_of [] = {#}"
 | |
| 734 |   "multiset_of (a # x) = multiset_of x + {# a #}"
 | |
| 735 | ||
| 736 | lemma multiset_of_zero_iff[simp]: "(multiset_of x = {#}) = (x = [])"
 | |
| 18258 | 737 | by (induct x) auto | 
| 15072 | 738 | |
| 739 | lemma multiset_of_zero_iff_right[simp]: "({#} = multiset_of x) = (x = [])"
 | |
| 18258 | 740 | by (induct x) auto | 
| 15072 | 741 | |
| 742 | lemma set_of_multiset_of[simp]: "set_of(multiset_of x) = set x" | |
| 18258 | 743 | by (induct x) auto | 
| 15867 | 744 | |
| 745 | lemma mem_set_multiset_eq: "x \<in> set xs = (x :# multiset_of xs)" | |
| 746 | by (induct xs) auto | |
| 15072 | 747 | |
| 18258 | 748 | lemma multiset_of_append [simp]: | 
| 749 | "multiset_of (xs @ ys) = multiset_of xs + multiset_of ys" | |
| 20503 | 750 | by (induct xs arbitrary: ys) (auto simp: union_ac) | 
| 18730 | 751 | |
| 15072 | 752 | lemma surj_multiset_of: "surj multiset_of" | 
| 17200 | 753 | apply (unfold surj_def, rule allI) | 
| 754 | apply (rule_tac M=y in multiset_induct, auto) | |
| 755 | apply (rule_tac x = "x # xa" in exI, auto) | |
| 10249 | 756 | done | 
| 757 | ||
| 15072 | 758 | lemma set_count_greater_0: "set x = {a. 0 < count (multiset_of x) a}"
 | 
| 18258 | 759 | by (induct x) auto | 
| 15072 | 760 | |
| 17200 | 761 | lemma distinct_count_atmost_1: | 
| 15072 | 762 | "distinct x = (! a. count (multiset_of x) a = (if a \<in> set x then 1 else 0))" | 
| 18258 | 763 | apply (induct x, simp, rule iffI, simp_all) | 
| 17200 | 764 | apply (rule conjI) | 
| 765 | apply (simp_all add: set_of_multiset_of [THEN sym] del: set_of_multiset_of) | |
| 15072 | 766 | apply (erule_tac x=a in allE, simp, clarify) | 
| 17200 | 767 | apply (erule_tac x=aa in allE, simp) | 
| 15072 | 768 | done | 
| 769 | ||
| 17200 | 770 | lemma multiset_of_eq_setD: | 
| 15867 | 771 | "multiset_of xs = multiset_of ys \<Longrightarrow> set xs = set ys" | 
| 772 | by (rule) (auto simp add:multiset_eq_conv_count_eq set_count_greater_0) | |
| 773 | ||
| 17200 | 774 | lemma set_eq_iff_multiset_of_eq_distinct: | 
| 775 | "\<lbrakk>distinct x; distinct y\<rbrakk> | |
| 15072 | 776 | \<Longrightarrow> (set x = set y) = (multiset_of x = multiset_of y)" | 
| 17200 | 777 | by (auto simp: multiset_eq_conv_count_eq distinct_count_atmost_1) | 
| 15072 | 778 | |
| 17200 | 779 | lemma set_eq_iff_multiset_of_remdups_eq: | 
| 15072 | 780 | "(set x = set y) = (multiset_of (remdups x) = multiset_of (remdups y))" | 
| 17200 | 781 | apply (rule iffI) | 
| 782 | apply (simp add: set_eq_iff_multiset_of_eq_distinct[THEN iffD1]) | |
| 783 | apply (drule distinct_remdups[THEN distinct_remdups | |
| 784 | [THEN set_eq_iff_multiset_of_eq_distinct[THEN iffD2]]]) | |
| 15072 | 785 | apply simp | 
| 10249 | 786 | done | 
| 787 | ||
| 18258 | 788 | lemma multiset_of_compl_union [simp]: | 
| 789 | "multiset_of [x\<in>xs. P x] + multiset_of [x\<in>xs. \<not>P x] = multiset_of xs" | |
| 15630 | 790 | by (induct xs) (auto simp: union_ac) | 
| 15072 | 791 | |
| 17200 | 792 | lemma count_filter: | 
| 18258 | 793 | "count (multiset_of xs) x = length [y \<in> xs. y = x]" | 
| 794 | by (induct xs) auto | |
| 15867 | 795 | |
| 796 | ||
| 15072 | 797 | subsection {* Pointwise ordering induced by count *}
 | 
| 798 | ||
| 19086 | 799 | definition | 
| 21404 
eb85850d3eb7
more robust syntax for definition/abbreviation/notation;
 wenzelm parents: 
21214diff
changeset | 800 |   mset_le :: "['a multiset, 'a multiset] \<Rightarrow> bool"  ("_ \<le># _"  [50,51] 50) where
 | 
| 19086 | 801 | "(xs \<le># ys) = (\<forall>a. count xs a \<le> count ys a)" | 
| 15072 | 802 | |
| 803 | lemma mset_le_refl[simp]: "xs \<le># xs" | |
| 18730 | 804 | unfolding mset_le_def by auto | 
| 15072 | 805 | |
| 806 | lemma mset_le_trans: "\<lbrakk> xs \<le># ys; ys \<le># zs \<rbrakk> \<Longrightarrow> xs \<le># zs" | |
| 18730 | 807 | unfolding mset_le_def by (fast intro: order_trans) | 
| 15072 | 808 | |
| 809 | lemma mset_le_antisym: "\<lbrakk> xs\<le># ys; ys \<le># xs\<rbrakk> \<Longrightarrow> xs = ys" | |
| 17200 | 810 | apply (unfold mset_le_def) | 
| 811 | apply (rule multiset_eq_conv_count_eq[THEN iffD2]) | |
| 15072 | 812 | apply (blast intro: order_antisym) | 
| 813 | done | |
| 814 | ||
| 17200 | 815 | lemma mset_le_exists_conv: | 
| 816 | "(xs \<le># ys) = (\<exists>zs. ys = xs + zs)" | |
| 817 | apply (unfold mset_le_def, rule iffI, rule_tac x = "ys - xs" in exI) | |
| 15072 | 818 | apply (auto intro: multiset_eq_conv_count_eq [THEN iffD2]) | 
| 819 | done | |
| 820 | ||
| 821 | lemma mset_le_mono_add_right_cancel[simp]: "(xs + zs \<le># ys + zs) = (xs \<le># ys)" | |
| 18730 | 822 | unfolding mset_le_def by auto | 
| 15072 | 823 | |
| 824 | lemma mset_le_mono_add_left_cancel[simp]: "(zs + xs \<le># zs + ys) = (xs \<le># ys)" | |
| 18730 | 825 | unfolding mset_le_def by auto | 
| 15072 | 826 | |
| 17200 | 827 | lemma mset_le_mono_add: "\<lbrakk> xs \<le># ys; vs \<le># ws \<rbrakk> \<Longrightarrow> xs + vs \<le># ys + ws" | 
| 828 | apply (unfold mset_le_def) | |
| 829 | apply auto | |
| 15072 | 830 | apply (erule_tac x=a in allE)+ | 
| 831 | apply auto | |
| 832 | done | |
| 833 | ||
| 834 | lemma mset_le_add_left[simp]: "xs \<le># xs + ys" | |
| 18730 | 835 | unfolding mset_le_def by auto | 
| 15072 | 836 | |
| 837 | lemma mset_le_add_right[simp]: "ys \<le># xs + ys" | |
| 18730 | 838 | unfolding mset_le_def by auto | 
| 15072 | 839 | |
| 840 | lemma multiset_of_remdups_le: "multiset_of (remdups x) \<le># multiset_of x" | |
| 17200 | 841 | apply (induct x) | 
| 842 | apply auto | |
| 843 | apply (rule mset_le_trans) | |
| 844 | apply auto | |
| 845 | done | |
| 15072 | 846 | |
| 10249 | 847 | end |