# HG changeset patch # User haftmann # Date 1456523051 -3600 # Node ID 9527ff088c15799d5a7604fa974242f8b75b87a8 # Parent 25271ff79171c7a51182bf99f19decf241fed9fa more succint formulation of membership for multisets, similar to lists; discontinued ASCII notation for multiset membership; more theorems on multisets, dropping redundant interpretation; modernized notation; some annotations concerning future work diff -r 25271ff79171 -r 9527ff088c15 NEWS --- a/NEWS Fri Feb 26 22:15:09 2016 +0100 +++ b/NEWS Fri Feb 26 22:44:11 2016 +0100 @@ -35,6 +35,23 @@ * Renamed split_if -> if_split and split_if_asm -> if_split_asm to resemble the f.split naming convention, INCOMPATIBILITY. +* Multiset membership is now expressed using set_mset rather than count. +ASCII infix syntax ":#" has been discontinued. + + - Expressions "count M a > 0" and similar simplify to membership + by default. + + - Converting between "count M a = 0" and non-membership happens using + equations count_eq_zero_iff and not_in_iff. + + - Rules count_inI and in_countE obtain facts of the form + "count M a = n" from membership. + + - Rules count_in_diffI and in_diff_countE obtain facts of the form + "count M a = n + count N a" from membership on difference sets. + +INCOMPATIBILITY. + * Compound constants INFIMUM and SUPREMUM are mere abbreviations now. INCOMPATIBILITY. diff -r 25271ff79171 -r 9527ff088c15 src/HOL/Algebra/Divisibility.thy --- a/src/HOL/Algebra/Divisibility.thy Fri Feb 26 22:15:09 2016 +0100 +++ b/src/HOL/Algebra/Divisibility.thy Fri Feb 26 22:44:11 2016 +0100 @@ -2169,9 +2169,8 @@ have "\c cs. c \ carrier G \ set cs \ carrier G \ wfactors G cs c \ fmset G cs = fmset G bs - fmset G as" proof (intro mset_wfactorsEx, simp) fix X - assume "count (fmset G as) X < count (fmset G bs) X" - hence "0 < count (fmset G bs) X" by simp - hence "X \ set_mset (fmset G bs)" by simp + assume "X \# fmset G bs - fmset G as" + hence "X \# fmset G bs" by (rule in_diffD) hence "X \ set (map (assocs G) bs)" by (simp add: fmset_def) hence "\x. x \ set bs \ X = assocs G x" by (induct bs) auto from this obtain x @@ -2595,8 +2594,8 @@ fmset G cs = fmset G as #\ fmset G bs" proof (intro mset_wfactorsEx) fix X - assume "X \ set_mset (fmset G as #\ fmset G bs)" - hence "X \ set_mset (fmset G as)" by (simp add: multiset_inter_def) + assume "X \# fmset G as #\ fmset G bs" + hence "X \# fmset G as" by simp hence "X \ set (map (assocs G) as)" by (simp add: fmset_def) hence "\x. X = assocs G x \ x \ set as" by (induct as) auto from this obtain x @@ -2673,9 +2672,9 @@ fmset G cs = (fmset G as - fmset G bs) + fmset G bs" proof (intro mset_wfactorsEx) fix X - assume "X \ set_mset ((fmset G as - fmset G bs) + fmset G bs)" - hence "X \ set_mset (fmset G as) \ X \ set_mset (fmset G bs)" - by (cases "X :# fmset G bs", simp, simp) + assume "X \# (fmset G as - fmset G bs) + fmset G bs" + hence "X \# fmset G as \ X \# fmset G bs" + by (auto dest: in_diffD) moreover { assume "X \ set_mset (fmset G as)" diff -r 25271ff79171 -r 9527ff088c15 src/HOL/Library/Multiset.thy --- a/src/HOL/Library/Multiset.thy Fri Feb 26 22:15:09 2016 +0100 +++ b/src/HOL/Library/Multiset.thy Fri Feb 26 22:44:11 2016 +0100 @@ -25,12 +25,6 @@ setup_lifting type_definition_multiset -abbreviation Melem :: "'a \ 'a multiset \ bool" (infix "\#" 50) - where "a \# M \ 0 < count M a" - -notation (ASCII) - Melem ("(_/ :# _)" [50, 51] 50) (* FIXME !? *) - lemma multiset_eq_iff: "M = N \ (\a. count M a = count N a)" by (simp only: count_inject [symmetric] fun_eq_iff) @@ -114,29 +108,154 @@ subsection \Basic operations\ +subsubsection \Conversion to set and membership\ + +definition set_mset :: "'a multiset \ 'a set" + where "set_mset M = {x. count M x > 0}" + +abbreviation Melem :: "'a \ 'a multiset \ bool" (infix "\#" 50) + where "a \# M \ a \ set_mset M" + +abbreviation not_Melem :: "'a \ 'a multiset \ bool" (infix "\#" 50) + where "a \# M \ a \ set_mset M" + +context +begin + +qualified abbreviation Ball :: "'a multiset \ ('a \ bool) \ bool" + where "Ball M \ Set.Ball (set_mset M)" + +qualified abbreviation Bex :: "'a multiset \ ('a \ bool) \ bool" + where "Bex M \ Set.Bex (set_mset M)" + +end + +syntax + "_MBall" :: "pttrn \ 'a set \ bool \ bool" ("(3\_\#_./ _)" [0, 0, 10] 10) + "_MBex" :: "pttrn \ 'a set \ bool \ bool" ("(3\_\#_./ _)" [0, 0, 10] 10) + +translations + "\x\#A. P" \ "CONST Multiset.Ball A (\x. P)" + "\x\#A. P" \ "CONST Multiset.Bex A (\x. P)" + +lemma count_eq_zero_iff: + "count M x = 0 \ x \# M" + by (auto simp add: set_mset_def) + +lemma not_in_iff: + "x \# M \ count M x = 0" + by (auto simp add: count_eq_zero_iff) + +lemma count_greater_zero_iff [simp]: + "count M x > 0 \ x \# M" + by (auto simp add: set_mset_def) + +lemma count_inI: + assumes "count M x = 0 \ False" + shows "x \# M" +proof (rule ccontr) + assume "x \# M" + with assms show False by (simp add: not_in_iff) +qed + +lemma in_countE: + assumes "x \# M" + obtains n where "count M x = Suc n" +proof - + from assms have "count M x > 0" by simp + then obtain n where "count M x = Suc n" + using gr0_conv_Suc by blast + with that show thesis . +qed + +lemma count_greater_eq_Suc_zero_iff [simp]: + "count M x \ Suc 0 \ x \# M" + by (simp add: Suc_le_eq) + +lemma count_greater_eq_one_iff [simp]: + "count M x \ 1 \ x \# M" + by simp + +lemma set_mset_empty [simp]: + "set_mset {#} = {}" + by (simp add: set_mset_def) + +lemma set_mset_single [simp]: + "set_mset {#b#} = {b}" + by (simp add: set_mset_def) + +lemma set_mset_eq_empty_iff [simp]: + "set_mset M = {} \ M = {#}" + by (auto simp add: multiset_eq_iff count_eq_zero_iff) + +lemma finite_set_mset [iff]: + "finite (set_mset M)" + using count [of M] by (simp add: multiset_def) + + subsubsection \Union\ -lemma count_union [simp]: "count (M + N) a = count M a + count N a" +lemma count_union [simp]: + "count (M + N) a = count M a + count N a" by (simp add: plus_multiset.rep_eq) +lemma set_mset_union [simp]: + "set_mset (M + N) = set_mset M \ set_mset N" + by (simp only: set_eq_iff count_greater_zero_iff [symmetric] count_union) simp + subsubsection \Difference\ -instantiation multiset :: (type) comm_monoid_diff -begin - -instance - by (standard; transfer; simp add: fun_eq_iff) - -end - -lemma count_diff [simp]: "count (M - N) a = count M a - count N a" +instance multiset :: (type) comm_monoid_diff + by standard (transfer; simp add: fun_eq_iff) + +lemma count_diff [simp]: + "count (M - N) a = count M a - count N a" by (simp add: minus_multiset.rep_eq) +lemma in_diff_count: + "a \# M - N \ count N a < count M a" + by (simp add: set_mset_def) + +lemma count_in_diffI: + assumes "\n. count N x = n + count M x \ False" + shows "x \# M - N" +proof (rule ccontr) + assume "x \# M - N" + then have "count N x = (count N x - count M x) + count M x" + by (simp add: in_diff_count not_less) + with assms show False by auto +qed + +lemma in_diff_countE: + assumes "x \# M - N" + obtains n where "count M x = Suc n + count N x" +proof - + from assms have "count M x - count N x > 0" by (simp add: in_diff_count) + then have "count M x > count N x" by simp + then obtain n where "count M x = Suc n + count N x" + using less_iff_Suc_add by auto + with that show thesis . +qed + +lemma in_diffD: + assumes "a \# M - N" + shows "a \# M" +proof - + have "0 \ count N a" by simp + also from assms have "count N a < count M a" + by (simp add: in_diff_count) + finally show ?thesis by simp +qed + +lemma set_mset_diff: + "set_mset (M - N) = {a. count N a < count M a}" + by (simp add: set_mset_def) + lemma diff_empty [simp]: "M - {#} = M \ {#} - M = {#}" by rule (fact Groups.diff_zero, fact Groups.zero_diff) -lemma diff_cancel[simp]: "A - A = {#}" +lemma diff_cancel [simp]: "A - A = {#}" by (fact Groups.diff_cancel) lemma diff_union_cancelR [simp]: "M + N - N = (M::'a multiset)" @@ -164,8 +283,22 @@ lemma diff_union_swap: "a \ b \ M - {#a#} + {#b#} = M + {#b#} - {#a#}" by (auto simp add: multiset_eq_iff) -lemma diff_union_single_conv: "a \# J \ I + J - {#a#} = I + (J - {#a#})" - by (simp add: multiset_eq_iff) +lemma diff_union_single_conv: + "a \# J \ I + J - {#a#} = I + (J - {#a#})" + by (simp add: multiset_eq_iff Suc_le_eq) + +lemma mset_add [elim?]: + assumes "a \# A" + obtains B where "A = B + {#a#}" +proof - + from assms have "A = (A - {#a#}) + {#a#}" + by simp + with that show thesis . +qed + +lemma union_iff: + "a \# A + B \ a \# A \ a \# B" + by auto subsubsection \Equality of multisets\ @@ -186,7 +319,7 @@ by (auto simp add: multiset_eq_iff) lemma diff_single_trivial: "\ x \# M \ M - {#x#} = M" - by (auto simp add: multiset_eq_iff) + by (auto simp add: multiset_eq_iff not_in_iff) lemma diff_single_eq_union: "x \# M \ M - {#x#} = N \ M = N + {#x#}" by auto @@ -197,12 +330,13 @@ lemma union_single_eq_member: "M + {#x#} = N \ x \# N" by auto -lemma union_is_single: "M + N = {#a#} \ M = {#a#} \ N={#} \ M = {#} \ N = {#a#}" +lemma union_is_single: + "M + N = {#a#} \ M = {#a#} \ N = {#} \ M = {#} \ N = {#a#}" (is "?lhs = ?rhs") proof show ?lhs if ?rhs using that by auto show ?rhs if ?lhs - using that by (simp add: multiset_eq_iff split: if_splits) (metis add_is_1) + by (metis Multiset.diff_cancel add.commute add_diff_cancel_left' diff_add_zero diff_single_trivial insert_DiffM that) qed lemma single_is_union: "{#a#} = M + N \ {#a#} = M \ N = {#} \ M = {#} \ {#a#} = N" @@ -271,17 +405,15 @@ definition subset_mset :: "'a multiset \ 'a multiset \ bool" (infix "\#" 50) where "A \# B = (A \# B \ A \ B)" -abbreviation (input) supseteq_mset :: "'a multiset \ 'a multiset \ bool" where - "supseteq_mset A B == B \# A" - -abbreviation (input) supset_mset :: "'a multiset \ 'a multiset \ bool" where - "supset_mset A B == B \# A" +abbreviation (input) supseteq_mset :: "'a multiset \ 'a multiset \ bool" (infix "\#" 50) + where "supseteq_mset A B \ B \# A" + +abbreviation (input) supset_mset :: "'a multiset \ 'a multiset \ bool" (infix "\#" 50) + where "supset_mset A B \ B \# A" notation (input) subseteq_mset (infix "\#" 50) and - supseteq_mset (infix "\#" 50) and - supseteq_mset (infix "\#" 50) and - supset_mset (infix "\#" 50) + supseteq_mset (infix "\#" 50) notation (ASCII) subseteq_mset (infix "<=#" 50) and @@ -291,11 +423,17 @@ interpretation subset_mset: ordered_ab_semigroup_add_imp_le "op +" "op -" "op \#" "op \#" by standard (auto simp add: subset_mset_def subseteq_mset_def multiset_eq_iff intro: order_trans antisym) - -lemma mset_less_eqI: "(\x. count A x \ count B x) \ A \# B" + -- \FIXME: avoid junk stemming from type class interpretation\ + +lemma mset_less_eqI: + "(\a. count A a \ count B a) \ A \# B" by (simp add: subseteq_mset_def) -lemma mset_le_exists_conv: "(A::'a multiset) \# B \ (\C. B = A + C)" +lemma mset_less_eq_count: + "A \# B \ count A a \ count B a" + by (simp add: subseteq_mset_def) + +lemma mset_le_exists_conv: "(A::'a multiset) \# B \ (\C. B = A + C)" unfolding subseteq_mset_def apply (rule iffI) apply (rule exI [where x = "B - A"]) @@ -308,87 +446,113 @@ declare subset_mset.zero_order[simp del] -- \this removes some simp rules not in the usual order for multisets\ -lemma mset_le_mono_add_right_cancel [simp]: "(A::'a multiset) + C \# B + C \ A \# B" - by (fact subset_mset.add_le_cancel_right) - -lemma mset_le_mono_add_left_cancel [simp]: "C + (A::'a multiset) \# C + B \ A \# B" - by (fact subset_mset.add_le_cancel_left) - -lemma mset_le_mono_add: "(A::'a multiset) \# B \ C \# D \ A + C \# B + D" - by (fact subset_mset.add_mono) - -lemma mset_le_add_left [simp]: "(A::'a multiset) \# A + B" - unfolding subseteq_mset_def by auto - -lemma mset_le_add_right [simp]: "B \# (A::'a multiset) + B" - unfolding subseteq_mset_def by auto - -lemma mset_le_single: "a \# B \ {#a#} \# B" - by (simp add: subseteq_mset_def) - +lemma mset_le_mono_add_right_cancel [simp]: "(A::'a multiset) + C \# B + C \ A \# B" + by (fact subset_mset.add_le_cancel_right) + +lemma mset_le_mono_add_left_cancel [simp]: "C + (A::'a multiset) \# C + B \ A \# B" + by (fact subset_mset.add_le_cancel_left) + +lemma mset_le_mono_add: "(A::'a multiset) \# B \ C \# D \ A + C \# B + D" + by (fact subset_mset.add_mono) + +lemma mset_le_add_left [simp]: "(A::'a multiset) \# A + B" + unfolding subseteq_mset_def by auto + +lemma mset_le_add_right [simp]: "B \# (A::'a multiset) + B" + unfolding subseteq_mset_def by auto + +lemma single_subset_iff [simp]: + "{#a#} \# M \ a \# M" + by (auto simp add: subseteq_mset_def Suc_le_eq) + +lemma mset_le_single: "a \# B \ {#a#} \# B" + by (simp add: subseteq_mset_def Suc_le_eq) + lemma multiset_diff_union_assoc: fixes A B C D :: "'a multiset" - shows "C \# B \ A + B - C = A + (B - C)" - by (simp add: subset_mset.diff_add_assoc) - + shows "C \# B \ A + B - C = A + (B - C)" + by (fact subset_mset.diff_add_assoc) + lemma mset_le_multiset_union_diff_commute: fixes A B C D :: "'a multiset" - shows "B \# A \ A - B + C = A + C - B" -by (simp add: subset_mset.add_diff_assoc2) - -lemma diff_le_self[simp]: "(M::'a multiset) - N \# M" -by(simp add: subseteq_mset_def) - -lemma mset_lessD: "A <# B \ x \# A \ x \# B" -apply (clarsimp simp: subset_mset_def subseteq_mset_def) -apply (erule allE [where x = x]) -apply auto -done - -lemma mset_leD: "A \# B \ x \# A \ x \# B" -apply (clarsimp simp: subset_mset_def subseteq_mset_def) -apply (erule allE [where x = x]) -apply auto -done - -lemma mset_less_insertD: "(A + {#x#} <# B) \ (x \# B \ A <# B)" -apply (rule conjI) - apply (simp add: mset_lessD) -apply (clarsimp simp: subset_mset_def subseteq_mset_def) -apply safe - apply (erule_tac x = a in allE) - apply (auto split: if_split_asm) -done - -lemma mset_le_insertD: "(A + {#x#} \# B) \ (x \# B \ A \# B)" + shows "B \# A \ A - B + C = A + C - B" + by (fact subset_mset.add_diff_assoc2) + +lemma diff_le_self[simp]: + "(M::'a multiset) - N \# M" + by (simp add: subseteq_mset_def) + +lemma mset_leD: + assumes "A \# B" and "x \# A" + shows "x \# B" +proof - + from \x \# A\ have "count A x > 0" by simp + also from \A \# B\ have "count A x \ count B x" + by (simp add: subseteq_mset_def) + finally show ?thesis by simp +qed + +lemma mset_lessD: + "A \# B \ x \# A \ x \# B" + by (auto intro: mset_leD [of A]) + +lemma set_mset_mono: + "A \# B \ set_mset A \ set_mset B" + by (metis mset_leD subsetI) + +lemma mset_le_insertD: + "A + {#x#} \# B \ x \# B \ A \# B" apply (rule conjI) apply (simp add: mset_leD) -apply (force simp: subset_mset_def subseteq_mset_def split: if_split_asm) + apply (clarsimp simp: subset_mset_def subseteq_mset_def) + apply safe + apply (erule_tac x = a in allE) + apply (auto split: if_split_asm) done -lemma mset_less_of_empty[simp]: "A <# {#} \ False" +lemma mset_less_insertD: + "A + {#x#} \# B \ x \# B \ A \# B" + by (rule mset_le_insertD) simp + +lemma mset_less_of_empty[simp]: "A \# {#} \ False" by (auto simp add: subseteq_mset_def subset_mset_def multiset_eq_iff) -lemma empty_le[simp]: "{#} \# A" - unfolding mset_le_exists_conv by auto - -lemma le_empty[simp]: "(M \# {#}) = (M = {#})" +lemma empty_le [simp]: "{#} \# A" unfolding mset_le_exists_conv by auto - -lemma multi_psub_of_add_self[simp]: "A <# A + {#x#}" + +lemma insert_subset_eq_iff: + "{#a#} + A \# B \ a \# B \ A \# B - {#a#}" + using le_diff_conv2 [of "Suc 0" "count B a" "count A a"] + apply (auto simp add: subseteq_mset_def not_in_iff Suc_le_eq) + apply (rule ccontr) + apply (auto simp add: not_in_iff) + done + +lemma insert_union_subset_iff: + "{#a#} + A \# B \ a \# B \ A \# B - {#a#}" + by (auto simp add: insert_subset_eq_iff subset_mset_def insert_DiffM) + +lemma subset_eq_diff_conv: + "A - C \# B \ A \# B + C" + by (simp add: subseteq_mset_def le_diff_conv) + +lemma le_empty [simp]: "M \# {#} \ M = {#}" + unfolding mset_le_exists_conv by auto + +lemma multi_psub_of_add_self[simp]: "A \# A + {#x#}" by (auto simp: subset_mset_def subseteq_mset_def) -lemma multi_psub_self[simp]: "(A::'a multiset) <# A = False" +lemma multi_psub_self[simp]: "(A::'a multiset) \# A = False" by simp -lemma mset_less_add_bothsides: "N + {#x#} <# M + {#x#} \ N <# M" +lemma mset_less_add_bothsides: "N + {#x#} \# M + {#x#} \ N \# M" by (fact subset_mset.add_less_imp_less_right) -lemma mset_less_empty_nonempty: "{#} <# S \ S \ {#}" +lemma mset_less_empty_nonempty: "{#} \# S \ S \ {#}" by (fact subset_mset.zero_less_iff_neq_zero) -lemma mset_less_diff_self: "c \# B \ B - {#c#} <# B" - by (auto simp: subset_mset_def subseteq_mset_def multiset_eq_iff) +lemma mset_less_diff_self: "c \# B \ B - {#c#} \# B" + by (auto simp: subset_mset_def elim: mset_add) subsubsection \Intersection\ @@ -396,20 +560,32 @@ definition inf_subset_mset :: "'a multiset \ 'a multiset \ 'a multiset" (infixl "#\" 70) where multiset_inter_def: "inf_subset_mset A B = A - (A - B)" -interpretation subset_mset: semilattice_inf inf_subset_mset "op \#" "op <#" +interpretation subset_mset: semilattice_inf inf_subset_mset "op \#" "op \#" proof - have [simp]: "m \ n \ m \ q \ m \ n - (n - q)" for m n q :: nat by arith - show "class.semilattice_inf op #\ op \# op <#" + show "class.semilattice_inf op #\ op \# op \#" by standard (auto simp add: multiset_inter_def subseteq_mset_def) qed - + -- \FIXME: avoid junk stemming from type class interpretation\ lemma multiset_inter_count [simp]: fixes A B :: "'a multiset" shows "count (A #\ B) x = min (count A x) (count B x)" by (simp add: multiset_inter_def) +lemma set_mset_inter [simp]: + "set_mset (A #\ B) = set_mset A \ set_mset B" + by (simp only: set_eq_iff count_greater_zero_iff [symmetric] multiset_inter_count) simp + +lemma diff_intersect_left_idem [simp]: + "M - M #\ N = M - N" + by (simp add: multiset_eq_iff min_def) + +lemma diff_intersect_right_idem [simp]: + "M - N #\ M = M - N" + by (simp add: multiset_eq_iff min_def) + lemma multiset_inter_single: "a \ b \ {#a#} #\ {#b#} = {#}" by (rule multiset_eqI) auto @@ -421,11 +597,37 @@ from assms have "min (count B x) (count C x) = 0" by (auto simp add: multiset_eq_iff) then have "count B x = 0 \ count C x = 0" - by auto + unfolding min_def by (auto split: if_splits) then show "count (A + B - C) x = count (A - C + B) x" by auto qed +lemma disjunct_not_in: + "A #\ B = {#} \ (\a. a \# A \ a \# B)" (is "?P \ ?Q") +proof + assume ?P + show ?Q + proof + fix a + from \?P\ have "min (count A a) (count B a) = 0" + by (simp add: multiset_eq_iff) + then have "count A a = 0 \ count B a = 0" + by (cases "count A a \ count B a") (simp_all add: min_def) + then show "a \# A \ a \# B" + by (simp add: not_in_iff) + qed +next + assume ?Q + show ?P + proof (rule multiset_eqI) + fix a + from \?Q\ have "count A a = 0 \ count B a = 0" + by (auto simp add: not_in_iff) + then show "count (A #\ B) a = count {#} a" + by auto + qed +qed + lemma empty_inter [simp]: "{#} #\ M = {#}" by (simp add: multiset_eq_iff) @@ -433,55 +635,123 @@ by (simp add: multiset_eq_iff) lemma inter_add_left1: "\ x \# N \ (M + {#x#}) #\ N = M #\ N" - by (simp add: multiset_eq_iff) + by (simp add: multiset_eq_iff not_in_iff) lemma inter_add_left2: "x \# N \ (M + {#x#}) #\ N = (M #\ (N - {#x#})) + {#x#}" - by (simp add: multiset_eq_iff) + by (auto simp add: multiset_eq_iff elim: mset_add) lemma inter_add_right1: "\ x \# N \ N #\ (M + {#x#}) = N #\ M" - by (simp add: multiset_eq_iff) + by (simp add: multiset_eq_iff not_in_iff) lemma inter_add_right2: "x \# N \ N #\ (M + {#x#}) = ((N - {#x#}) #\ M) + {#x#}" - by (simp add: multiset_eq_iff) + by (auto simp add: multiset_eq_iff elim: mset_add) + +lemma disjunct_set_mset_diff: + assumes "M #\ N = {#}" + shows "set_mset (M - N) = set_mset M" +proof (rule set_eqI) + fix a + from assms have "a \# M \ a \# N" + by (simp add: disjunct_not_in) + then show "a \# M - N \ a \# M" + by (auto dest: in_diffD) (simp add: in_diff_count not_in_iff) +qed + +lemma at_most_one_mset_mset_diff: + assumes "a \# M - {#a#}" + shows "set_mset (M - {#a#}) = set_mset M - {a}" + using assms by (auto simp add: not_in_iff in_diff_count set_eq_iff) + +lemma more_than_one_mset_mset_diff: + assumes "a \# M - {#a#}" + shows "set_mset (M - {#a#}) = set_mset M" +proof (rule set_eqI) + fix b + have "Suc 0 < count M b \ count M b > 0" by arith + then show "b \# M - {#a#} \ b \# M" + using assms by (auto simp add: in_diff_count) +qed + +lemma inter_iff: + "a \# A #\ B \ a \# A \ a \# B" + by simp + +lemma inter_union_distrib_left: + "A #\ B + C = (A + C) #\ (B + C)" + by (simp add: multiset_eq_iff min_add_distrib_left) + +lemma inter_union_distrib_right: + "C + A #\ B = (C + A) #\ (C + B)" + using inter_union_distrib_left [of A B C] by (simp add: ac_simps) + +lemma inter_subset_eq_union: + "A #\ B \# A + B" + by (auto simp add: subseteq_mset_def) subsubsection \Bounded union\ definition sup_subset_mset :: "'a multiset \ 'a multiset \ 'a multiset"(infixl "#\" 70) - where "sup_subset_mset A B = A + (B - A)" - -interpretation subset_mset: semilattice_sup sup_subset_mset "op \#" "op <#" + where "sup_subset_mset A B = A + (B - A)" -- \FIXME irregular fact name\ + +interpretation subset_mset: semilattice_sup sup_subset_mset "op \#" "op \#" proof - have [simp]: "m \ n \ q \ n \ m + (q - m) \ n" for m n q :: nat by arith - show "class.semilattice_sup op #\ op \# op <#" + show "class.semilattice_sup op #\ op \# op \#" by standard (auto simp add: sup_subset_mset_def subseteq_mset_def) qed - -lemma sup_subset_mset_count [simp]: "count (A #\ B) x = max (count A x) (count B x)" + -- \FIXME: avoid junk stemming from type class interpretation\ + +lemma sup_subset_mset_count [simp]: -- \FIXME irregular fact name\ + "count (A #\ B) x = max (count A x) (count B x)" by (simp add: sup_subset_mset_def) +lemma set_mset_sup [simp]: + "set_mset (A #\ B) = set_mset A \ set_mset B" + by (simp only: set_eq_iff count_greater_zero_iff [symmetric] sup_subset_mset_count) + (auto simp add: not_in_iff elim: mset_add) + lemma empty_sup [simp]: "{#} #\ M = M" by (simp add: multiset_eq_iff) lemma sup_empty [simp]: "M #\ {#} = M" by (simp add: multiset_eq_iff) -lemma sup_add_left1: "\ x \# N \ (M + {#x#}) #\ N = (M #\ N) + {#x#}" +lemma sup_union_left1: "\ x \# N \ (M + {#x#}) #\ N = (M #\ N) + {#x#}" + by (simp add: multiset_eq_iff not_in_iff) + +lemma sup_union_left2: "x \# N \ (M + {#x#}) #\ N = (M #\ (N - {#x#})) + {#x#}" by (simp add: multiset_eq_iff) -lemma sup_add_left2: "x \# N \ (M + {#x#}) #\ N = (M #\ (N - {#x#})) + {#x#}" +lemma sup_union_right1: "\ x \# N \ N #\ (M + {#x#}) = (N #\ M) + {#x#}" + by (simp add: multiset_eq_iff not_in_iff) + +lemma sup_union_right2: "x \# N \ N #\ (M + {#x#}) = ((N - {#x#}) #\ M) + {#x#}" by (simp add: multiset_eq_iff) -lemma sup_add_right1: "\ x \# N \ N #\ (M + {#x#}) = (N #\ M) + {#x#}" - by (simp add: multiset_eq_iff) - -lemma sup_add_right2: "x \# N \ N #\ (M + {#x#}) = ((N - {#x#}) #\ M) + {#x#}" - by (simp add: multiset_eq_iff) +lemma sup_union_distrib_left: + "A #\ B + C = (A + C) #\ (B + C)" + by (simp add: multiset_eq_iff max_add_distrib_left) + +lemma union_sup_distrib_right: + "C + A #\ B = (C + A) #\ (C + B)" + using sup_union_distrib_left [of A B C] by (simp add: ac_simps) + +lemma union_diff_inter_eq_sup: + "A + B - A #\ B = A #\ B" + by (auto simp add: multiset_eq_iff) + +lemma union_diff_sup_eq_inter: + "A + B - A #\ B = A #\ B" + by (auto simp add: multiset_eq_iff) + subsubsection \Subset is an order\ + interpretation subset_mset: order "op \#" "op <#" by unfold_locales auto + subsubsection \Filter (with comprehension syntax)\ text \Multiset comprehension\ @@ -490,9 +760,21 @@ is "\P M. \x. if P x then M x else 0" by (rule filter_preserves_multiset) -lemma count_filter_mset [simp]: "count (filter_mset P M) a = (if P a then count M a else 0)" +syntax (ASCII) + "_MCollect" :: "pttrn \ 'a multiset \ bool \ 'a multiset" ("(1{# _ :# _./ _#})") +syntax + "_MCollect" :: "pttrn \ 'a multiset \ bool \ 'a multiset" ("(1{# _ \# _./ _#})") +translations + "{#x \# M. P#}" == "CONST filter_mset (\x. P) M" + +lemma count_filter_mset [simp]: + "count (filter_mset P M) a = (if P a then count M a else 0)" by (simp add: filter_mset.rep_eq) +lemma set_mset_filter [simp]: + "set_mset (filter_mset P M) = {a \ set_mset M. P a}" + by (simp only: set_eq_iff count_greater_zero_iff [symmetric] count_filter_mset) simp + lemma filter_empty_mset [simp]: "filter_mset P {#} = {#}" by (rule multiset_eqI) simp @@ -508,60 +790,44 @@ lemma filter_inter_mset [simp]: "filter_mset P (M #\ N) = filter_mset P M #\ filter_mset P N" by (rule multiset_eqI) simp -lemma multiset_filter_subset[simp]: "filter_mset f M \# M" +lemma multiset_filter_subset[simp]: "filter_mset f M \# M" by (simp add: mset_less_eqI) lemma multiset_filter_mono: - assumes "A \# B" - shows "filter_mset f A \# filter_mset f B" + assumes "A \# B" + shows "filter_mset f A \# filter_mset f B" proof - from assms[unfolded mset_le_exists_conv] obtain C where B: "B = A + C" by auto show ?thesis unfolding B by auto qed -syntax (ASCII) - "_MCollect" :: "pttrn \ 'a multiset \ bool \ 'a multiset" ("(1{# _ :# _./ _#})") -syntax - "_MCollect" :: "pttrn \ 'a multiset \ bool \ 'a multiset" ("(1{# _ \# _./ _#})") -translations - "{#x \# M. P#}" == "CONST filter_mset (\x. P) M" - - -subsubsection \Set of elements\ - -definition set_mset :: "'a multiset \ 'a set" - where "set_mset M = {x. x \# M}" - -lemma set_mset_empty [simp]: "set_mset {#} = {}" -by (simp add: set_mset_def) - -lemma set_mset_single [simp]: "set_mset {#b#} = {b}" -by (simp add: set_mset_def) - -lemma set_mset_union [simp]: "set_mset (M + N) = set_mset M \ set_mset N" -by (auto simp add: set_mset_def) - -lemma set_mset_eq_empty_iff [simp]: "(set_mset M = {}) = (M = {#})" -by (auto simp add: set_mset_def multiset_eq_iff) - -lemma mem_set_mset_iff [simp]: "(x \ set_mset M) = (x \# M)" -by (auto simp add: set_mset_def) - -lemma set_mset_filter [simp]: "set_mset {# x\#M. P x #} = set_mset M \ {x. P x}" -by (auto simp add: set_mset_def) - -lemma finite_set_mset [iff]: "finite (set_mset M)" - using count [of M] by (simp add: multiset_def set_mset_def) - -lemma finite_Collect_mem [iff]: "finite {x. x \# M}" - unfolding set_mset_def[symmetric] by simp - -lemma set_mset_mono: "A \# B \ set_mset A \ set_mset B" - by (metis mset_leD subsetI mem_set_mset_iff) - -lemma ball_set_mset_iff: "(\x \ set_mset M. P x) \ (\x. x \# M \ P x)" - by auto +lemma filter_mset_eq_conv: + "filter_mset P M = N \ N \# M \ (\b\#N. P b) \ (\a\#M - N. \ P a)" (is "?P \ ?Q") +proof + assume ?P then show ?Q by auto (simp add: multiset_eq_iff in_diff_count) +next + assume ?Q + then obtain Q where M: "M = N + Q" + by (auto simp add: mset_le_exists_conv) + then have MN: "M - N = Q" by simp + show ?P + proof (rule multiset_eqI) + fix a + from \?Q\ MN have *: "\ P a \ a \# N" "P a \ a \# Q" + by auto + show "count (filter_mset P M) a = count N a" + proof (cases "a \# M") + case True + with * show ?thesis + by (simp add: not_in_iff M) + next + case False then have "count M a = 0" + by (simp add: not_in_iff) + with M show ?thesis by simp + qed + qed +qed subsubsection \Size\ @@ -602,10 +868,8 @@ lemma setsum_wcount_Int: "finite A \ setsum (wcount f N) (A \ set_mset N) = setsum (wcount f N) A" -apply (induct rule: finite_induct) - apply simp -apply (simp add: Int_insert_left set_mset_def wcount_def) -done + by (induct rule: finite_induct) + (simp_all add: Int_insert_left wcount_def count_eq_zero_iff) lemma size_multiset_union [simp]: "size_multiset f (M + N::'a multiset) = size_multiset f M + size_multiset f N" @@ -617,8 +881,9 @@ lemma size_union [simp]: "size (M + N::'a multiset) = size M + size N" by (auto simp add: size_multiset_overloaded_def) -lemma size_multiset_eq_0_iff_empty [iff]: "(size_multiset f M = 0) = (M = {#})" -by (auto simp add: size_multiset_eq multiset_eq_iff) +lemma size_multiset_eq_0_iff_empty [iff]: + "size_multiset f M = 0 \ M = {#}" + by (auto simp add: size_multiset_eq count_eq_zero_iff) lemma size_eq_0_iff_empty [iff]: "(size M = 0) = (M = {#})" by (auto simp add: size_multiset_overloaded_def) @@ -644,7 +909,7 @@ lemma size_mset_mono: fixes A B :: "'a multiset" - assumes "A \# B" + assumes "A \# B" shows "size A \ size B" proof - from assms[unfolded mset_le_exists_conv] @@ -656,9 +921,10 @@ by (rule size_mset_mono[OF multiset_filter_subset]) lemma size_Diff_submset: - "M \# M' \ size (M' - M) = size M' - size(M::'a multiset)" + "M \# M' \ size (M' - M) = size M' - size(M::'a multiset)" by (metis add_diff_cancel_left' size_union mset_le_exists_conv) + subsection \Induction and case splits\ theorem multiset_induct [case_names empty add, induct type: multiset]: @@ -691,7 +957,7 @@ apply auto done -lemma mset_less_size: "(A::'a multiset) <# B \ size A < size B" +lemma mset_less_size: "(A::'a multiset) \# B \ size A < size B" proof (induct A arbitrary: B) case (empty M) then have "M \ {#}" by (simp add: mset_less_empty_nonempty) @@ -700,54 +966,55 @@ then show ?case by simp next case (add S x T) - have IH: "\B. S <# B \ size S < size B" by fact - have SxsubT: "S + {#x#} <# T" by fact - then have "x \# T" and "S <# T" by (auto dest: mset_less_insertD) + have IH: "\B. S \# B \ size S < size B" by fact + have SxsubT: "S + {#x#} \# T" by fact + then have "x \# T" and "S \# T" + by (auto dest: mset_less_insertD) then obtain T' where T: "T = T' + {#x#}" by (blast dest: multi_member_split) - then have "S <# T'" using SxsubT + then have "S \# T'" using SxsubT by (blast intro: mset_less_add_bothsides) then have "size S < size T'" using IH by simp then show ?case using T by simp qed - lemma size_1_singleton_mset: "size M = 1 \ \a. M = {#a#}" by (cases M) auto + subsubsection \Strong induction and subset induction for multisets\ text \Well-foundedness of strict subset relation\ -lemma wf_less_mset_rel: "wf {(M, N :: 'a multiset). M <# N}" +lemma wf_less_mset_rel: "wf {(M, N :: 'a multiset). M \# N}" apply (rule wf_measure [THEN wf_subset, where f1=size]) apply (clarsimp simp: measure_def inv_image_def mset_less_size) done lemma full_multiset_induct [case_names less]: -assumes ih: "\B. \(A::'a multiset). A <# B \ P A \ P B" +assumes ih: "\B. \(A::'a multiset). A \# B \ P A \ P B" shows "P B" apply (rule wf_less_mset_rel [THEN wf_induct]) apply (rule ih, auto) done lemma multi_subset_induct [consumes 2, case_names empty add]: - assumes "F \# A" + assumes "F \# A" and empty: "P {#}" and insert: "\a F. a \# A \ P F \ P (F + {#a#})" shows "P F" proof - - from \F \# A\ + from \F \# A\ show ?thesis proof (induct F) show "P {#}" by fact next fix x F - assume P: "F \# A \ P F" and i: "F + {#x#} \# A" + assume P: "F \# A \ P F" and i: "F + {#x#} \# A" show "P (F + {#x#})" proof (rule insert) from i show "x \# A" by (auto dest: mset_le_insertD) - from i have "F \# A" by (auto dest: mset_le_insertD) + from i have "F \# A" by (auto dest: mset_le_insertD) with P show "P F" . qed qed @@ -775,7 +1042,8 @@ show ?thesis proof (cases "x \ set_mset M") case False - then have *: "count (M + {#x#}) x = 1" by simp + then have *: "count (M + {#x#}) x = 1" + by (simp add: not_in_iff) from False have "Finite_Set.fold (\y. f y ^^ count (M + {#x#}) y) s (set_mset M) = Finite_Set.fold (\y. f y ^^ count M y) s (set_mset M)" by (auto intro!: Finite_Set.fold_cong comp_fun_commute_funpow) @@ -893,7 +1161,7 @@ \ lemma in_image_mset: "y \# {#f x. x \# M#} \ y \ f ` set_mset M" -by (metis mem_set_mset_iff set_image_mset) +by (metis set_image_mset) functor image_mset: image_mset proof - @@ -949,8 +1217,8 @@ lemma set_mset_mset[simp]: "set_mset (mset x) = set x" by (induct x) auto -lemma mem_set_multiset_eq: "x \ set xs = (x \# mset xs)" -by (induct xs) auto +lemma set_mset_comp_mset [simp]: "set_mset \ mset = set" + by (simp add: fun_eq_iff) lemma size_mset [simp]: "size (mset xs) = length xs" by (induct xs) simp_all @@ -974,23 +1242,32 @@ apply auto done -lemma set_count_greater_0: "set x = {a. count (mset x) a > 0}" -by (induct x) auto - lemma distinct_count_atmost_1: "distinct x = (\a. count (mset x) a = (if a \ set x then 1 else 0))" - apply (induct x, simp, rule iffI, simp_all) - subgoal for a b - apply (rule conjI) - apply (simp_all add: set_mset_mset [symmetric] del: set_mset_mset) - apply (erule_tac x = a in allE, simp) - apply clarify - apply (erule_tac x = aa in allE, simp) - done - done - -lemma mset_eq_setD: "mset xs = mset ys \ set xs = set ys" -by (rule) (auto simp add:multiset_eq_iff set_count_greater_0) +proof (induct x) + case Nil then show ?case by simp +next + case (Cons x xs) show ?case (is "?lhs \ ?rhs") + proof + assume ?lhs then show ?rhs using Cons by simp + next + assume ?rhs then have "x \ set xs" + by (simp split: if_splits) + moreover from \?rhs\ have "(\a. count (mset xs) a = + (if a \ set xs then 1 else 0))" + by (auto split: if_splits simp add: count_eq_zero_iff) + ultimately show ?lhs using Cons by simp + qed +qed + +lemma mset_eq_setD: + assumes "mset xs = mset ys" + shows "set xs = set ys" +proof - + from assms have "set_mset (mset xs) = set_mset (mset ys)" + by simp + then show ?thesis by simp +qed lemma set_eq_iff_mset_eq_distinct: "distinct x \ distinct y \ @@ -1146,7 +1423,7 @@ unfolding replicate_mset_def by (induct n) (auto intro: add.commute) lemma in_replicate_mset[simp]: "x \# replicate_mset n y \ n > 0 \ x = y" - unfolding replicate_mset_def by (induct n) simp_all + unfolding replicate_mset_def by (induct n) auto lemma count_replicate_mset[simp]: "count (replicate_mset n x) y = (if y = x then n else 0)" unfolding replicate_mset_def by (induct n) simp_all @@ -1157,7 +1434,7 @@ lemma size_replicate_mset[simp]: "size (replicate_mset n M) = n" by (induct n, simp_all) -lemma count_le_replicate_mset_le: "n \ count M x \ replicate_mset n x \# M" +lemma count_le_replicate_mset_le: "n \ count M x \ replicate_mset n x \# M" by (auto simp add: assms mset_less_eqI) (metis count_replicate_mset subseteq_mset_def) lemma filter_eq_replicate_mset: "{#y \# D. y = x#} = replicate_mset (count D x) x" @@ -1237,7 +1514,7 @@ lemma msetsum_diff: fixes M N :: "('a :: ordered_cancel_comm_monoid_diff) multiset" - shows "N \# M \ msetsum (M - N) = msetsum M - msetsum N" + shows "N \# M \ msetsum (M - N) = msetsum M - msetsum N" by (metis add_diff_cancel_right' msetsum.union subset_mset.diff_add) lemma size_eq_msetsum: "size M = msetsum (image_mset (\_. 1) M)" @@ -1246,7 +1523,7 @@ next case (add M x) then show ?case by (cases "x \ set_mset M") - (simp_all del: mem_set_mset_iff add: size_multiset_overloaded_eq setsum.distrib setsum.delta' insert_absorb, simp) + (simp_all add: size_multiset_overloaded_eq setsum.distrib setsum.delta' insert_absorb not_in_iff) qed syntax (ASCII) @@ -1257,7 +1534,8 @@ "\i \# A. b" \ "CONST msetsum (CONST image_mset (\i. b) A)" abbreviation Union_mset :: "'a multiset multiset \ 'a multiset" ("\#_" [900] 900) - where "\# MM \ msetsum MM" + where "\# MM \ msetsum MM" -- \FIXME ambiguous notation -- + could likewise refer to @{text "\#"}\ lemma set_mset_Union_mset[simp]: "set_mset (\# MM) = (\M \ set_mset MM. set_mset M)" by (induct MM) auto @@ -1322,10 +1600,30 @@ then show ?thesis by simp qed -lemma (in semidom) msetprod_zero_iff: - "msetprod A = 0 \ (\a\set_mset A. a = 0)" +lemma (in semidom) msetprod_zero_iff [iff]: + "msetprod A = 0 \ 0 \# A" by (induct A) auto +lemma (in semidom_divide) msetprod_diff: + assumes "B \# A" and "0 \# B" + shows "msetprod (A - B) = msetprod A div msetprod B" +proof - + from assms obtain C where "A = B + C" + by (metis subset_mset.add_diff_inverse) + with assms show ?thesis by simp +qed + +lemma (in semidom_divide) msetprod_minus: + assumes "a \# A" and "a \ 0" + shows "msetprod (A - {#a#}) = msetprod A div a" + using assms msetprod_diff [of "{#a#}" A] + by (auto simp add: single_subset_iff) + +lemma (in normalization_semidom) normalized_msetprodI: + assumes "\a. a \# A \ normalize a = a" + shows "normalize (msetprod A) = msetprod A" + using assms by (induct A) (simp_all add: normalize_mult) + subsection \Alternative representations\ @@ -1362,8 +1660,10 @@ by (simp add: filter_remove1) with Cons.prems have "sort_key f xs = remove1 x ys" by (auto intro!: Cons.hyps simp add: sorted_map_remove1) - moreover from Cons.prems have "x \ set ys" - by (auto simp add: mem_set_multiset_eq intro!: ccontr) + moreover from Cons.prems have "x \# mset ys" + by auto + then have "x \ set ys" + by simp ultimately show ?case using Cons.prems by (simp add: insort_key_remove1) qed @@ -1511,7 +1811,7 @@ hide_const (open) part -lemma mset_remdups_le: "mset (remdups xs) \# mset xs" +lemma mset_remdups_le: "mset (remdups xs) \# mset xs" by (induct xs) (auto intro: subset_mset.order_trans) lemma mset_update: @@ -1554,6 +1854,16 @@ definition mult :: "('a \ 'a) set \ ('a multiset \ 'a multiset) set" where "mult r = (mult1 r)\<^sup>+" +lemma mult1I: + assumes "M = M0 + {#a#}" and "N = M0 + K" and "\b. b \# K \ (b, a) \ r" + shows "(N, M) \ mult1 r" + using assms unfolding mult1_def by blast + +lemma mult1E: + assumes "(N, M) \ mult1 r" + obtains a M0 K where "M = M0 + {#a#}" "N = M0 + K" "\b. b \# K \ (b, a) \ r" + using assms unfolding mult1_def by blast + lemma not_less_empty [iff]: "(M, {#}) \ mult1 r" by (simp add: mult1_def) @@ -1672,7 +1982,7 @@ "trans r \ (M, N) \ mult r \ \I J K. N = I + J \ M = I + K \ J \ {#} \ (\k \ set_mset K. \j \ set_mset J. (k, j) \ r)" -apply (unfold mult_def mult1_def set_mset_def) +apply (unfold mult_def mult1_def) apply (erule converse_trancl_induct, clarify) apply (rule_tac x = M0 in exI, simp, clarify) apply (case_tac "a \# K") @@ -1683,7 +1993,7 @@ apply (drule_tac f = "\M. M - {#a#}" and x="S + T" for S T in arg_cong) apply (simp add: diff_union_single_conv) apply (simp (no_asm_use) add: trans_def) - apply blast + apply (metis (no_types, hide_lams) Multiset.diff_right_commute Un_iff diff_single_trivial multi_drop_mem_not_eq) apply (subgoal_tac "a \# I") apply (rule_tac x = "I - {#a#}" in exI) apply (rule_tac x = "J + {#a#}" in exI) @@ -1694,10 +2004,10 @@ apply (drule_tac f = "\M. M - {#a#}" and x="S + T" for S T in arg_cong, simp) apply (simp add: multiset_eq_iff split: nat_diff_split) apply (simp (no_asm_use) add: trans_def) +apply (subgoal_tac "a \# (M0 + {#a#})") + apply (simp_all add: not_in_iff) apply blast -apply (subgoal_tac "a \# (M0 + {#a#})") - apply simp -apply (simp (no_asm)) + apply (metis add.comm_neutral add_diff_cancel_right' count_eq_zero_iff diff_single_trivial multi_self_add_other_not_self plus_multiset.rep_eq) done lemma one_step_implies_mult_aux: @@ -1711,7 +2021,7 @@ apply (case_tac "J' = {#}") apply (simp add: mult_def) apply (rule r_into_trancl) - apply (simp add: mult1_def set_mset_def, blast) + apply (simp add: mult1_def, blast) txt \Now we know @{term "J' \ {#}"}.\ apply (cut_tac M = K and P = "\x. (x, a) \ r" in multiset_partition) apply (erule_tac P = "\k \ set_mset K. P k" for P in rev_mp) @@ -1725,7 +2035,7 @@ apply (simp (no_asm_use) add: add.assoc [symmetric] mult_def) apply (erule trancl_trans) apply (rule r_into_trancl) -apply (simp add: mult1_def set_mset_def) +apply (simp add: mult1_def) apply (rule_tac x = a in exI) apply (rule_tac x = "I + J'" in exI) apply (simp add: ac_simps) @@ -1739,6 +2049,17 @@ subsubsection \Partial-order properties\ +lemma (in order) mult1_lessE: + assumes "(N, M) \ mult1 {(a, b). a < b}" + obtains a M0 K where "M = M0 + {#a#}" "N = M0 + K" + "a \# K" "\b. b \# K \ b < a" +proof - + from assms obtain a M0 K where "M = M0 + {#a#}" "N = M0 + K" + "\b. b \# K \ b < a" by (blast elim: mult1E) + moreover from this(3) [of a] have "a \# K" by auto + ultimately show thesis by (auto intro: that) +qed + definition less_multiset :: "'a::order multiset \ 'a multiset \ bool" (infix "#\#" 50) where "M' #\# M \ (M', M) \ mult {(x', x). x' < x}" @@ -1774,7 +2095,7 @@ unfolding less_multiset_def mult_def by (blast intro: trancl_trans) show "class.order (le_multiset :: 'a multiset \ _) less_multiset" by standard (auto simp add: le_multiset_def irrefl dest: trans) -qed +qed -- \FIXME avoid junk stemming from type class interpretation\ lemma mult_less_irrefl [elim!]: fixes M :: "'a::order multiset" @@ -1989,7 +2310,7 @@ lemma multi_union_self_other_eq: "(A::'a multiset) + X = A + Y \ X = Y" by (fact add_left_imp_eq) -lemma mset_less_trans: "(M::'a multiset) <# K \ K <# N \ M <# N" +lemma mset_less_trans: "(M::'a multiset) \# K \ K \# N \ M \# N" by (fact subset_mset.less_trans) lemma multiset_inter_commute: "A #\ B = B #\ A" @@ -2075,7 +2396,7 @@ if x \ set ys then (remove1 x ys, x # zs) else (ys, zs)) xs (ys, zs))) = (mset xs #\ mset ys) + mset zs" by (induct xs arbitrary: ys) - (auto simp add: mem_set_multiset_eq inter_add_right1 inter_add_right2 ac_simps) + (auto simp add: inter_add_right1 inter_add_right2 ac_simps) then show ?thesis by simp qed @@ -2118,8 +2439,8 @@ None \ None | Some (ys1,_,ys2) \ ms_lesseq_impl xs (ys1 @ ys2))" -lemma ms_lesseq_impl: "(ms_lesseq_impl xs ys = None \ \ mset xs \# mset ys) \ - (ms_lesseq_impl xs ys = Some True \ mset xs <# mset ys) \ +lemma ms_lesseq_impl: "(ms_lesseq_impl xs ys = None \ \ mset xs \# mset ys) \ + (ms_lesseq_impl xs ys = Some True \ mset xs \# mset ys) \ (ms_lesseq_impl xs ys = Some False \ mset xs = mset ys)" proof (induct xs arbitrary: ys) case (Nil ys) @@ -2131,13 +2452,13 @@ case None hence x: "x \ set ys" by (simp add: extract_None_iff) { - assume "mset (x # xs) \# mset ys" + assume "mset (x # xs) \# mset ys" from set_mset_mono[OF this] x have False by simp } note nle = this moreover { - assume "mset (x # xs) <# mset ys" - hence "mset (x # xs) \# mset ys" by auto + assume "mset (x # xs) \# mset ys" + hence "mset (x # xs) \# mset ys" by auto from nle[OF this] have False . } ultimately show ?thesis using None by auto @@ -2156,10 +2477,10 @@ qed qed -lemma [code]: "mset xs \# mset ys \ ms_lesseq_impl xs ys \ None" +lemma [code]: "mset xs \# mset ys \ ms_lesseq_impl xs ys \ None" using ms_lesseq_impl[of xs ys] by (cases "ms_lesseq_impl xs ys", auto) -lemma [code]: "mset xs <# mset ys \ ms_lesseq_impl xs ys = Some True" +lemma [code]: "mset xs \# mset ys \ ms_lesseq_impl xs ys = Some True" using ms_lesseq_impl[of xs ys] by (cases "ms_lesseq_impl xs ys", auto) instantiation multiset :: (equal) equal @@ -2344,8 +2665,7 @@ show "image_mset (g \ f) = image_mset g \ image_mset f" for f g unfolding comp_def by (rule ext) (simp add: comp_def image_mset.compositionality) show "(\z. z \ set_mset X \ f z = g z) \ image_mset f X = image_mset g X" for f g X - by (induct X) (simp_all (no_asm), - metis One_nat_def Un_iff count_single mem_set_mset_iff set_mset_union zero_less_Suc) + by (induct X) simp_all show "set_mset \ image_mset f = op ` f \ set_mset" for f by auto show "card_order natLeq" @@ -2476,7 +2796,7 @@ proof - obtain a where a: "a \# M" and fa: "f a = b" using multiset.set_map[of f M] unfolding assms - by (metis image_iff mem_set_mset_iff union_single_eq_member) + by (metis image_iff union_single_eq_member) then obtain M1 where M: "M = M1 + {#a#}" using multi_member_split by metis have "image_mset f M1 = N" using assms unfolding M fa[symmetric] by simp thus ?thesis using M fa by blast diff -r 25271ff79171 -r 9527ff088c15 src/HOL/Library/Multiset_Order.thy --- a/src/HOL/Library/Multiset_Order.thy Fri Feb 26 22:15:09 2016 +0100 +++ b/src/HOL/Library/Multiset_Order.thy Fri Feb 26 22:44:11 2016 +0100 @@ -77,22 +77,29 @@ definition less_multiset\<^sub>H\<^sub>O where "less_multiset\<^sub>H\<^sub>O M N \ M \ N \ (\y. count N y < count M y \ (\x. y < x \ count M x < count N x))" -lemma mult_imp_less_multiset\<^sub>H\<^sub>O: "(M, N) \ mult {(x, y). x < y} \ less_multiset\<^sub>H\<^sub>O M N" -proof (unfold mult_def less_multiset\<^sub>H\<^sub>O_def, induct rule: trancl_induct) +lemma mult_imp_less_multiset\<^sub>H\<^sub>O: + "(M, N) \ mult {(x, y). x < y} \ less_multiset\<^sub>H\<^sub>O M N" +proof (unfold mult_def, induct rule: trancl_induct) case (base P) - then show ?case unfolding mult1_def by force + then show ?case + by (auto elim!: mult1_lessE simp add: count_eq_zero_iff less_multiset\<^sub>H\<^sub>O_def split: if_splits dest!: Suc_lessD) next case (step N P) + from step(3) have "M \ N" and + **: "\y. count N y < count M y \ (\x>y. count M x < count N x)" + by (simp_all add: less_multiset\<^sub>H\<^sub>O_def) from step(2) obtain M0 a K where - *: "P = M0 + {#a#}" "N = M0 + K" "\b. b \# K \ b < a" - unfolding mult1_def by blast - then have count_K_a: "count K a = 0" by auto - with step(3) *(1,2) have "M \ P" by (force dest: *(3) split: if_splits) + *: "P = M0 + {#a#}" "N = M0 + K" "a \# K" "\b. b \# K \ b < a" + by (blast elim: mult1_lessE) + from \M \ N\ ** *(1,2,3) have "M \ P" by (force dest: *(4) split: if_splits) moreover { assume "count P a \ count M a" - with count_K_a have "count N a < count M a" unfolding *(1,2) by auto - with step(3) obtain z where z: "z > a" "count M z < count N z" by blast - with * have "count N z \ count P z" by force + with \a \# K\ have "count N a < count M a" unfolding *(1,2) + by (auto simp add: not_in_iff) + with ** obtain z where z: "z > a" "count M z < count N z" + by blast + with * have "count N z \ count P z" + by (force simp add: not_in_iff) with z have "\z > a. count M z < count P z" by auto } note count_a = this { fix y @@ -106,27 +113,29 @@ show ?thesis proof (cases "y \# K") case True - with *(3) have "y < a" by simp + with *(4) have "y < a" by simp then show ?thesis by (cases "count P a \ count M a") (auto dest: count_a intro: less_trans) next case False - with \y \ a\ have "count P y = count N y" unfolding *(1,2) by simp - with count_y step(3) obtain z where z: "z > y" "count M z < count N z" by auto + with \y \ a\ have "count P y = count N y" unfolding *(1,2) + by (simp add: not_in_iff) + with count_y ** obtain z where z: "z > y" "count M z < count N z" by auto show ?thesis proof (cases "z \# K") case True - with *(3) have "z < a" by simp + with *(4) have "z < a" by simp with z(1) show ?thesis by (cases "count P a \ count M a") (auto dest!: count_a intro: less_trans) next case False - with count_K_a have "count N z \ count P z" unfolding * by auto + with \a \# K\ have "count N z \ count P z" unfolding * + by (auto simp add: not_in_iff) with z show ?thesis by auto qed qed qed } - ultimately show ?case by blast + ultimately show ?case unfolding less_multiset\<^sub>H\<^sub>O_def by blast qed lemma less_multiset\<^sub>D\<^sub>M_imp_mult: @@ -157,10 +166,12 @@ proof (intro allI impI) fix k assume "k \# Y" - then have "count N k < count M k" unfolding Y_def by auto + then have "count N k < count M k" unfolding Y_def + by (auto simp add: in_diff_count) with \less_multiset\<^sub>H\<^sub>O M N\ obtain a where "k < a" and "count M a < count N a" unfolding less_multiset\<^sub>H\<^sub>O_def by blast - then show "\a. a \# X \ k < a" unfolding X_def by auto + then show "\a. a \# X \ k < a" unfolding X_def + by (auto simp add: in_diff_count) qed qed @@ -295,12 +306,13 @@ add.commute)+ lemma ex_gt_imp_less_multiset: "(\y :: 'a :: linorder. y \# N \ (\x. x \# M \ x < y)) \ M #\# N" - unfolding less_multiset\<^sub>H\<^sub>O by (metis less_irrefl less_nat_zero_code not_gr0) - + unfolding less_multiset\<^sub>H\<^sub>O + by (metis count_eq_zero_iff count_greater_zero_iff less_le_not_le) + lemma ex_gt_count_imp_less_multiset: "(\y :: 'a :: linorder. y \# M + N \ y \ x) \ count M x < count N x \ M #\# N" - unfolding less_multiset\<^sub>H\<^sub>O by (metis add.left_neutral add_lessD1 dual_order.strict_iff_order - less_not_sym mset_leD mset_le_add_left) + unfolding less_multiset\<^sub>H\<^sub>O + by (metis add_gr_0 count_union mem_Collect_eq not_gr0 not_le not_less_iff_gr_or_eq set_mset_def) lemma union_less_diff_plus: "P \# M \ N #\# P \ M - P + N #\# M" by (drule subset_mset.diff_add[symmetric]) (metis union_less_mono2) diff -r 25271ff79171 -r 9527ff088c15 src/HOL/Number_Theory/UniqueFactorization.thy --- a/src/HOL/Number_Theory/UniqueFactorization.thy Fri Feb 26 22:15:09 2016 +0100 +++ b/src/HOL/Number_Theory/UniqueFactorization.thy Fri Feb 26 22:44:11 2016 +0100 @@ -93,7 +93,7 @@ next case False then show ?thesis - by auto + by (auto simp add: not_in_iff) qed finally have "a ^ count M a dvd a ^ count N a * (\i \ (set_mset N - {a}). i ^ count N i)" . moreover @@ -111,7 +111,7 @@ next case False then show ?thesis - by auto + by (auto simp add: not_in_iff) qed lemma multiset_prime_factorization_unique: @@ -437,7 +437,7 @@ apply (cases "n = 0") apply auto apply (frule multiset_prime_factorization) - apply (auto simp add: set_mset_def multiplicity_nat_def) + apply (auto simp add: multiplicity_nat_def count_eq_zero_iff) done lemma multiplicity_not_factor_nat [simp]: diff -r 25271ff79171 -r 9527ff088c15 src/HOL/UNITY/Comp/AllocBase.thy --- a/src/HOL/UNITY/Comp/AllocBase.thy Fri Feb 26 22:15:09 2016 +0100 +++ b/src/HOL/UNITY/Comp/AllocBase.thy Fri Feb 26 22:44:11 2016 +0100 @@ -41,7 +41,7 @@ lemma bag_of_append [simp]: "bag_of (l@l') = bag_of l + bag_of l'" by (induct l) (simp_all add: ac_simps) -lemma subseteq_le_multiset: "A #<=# A + B" +lemma subseteq_le_multiset: "A #\# A + B" unfolding le_multiset_def apply (cases B; simp) apply (rule HOL.disjI1) apply (rule union_less_mono2[of "{#}" "_ + {#_#}" A, simplified]) diff -r 25271ff79171 -r 9527ff088c15 src/HOL/UNITY/Follows.thy --- a/src/HOL/UNITY/Follows.thy Fri Feb 26 22:15:09 2016 +0100 +++ b/src/HOL/UNITY/Follows.thy Fri Feb 26 22:44:11 2016 +0100 @@ -36,10 +36,17 @@ lemma Follows_constant [iff]: "F \ (%s. c) Fols (%s. c)" by (simp add: Follows_def) -lemma mono_Follows_o: "mono h ==> f Fols g \ (h o f) Fols (h o g)" -by (auto simp add: Follows_def mono_Increasing_o [THEN [2] rev_subsetD] - mono_Always_o [THEN [2] rev_subsetD] - mono_LeadsTo_o [THEN [2] rev_subsetD, THEN INT_D]) +lemma mono_Follows_o: + assumes "mono h" + shows "f Fols g \ (h o f) Fols (h o g)" +proof + fix x + assume "x \ f Fols g" + with assms show "x \ (h \ f) Fols (h \ g)" + by (auto simp add: Follows_def mono_Increasing_o [THEN [2] rev_subsetD] + mono_Always_o [THEN [2] rev_subsetD] + mono_LeadsTo_o [THEN [2] rev_subsetD, THEN INT_D]) +qed lemma mono_Follows_apply: "mono h ==> f Fols g \ (%x. h (f x)) Fols (%x. h (g x))" @@ -173,10 +180,10 @@ begin definition less_multiset :: "'a::order multiset \ 'a multiset \ bool" where - "M' < M \ M' #<# M" + "M' < M \ M' #\# M" definition less_eq_multiset :: "'a multiset \ 'a multiset \ bool" where - "(M'::'a multiset) \ M \ M' #<=# M" + "(M'::'a multiset) \ M \ M' #\# M" instance by standard (auto simp add: less_eq_multiset_def less_multiset_def multiset_order.less_le_not_le add.commute multiset_order.add_right_mono) diff -r 25271ff79171 -r 9527ff088c15 src/HOL/ex/Quicksort.thy --- a/src/HOL/ex/Quicksort.thy Fri Feb 26 22:15:09 2016 +0100 +++ b/src/HOL/ex/Quicksort.thy Fri Feb 26 22:44:11 2016 +0100 @@ -25,7 +25,11 @@ by (induct xs rule: quicksort.induct) (simp_all add: ac_simps) lemma set_quicksort [simp]: "set (quicksort xs) = set xs" - by (simp add: set_count_greater_0) +proof - + have "set_mset (mset (quicksort xs)) = set_mset (mset xs)" + by simp + then show ?thesis by (simp only: set_mset_mset) +qed lemma sorted_quicksort: "sorted (quicksort xs)" by (induct xs rule: quicksort.induct) (auto simp add: sorted_Cons sorted_append not_le less_imp_le)