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