src/HOL/Library/Multiset.thy
changeset 63310 caaacf37943f
parent 63290 9ac558ab0906
child 63358 a500677d4cec
equal deleted inserted replaced
63309:a77adb28a27a 63310:caaacf37943f
   454 
   454 
   455 interpretation subset_mset: ordered_ab_semigroup_add_imp_le "op +" "op -" "op \<subseteq>#" "op \<subset>#"
   455 interpretation subset_mset: ordered_ab_semigroup_add_imp_le "op +" "op -" "op \<subseteq>#" "op \<subset>#"
   456   by standard (auto simp add: subset_mset_def subseteq_mset_def multiset_eq_iff intro: order_trans antisym)
   456   by standard (auto simp add: subset_mset_def subseteq_mset_def multiset_eq_iff intro: order_trans antisym)
   457   \<comment> \<open>FIXME: avoid junk stemming from type class interpretation\<close>
   457   \<comment> \<open>FIXME: avoid junk stemming from type class interpretation\<close>
   458 
   458 
   459 lemma mset_less_eqI:
   459 lemma mset_subset_eqI:
   460   "(\<And>a. count A a \<le> count B a) \<Longrightarrow> A \<subseteq># B"
   460   "(\<And>a. count A a \<le> count B a) \<Longrightarrow> A \<subseteq># B"
   461   by (simp add: subseteq_mset_def)
   461   by (simp add: subseteq_mset_def)
   462 
   462 
   463 lemma mset_less_eq_count:
   463 lemma mset_subset_eq_count:
   464   "A \<subseteq># B \<Longrightarrow> count A a \<le> count B a"
   464   "A \<subseteq># B \<Longrightarrow> count A a \<le> count B a"
   465   by (simp add: subseteq_mset_def)
   465   by (simp add: subseteq_mset_def)
   466 
   466 
   467 lemma mset_le_exists_conv: "(A::'a multiset) \<subseteq># B \<longleftrightarrow> (\<exists>C. B = A + C)"
   467 lemma mset_subset_eq_exists_conv: "(A::'a multiset) \<subseteq># B \<longleftrightarrow> (\<exists>C. B = A + C)"
   468   unfolding subseteq_mset_def
   468   unfolding subseteq_mset_def
   469   apply (rule iffI)
   469   apply (rule iffI)
   470    apply (rule exI [where x = "B - A"])
   470    apply (rule exI [where x = "B - A"])
   471    apply (auto intro: multiset_eq_iff [THEN iffD2])
   471    apply (auto intro: multiset_eq_iff [THEN iffD2])
   472   done
   472   done
   473 
   473 
   474 interpretation subset_mset: ordered_cancel_comm_monoid_diff  "op +" 0 "op \<le>#" "op <#" "op -"
   474 interpretation subset_mset: ordered_cancel_comm_monoid_diff  "op +" 0 "op \<le>#" "op <#" "op -"
   475   by standard (simp, fact mset_le_exists_conv)
   475   by standard (simp, fact mset_subset_eq_exists_conv)
   476 
   476 
   477 declare subset_mset.zero_order[simp del]
   477 lemma mset_subset_eq_mono_add_right_cancel [simp]: "(A::'a multiset) + C \<subseteq># B + C \<longleftrightarrow> A \<subseteq># B"
   478   \<comment> \<open>this removes some simp rules not in the usual order for multisets\<close>
       
   479 
       
   480 lemma mset_le_mono_add_right_cancel [simp]: "(A::'a multiset) + C \<subseteq># B + C \<longleftrightarrow> A \<subseteq># B"
       
   481    by (fact subset_mset.add_le_cancel_right)
   478    by (fact subset_mset.add_le_cancel_right)
   482  
   479  
   483 lemma mset_le_mono_add_left_cancel [simp]: "C + (A::'a multiset) \<subseteq># C + B \<longleftrightarrow> A \<subseteq># B"
   480 lemma mset_subset_eq_mono_add_left_cancel [simp]: "C + (A::'a multiset) \<subseteq># C + B \<longleftrightarrow> A \<subseteq># B"
   484    by (fact subset_mset.add_le_cancel_left)
   481    by (fact subset_mset.add_le_cancel_left)
   485  
   482  
   486 lemma mset_le_mono_add: "(A::'a multiset) \<subseteq># B \<Longrightarrow> C \<subseteq># D \<Longrightarrow> A + C \<subseteq># B + D"
   483 lemma mset_subset_eq_mono_add: "(A::'a multiset) \<subseteq># B \<Longrightarrow> C \<subseteq># D \<Longrightarrow> A + C \<subseteq># B + D"
   487    by (fact subset_mset.add_mono)
   484    by (fact subset_mset.add_mono)
   488  
   485  
   489 lemma mset_le_add_left [simp]: "(A::'a multiset) \<subseteq># A + B"
   486 lemma mset_subset_eq_add_left [simp]: "(A::'a multiset) \<subseteq># A + B"
   490    unfolding subseteq_mset_def by auto
   487    unfolding subseteq_mset_def by auto
   491  
   488  
   492 lemma mset_le_add_right [simp]: "B \<subseteq># (A::'a multiset) + B"
   489 lemma mset_subset_eq_add_right [simp]: "B \<subseteq># (A::'a multiset) + B"
   493    unfolding subseteq_mset_def by auto
   490    unfolding subseteq_mset_def by auto
   494  
   491  
   495 lemma single_subset_iff [simp]:
   492 lemma single_subset_iff [simp]:
   496   "{#a#} \<subseteq># M \<longleftrightarrow> a \<in># M"
   493   "{#a#} \<subseteq># M \<longleftrightarrow> a \<in># M"
   497   by (auto simp add: subseteq_mset_def Suc_le_eq)
   494   by (auto simp add: subseteq_mset_def Suc_le_eq)
   498 
   495 
   499 lemma mset_le_single: "a \<in># B \<Longrightarrow> {#a#} \<subseteq># B"
   496 lemma mset_subset_eq_single: "a \<in># B \<Longrightarrow> {#a#} \<subseteq># B"
   500   by (simp add: subseteq_mset_def Suc_le_eq)
   497   by (simp add: subseteq_mset_def Suc_le_eq)
   501  
   498  
   502 lemma multiset_diff_union_assoc:
   499 lemma multiset_diff_union_assoc:
   503   fixes A B C D :: "'a multiset"
   500   fixes A B C D :: "'a multiset"
   504   shows "C \<subseteq># B \<Longrightarrow> A + B - C = A + (B - C)"
   501   shows "C \<subseteq># B \<Longrightarrow> A + B - C = A + (B - C)"
   505   by (fact subset_mset.diff_add_assoc)
   502   by (fact subset_mset.diff_add_assoc)
   506  
   503  
   507 lemma mset_le_multiset_union_diff_commute:
   504 lemma mset_subset_eq_multiset_union_diff_commute:
   508   fixes A B C D :: "'a multiset"
   505   fixes A B C D :: "'a multiset"
   509   shows "B \<subseteq># A \<Longrightarrow> A - B + C = A + C - B"
   506   shows "B \<subseteq># A \<Longrightarrow> A - B + C = A + C - B"
   510   by (fact subset_mset.add_diff_assoc2)
   507   by (fact subset_mset.add_diff_assoc2)
   511 
   508 
   512 lemma diff_le_self[simp]:
   509 lemma diff_subset_eq_self[simp]:
   513   "(M::'a multiset) - N \<subseteq># M"
   510   "(M::'a multiset) - N \<subseteq># M"
   514   by (simp add: subseteq_mset_def)
   511   by (simp add: subseteq_mset_def)
   515 
   512 
   516 lemma mset_leD:
   513 lemma mset_subset_eqD:
   517   assumes "A \<subseteq># B" and "x \<in># A"
   514   assumes "A \<subseteq># B" and "x \<in># A"
   518   shows "x \<in># B"
   515   shows "x \<in># B"
   519 proof -
   516 proof -
   520   from \<open>x \<in># A\<close> have "count A x > 0" by simp
   517   from \<open>x \<in># A\<close> have "count A x > 0" by simp
   521   also from \<open>A \<subseteq># B\<close> have "count A x \<le> count B x"
   518   also from \<open>A \<subseteq># B\<close> have "count A x \<le> count B x"
   522     by (simp add: subseteq_mset_def)
   519     by (simp add: subseteq_mset_def)
   523   finally show ?thesis by simp
   520   finally show ?thesis by simp
   524 qed
   521 qed
   525   
   522   
   526 lemma mset_lessD:
   523 lemma mset_subsetD:
   527   "A \<subset># B \<Longrightarrow> x \<in># A \<Longrightarrow> x \<in># B"
   524   "A \<subset># B \<Longrightarrow> x \<in># A \<Longrightarrow> x \<in># B"
   528   by (auto intro: mset_leD [of A])
   525   by (auto intro: mset_subset_eqD [of A])
   529 
   526 
   530 lemma set_mset_mono:
   527 lemma set_mset_mono:
   531   "A \<subseteq># B \<Longrightarrow> set_mset A \<subseteq> set_mset B"
   528   "A \<subseteq># B \<Longrightarrow> set_mset A \<subseteq> set_mset B"
   532   by (metis mset_leD subsetI)
   529   by (metis mset_subset_eqD subsetI)
   533 
   530 
   534 lemma mset_le_insertD:
   531 lemma mset_subset_eq_insertD:
   535   "A + {#x#} \<subseteq># B \<Longrightarrow> x \<in># B \<and> A \<subset># B"
   532   "A + {#x#} \<subseteq># B \<Longrightarrow> x \<in># B \<and> A \<subset># B"
   536 apply (rule conjI)
   533 apply (rule conjI)
   537  apply (simp add: mset_leD)
   534  apply (simp add: mset_subset_eqD)
   538  apply (clarsimp simp: subset_mset_def subseteq_mset_def)
   535  apply (clarsimp simp: subset_mset_def subseteq_mset_def)
   539  apply safe
   536  apply safe
   540   apply (erule_tac x = a in allE)
   537   apply (erule_tac x = a in allE)
   541   apply (auto split: if_split_asm)
   538   apply (auto split: if_split_asm)
   542 done
   539 done
   543 
   540 
   544 lemma mset_less_insertD:
   541 lemma mset_subset_insertD:
   545   "A + {#x#} \<subset># B \<Longrightarrow> x \<in># B \<and> A \<subset># B"
   542   "A + {#x#} \<subset># B \<Longrightarrow> x \<in># B \<and> A \<subset># B"
   546   by (rule mset_le_insertD) simp
   543   by (rule mset_subset_eq_insertD) simp
   547 
   544 
   548 lemma mset_less_of_empty[simp]: "A \<subset># {#} \<longleftrightarrow> False"
   545 lemma mset_subset_of_empty[simp]: "A \<subset># {#} \<longleftrightarrow> False"
   549   by (auto simp add: subseteq_mset_def subset_mset_def multiset_eq_iff)
   546   by (auto simp add: subseteq_mset_def subset_mset_def multiset_eq_iff)
   550 
   547 
   551 lemma empty_le [simp]: "{#} \<subseteq># A"
   548 lemma empty_le [simp]: "{#} \<subseteq># A"
   552   unfolding mset_le_exists_conv by auto
   549   unfolding mset_subset_eq_exists_conv by auto
   553  
   550  
   554 lemma insert_subset_eq_iff:
   551 lemma insert_subset_eq_iff:
   555   "{#a#} + A \<subseteq># B \<longleftrightarrow> a \<in># B \<and> A \<subseteq># B - {#a#}"
   552   "{#a#} + A \<subseteq># B \<longleftrightarrow> a \<in># B \<and> A \<subseteq># B - {#a#}"
   556   using le_diff_conv2 [of "Suc 0" "count B a" "count A a"]
   553   using le_diff_conv2 [of "Suc 0" "count B a" "count A a"]
   557   apply (auto simp add: subseteq_mset_def not_in_iff Suc_le_eq)
   554   apply (auto simp add: subseteq_mset_def not_in_iff Suc_le_eq)
   565 
   562 
   566 lemma subset_eq_diff_conv:
   563 lemma subset_eq_diff_conv:
   567   "A - C \<subseteq># B \<longleftrightarrow> A \<subseteq># B + C"
   564   "A - C \<subseteq># B \<longleftrightarrow> A \<subseteq># B + C"
   568   by (simp add: subseteq_mset_def le_diff_conv)
   565   by (simp add: subseteq_mset_def le_diff_conv)
   569 
   566 
   570 lemma le_empty [simp]: "M \<subseteq># {#} \<longleftrightarrow> M = {#}"
   567 lemma subset_eq_empty [simp]: "M \<subseteq># {#} \<longleftrightarrow> M = {#}"
   571   unfolding mset_le_exists_conv by auto
   568   unfolding mset_subset_eq_exists_conv by auto
   572 
   569 
   573 lemma multi_psub_of_add_self[simp]: "A \<subset># A + {#x#}"
   570 lemma multi_psub_of_add_self[simp]: "A \<subset># A + {#x#}"
   574   by (auto simp: subset_mset_def subseteq_mset_def)
   571   by (auto simp: subset_mset_def subseteq_mset_def)
   575 
   572 
   576 lemma multi_psub_self[simp]: "(A::'a multiset) \<subset># A = False"
   573 lemma multi_psub_self[simp]: "(A::'a multiset) \<subset># A = False"
   577   by simp
   574   by simp
   578 
   575 
   579 lemma mset_less_add_bothsides: "N + {#x#} \<subset># M + {#x#} \<Longrightarrow> N \<subset># M"
   576 lemma mset_subset_add_bothsides: "N + {#x#} \<subset># M + {#x#} \<Longrightarrow> N \<subset># M"
   580   by (fact subset_mset.add_less_imp_less_right)
   577   by (fact subset_mset.add_less_imp_less_right)
   581 
   578 
   582 lemma mset_less_empty_nonempty: "{#} \<subset># S \<longleftrightarrow> S \<noteq> {#}"
   579 lemma mset_subset_empty_nonempty: "{#} \<subset># S \<longleftrightarrow> S \<noteq> {#}"
   583   by (fact subset_mset.zero_less_iff_neq_zero)
   580   by (fact subset_mset.zero_less_iff_neq_zero)
   584 
   581 
   585 lemma mset_less_diff_self: "c \<in># B \<Longrightarrow> B - {#c#} \<subset># B"
   582 lemma mset_subset_diff_self: "c \<in># B \<Longrightarrow> B - {#c#} \<subset># B"
   586   by (auto simp: subset_mset_def elim: mset_add)
   583   by (auto simp: subset_mset_def elim: mset_add)
   587 
   584 
   588 
   585 
   589 subsubsection \<open>Intersection\<close>
   586 subsubsection \<open>Intersection\<close>
   590 
   587 
   820 
   817 
   821 lemma filter_inter_mset [simp]: "filter_mset P (M #\<inter> N) = filter_mset P M #\<inter> filter_mset P N"
   818 lemma filter_inter_mset [simp]: "filter_mset P (M #\<inter> N) = filter_mset P M #\<inter> filter_mset P N"
   822   by (rule multiset_eqI) simp
   819   by (rule multiset_eqI) simp
   823 
   820 
   824 lemma multiset_filter_subset[simp]: "filter_mset f M \<subseteq># M"
   821 lemma multiset_filter_subset[simp]: "filter_mset f M \<subseteq># M"
   825   by (simp add: mset_less_eqI)
   822   by (simp add: mset_subset_eqI)
   826 
   823 
   827 lemma multiset_filter_mono:
   824 lemma multiset_filter_mono:
   828   assumes "A \<subseteq># B"
   825   assumes "A \<subseteq># B"
   829   shows "filter_mset f A \<subseteq># filter_mset f B"
   826   shows "filter_mset f A \<subseteq># filter_mset f B"
   830 proof -
   827 proof -
   831   from assms[unfolded mset_le_exists_conv]
   828   from assms[unfolded mset_subset_eq_exists_conv]
   832   obtain C where B: "B = A + C" by auto
   829   obtain C where B: "B = A + C" by auto
   833   show ?thesis unfolding B by auto
   830   show ?thesis unfolding B by auto
   834 qed
   831 qed
   835 
   832 
   836 lemma filter_mset_eq_conv:
   833 lemma filter_mset_eq_conv:
   838 proof
   835 proof
   839   assume ?P then show ?Q by auto (simp add: multiset_eq_iff in_diff_count)
   836   assume ?P then show ?Q by auto (simp add: multiset_eq_iff in_diff_count)
   840 next
   837 next
   841   assume ?Q
   838   assume ?Q
   842   then obtain Q where M: "M = N + Q"
   839   then obtain Q where M: "M = N + Q"
   843     by (auto simp add: mset_le_exists_conv)
   840     by (auto simp add: mset_subset_eq_exists_conv)
   844   then have MN: "M - N = Q" by simp
   841   then have MN: "M - N = Q" by simp
   845   show ?P
   842   show ?P
   846   proof (rule multiset_eqI)
   843   proof (rule multiset_eqI)
   847     fix a
   844     fix a
   848     from \<open>?Q\<close> MN have *: "\<not> P a \<Longrightarrow> a \<notin># N" "P a \<Longrightarrow> a \<notin># Q"
   845     from \<open>?Q\<close> MN have *: "\<not> P a \<Longrightarrow> a \<notin># N" "P a \<Longrightarrow> a \<notin># Q"
   941 lemma size_mset_mono:
   938 lemma size_mset_mono:
   942   fixes A B :: "'a multiset"
   939   fixes A B :: "'a multiset"
   943   assumes "A \<subseteq># B"
   940   assumes "A \<subseteq># B"
   944   shows "size A \<le> size B"
   941   shows "size A \<le> size B"
   945 proof -
   942 proof -
   946   from assms[unfolded mset_le_exists_conv]
   943   from assms[unfolded mset_subset_eq_exists_conv]
   947   obtain C where B: "B = A + C" by auto
   944   obtain C where B: "B = A + C" by auto
   948   show ?thesis unfolding B by (induct C) auto
   945   show ?thesis unfolding B by (induct C) auto
   949 qed
   946 qed
   950 
   947 
   951 lemma size_filter_mset_lesseq[simp]: "size (filter_mset f M) \<le> size M"
   948 lemma size_filter_mset_lesseq[simp]: "size (filter_mset f M) \<le> size M"
   952 by (rule size_mset_mono[OF multiset_filter_subset])
   949 by (rule size_mset_mono[OF multiset_filter_subset])
   953 
   950 
   954 lemma size_Diff_submset:
   951 lemma size_Diff_submset:
   955   "M \<subseteq># M' \<Longrightarrow> size (M' - M) = size M' - size(M::'a multiset)"
   952   "M \<subseteq># M' \<Longrightarrow> size (M' - M) = size M' - size(M::'a multiset)"
   956 by (metis add_diff_cancel_left' size_union mset_le_exists_conv)
   953 by (metis add_diff_cancel_left' size_union mset_subset_eq_exists_conv)
   957 
   954 
   958 
   955 
   959 subsection \<open>Induction and case splits\<close>
   956 subsection \<open>Induction and case splits\<close>
   960 
   957 
   961 theorem multiset_induct [case_names empty add, induct type: multiset]:
   958 theorem multiset_induct [case_names empty add, induct type: multiset]:
   986 lemma multiset_partition: "M = {# x\<in>#M. P x #} + {# x\<in>#M. \<not> P x #}"
   983 lemma multiset_partition: "M = {# x\<in>#M. P x #} + {# x\<in>#M. \<not> P x #}"
   987 apply (subst multiset_eq_iff)
   984 apply (subst multiset_eq_iff)
   988 apply auto
   985 apply auto
   989 done
   986 done
   990 
   987 
   991 lemma mset_less_size: "(A::'a multiset) \<subset># B \<Longrightarrow> size A < size B"
   988 lemma mset_subset_size: "(A::'a multiset) \<subset># B \<Longrightarrow> size A < size B"
   992 proof (induct A arbitrary: B)
   989 proof (induct A arbitrary: B)
   993   case (empty M)
   990   case (empty M)
   994   then have "M \<noteq> {#}" by (simp add: mset_less_empty_nonempty)
   991   then have "M \<noteq> {#}" by (simp add: mset_subset_empty_nonempty)
   995   then obtain M' x where "M = M' + {#x#}"
   992   then obtain M' x where "M = M' + {#x#}"
   996     by (blast dest: multi_nonempty_split)
   993     by (blast dest: multi_nonempty_split)
   997   then show ?case by simp
   994   then show ?case by simp
   998 next
   995 next
   999   case (add S x T)
   996   case (add S x T)
  1000   have IH: "\<And>B. S \<subset># B \<Longrightarrow> size S < size B" by fact
   997   have IH: "\<And>B. S \<subset># B \<Longrightarrow> size S < size B" by fact
  1001   have SxsubT: "S + {#x#} \<subset># T" by fact
   998   have SxsubT: "S + {#x#} \<subset># T" by fact
  1002   then have "x \<in># T" and "S \<subset># T"
   999   then have "x \<in># T" and "S \<subset># T"
  1003     by (auto dest: mset_less_insertD)
  1000     by (auto dest: mset_subset_insertD)
  1004   then obtain T' where T: "T = T' + {#x#}"
  1001   then obtain T' where T: "T = T' + {#x#}"
  1005     by (blast dest: multi_member_split)
  1002     by (blast dest: multi_member_split)
  1006   then have "S \<subset># T'" using SxsubT
  1003   then have "S \<subset># T'" using SxsubT
  1007     by (blast intro: mset_less_add_bothsides)
  1004     by (blast intro: mset_subset_add_bothsides)
  1008   then have "size S < size T'" using IH by simp
  1005   then have "size S < size T'" using IH by simp
  1009   then show ?case using T by simp
  1006   then show ?case using T by simp
  1010 qed
  1007 qed
  1011 
  1008 
  1012 lemma size_1_singleton_mset: "size M = 1 \<Longrightarrow> \<exists>a. M = {#a#}"
  1009 lemma size_1_singleton_mset: "size M = 1 \<Longrightarrow> \<exists>a. M = {#a#}"
  1015 
  1012 
  1016 subsubsection \<open>Strong induction and subset induction for multisets\<close>
  1013 subsubsection \<open>Strong induction and subset induction for multisets\<close>
  1017 
  1014 
  1018 text \<open>Well-foundedness of strict subset relation\<close>
  1015 text \<open>Well-foundedness of strict subset relation\<close>
  1019 
  1016 
  1020 lemma wf_less_mset_rel: "wf {(M, N :: 'a multiset). M \<subset># N}"
  1017 lemma wf_subset_mset_rel: "wf {(M, N :: 'a multiset). M \<subset># N}"
  1021 apply (rule wf_measure [THEN wf_subset, where f1=size])
  1018 apply (rule wf_measure [THEN wf_subset, where f1=size])
  1022 apply (clarsimp simp: measure_def inv_image_def mset_less_size)
  1019 apply (clarsimp simp: measure_def inv_image_def mset_subset_size)
  1023 done
  1020 done
  1024 
  1021 
  1025 lemma full_multiset_induct [case_names less]:
  1022 lemma full_multiset_induct [case_names less]:
  1026 assumes ih: "\<And>B. \<forall>(A::'a multiset). A \<subset># B \<longrightarrow> P A \<Longrightarrow> P B"
  1023 assumes ih: "\<And>B. \<forall>(A::'a multiset). A \<subset># B \<longrightarrow> P A \<Longrightarrow> P B"
  1027 shows "P B"
  1024 shows "P B"
  1028 apply (rule wf_less_mset_rel [THEN wf_induct])
  1025 apply (rule wf_subset_mset_rel [THEN wf_induct])
  1029 apply (rule ih, auto)
  1026 apply (rule ih, auto)
  1030 done
  1027 done
  1031 
  1028 
  1032 lemma multi_subset_induct [consumes 2, case_names empty add]:
  1029 lemma multi_subset_induct [consumes 2, case_names empty add]:
  1033   assumes "F \<subseteq># A"
  1030   assumes "F \<subseteq># A"
  1042   next
  1039   next
  1043     fix x F
  1040     fix x F
  1044     assume P: "F \<subseteq># A \<Longrightarrow> P F" and i: "F + {#x#} \<subseteq># A"
  1041     assume P: "F \<subseteq># A \<Longrightarrow> P F" and i: "F + {#x#} \<subseteq># A"
  1045     show "P (F + {#x#})"
  1042     show "P (F + {#x#})"
  1046     proof (rule insert)
  1043     proof (rule insert)
  1047       from i show "x \<in># A" by (auto dest: mset_le_insertD)
  1044       from i show "x \<in># A" by (auto dest: mset_subset_eq_insertD)
  1048       from i have "F \<subseteq># A" by (auto dest: mset_le_insertD)
  1045       from i have "F \<subseteq># A" by (auto dest: mset_subset_eq_insertD)
  1049       with P show "P F" .
  1046       with P show "P F" .
  1050     qed
  1047     qed
  1051   qed
  1048   qed
  1052 qed
  1049 qed
  1053 
  1050 
  1538   by (auto split: if_splits)
  1535   by (auto split: if_splits)
  1539 
  1536 
  1540 lemma size_replicate_mset[simp]: "size (replicate_mset n M) = n"
  1537 lemma size_replicate_mset[simp]: "size (replicate_mset n M) = n"
  1541   by (induct n, simp_all)
  1538   by (induct n, simp_all)
  1542 
  1539 
  1543 lemma count_le_replicate_mset_le: "n \<le> count M x \<longleftrightarrow> replicate_mset n x \<subseteq># M"
  1540 lemma count_le_replicate_mset_subset_eq: "n \<le> count M x \<longleftrightarrow> replicate_mset n x \<subseteq># M"
  1544   by (auto simp add: mset_less_eqI) (metis count_replicate_mset subseteq_mset_def)
  1541   by (auto simp add: mset_subset_eqI) (metis count_replicate_mset subseteq_mset_def)
  1545 
  1542 
  1546 lemma filter_eq_replicate_mset: "{#y \<in># D. y = x#} = replicate_mset (count D x) x"
  1543 lemma filter_eq_replicate_mset: "{#y \<in># D. y = x#} = replicate_mset (count D x) x"
  1547   by (induct D) simp_all
  1544   by (induct D) simp_all
  1548 
  1545 
  1549 lemma replicate_count_mset_eq_filter_eq:
  1546 lemma replicate_count_mset_eq_filter_eq:
  1912 
  1909 
  1913 end
  1910 end
  1914 
  1911 
  1915 hide_const (open) part
  1912 hide_const (open) part
  1916 
  1913 
  1917 lemma mset_remdups_le: "mset (remdups xs) \<subseteq># mset xs"
  1914 lemma mset_remdups_subset_eq: "mset (remdups xs) \<subseteq># mset xs"
  1918   by (induct xs) (auto intro: subset_mset.order_trans)
  1915   by (induct xs) (auto intro: subset_mset.order_trans)
  1919 
  1916 
  1920 lemma mset_update:
  1917 lemma mset_update:
  1921   "i < length ls \<Longrightarrow> mset (ls[i := v]) = mset ls - {#ls ! i#} + {#v#}"
  1918   "i < length ls \<Longrightarrow> mset (ls[i := v]) = mset ls - {#ls ! i#} + {#v#}"
  1922 proof (induct ls arbitrary: i)
  1919 proof (induct ls arbitrary: i)
  1932       apply simp
  1929       apply simp
  1933       apply (subst add.assoc)
  1930       apply (subst add.assoc)
  1934       apply (subst add.commute [of "{#v#}" "{#x#}"])
  1931       apply (subst add.commute [of "{#v#}" "{#x#}"])
  1935       apply (subst add.assoc [symmetric])
  1932       apply (subst add.assoc [symmetric])
  1936       apply simp
  1933       apply simp
  1937       apply (rule mset_le_multiset_union_diff_commute)
  1934       apply (rule mset_subset_eq_multiset_union_diff_commute)
  1938       apply (simp add: mset_le_single nth_mem_mset)
  1935       apply (simp add: mset_subset_eq_single nth_mem_mset)
  1939       done
  1936       done
  1940   qed
  1937   qed
  1941 qed
  1938 qed
  1942 
  1939 
  1943 lemma mset_swap:
  1940 lemma mset_swap:
  2522   by (fact add_left_cancel)
  2519   by (fact add_left_cancel)
  2523 
  2520 
  2524 lemma multi_union_self_other_eq: "(A::'a multiset) + X = A + Y \<Longrightarrow> X = Y"
  2521 lemma multi_union_self_other_eq: "(A::'a multiset) + X = A + Y \<Longrightarrow> X = Y"
  2525   by (fact add_left_imp_eq)
  2522   by (fact add_left_imp_eq)
  2526 
  2523 
  2527 lemma mset_less_trans: "(M::'a multiset) \<subset># K \<Longrightarrow> K \<subset># N \<Longrightarrow> M \<subset># N"
  2524 lemma mset_subset_trans: "(M::'a multiset) \<subset># K \<Longrightarrow> K \<subset># N \<Longrightarrow> M \<subset># N"
  2528   by (fact subset_mset.less_trans)
  2525   by (fact subset_mset.less_trans)
  2529 
  2526 
  2530 lemma multiset_inter_commute: "A #\<inter> B = B #\<inter> A"
  2527 lemma multiset_inter_commute: "A #\<inter> B = B #\<inter> A"
  2531   by (fact subset_mset.inf.commute)
  2528   by (fact subset_mset.inf.commute)
  2532 
  2529 
  2648   apply (simp_all add: add.commute)
  2645   apply (simp_all add: add.commute)
  2649   done
  2646   done
  2650 
  2647 
  2651 declare size_mset [code]
  2648 declare size_mset [code]
  2652 
  2649 
  2653 fun ms_lesseq_impl :: "'a list \<Rightarrow> 'a list \<Rightarrow> bool option" where
  2650 fun subset_eq_mset_impl :: "'a list \<Rightarrow> 'a list \<Rightarrow> bool option" where
  2654   "ms_lesseq_impl [] ys = Some (ys \<noteq> [])"
  2651   "subset_eq_mset_impl [] ys = Some (ys \<noteq> [])"
  2655 | "ms_lesseq_impl (Cons x xs) ys = (case List.extract (op = x) ys of
  2652 | "subset_eq_mset_impl (Cons x xs) ys = (case List.extract (op = x) ys of
  2656      None \<Rightarrow> None
  2653      None \<Rightarrow> None
  2657    | Some (ys1,_,ys2) \<Rightarrow> ms_lesseq_impl xs (ys1 @ ys2))"
  2654    | Some (ys1,_,ys2) \<Rightarrow> subset_eq_mset_impl xs (ys1 @ ys2))"
  2658 
  2655 
  2659 lemma ms_lesseq_impl: "(ms_lesseq_impl xs ys = None \<longleftrightarrow> \<not> mset xs \<subseteq># mset ys) \<and>
  2656 lemma subset_eq_mset_impl: "(subset_eq_mset_impl xs ys = None \<longleftrightarrow> \<not> mset xs \<subseteq># mset ys) \<and>
  2660   (ms_lesseq_impl xs ys = Some True \<longleftrightarrow> mset xs \<subset># mset ys) \<and>
  2657   (subset_eq_mset_impl xs ys = Some True \<longleftrightarrow> mset xs \<subset># mset ys) \<and>
  2661   (ms_lesseq_impl xs ys = Some False \<longrightarrow> mset xs = mset ys)"
  2658   (subset_eq_mset_impl xs ys = Some False \<longrightarrow> mset xs = mset ys)"
  2662 proof (induct xs arbitrary: ys)
  2659 proof (induct xs arbitrary: ys)
  2663   case (Nil ys)
  2660   case (Nil ys)
  2664   show ?case by (auto simp: mset_less_empty_nonempty)
  2661   show ?case by (auto simp: mset_subset_empty_nonempty)
  2665 next
  2662 next
  2666   case (Cons x xs ys)
  2663   case (Cons x xs ys)
  2667   show ?case
  2664   show ?case
  2668   proof (cases "List.extract (op = x) ys")
  2665   proof (cases "List.extract (op = x) ys")
  2669     case None
  2666     case None
  2684     obtain ys1 y ys2 where res: "res = (ys1,y,ys2)" by (cases res, auto)
  2681     obtain ys1 y ys2 where res: "res = (ys1,y,ys2)" by (cases res, auto)
  2685     note Some = Some[unfolded res]
  2682     note Some = Some[unfolded res]
  2686     from extract_SomeE[OF Some] have "ys = ys1 @ x # ys2" by simp
  2683     from extract_SomeE[OF Some] have "ys = ys1 @ x # ys2" by simp
  2687     hence id: "mset ys = mset (ys1 @ ys2) + {#x#}"
  2684     hence id: "mset ys = mset (ys1 @ ys2) + {#x#}"
  2688       by (auto simp: ac_simps)
  2685       by (auto simp: ac_simps)
  2689     show ?thesis unfolding ms_lesseq_impl.simps
  2686     show ?thesis unfolding subset_eq_mset_impl.simps
  2690       unfolding Some option.simps split
  2687       unfolding Some option.simps split
  2691       unfolding id
  2688       unfolding id
  2692       using Cons[of "ys1 @ ys2"]
  2689       using Cons[of "ys1 @ ys2"]
  2693       unfolding subset_mset_def subseteq_mset_def by auto
  2690       unfolding subset_mset_def subseteq_mset_def by auto
  2694   qed
  2691   qed
  2695 qed
  2692 qed
  2696 
  2693 
  2697 lemma [code]: "mset xs \<subseteq># mset ys \<longleftrightarrow> ms_lesseq_impl xs ys \<noteq> None"
  2694 lemma [code]: "mset xs \<subseteq># mset ys \<longleftrightarrow> subset_eq_mset_impl xs ys \<noteq> None"
  2698   using ms_lesseq_impl[of xs ys] by (cases "ms_lesseq_impl xs ys", auto)
  2695   using subset_eq_mset_impl[of xs ys] by (cases "subset_eq_mset_impl xs ys", auto)
  2699 
  2696 
  2700 lemma [code]: "mset xs \<subset># mset ys \<longleftrightarrow> ms_lesseq_impl xs ys = Some True"
  2697 lemma [code]: "mset xs \<subset># mset ys \<longleftrightarrow> subset_eq_mset_impl xs ys = Some True"
  2701   using ms_lesseq_impl[of xs ys] by (cases "ms_lesseq_impl xs ys", auto)
  2698   using subset_eq_mset_impl[of xs ys] by (cases "subset_eq_mset_impl xs ys", auto)
  2702 
  2699 
  2703 instantiation multiset :: (equal) equal
  2700 instantiation multiset :: (equal) equal
  2704 begin
  2701 begin
  2705 
  2702 
  2706 definition
  2703 definition
  2707   [code del]: "HOL.equal A (B :: 'a multiset) \<longleftrightarrow> A = B"
  2704   [code del]: "HOL.equal A (B :: 'a multiset) \<longleftrightarrow> A = B"
  2708 lemma [code]: "HOL.equal (mset xs) (mset ys) \<longleftrightarrow> ms_lesseq_impl xs ys = Some False"
  2705 lemma [code]: "HOL.equal (mset xs) (mset ys) \<longleftrightarrow> subset_eq_mset_impl xs ys = Some False"
  2709   unfolding equal_multiset_def
  2706   unfolding equal_multiset_def
  2710   using ms_lesseq_impl[of xs ys] by (cases "ms_lesseq_impl xs ys", auto)
  2707   using subset_eq_mset_impl[of xs ys] by (cases "subset_eq_mset_impl xs ys", auto)
  2711 
  2708 
  2712 instance
  2709 instance
  2713   by standard (simp add: equal_multiset_def)
  2710   by standard (simp add: equal_multiset_def)
  2714 
  2711 
  2715 end
  2712 end