diff --git a/thys/Nested_Multisets_Ordinals/Multiset_More.thy b/thys/Nested_Multisets_Ordinals/Multiset_More.thy --- a/thys/Nested_Multisets_Ordinals/Multiset_More.thy +++ b/thys/Nested_Multisets_Ordinals/Multiset_More.thy @@ -1,1027 +1,1032 @@ (* Title: More about Multisets Author: Mathias Fleury , 2015 Author: Jasmin Blanchette , 2014, 2015 Author: Anders Schlichtkrull , 2017 Author: Dmitriy Traytel , 2014 Maintainer: Mathias Fleury *) section \More about Multisets\ theory Multiset_More imports "HOL-Library.Multiset_Order" "HOL-Library.Sublist" begin text \ Isabelle's theory of finite multisets is not as developed as other areas, such as lists and sets. The present theory introduces some missing concepts and lemmas. Some of it is expected to move to Isabelle's library. \ subsection \Basic Setup\ declare diff_single_trivial [simp] in_image_mset [iff] image_mset.compositionality [simp] (*To have the same rules as the set counter-part*) mset_subset_eqD[dest, intro?] (*@{thm subsetD}*) Multiset.in_multiset_in_set[simp] inter_add_left1[simp] inter_add_left2[simp] inter_add_right1[simp] inter_add_right2[simp] sum_mset_sum_list[simp] subsection \Lemmas about Intersection, Union and Pointwise Inclusion\ lemma subset_mset_imp_subset_add_mset: "A \# B \ A \# add_mset x B" by (metis add_mset_diff_bothsides diff_subset_eq_self multiset_inter_def subset_mset.inf.absorb2) lemma subset_add_mset_notin_subset_mset: \A \# add_mset b B \ b \# A \ A \# B\ by (simp add: subset_mset.le_iff_sup) lemma subset_msetE: "\A \# B; \A \# B; \ B \# A\ \ R\ \ R" by (simp add: subset_mset.less_le_not_le) lemma Diff_triv_mset: "M \# N = {#} \ M - N = M" by (metis diff_intersect_left_idem diff_zero) lemma diff_intersect_sym_diff: "(A - B) \# (B - A) = {#}" unfolding multiset_inter_def proof - have "A - (B - (B - A)) = A - B" by (metis diff_intersect_right_idem multiset_inter_def) then show "A - B - (A - B - (B - A)) = {#}" by (metis diff_add diff_cancel diff_subset_eq_self subset_mset.diff_add) qed declare subset_msetE [elim!] lemma subseq_mset_subseteq_mset: "subseq xs ys \ mset xs \# mset ys" proof (induct xs arbitrary: ys) case (Cons x xs) note Outer_Cons = this then show ?case proof (induct ys) case (Cons y ys) have "subseq xs ys" by (metis Cons.prems(2) subseq_Cons' subseq_Cons2_iff) then show ?case using Cons by (metis mset.simps(2) mset_subset_eq_add_mset_cancel subseq_Cons2_iff subset_mset_imp_subset_add_mset) qed simp qed simp subsection \Lemmas about Filter and Image\ lemma count_image_mset_ge_count: "count (image_mset f A) (f b) \ count A b" by (induction A) auto lemma count_image_mset_inj: assumes \inj f\ shows \count (image_mset f M) (f x) = count M x\ by (induct M) (use assms in \auto simp: inj_on_def\) lemma count_image_mset_le_count_inj_on: "inj_on f (set_mset M) \ count (image_mset f M) y \ count M (inv_into (set_mset M) f y)" proof (induct M) case (add x M) note ih = this(1) and inj_xM = this(2) have inj_M: "inj_on f (set_mset M)" using inj_xM by simp show ?case proof (cases "x \# M") case x_in_M: True show ?thesis proof (cases "y = f x") case y_eq_fx: True show ?thesis using x_in_M ih[OF inj_M] unfolding y_eq_fx by (simp add: inj_M insert_absorb) next case y_ne_fx: False show ?thesis using x_in_M ih[OF inj_M] y_ne_fx insert_absorb by fastforce qed next case x_ni_M: False show ?thesis proof (cases "y = f x") case y_eq_fx: True have "f x \# image_mset f M" using x_ni_M inj_xM by force thus ?thesis unfolding y_eq_fx by (metis (no_types) inj_xM count_add_mset count_greater_eq_Suc_zero_iff count_inI image_mset_add_mset inv_into_f_f union_single_eq_member) next case y_ne_fx: False show ?thesis proof (rule ccontr) assume neg_conj: "\ count (image_mset f (add_mset x M)) y \ count (add_mset x M) (inv_into (set_mset (add_mset x M)) f y)" have cnt_y: "count (add_mset (f x) (image_mset f M)) y = count (image_mset f M) y" using y_ne_fx by simp have "inv_into (set_mset M) f y \# add_mset x M \ inv_into (set_mset (add_mset x M)) f (f (inv_into (set_mset M) f y)) = inv_into (set_mset M) f y" by (meson inj_xM inv_into_f_f) hence "0 < count (image_mset f (add_mset x M)) y \ count M (inv_into (set_mset M) f y) = 0 \ x = inv_into (set_mset M) f y" using neg_conj cnt_y ih[OF inj_M] by (metis (no_types) count_add_mset count_greater_zero_iff count_inI f_inv_into_f image_mset_add_mset set_image_mset) thus False using neg_conj cnt_y x_ni_M ih[OF inj_M] by (metis (no_types) count_greater_zero_iff count_inI eq_iff image_mset_add_mset less_imp_le) qed qed qed qed simp lemma mset_filter_compl: "mset (filter p xs) + mset (filter (Not \ p) xs) = mset xs" by (induction xs) (auto simp: ac_simps) text \Near duplicate of @{thm [source] filter_eq_replicate_mset}: @{thm filter_eq_replicate_mset}.\ lemma filter_mset_eq: "filter_mset ((=) L) A = replicate_mset (count A L) L" by (auto simp: multiset_eq_iff) lemma filter_mset_cong[fundef_cong]: assumes "M = M'" "\a. a \# M \ P a = Q a" shows "filter_mset P M = filter_mset Q M" proof - have "M - filter_mset Q M = filter_mset (\a. \Q a) M" by (metis multiset_partition add_diff_cancel_left') then show ?thesis by (auto simp: filter_mset_eq_conv assms) qed lemma image_mset_filter_swap: "image_mset f {# x \# M. P (f x)#} = {# x \# image_mset f M. P x#}" by (induction M) auto lemma image_mset_cong2: "(\x. x \# M \ f x = g x) \ M = N \ image_mset f M = image_mset g N" by (hypsubst, rule image_mset_cong) lemma filter_mset_empty_conv: \(filter_mset P M = {#}) = (\L\#M. \ P L)\ by (induction M) auto lemma multiset_filter_mono2: \filter_mset P A \# filter_mset Q A \ (\a\#A. P a \ Q a)\ by (induction A) (auto intro: subset_mset.order.trans) lemma image_filter_cong: assumes \\C. C \# M \ P C \ f C = g C\ shows \{#f C. C \# {#C \# M. P C#}#} = {#g C | C\# M. P C#}\ using assms by (induction M) auto lemma image_mset_filter_swap2: \{#C \# {#P x. x \# D#}. Q C #} = {#P x. x \# {#C| C \# D. Q (P C)#}#}\ by (simp add: image_mset_filter_swap) declare image_mset_cong2 [cong] lemma filter_mset_empty_if_finite_and_filter_set_empty: assumes "{x \ X. P x} = {}" and "finite X" shows "{#x \# mset_set X. P x#} = {#}" proof - have empty_empty: "\Y. set_mset Y = {} \ Y = {#}" by auto from assms have "set_mset {#x \# mset_set X. P x#} = {}" by auto then show ?thesis by (rule empty_empty) qed subsection \Lemmas about Sum\ lemma sum_image_mset_sum_map[simp]: "sum_mset (image_mset f (mset xs)) = sum_list (map f xs)" by (metis mset_map sum_mset_sum_list) lemma sum_image_mset_mono: fixes f :: "'a \ 'b::canonically_ordered_monoid_add" assumes sub: "A \# B" shows "(\m \# A. f m) \ (\m \# B. f m)" by (metis image_mset_union le_iff_add sub subset_mset.add_diff_inverse sum_mset.union) lemma sum_image_mset_mono_mem: "n \# M \ f n \ (\m \# M. f m)" for f :: "'a \ 'b::canonically_ordered_monoid_add" using le_iff_add multi_member_split by fastforce lemma count_sum_mset_if_1_0: \count M a = (\x\#M. if x = a then 1 else 0)\ by (induction M) auto lemma sum_mset_dvd: fixes k :: "'a::comm_semiring_1_cancel" assumes "\m \# M. k dvd f m" shows "k dvd (\m \# M. f m)" using assms by (induct M) auto lemma sum_mset_distrib_div_if_dvd: fixes k :: "'a::unique_euclidean_semiring" assumes "\m \# M. k dvd f m" shows "(\m \# M. f m) div k = (\m \# M. f m div k)" using assms by (induct M) (auto simp: div_plus_div_distrib_dvd_left) subsection \Lemmas about Remove\ lemma set_mset_minus_replicate_mset[simp]: "n \ count A a \ set_mset (A - replicate_mset n a) = set_mset A - {a}" "n < count A a \ set_mset (A - replicate_mset n a) = set_mset A" unfolding set_mset_def by (auto split: if_split simp: not_in_iff) abbreviation removeAll_mset :: "'a \ 'a multiset \ 'a multiset" where "removeAll_mset C M \ M - replicate_mset (count M C) C" lemma mset_removeAll[simp, code]: "removeAll_mset C (mset L) = mset (removeAll C L)" by (induction L) (auto simp: ac_simps multiset_eq_iff split: if_split_asm) lemma removeAll_mset_filter_mset: "removeAll_mset C M = filter_mset ((\) C) M" by (induction M) (auto simp: ac_simps multiset_eq_iff) abbreviation remove1_mset :: "'a \ 'a multiset \ 'a multiset" where "remove1_mset C M \ M - {#C#}" lemma removeAll_subseteq_remove1_mset: "removeAll_mset x M \# remove1_mset x M" by (auto simp: subseteq_mset_def) lemma in_remove1_mset_neq: assumes ab: "a \ b" shows "a \# remove1_mset b C \ a \# C" by (metis assms diff_single_trivial in_diffD insert_DiffM insert_noteq_member) lemma size_mset_removeAll_mset_le_iff: "size (removeAll_mset x M) < size M \ x \# M" by (auto intro: count_inI mset_subset_size simp: subset_mset_def multiset_eq_iff) lemma size_remove1_mset_If: \size (remove1_mset x M) = size M - (if x \# M then 1 else 0)\ by (auto simp: size_Diff_subset_Int) lemma size_mset_remove1_mset_le_iff: "size (remove1_mset x M) < size M \ x \# M" using less_irrefl by (fastforce intro!: mset_subset_size elim: in_countE simp: subset_mset_def multiset_eq_iff) lemma remove_1_mset_id_iff_notin: "remove1_mset a M = M \ a \# M" by (meson diff_single_trivial multi_drop_mem_not_eq) lemma id_remove_1_mset_iff_notin: "M = remove1_mset a M \ a \# M" using remove_1_mset_id_iff_notin by metis lemma remove1_mset_eqE: "remove1_mset L x1 = M \ (L \# x1 \ x1 = M + {#L#} \ P) \ (L \# x1 \ x1 = M \ P) \ P" by (cases "L \# x1") auto lemma image_filter_ne_mset[simp]: "image_mset f {#x \# M. f x \ y#} = removeAll_mset y (image_mset f M)" by (induction M) simp_all lemma image_mset_remove1_mset_if: "image_mset f (remove1_mset a M) = (if a \# M then remove1_mset (f a) (image_mset f M) else image_mset f M)" by (auto simp: image_mset_Diff) lemma filter_mset_neq: "{#x \# M. x \ y#} = removeAll_mset y M" by (metis add_diff_cancel_left' filter_eq_replicate_mset multiset_partition) lemma filter_mset_neq_cond: "{#x \# M. P x \ x \ y#} = removeAll_mset y {# x\#M. P x#}" by (metis filter_filter_mset filter_mset_neq) lemma remove1_mset_add_mset_If: "remove1_mset L (add_mset L' C) = (if L = L' then C else remove1_mset L C + {#L'#})" by (auto simp: multiset_eq_iff) lemma minus_remove1_mset_if: "A - remove1_mset b B = (if b \# B \ b \# A \ count A b \ count B b then {#b#} + (A - B) else A - B)" by (auto simp: multiset_eq_iff count_greater_zero_iff[symmetric] simp del: count_greater_zero_iff) lemma add_mset_eq_add_mset_ne: "a \ b \ add_mset a A = add_mset b B \ a \# B \ b \# A \ A = add_mset b (B - {#a#})" by (metis (no_types, lifting) diff_single_eq_union diff_union_swap multi_self_add_other_not_self remove_1_mset_id_iff_notin union_single_eq_diff) lemma add_mset_eq_add_mset: \add_mset a M = add_mset b M' \ (a = b \ M = M') \ (a \ b \ b \# M \ add_mset a (M - {#b#}) = M')\ by (metis add_mset_eq_add_mset_ne add_mset_remove_trivial union_single_eq_member) (* TODO move to Multiset: could replace add_mset_remove_trivial_eq? *) lemma add_mset_remove_trivial_iff: \N = add_mset a (N - {#b#}) \ a \# N \ a = b\ by (metis add_left_cancel add_mset_remove_trivial insert_DiffM2 single_eq_single size_mset_remove1_mset_le_iff union_single_eq_member) lemma trivial_add_mset_remove_iff: \add_mset a (N - {#b#}) = N \ a \# N \ a = b\ by (subst eq_commute) (fact add_mset_remove_trivial_iff) lemma remove1_single_empty_iff[simp]: \remove1_mset L {#L'#} = {#} \ L = L'\ using add_mset_remove_trivial_iff by fastforce lemma add_mset_less_imp_less_remove1_mset: assumes xM_lt_N: "add_mset x M < N" shows "M < remove1_mset x N" proof - have "M < N" using assms le_multiset_right_total mset_le_trans by blast then show ?thesis by (metis add_less_cancel_right add_mset_add_single diff_single_trivial insert_DiffM2 xM_lt_N) qed subsection \Lemmas about Replicate\ lemma replicate_mset_minus_replicate_mset_same[simp]: "replicate_mset m x - replicate_mset n x = replicate_mset (m - n) x" by (induct m arbitrary: n, simp, metis left_diff_repeat_mset_distrib' repeat_mset_replicate_mset) lemma replicate_mset_subset_iff_lt[simp]: "replicate_mset m x \# replicate_mset n x \ m < n" by (induct n m rule: diff_induct) (auto intro: subset_mset.gr_zeroI) lemma replicate_mset_subseteq_iff_le[simp]: "replicate_mset m x \# replicate_mset n x \ m \ n" by (induct n m rule: diff_induct) auto lemma replicate_mset_lt_iff_lt[simp]: "replicate_mset m x < replicate_mset n x \ m < n" by (induct n m rule: diff_induct) (auto intro: subset_mset.gr_zeroI gr_zeroI) lemma replicate_mset_le_iff_le[simp]: "replicate_mset m x \ replicate_mset n x \ m \ n" by (induct n m rule: diff_induct) auto lemma replicate_mset_eq_iff[simp]: "replicate_mset m x = replicate_mset n y \ m = n \ (m \ 0 \ x = y)" by (cases m; cases n; simp) (metis in_replicate_mset insert_noteq_member size_replicate_mset union_single_eq_diff) lemma replicate_mset_plus: "replicate_mset (a + b) C = replicate_mset a C + replicate_mset b C" by (induct a) (auto simp: ac_simps) lemma mset_replicate_replicate_mset: "mset (replicate n L) = replicate_mset n L" by (induction n) auto lemma set_mset_single_iff_replicate_mset: "set_mset U = {a} \ (\n > 0. U = replicate_mset n a)" by (rule, metis count_greater_zero_iff count_replicate_mset insertI1 multi_count_eq singletonD zero_less_iff_neq_zero, force) lemma ex_replicate_mset_if_all_elems_eq: assumes "\x \# M. x = y" shows "\n. M = replicate_mset n y" using assms by (metis count_replicate_mset mem_Collect_eq multiset_eqI neq0_conv set_mset_def) subsection \Multiset and Set Conversions\ lemma count_mset_set_if: "count (mset_set A) a = (if a \ A \ finite A then 1 else 0)" by auto lemma mset_set_set_mset_empty_mempty[iff]: "mset_set (set_mset D) = {#} \ D = {#}" by (simp add: mset_set_empty_iff) lemma count_mset_set_le_one: "count (mset_set A) x \ 1" by (simp add: count_mset_set_if) lemma mset_set_set_mset_subseteq[simp]: "mset_set (set_mset A) \# A" by (simp add: mset_set_set_mset_msubset) lemma mset_sorted_list_of_set[simp]: "mset (sorted_list_of_set A) = mset_set A" by (metis mset_sorted_list_of_multiset sorted_list_of_mset_set) lemma sorted_sorted_list_of_multiset[simp]: "sorted (sorted_list_of_multiset (M :: 'a::linorder multiset))" by (metis mset_sorted_list_of_multiset sorted_list_of_multiset_mset sorted_sort) lemma mset_take_subseteq: "mset (take n xs) \# mset xs" apply (induct xs arbitrary: n) apply simp by (case_tac n) simp_all lemma sorted_list_of_multiset_eq_Nil[simp]: "sorted_list_of_multiset M = [] \ M = {#}" by (metis mset_sorted_list_of_multiset sorted_list_of_multiset_empty) subsection \Duplicate Removal\ (* TODO: use abbreviation? *) definition remdups_mset :: "'v multiset \ 'v multiset" where "remdups_mset S = mset_set (set_mset S)" lemma set_mset_remdups_mset[simp]: \set_mset (remdups_mset A) = set_mset A\ unfolding remdups_mset_def by auto lemma count_remdups_mset_eq_1: "a \# remdups_mset A \ count (remdups_mset A) a = 1" unfolding remdups_mset_def by (auto simp: count_eq_zero_iff intro: count_inI) lemma remdups_mset_empty[simp]: "remdups_mset {#} = {#}" unfolding remdups_mset_def by auto lemma remdups_mset_singleton[simp]: "remdups_mset {#a#} = {#a#}" unfolding remdups_mset_def by auto lemma remdups_mset_eq_empty[iff]: "remdups_mset D = {#} \ D = {#}" unfolding remdups_mset_def by blast lemma remdups_mset_singleton_sum[simp]: "remdups_mset (add_mset a A) = (if a \# A then remdups_mset A else add_mset a (remdups_mset A))" unfolding remdups_mset_def by (simp_all add: insert_absorb) lemma mset_remdups_remdups_mset[simp]: "mset (remdups D) = remdups_mset (mset D)" by (induction D) (auto simp add: ac_simps) declare mset_remdups_remdups_mset[symmetric, code] definition distinct_mset :: "'a multiset \ bool" where "distinct_mset S \ (\a. a \# S \ count S a = 1)" lemma distinct_mset_count_less_1: "distinct_mset S \ (\a. count S a \ 1)" using eq_iff nat_le_linear unfolding distinct_mset_def by fastforce lemma distinct_mset_empty[simp]: "distinct_mset {#}" unfolding distinct_mset_def by auto lemma distinct_mset_singleton: "distinct_mset {#a#}" unfolding distinct_mset_def by auto lemma distinct_mset_union: assumes dist: "distinct_mset (A + B)" shows "distinct_mset A" unfolding distinct_mset_count_less_1 proof (rule allI) fix a have \count A a \ count (A + B) a\ by auto moreover have \count (A + B) a \ 1\ using dist unfolding distinct_mset_count_less_1 by auto ultimately show \count A a \ 1\ by simp qed lemma distinct_mset_minus[simp]: "distinct_mset A \ distinct_mset (A - B)" by (metis diff_subset_eq_self mset_subset_eq_exists_conv distinct_mset_union) lemma count_remdups_mset_If: \count (remdups_mset A) a = (if a \# A then 1 else 0)\ unfolding remdups_mset_def by auto lemma distinct_mset_rempdups_union_mset: assumes "distinct_mset A" and "distinct_mset B" shows "A \# B = remdups_mset (A + B)" using assms nat_le_linear unfolding remdups_mset_def by (force simp add: multiset_eq_iff max_def count_mset_set_if distinct_mset_def not_in_iff) lemma distinct_mset_add_mset[simp]: "distinct_mset (add_mset a L) \ a \# L \ distinct_mset L" unfolding distinct_mset_def apply (rule iffI) apply (auto split: if_split_asm; fail)[] by (auto simp: not_in_iff; fail) lemma distinct_mset_size_eq_card: "distinct_mset C \ size C = card (set_mset C)" by (induction C) auto lemma distinct_mset_add: "distinct_mset (L + L') \ distinct_mset L \ distinct_mset L' \ L \# L' = {#}" by (induction L arbitrary: L') auto lemma distinct_mset_set_mset_ident[simp]: "distinct_mset M \ mset_set (set_mset M) = M" by (induction M) auto lemma distinct_finite_set_mset_subseteq_iff[iff]: assumes "distinct_mset M" "finite N" shows "set_mset M \ N \ M \# mset_set N" by (metis assms distinct_mset_set_mset_ident finite_set_mset msubset_mset_set_iff) lemma distinct_mem_diff_mset: assumes dist: "distinct_mset M" and mem: "x \ set_mset (M - N)" shows "x \ set_mset N" proof - have "count M x = 1" using dist mem by (meson distinct_mset_def in_diffD) then show ?thesis using mem by (metis count_greater_eq_one_iff in_diff_count not_less) qed lemma distinct_set_mset_eq: assumes "distinct_mset M" "distinct_mset N" "set_mset M = set_mset N" shows "M = N" using assms distinct_mset_set_mset_ident by fastforce lemma distinct_mset_union_mset[simp]: \distinct_mset (D \# C) \ distinct_mset D \ distinct_mset C\ unfolding distinct_mset_count_less_1 by force lemma distinct_mset_inter_mset: "distinct_mset C \ distinct_mset (C \# D)" "distinct_mset D \ distinct_mset (C \# D)" by (simp_all add: multiset_inter_def, metis distinct_mset_minus multiset_inter_commute multiset_inter_def) lemma distinct_mset_remove1_All: "distinct_mset C \ remove1_mset L C = removeAll_mset L C" by (auto simp: multiset_eq_iff distinct_mset_count_less_1) lemma distinct_mset_size_2: "distinct_mset {#a, b#} \ a \ b" by auto lemma distinct_mset_filter: "distinct_mset M \ distinct_mset {# L \# M. P L#}" by (simp add: distinct_mset_def) lemma distinct_mset_mset_distinct[simp]: \distinct_mset (mset xs) = distinct xs\ by (induction xs) auto lemma distinct_image_mset_inj: \inj_on f (set_mset M) \ distinct_mset (image_mset f M) \ distinct_mset M\ by (induction M) (auto simp: inj_on_def) subsection \Repeat Operation\ lemma repeat_mset_compower: "repeat_mset n A = (((+) A) ^^ n) {#}" by (induction n) auto lemma repeat_mset_prod: "repeat_mset (m * n) A = (((+) (repeat_mset n A)) ^^ m) {#}" by (induction m) (auto simp: repeat_mset_distrib) subsection \Cartesian Product\ text \Definition of the cartesian products over multisets. The construction mimics of the cartesian product on sets and use the same theorem names (adding only the suffix \_mset\ to Sigma and Times). See file @{file \~~/src/HOL/Product_Type.thy\}\ definition Sigma_mset :: "'a multiset \ ('a \ 'b multiset) \ ('a \ 'b) multiset" where "Sigma_mset A B \ \# {#{#(a, b). b \# B a#}. a \# A #}" abbreviation Times_mset :: "'a multiset \ 'b multiset \ ('a \ 'b) multiset" (infixr "\#" 80) where "Times_mset A B \ Sigma_mset A (\_. B)" hide_const (open) Times_mset text \Contrary to the set version @{term \SIGMA x:A. B\}, we use the non-ASCII symbol \\#\.\ syntax "_Sigma_mset" :: "[pttrn, 'a multiset, 'b multiset] => ('a * 'b) multiset" ("(3SIGMAMSET _\#_./ _)" [0, 0, 10] 10) translations "SIGMAMSET x\#A. B" == "CONST Sigma_mset A (\x. B)" text \Link between the multiset and the set cartesian product:\ lemma Times_mset_Times: "set_mset (A \# B) = set_mset A \ set_mset B" unfolding Sigma_mset_def by auto lemma Sigma_msetI [intro!]: "\a \# A; b \# B a\ \ (a, b) \# Sigma_mset A B" by (unfold Sigma_mset_def) auto lemma Sigma_msetE[elim!]: "\c \# Sigma_mset A B; \x y. \x \# A; y \# B x; c = (x, y)\ \ P\ \ P" by (unfold Sigma_mset_def) auto text \Elimination of @{term "(a, b) \# A \# B"} -- introduces no eigenvariables.\ lemma Sigma_msetD1: "(a, b) \# Sigma_mset A B \ a \# A" by blast lemma Sigma_msetD2: "(a, b) \# Sigma_mset A B \ b \# B a" by blast lemma Sigma_msetE2: "\(a, b) \# Sigma_mset A B; \a \# A; b \# B a\ \ P\ \ P" by blast lemma Sigma_mset_cong: "\A = B; \x. x \# B \ C x = D x\ \ (SIGMAMSET x \# A. C x) = (SIGMAMSET x \# B. D x)" by (metis (mono_tags, lifting) Sigma_mset_def image_mset_cong) lemma count_sum_mset: "count (\# M) b = (\P \# M. count P b)" by (induction M) auto lemma Sigma_mset_plus_distrib1[simp]: "Sigma_mset (A + B) C = Sigma_mset A C + Sigma_mset B C" unfolding Sigma_mset_def by auto lemma Sigma_mset_plus_distrib2[simp]: "Sigma_mset A (\i. B i + C i) = Sigma_mset A B + Sigma_mset A C" unfolding Sigma_mset_def by (induction A) (auto simp: multiset_eq_iff) lemma Times_mset_single_left: "{#a#} \# B = image_mset (Pair a) B" unfolding Sigma_mset_def by auto lemma Times_mset_single_right: "A \# {#b#} = image_mset (\a. Pair a b) A" unfolding Sigma_mset_def by (induction A) auto lemma Times_mset_single_single[simp]: "{#a#} \# {#b#} = {#(a, b)#}" unfolding Sigma_mset_def by simp lemma count_image_mset_Pair: "count (image_mset (Pair a) B) (x, b) = (if x = a then count B b else 0)" by (induction B) auto lemma count_Sigma_mset: "count (Sigma_mset A B) (a, b) = count A a * count (B a) b" by (induction A) (auto simp: Sigma_mset_def count_image_mset_Pair) lemma Sigma_mset_empty1[simp]: "Sigma_mset {#} B = {#}" unfolding Sigma_mset_def by auto lemma Sigma_mset_empty2[simp]: "A \# {#} = {#}" by (auto simp: multiset_eq_iff count_Sigma_mset) lemma Sigma_mset_mono: assumes "A \# C" and "\x. x \# A \ B x \# D x" shows "Sigma_mset A B \# Sigma_mset C D" proof - have "count A a * count (B a) b \ count C a * count (D a) b" for a b using assms unfolding subseteq_mset_def by (metis count_inI eq_iff mult_eq_0_iff mult_le_mono) then show ?thesis by (auto simp: subseteq_mset_def count_Sigma_mset) qed lemma mem_Sigma_mset_iff[iff]: "((a,b) \# Sigma_mset A B) = (a \# A \ b \# B a)" by blast lemma mem_Times_mset_iff: "x \# A \# B \ fst x \# A \ snd x \# B" by (induct x) simp lemma Sigma_mset_empty_iff: "(SIGMAMSET i\#I. X i) = {#} \ (\i\#I. X i = {#})" by (auto simp: Sigma_mset_def) lemma Times_mset_subset_mset_cancel1: "x \# A \ (A \# B \# A \# C) = (B \# C)" by (auto simp: subseteq_mset_def count_Sigma_mset) lemma Times_mset_subset_mset_cancel2: "x \# C \ (A \# C \# B \# C) = (A \# B)" by (auto simp: subseteq_mset_def count_Sigma_mset) lemma Times_mset_eq_cancel2: "x \# C \ (A \# C = B \# C) = (A = B)" by (auto simp: multiset_eq_iff count_Sigma_mset dest!: in_countE) lemma split_paired_Ball_mset_Sigma_mset[simp]: "(\z\#Sigma_mset A B. P z) \ (\x\#A. \y\#B x. P (x, y))" by blast lemma split_paired_Bex_mset_Sigma_mset[simp]: "(\z\#Sigma_mset A B. P z) \ (\x\#A. \y\#B x. P (x, y))" by blast lemma sum_mset_if_eq_constant: "(\x\#M. if a = x then (f x) else 0) = (((+) (f a)) ^^ (count M a)) 0" by (induction M) (auto simp: ac_simps) lemma iterate_op_plus: "(((+) k) ^^ m) 0 = k * m" by (induction m) auto lemma untion_image_mset_Pair_distribute: "\#{#image_mset (Pair x) (C x). x \# J - I#} = \# {#image_mset (Pair x) (C x). x \# J#} - \#{#image_mset (Pair x) (C x). x \# I#}" by (auto simp: multiset_eq_iff count_sum_mset count_image_mset_Pair sum_mset_if_eq_constant iterate_op_plus diff_mult_distrib2) lemma Sigma_mset_Un_distrib1: "Sigma_mset (I \# J) C = Sigma_mset I C \# Sigma_mset J C" by (auto simp: Sigma_mset_def sup_subset_mset_def untion_image_mset_Pair_distribute) lemma Sigma_mset_Un_distrib2: "(SIGMAMSET i\#I. A i \# B i) = Sigma_mset I A \# Sigma_mset I B" by (auto simp: multiset_eq_iff count_sum_mset count_image_mset_Pair sum_mset_if_eq_constant Sigma_mset_def diff_mult_distrib2 iterate_op_plus max_def not_in_iff) lemma Sigma_mset_Int_distrib1: "Sigma_mset (I \# J) C = Sigma_mset I C \# Sigma_mset J C" by (auto simp: multiset_eq_iff count_sum_mset count_image_mset_Pair sum_mset_if_eq_constant Sigma_mset_def iterate_op_plus min_def not_in_iff) lemma Sigma_mset_Int_distrib2: "(SIGMAMSET i\#I. A i \# B i) = Sigma_mset I A \# Sigma_mset I B" by (auto simp: multiset_eq_iff count_sum_mset count_image_mset_Pair sum_mset_if_eq_constant Sigma_mset_def iterate_op_plus min_def not_in_iff) lemma Sigma_mset_Diff_distrib1: "Sigma_mset (I - J) C = Sigma_mset I C - Sigma_mset J C" by (auto simp: multiset_eq_iff count_sum_mset count_image_mset_Pair sum_mset_if_eq_constant Sigma_mset_def iterate_op_plus min_def not_in_iff diff_mult_distrib2) lemma Sigma_mset_Diff_distrib2: "(SIGMAMSET i\#I. A i - B i) = Sigma_mset I A - Sigma_mset I B" by (auto simp: multiset_eq_iff count_sum_mset count_image_mset_Pair sum_mset_if_eq_constant Sigma_mset_def iterate_op_plus min_def not_in_iff diff_mult_distrib) lemma Sigma_mset_Union: "Sigma_mset (\#X) B = (\# (image_mset (\A. Sigma_mset A B) X))" by (auto simp: multiset_eq_iff count_sum_mset count_image_mset_Pair sum_mset_if_eq_constant Sigma_mset_def iterate_op_plus min_def not_in_iff sum_mset_distrib_left) lemma Times_mset_Un_distrib1: "(A \# B) \# C = A \# C \# B \# C" by (fact Sigma_mset_Un_distrib1) lemma Times_mset_Int_distrib1: "(A \# B) \# C = A \# C \# B \# C" by (fact Sigma_mset_Int_distrib1) lemma Times_mset_Diff_distrib1: "(A - B) \# C = A \# C - B \# C" by (fact Sigma_mset_Diff_distrib1) lemma Times_mset_empty[simp]: "A \# B = {#} \ A = {#} \ B = {#}" by (auto simp: Sigma_mset_empty_iff) lemma Times_insert_left: "A \# add_mset x B = A \# B + image_mset (\a. Pair a x) A" unfolding add_mset_add_single[of x B] Sigma_mset_plus_distrib2 by (simp add: Times_mset_single_right) lemma Times_insert_right: "add_mset a A \# B = A \# B + image_mset (Pair a) B" unfolding add_mset_add_single[of a A] Sigma_mset_plus_distrib1 by (simp add: Times_mset_single_left) lemma fst_image_mset_times_mset [simp]: "image_mset fst (A \# B) = (if B = {#} then {#} else repeat_mset (size B) A)" by (induct B) (auto simp: Times_mset_single_right ac_simps Times_insert_left) lemma snd_image_mset_times_mset [simp]: "image_mset snd (A \# B) = (if A = {#} then {#} else repeat_mset (size A) B)" by (induct B) (auto simp add: Times_mset_single_right Times_insert_left image_mset_const_eq) lemma product_swap_mset: "image_mset prod.swap (A \# B) = B \# A" by (induction A) (auto simp add: Times_mset_single_left Times_mset_single_right Times_insert_right Times_insert_left) context begin qualified definition product_mset :: "'a multiset \ 'b multiset \ ('a \ 'b) multiset" where [code_abbrev]: "product_mset A B = A \# B" lemma member_product_mset: "x \# product_mset A B \ x \# A \# B" by (simp add: Multiset_More.product_mset_def) end lemma count_Sigma_mset_abs_def: "count (Sigma_mset A B) = (\(a, b) \ count A a * count (B a) b)" by (auto simp: fun_eq_iff count_Sigma_mset) lemma Times_mset_image_mset1: "image_mset f A \# B = image_mset (\(a, b). (f a, b)) (A \# B)" by (induct B) (auto simp: Times_insert_left) lemma Times_mset_image_mset2: "A \# image_mset f B = image_mset (\(a, b). (a, f b)) (A \# B)" by (induct A) (auto simp: Times_insert_right) lemma sum_le_singleton: "A \ {x} \ sum f A = (if x \ A then f x else 0)" by (auto simp: subset_singleton_iff elim: finite_subset) lemma Times_mset_assoc: "(A \# B) \# C = image_mset (\(a, b, c). ((a, b), c)) (A \# B \# C)" by (auto simp: multiset_eq_iff count_Sigma_mset count_image_mset vimage_def Times_mset_Times Int_commute count_eq_zero_iff intro!: trans[OF _ sym[OF sum_le_singleton[of _ "(_, _, _)"]]] cong: sum.cong if_cong) subsection \Transfer Rules\ lemma plus_multiset_transfer[transfer_rule]: "(rel_fun (rel_mset R) (rel_fun (rel_mset R) (rel_mset R))) (+) (+)" by (unfold rel_fun_def rel_mset_def) (force dest: list_all2_appendI intro: exI[of _ "_ @ _"] conjI[rotated]) lemma minus_multiset_transfer[transfer_rule]: assumes [transfer_rule]: "bi_unique R" shows "(rel_fun (rel_mset R) (rel_fun (rel_mset R) (rel_mset R))) (-) (-)" proof (unfold rel_fun_def rel_mset_def, safe) fix xs ys xs' ys' assume [transfer_rule]: "list_all2 R xs ys" "list_all2 R xs' ys'" have "list_all2 R (fold remove1 xs' xs) (fold remove1 ys' ys)" by transfer_prover moreover have "mset (fold remove1 xs' xs) = mset xs - mset xs'" by (induct xs' arbitrary: xs) auto moreover have "mset (fold remove1 ys' ys) = mset ys - mset ys'" by (induct ys' arbitrary: ys) auto ultimately show "\xs'' ys''. mset xs'' = mset xs - mset xs' \ mset ys'' = mset ys - mset ys' \ list_all2 R xs'' ys''" by blast qed declare rel_mset_Zero[transfer_rule] lemma count_transfer[transfer_rule]: assumes "bi_unique R" shows "(rel_fun (rel_mset R) (rel_fun R (=))) count count" unfolding rel_fun_def rel_mset_def proof safe fix x y xs ys assume "list_all2 R xs ys" "R x y" then show "count (mset xs) x = count (mset ys) y" proof (induct xs ys rule: list.rel_induct) case (Cons x' xs y' ys) then show ?case using assms unfolding bi_unique_alt_def2 by (auto simp: rel_fun_def) qed simp qed lemma subseteq_multiset_transfer[transfer_rule]: assumes [transfer_rule]: "bi_unique R" "right_total R" shows "(rel_fun (rel_mset R) (rel_fun (rel_mset R) (=))) (\M N. filter_mset (Domainp R) M \# filter_mset (Domainp R) N) (\#)" proof - have count_filter_mset_less: "(\a. count (filter_mset (Domainp R) M) a \ count (filter_mset (Domainp R) N) a) \ (\a \ {x. Domainp R x}. count M a \ count N a)" for M and N by auto show ?thesis unfolding subseteq_mset_def count_filter_mset_less by transfer_prover qed lemma sum_mset_transfer[transfer_rule]: "R 0 0 \ rel_fun R (rel_fun R R) (+) (+) \ (rel_fun (rel_mset R) R) sum_mset sum_mset" using sum_list_transfer[of R] unfolding rel_fun_def rel_mset_def by auto lemma Sigma_mset_transfer[transfer_rule]: "(rel_fun (rel_mset R) (rel_fun (rel_fun R (rel_mset S)) (rel_mset (rel_prod R S)))) Sigma_mset Sigma_mset" by (unfold Sigma_mset_def) transfer_prover subsection \Even More about Multisets\ subsubsection \Multisets and Functions\ lemma range_image_mset: assumes "set_mset Ds \ range f" shows "Ds \ range (image_mset f)" proof - have "\D. D \# Ds \ (\C. f C = D)" using assms by blast then obtain f_i where f_p: "\D. D \# Ds \ (f (f_i D) = D)" by metis define Cs where "Cs \ image_mset f_i Ds" from f_p Cs_def have "image_mset f Cs = Ds" by auto then show ?thesis by blast qed subsubsection \Multisets and Lists\ lemma length_sorted_list_of_multiset[simp]: "length (sorted_list_of_multiset A) = size A" by (metis mset_sorted_list_of_multiset size_mset) definition list_of_mset :: "'a multiset \ 'a list" where "list_of_mset m = (SOME l. m = mset l)" lemma list_of_mset_exi: "\l. m = mset l" using ex_mset by metis lemma mset_list_of_mset [simp]: "mset (list_of_mset m) = m" by (metis (mono_tags, lifting) ex_mset list_of_mset_def someI_ex) lemma length_list_of_mset[simp]: "length (list_of_mset A) = size A" unfolding list_of_mset_def by (metis (mono_tags) ex_mset size_mset someI_ex) lemma range_mset_map: assumes "set_mset Ds \ range f" shows "Ds \ range (\Cl. mset (map f Cl))" proof - have "Ds \ range (image_mset f)" by (simp add: assms range_image_mset) then obtain Cs where Cs_p: "image_mset f Cs = Ds" by auto define Cl where "Cl = list_of_mset Cs" then have "mset Cl = Cs" by auto then have "image_mset f (mset Cl) = Ds" using Cs_p by auto then have "mset (map f Cl) = Ds" by auto then show ?thesis by auto qed lemma list_of_mset_empty[iff]: "list_of_mset m = [] \ m = {#}" by (metis (mono_tags, lifting) ex_mset list_of_mset_def mset_zero_iff_right someI_ex) lemma in_mset_conv_nth: "(x \# mset xs) = (\i# LL" assumes "LL \ set Ci" shows "L \# sum_list Ci" using assms by (induction Ci) auto lemma in_mset_sum_list2: assumes "L \# sum_list Ci" obtains LL where "LL \ set Ci" "L \# LL" using assms by (induction Ci) auto +(* TODO: Make [simp]. *) +lemma in_mset_sum_list_iff: "a \# sum_list \ \ (\A \ set \. a \# A)" + by (metis in_mset_sum_list in_mset_sum_list2) + lemma subseteq_list_Union_mset: assumes "length Ci = n" assumes "length CAi = n" assumes "\i# CAi ! i " shows "\# (mset Ci) \# \# (mset CAi)" using assms proof (induction n arbitrary: Ci CAi) case 0 then show ?case by auto next case (Suc n) from Suc have "\i# tl CAi ! i" by (simp add: nth_tl) hence "\#(mset (tl Ci)) \# \#(mset (tl CAi))" using Suc by auto moreover have "hd Ci \# hd CAi" using Suc by (metis hd_conv_nth length_greater_0_conv zero_less_Suc) ultimately show "\#(mset Ci) \# \#(mset CAi)" using Suc by (cases Ci; cases CAi) (auto intro: subset_mset.add_mono) qed subsubsection \More on Multisets and Functions\ lemma subseteq_mset_size_eql: "X \# Y \ size Y = size X \ X = Y" using mset_subset_size subset_mset_def by fastforce lemma image_mset_of_subset_list: assumes "image_mset \ C' = mset lC" shows "\qC'. map \ qC' = lC \ mset qC' = C'" using assms apply (induction lC arbitrary: C') subgoal by simp subgoal by (fastforce dest!: msed_map_invR intro: exI[of _ \_ # _\]) done lemma image_mset_of_subset: assumes "A \# image_mset \ C'" shows "\A'. image_mset \ A' = A \ A' \# C'" proof - define C where "C = image_mset \ C'" define lA where "lA = list_of_mset A" define lD where "lD = list_of_mset (C-A)" define lC where "lC = lA @ lD" have "mset lC = C" using C_def assms unfolding lD_def lC_def lA_def by auto then have "\qC'. map \ qC' = lC \ mset qC' = C'" using assms image_mset_of_subset_list unfolding C_def by metis then obtain qC' where qC'_p: "map \ qC' = lC \ mset qC' = C'" by auto let ?lA' = "take (length lA) qC'" have m: "map \ ?lA' = lA" using qC'_p lC_def by (metis append_eq_conv_conj take_map) let ?A' = "mset ?lA'" have "image_mset \ ?A' = A" using m using lA_def by (metis (full_types) ex_mset list_of_mset_def mset_map someI_ex) moreover have "?A' \# C'" using qC'_p unfolding lA_def using mset_take_subseteq by blast ultimately show ?thesis by blast qed lemma all_the_same: "\x \# X. x = y \ card (set_mset X) \ Suc 0" by (metis card.empty card.insert card_mono finite.intros(1) finite_insert le_SucI singletonI subsetI) lemma Melem_subseteq_Union_mset[simp]: assumes "x \# T" shows "x \# \#T" using assms sum_mset.remove by force lemma Melem_subset_eq_sum_list[simp]: assumes "x \# mset T" shows "x \# sum_list T" using assms by (metis mset_subset_eq_add_left sum_mset.remove sum_mset_sum_list) lemma less_subset_eq_Union_mset[simp]: assumes "i < length CAi" shows "CAi ! i \# \#(mset CAi)" proof - from assms have "CAi ! i \# mset CAi" by auto then show ?thesis by auto qed lemma less_subset_eq_sum_list[simp]: assumes "i < length CAi" shows "CAi ! i \# sum_list CAi" proof - from assms have "CAi ! i \# mset CAi" by auto then show ?thesis by auto qed subsubsection \More on Multiset Order\ lemma less_multiset_doubletons: assumes - "y < t \ y < s" - "x < t \ x < s" + "y < t \ y < s" + "x < t \ x < s" shows - "{# y, x#} < {# t, s#}" + "{#y, x#} < {#t, s#}" unfolding less_multiset\<^sub>D\<^sub>M proof (intro exI) - let ?X = "{# t, s#}" + let ?X = "{#t, s#}" let ?Y = "{#y, x#}" - show "?X \ {#} \ ?X \# {#t, s#} \ {#y, x#} = {#t, s#} - ?X + ?Y \ (\k. k \# ?Y \ (\a. a \# ?X \ k < a))" - using add_eq_conv_diff assms(1) assms(2) by auto + show "?X \ {#} \ ?X \# {#t, s#} \ {#y, x#} = {#t, s#} - ?X + ?Y + \ (\k. k \# ?Y \ (\a. a \# ?X \ k < a))" + using add_eq_conv_diff assms by auto qed end diff --git a/thys/Ordered_Resolution_Prover/Abstract_Substitution.thy b/thys/Ordered_Resolution_Prover/Abstract_Substitution.thy --- a/thys/Ordered_Resolution_Prover/Abstract_Substitution.thy +++ b/thys/Ordered_Resolution_Prover/Abstract_Substitution.thy @@ -1,1152 +1,1186 @@ (* Title: Abstract Substitutions Author: Dmitriy Traytel , 2014 Author: Jasmin Blanchette , 2014, 2017 Author: Anders Schlichtkrull , 2016, 2017 Maintainer: Anders Schlichtkrull *) section \Abstract Substitutions\ theory Abstract_Substitution imports Clausal_Logic Map2 begin text \ Atoms and substitutions are abstracted away behind some locales, to avoid having a direct dependency on the IsaFoR library. Conventions: \'s\ substitutions, \'a\ atoms. \ subsection \Library\ lemma f_Suc_decr_eventually_const: fixes f :: "nat \ nat" assumes leq: "\i. f (Suc i) \ f i" shows "\l. \l' \ l. f l' = f (Suc l')" proof (rule ccontr) assume a: "\l. \l' \ l. f l' = f (Suc l')" have "\i. \i'. i' > i \ f i' < f i" proof fix i from a have "\l' \ i. f l' \ f (Suc l')" by auto then obtain l' where l'_p: "l' \ i \ f l' \ f (Suc l')" by metis then have "f l' > f (Suc l')" using leq le_eq_less_or_eq by auto moreover have "f i \ f l'" using leq l'_p by (induction l' arbitrary: i) (blast intro: lift_Suc_antimono_le)+ ultimately show "\i' > i. f i' < f i" using l'_p less_le_trans by blast qed then obtain g_sm :: "nat \ nat" where g_sm_p: "\i. g_sm i > i \ f (g_sm i) < f i" by metis define c :: "nat \ nat" where "\n. c n = (g_sm ^^ n) 0" have "f (c i) > f (c (Suc i))" for i by (induction i) (auto simp: c_def g_sm_p) then have "\i. (f \ c) i > (f \ c) (Suc i)" by auto then have "\fc :: nat \ nat. \i. fc i > fc (Suc i)" by metis then show False using wf_less_than by (simp add: wf_iff_no_infinite_down_chain) qed subsection \Substitution Operators\ locale substitution_ops = fixes subst_atm :: "'a \ 's \ 'a" and id_subst :: 's and comp_subst :: "'s \ 's \ 's" begin abbreviation subst_atm_abbrev :: "'a \ 's \ 'a" (infixl "\a" 67) where "subst_atm_abbrev \ subst_atm" abbreviation comp_subst_abbrev :: "'s \ 's \ 's" (infixl "\" 67) where "comp_subst_abbrev \ comp_subst" definition comp_substs :: "'s list \ 's list \ 's list" (infixl "\s" 67) where "\s \s \s = map2 comp_subst \s \s" definition subst_atms :: "'a set \ 's \ 'a set" (infixl "\as" 67) where "AA \as \ = (\A. A \a \) ` AA" definition subst_atmss :: "'a set set \ 's \ 'a set set" (infixl "\ass" 67) where "AAA \ass \ = (\AA. AA \as \) ` AAA" definition subst_atm_list :: "'a list \ 's \ 'a list" (infixl "\al" 67) where "As \al \ = map (\A. A \a \) As" definition subst_atm_mset :: "'a multiset \ 's \ 'a multiset" (infixl "\am" 67) where "AA \am \ = image_mset (\A. A \a \) AA" definition subst_atm_mset_list :: "'a multiset list \ 's \ 'a multiset list" (infixl "\aml" 67) where "AAA \aml \ = map (\AA. AA \am \) AAA" definition subst_atm_mset_lists :: "'a multiset list \ 's list \ 'a multiset list" (infixl "\\aml" 67) where "AAs \\aml \s = map2 (\am) AAs \s" definition subst_lit :: "'a literal \ 's \ 'a literal" (infixl "\l" 67) where "L \l \ = map_literal (\A. A \a \) L" lemma atm_of_subst_lit[simp]: "atm_of (L \l \) = atm_of L \a \" unfolding subst_lit_def by (cases L) simp+ definition subst_cls :: "'a clause \ 's \ 'a clause" (infixl "\" 67) where "AA \ \ = image_mset (\A. A \l \) AA" definition subst_clss :: "'a clause set \ 's \ 'a clause set" (infixl "\cs" 67) where "AA \cs \ = (\A. A \ \) ` AA" definition subst_cls_list :: "'a clause list \ 's \ 'a clause list" (infixl "\cl" 67) where "Cs \cl \ = map (\A. A \ \) Cs" definition subst_cls_lists :: "'a clause list \ 's list \ 'a clause list" (infixl "\\cl" 67) where "Cs \\cl \s = map2 (\) Cs \s" definition subst_cls_mset :: "'a clause multiset \ 's \ 'a clause multiset" (infixl "\cm" 67) where "CC \cm \ = image_mset (\A. A \ \) CC" lemma subst_cls_add_mset[simp]: "add_mset L C \ \ = add_mset (L \l \) (C \ \)" unfolding subst_cls_def by simp lemma subst_cls_mset_add_mset[simp]: "add_mset C CC \cm \ = add_mset (C \ \) (CC \cm \)" unfolding subst_cls_mset_def by simp definition generalizes_atm :: "'a \ 'a \ bool" where "generalizes_atm A B \ (\\. A \a \ = B)" definition strictly_generalizes_atm :: "'a \ 'a \ bool" where "strictly_generalizes_atm A B \ generalizes_atm A B \ \ generalizes_atm B A" definition generalizes_lit :: "'a literal \ 'a literal \ bool" where "generalizes_lit L M \ (\\. L \l \ = M)" definition strictly_generalizes_lit :: "'a literal \ 'a literal \ bool" where "strictly_generalizes_lit L M \ generalizes_lit L M \ \ generalizes_lit M L" definition generalizes_cls :: "'a clause \ 'a clause \ bool" where "generalizes_cls C D \ (\\. C \ \ = D)" definition strictly_generalizes_cls :: "'a clause \ 'a clause \ bool" where "strictly_generalizes_cls C D \ generalizes_cls C D \ \ generalizes_cls D C" definition subsumes :: "'a clause \ 'a clause \ bool" where "subsumes C D \ (\\. C \ \ \# D)" definition strictly_subsumes :: "'a clause \ 'a clause \ bool" where "strictly_subsumes C D \ subsumes C D \ \ subsumes D C" definition variants :: "'a clause \ 'a clause \ bool" where "variants C D \ generalizes_cls C D \ generalizes_cls D C" definition is_renaming :: "'s \ bool" where "is_renaming \ \ (\\. \ \ \ = id_subst)" definition is_renaming_list :: "'s list \ bool" where "is_renaming_list \s \ (\\ \ set \s. is_renaming \)" definition inv_renaming :: "'s \ 's" where "inv_renaming \ = (SOME \. \ \ \ = id_subst)" definition is_ground_atm :: "'a \ bool" where "is_ground_atm A \ (\\. A = A \a \)" definition is_ground_atms :: "'a set \ bool" where "is_ground_atms AA = (\A \ AA. is_ground_atm A)" definition is_ground_atm_list :: "'a list \ bool" where "is_ground_atm_list As \ (\A \ set As. is_ground_atm A)" definition is_ground_atm_mset :: "'a multiset \ bool" where "is_ground_atm_mset AA \ (\A. A \# AA \ is_ground_atm A)" definition is_ground_lit :: "'a literal \ bool" where "is_ground_lit L \ is_ground_atm (atm_of L)" definition is_ground_cls :: "'a clause \ bool" where "is_ground_cls C \ (\L. L \# C \ is_ground_lit L)" definition is_ground_clss :: "'a clause set \ bool" where "is_ground_clss CC \ (\C \ CC. is_ground_cls C)" definition is_ground_cls_list :: "'a clause list \ bool" where "is_ground_cls_list CC \ (\C \ set CC. is_ground_cls C)" definition is_ground_subst :: "'s \ bool" where "is_ground_subst \ \ (\A. is_ground_atm (A \a \))" definition is_ground_subst_list :: "'s list \ bool" where "is_ground_subst_list \s \ (\\ \ set \s. is_ground_subst \)" definition grounding_of_cls :: "'a clause \ 'a clause set" where "grounding_of_cls C = {C \ \ | \. is_ground_subst \}" definition grounding_of_clss :: "'a clause set \ 'a clause set" where "grounding_of_clss CC = (\C \ CC. grounding_of_cls C)" definition is_unifier :: "'s \ 'a set \ bool" where "is_unifier \ AA \ card (AA \as \) \ 1" definition is_unifiers :: "'s \ 'a set set \ bool" where "is_unifiers \ AAA \ (\AA \ AAA. is_unifier \ AA)" definition is_mgu :: "'s \ 'a set set \ bool" where "is_mgu \ AAA \ is_unifiers \ AAA \ (\\. is_unifiers \ AAA \ (\\. \ = \ \ \))" definition var_disjoint :: "'a clause list \ bool" where "var_disjoint Cs \ (\\s. length \s = length Cs \ (\\. \i < length Cs. \S. S \# Cs ! i \ S \ \s ! i = S \ \))" end subsection \Substitution Lemmas\ locale substitution = substitution_ops subst_atm id_subst comp_subst for subst_atm :: "'a \ 's \ 'a" and id_subst :: 's and comp_subst :: "'s \ 's \ 's" + fixes renamings_apart :: "'a clause list \ 's list" and atm_of_atms :: "'a list \ 'a" assumes subst_atm_id_subst[simp]: "A \a id_subst = A" and subst_atm_comp_subst[simp]: "A \a (\ \ \) = (A \a \) \a \" and subst_ext: "(\A. A \a \ = A \a \) \ \ = \" and make_ground_subst: "is_ground_cls (C \ \) \ \\. is_ground_subst \ \C \ \ = C \ \" and wf_strictly_generalizes_atm: "wfP strictly_generalizes_atm" and renamings_apart_length: "length (renamings_apart Cs) = length Cs" and renamings_apart_renaming: "\ \ set (renamings_apart Cs) \ is_renaming \" and renamings_apart_var_disjoint: "var_disjoint (Cs \\cl (renamings_apart Cs))" and atm_of_atms_subst: "\As Bs. atm_of_atms As \a \ = atm_of_atms Bs \ map (\A. A \a \) As = Bs" begin lemma subst_ext_iff: "\ = \ \ (\A. A \a \ = A \a \)" by (blast intro: subst_ext) subsubsection \Identity Substitution\ lemma id_subst_comp_subst[simp]: "id_subst \ \ = \" by (rule subst_ext) simp lemma comp_subst_id_subst[simp]: "\ \ id_subst = \" by (rule subst_ext) simp lemma id_subst_comp_substs[simp]: "replicate (length \s) id_subst \s \s = \s" using comp_substs_def by (induction \s) auto lemma comp_substs_id_subst[simp]: "\s \s replicate (length \s) id_subst = \s" using comp_substs_def by (induction \s) auto lemma subst_atms_id_subst[simp]: "AA \as id_subst = AA" unfolding subst_atms_def by simp lemma subst_atmss_id_subst[simp]: "AAA \ass id_subst = AAA" unfolding subst_atmss_def by simp lemma subst_atm_list_id_subst[simp]: "As \al id_subst = As" unfolding subst_atm_list_def by auto lemma subst_atm_mset_id_subst[simp]: "AA \am id_subst = AA" unfolding subst_atm_mset_def by simp lemma subst_atm_mset_list_id_subst[simp]: "AAs \aml id_subst = AAs" unfolding subst_atm_mset_list_def by simp lemma subst_atm_mset_lists_id_subst[simp]: "AAs \\aml replicate (length AAs) id_subst = AAs" unfolding subst_atm_mset_lists_def by (induct AAs) auto lemma subst_lit_id_subst[simp]: "L \l id_subst = L" unfolding subst_lit_def by (simp add: literal.map_ident) lemma subst_cls_id_subst[simp]: "C \ id_subst = C" unfolding subst_cls_def by simp lemma subst_clss_id_subst[simp]: "CC \cs id_subst = CC" unfolding subst_clss_def by simp lemma subst_cls_list_id_subst[simp]: "Cs \cl id_subst = Cs" unfolding subst_cls_list_def by simp lemma subst_cls_lists_id_subst[simp]: "Cs \\cl replicate (length Cs) id_subst = Cs" unfolding subst_cls_lists_def by (induct Cs) auto lemma subst_cls_mset_id_subst[simp]: "CC \cm id_subst = CC" unfolding subst_cls_mset_def by simp subsubsection \Associativity of Composition\ lemma comp_subst_assoc[simp]: "\ \ (\ \ \) = \ \ \ \ \" by (rule subst_ext) simp subsubsection \Compatibility of Substitution and Composition\ lemma subst_atms_comp_subst[simp]: "AA \as (\ \ \) = AA \as \ \as \" unfolding subst_atms_def by auto lemma subst_atmss_comp_subst[simp]: "AAA \ass (\ \ \) = AAA \ass \ \ass \" unfolding subst_atmss_def by auto lemma subst_atm_list_comp_subst[simp]: "As \al (\ \ \) = As \al \ \al \" unfolding subst_atm_list_def by auto lemma subst_atm_mset_comp_subst[simp]: "AA \am (\ \ \) = AA \am \ \am \" unfolding subst_atm_mset_def by auto lemma subst_atm_mset_list_comp_subst[simp]: "AAs \aml (\ \ \) = (AAs \aml \) \aml \" unfolding subst_atm_mset_list_def by auto lemma subst_atm_mset_lists_comp_substs[simp]: "AAs \\aml (\s \s \s) = AAs \\aml \s \\aml \s" unfolding subst_atm_mset_lists_def comp_substs_def map_zip_map map_zip_map2 map_zip_assoc by (simp add: split_def) lemma subst_lit_comp_subst[simp]: "L \l (\ \ \) = L \l \ \l \" unfolding subst_lit_def by (auto simp: literal.map_comp o_def) lemma subst_cls_comp_subst[simp]: "C \ (\ \ \) = C \ \ \ \" unfolding subst_cls_def by auto lemma subst_clsscomp_subst[simp]: "CC \cs (\ \ \) = CC \cs \ \cs \" unfolding subst_clss_def by auto lemma subst_cls_list_comp_subst[simp]: "Cs \cl (\ \ \) = Cs \cl \ \cl \" unfolding subst_cls_list_def by auto lemma subst_cls_lists_comp_substs[simp]: "Cs \\cl (\s \s \s) = Cs \\cl \s \\cl \s" unfolding subst_cls_lists_def comp_substs_def map_zip_map map_zip_map2 map_zip_assoc by (simp add: split_def) lemma subst_cls_mset_comp_subst[simp]: "CC \cm (\ \ \) = CC \cm \ \cm \" unfolding subst_cls_mset_def by auto subsubsection \``Commutativity'' of Membership and Substitution\ lemma Melem_subst_atm_mset[simp]: "A \# AA \am \ \ (\B. B \# AA \ A = B \a \)" unfolding subst_atm_mset_def by auto lemma Melem_subst_cls[simp]: "L \# C \ \ \ (\M. M \# C \ L = M \l \)" unfolding subst_cls_def by auto lemma Melem_subst_cls_mset[simp]: "AA \# CC \cm \ \ (\BB. BB \# CC \ AA = BB \ \)" unfolding subst_cls_mset_def by auto subsubsection \Signs and Substitutions\ lemma subst_lit_is_neg[simp]: "is_neg (L \l \) = is_neg L" unfolding subst_lit_def by auto lemma subst_lit_is_pos[simp]: "is_pos (L \l \) = is_pos L" unfolding subst_lit_def by auto lemma subst_minus[simp]: "(- L) \l \ = - (L \l \)" by (simp add: literal.map_sel subst_lit_def uminus_literal_def) subsubsection \Substitution on Literal(s)\ lemma eql_neg_lit_eql_atm[simp]: "(Neg A' \l \) = Neg A \ A' \a \ = A" by (simp add: subst_lit_def) lemma eql_pos_lit_eql_atm[simp]: "(Pos A' \l \) = Pos A \ A' \a \ = A" by (simp add: subst_lit_def) lemma subst_cls_negs[simp]: "(negs AA) \ \ = negs (AA \am \)" unfolding subst_cls_def subst_lit_def subst_atm_mset_def by auto lemma subst_cls_poss[simp]: "(poss AA) \ \ = poss (AA \am \)" unfolding subst_cls_def subst_lit_def subst_atm_mset_def by auto lemma atms_of_subst_atms: "atms_of C \as \ = atms_of (C \ \)" proof - have "atms_of (C \ \) = set_mset (image_mset atm_of (image_mset (map_literal (\A. A \a \)) C))" unfolding subst_cls_def subst_atms_def subst_lit_def atms_of_def by auto also have "... = set_mset (image_mset (\A. A \a \) (image_mset atm_of C))" by simp (meson literal.map_sel) finally show "atms_of C \as \ = atms_of (C \ \)" unfolding subst_atms_def atms_of_def by auto qed lemma in_image_Neg_is_neg[simp]: "L \l \ \ Neg ` AA \ is_neg L" by (metis bex_imageD literal.disc(2) literal.map_disc_iff subst_lit_def) lemma subst_lit_in_negs_subst_is_neg: "L \l \ \# (negs AA) \ \ \ is_neg L" by simp lemma subst_lit_in_negs_is_neg: "L \l \ \# negs AA \ is_neg L" by simp subsubsection \Substitution on Empty\ lemma subst_atms_empty[simp]: "{} \as \ = {}" unfolding subst_atms_def by auto lemma subst_atmss_empty[simp]: "{} \ass \ = {}" unfolding subst_atmss_def by auto lemma comp_substs_empty_iff[simp]: "\s \s \s = [] \ \s = [] \ \s = []" using comp_substs_def map2_empty_iff by auto lemma subst_atm_list_empty[simp]: "[] \al \ = []" unfolding subst_atm_list_def by auto lemma subst_atm_mset_empty[simp]: "{#} \am \ = {#}" unfolding subst_atm_mset_def by auto lemma subst_atm_mset_list_empty[simp]: "[] \aml \ = []" unfolding subst_atm_mset_list_def by auto lemma subst_atm_mset_lists_empty[simp]: "[] \\aml \s = []" unfolding subst_atm_mset_lists_def by auto lemma subst_cls_empty[simp]: "{#} \ \ = {#}" unfolding subst_cls_def by auto lemma subst_clss_empty[simp]: "{} \cs \ = {}" unfolding subst_clss_def by auto lemma subst_cls_list_empty[simp]: "[] \cl \ = []" unfolding subst_cls_list_def by auto lemma subst_cls_lists_empty[simp]: "[] \\cl \s = []" unfolding subst_cls_lists_def by auto lemma subst_scls_mset_empty[simp]: "{#} \cm \ = {#}" unfolding subst_cls_mset_def by auto lemma subst_atms_empty_iff[simp]: "AA \as \ = {} \ AA = {}" unfolding subst_atms_def by auto lemma subst_atmss_empty_iff[simp]: "AAA \ass \ = {} \ AAA = {}" unfolding subst_atmss_def by auto lemma subst_atm_list_empty_iff[simp]: "As \al \ = [] \ As = []" unfolding subst_atm_list_def by auto lemma subst_atm_mset_empty_iff[simp]: "AA \am \ = {#} \ AA = {#}" unfolding subst_atm_mset_def by auto lemma subst_atm_mset_list_empty_iff[simp]: "AAs \aml \ = [] \ AAs = []" unfolding subst_atm_mset_list_def by auto lemma subst_atm_mset_lists_empty_iff[simp]: "AAs \\aml \s = [] \ (AAs = [] \ \s = [])" using map2_empty_iff subst_atm_mset_lists_def by auto lemma subst_cls_empty_iff[simp]: "C \ \ = {#} \ C = {#}" unfolding subst_cls_def by auto lemma subst_clss_empty_iff[simp]: "CC \cs \ = {} \ CC = {}" unfolding subst_clss_def by auto lemma subst_cls_list_empty_iff[simp]: "Cs \cl \ = [] \ Cs = []" unfolding subst_cls_list_def by auto -lemma subst_cls_lists_empty_iff[simp]: "Cs \\cl \s = [] \ (Cs = [] \ \s = [])" +lemma subst_cls_lists_empty_iff[simp]: "Cs \\cl \s = [] \ Cs = [] \ \s = []" using map2_empty_iff subst_cls_lists_def by auto lemma subst_cls_mset_empty_iff[simp]: "CC \cm \ = {#} \ CC = {#}" unfolding subst_cls_mset_def by auto subsubsection \Substitution on a Union\ lemma subst_atms_union[simp]: "(AA \ BB) \as \ = AA \as \ \ BB \as \" unfolding subst_atms_def by auto lemma subst_atmss_union[simp]: "(AAA \ BBB) \ass \ = AAA \ass \ \ BBB \ass \" unfolding subst_atmss_def by auto lemma subst_atm_list_append[simp]: "(As @ Bs) \al \ = As \al \ @ Bs \al \" unfolding subst_atm_list_def by auto lemma subst_atm_mset_union[simp]: "(AA + BB) \am \ = AA \am \ + BB \am \" unfolding subst_atm_mset_def by auto lemma subst_atm_mset_list_append[simp]: "(AAs @ BBs) \aml \ = AAs \aml \ @ BBs \aml \" unfolding subst_atm_mset_list_def by auto lemma subst_cls_union[simp]: "(C + D) \ \ = C \ \ + D \ \" unfolding subst_cls_def by auto lemma subst_clss_union[simp]: "(CC \ DD) \cs \ = CC \cs \ \ DD \cs \" unfolding subst_clss_def by auto lemma subst_cls_list_append[simp]: "(Cs @ Ds) \cl \ = Cs \cl \ @ Ds \cl \" unfolding subst_cls_list_def by auto +lemma subst_cls_lists_append[simp]: + "length Cs = length \s \ length Cs' = length \s' \ + (Cs @ Cs') \\cl (\s @ \s') = Cs \\cl \s @ Cs' \\cl \s'" + unfolding subst_cls_lists_def by auto + lemma subst_cls_mset_union[simp]: "(CC + DD) \cm \ = CC \cm \ + DD \cm \" unfolding subst_cls_mset_def by auto subsubsection \Substitution on a Singleton\ lemma subst_atms_single[simp]: "{A} \as \ = {A \a \}" unfolding subst_atms_def by auto lemma subst_atmss_single[simp]: "{AA} \ass \ = {AA \as \}" unfolding subst_atmss_def by auto lemma subst_atm_list_single[simp]: "[A] \al \ = [A \a \]" unfolding subst_atm_list_def by auto lemma subst_atm_mset_single[simp]: "{#A#} \am \ = {#A \a \#}" unfolding subst_atm_mset_def by auto lemma subst_atm_mset_list[simp]: "[AA] \aml \ = [AA \am \]" unfolding subst_atm_mset_list_def by auto lemma subst_cls_single[simp]: "{#L#} \ \ = {#L \l \#}" by simp lemma subst_clss_single[simp]: "{C} \cs \ = {C \ \}" unfolding subst_clss_def by auto lemma subst_cls_list_single[simp]: "[C] \cl \ = [C \ \]" unfolding subst_cls_list_def by auto +lemma subst_cls_lists_single[simp]: "[C] \\cl [\] = [C \ \]" + unfolding subst_cls_lists_def by auto + lemma subst_cls_mset_single[simp]: "{#C#} \cm \ = {#C \ \#}" by simp subsubsection \Substitution on @{term Cons}\ lemma subst_atm_list_Cons[simp]: "(A # As) \al \ = A \a \ # As \al \" unfolding subst_atm_list_def by auto lemma subst_atm_mset_list_Cons[simp]: "(A # As) \aml \ = A \am \ # As \aml \" unfolding subst_atm_mset_list_def by auto lemma subst_atm_mset_lists_Cons[simp]: "(C # Cs) \\aml (\ # \s) = C \am \ # Cs \\aml \s" unfolding subst_atm_mset_lists_def by auto lemma subst_cls_list_Cons[simp]: "(C # Cs) \cl \ = C \ \ # Cs \cl \" unfolding subst_cls_list_def by auto lemma subst_cls_lists_Cons[simp]: "(C # Cs) \\cl (\ # \s) = C \ \ # Cs \\cl \s" unfolding subst_cls_lists_def by auto subsubsection \Substitution on @{term tl}\ -lemma subst_atm_list_tl[simp]: "tl (As \al \) = tl As \al \" - by (induction As) auto +lemma subst_atm_list_tl[simp]: "tl (As \al \) = tl As \al \" + by (cases As) auto -lemma subst_atm_mset_list_tl[simp]: "tl (AAs \aml \) = tl AAs \aml \" - by (induction AAs) auto +lemma subst_atm_mset_list_tl[simp]: "tl (AAs \aml \) = tl AAs \aml \" + by (cases AAs) auto + +lemma subst_cls_list_tl[simp]: "tl (Cs \cl \) = tl Cs \cl \" + by (cases Cs) auto + +lemma subst_cls_lists_tl[simp]: "length Cs = length \s \ tl (Cs \\cl \s) = tl Cs \\cl tl \s" + by (cases Cs; cases \s) auto subsubsection \Substitution on @{term nth}\ lemma comp_substs_nth[simp]: "length \s = length \s \ i < length \s \ (\s \s \s) ! i = (\s ! i) \ (\s ! i)" by (simp add: comp_substs_def) lemma subst_atm_list_nth[simp]: "i < length As \ (As \al \) ! i = As ! i \a \" unfolding subst_atm_list_def using less_Suc_eq_0_disj nth_map by force lemma subst_atm_mset_list_nth[simp]: "i < length AAs \ (AAs \aml \) ! i = (AAs ! i) \am \" unfolding subst_atm_mset_list_def by auto lemma subst_atm_mset_lists_nth[simp]: "length AAs = length \s \ i < length AAs \ (AAs \\aml \s) ! i = (AAs ! i) \am (\s ! i)" unfolding subst_atm_mset_lists_def by auto lemma subst_cls_list_nth[simp]: "i < length Cs \ (Cs \cl \) ! i = (Cs ! i) \ \" unfolding subst_cls_list_def using less_Suc_eq_0_disj nth_map by (induction Cs) auto lemma subst_cls_lists_nth[simp]: "length Cs = length \s \ i < length Cs \ (Cs \\cl \s) ! i = (Cs ! i) \ (\s ! i)" unfolding subst_cls_lists_def by auto subsubsection \Substitution on Various Other Functions\ lemma subst_clss_image[simp]: "image f X \cs \ = {f x \ \ | x. x \ X}" unfolding subst_clss_def by auto lemma subst_cls_mset_image_mset[simp]: "image_mset f X \cm \ = {# f x \ \. x \# X #}" unfolding subst_cls_mset_def by auto lemma mset_subst_atm_list_subst_atm_mset[simp]: "mset (As \al \) = mset (As) \am \" unfolding subst_atm_list_def subst_atm_mset_def by auto lemma mset_subst_cls_list_subst_cls_mset: "mset (Cs \cl \) = (mset Cs) \cm \" unfolding subst_cls_mset_def subst_cls_list_def by auto lemma sum_list_subst_cls_list_subst_cls[simp]: "sum_list (Cs \cl \) = sum_list Cs \ \" unfolding subst_cls_list_def by (induction Cs) auto lemma set_mset_subst_cls_mset_subst_clss: "set_mset (CC \cm \) = (set_mset CC) \cs \" by (simp add: subst_cls_mset_def subst_clss_def) lemma Neg_Melem_subst_atm_subst_cls[simp]: "Neg A \# C \ Neg (A \a \) \# C \ \ " by (metis Melem_subst_cls eql_neg_lit_eql_atm) lemma Pos_Melem_subst_atm_subst_cls[simp]: "Pos A \# C \ Pos (A \a \) \# C \ \ " by (metis Melem_subst_cls eql_pos_lit_eql_atm) lemma in_atms_of_subst[simp]: "B \ atms_of C \ B \a \ \ atms_of (C \ \)" by (metis atms_of_subst_atms image_iff subst_atms_def) subsubsection \Renamings\ lemma is_renaming_id_subst[simp]: "is_renaming id_subst" unfolding is_renaming_def by simp lemma is_renamingD: "is_renaming \ \ (\A1 A2. A1 \a \ = A2 \a \ \ A1 = A2)" by (metis is_renaming_def subst_atm_comp_subst subst_atm_id_subst) lemma inv_renaming_cancel_r[simp]: "is_renaming r \ r \ inv_renaming r = id_subst" unfolding inv_renaming_def is_renaming_def by (metis (mono_tags) someI_ex) lemma inv_renaming_cancel_r_list[simp]: "is_renaming_list rs \ rs \s map inv_renaming rs = replicate (length rs) id_subst" unfolding is_renaming_list_def by (induction rs) (auto simp add: comp_substs_def) lemma Nil_comp_substs[simp]: "[] \s s = []" unfolding comp_substs_def by auto lemma comp_substs_Nil[simp]: "s \s [] = []" unfolding comp_substs_def by auto lemma is_renaming_idempotent_id_subst: "is_renaming r \ r \ r = r \ r = id_subst" by (metis comp_subst_assoc comp_subst_id_subst inv_renaming_cancel_r) lemma is_renaming_left_id_subst_right_id_subst: "is_renaming r \ s \ r = id_subst \ r \ s = id_subst" by (metis comp_subst_assoc comp_subst_id_subst is_renaming_def) lemma is_renaming_closure: "is_renaming r1 \ is_renaming r2 \ is_renaming (r1 \ r2)" unfolding is_renaming_def by (metis comp_subst_assoc comp_subst_id_subst) lemma is_renaming_inv_renaming_cancel_atm[simp]: "is_renaming \ \ A \a \ \a inv_renaming \ = A" by (metis inv_renaming_cancel_r subst_atm_comp_subst subst_atm_id_subst) lemma is_renaming_inv_renaming_cancel_atms[simp]: "is_renaming \ \ AA \as \ \as inv_renaming \ = AA" by (metis inv_renaming_cancel_r subst_atms_comp_subst subst_atms_id_subst) lemma is_renaming_inv_renaming_cancel_atmss[simp]: "is_renaming \ \ AAA \ass \ \ass inv_renaming \ = AAA" by (metis inv_renaming_cancel_r subst_atmss_comp_subst subst_atmss_id_subst) lemma is_renaming_inv_renaming_cancel_atm_list[simp]: "is_renaming \ \ As \al \ \al inv_renaming \ = As" by (metis inv_renaming_cancel_r subst_atm_list_comp_subst subst_atm_list_id_subst) lemma is_renaming_inv_renaming_cancel_atm_mset[simp]: "is_renaming \ \ AA \am \ \am inv_renaming \ = AA" by (metis inv_renaming_cancel_r subst_atm_mset_comp_subst subst_atm_mset_id_subst) lemma is_renaming_inv_renaming_cancel_atm_mset_list[simp]: "is_renaming \ \ (AAs \aml \) \aml inv_renaming \ = AAs" by (metis inv_renaming_cancel_r subst_atm_mset_list_comp_subst subst_atm_mset_list_id_subst) lemma is_renaming_list_inv_renaming_cancel_atm_mset_lists[simp]: "length AAs = length \s \ is_renaming_list \s \ AAs \\aml \s \\aml map inv_renaming \s = AAs" - by (metis inv_renaming_cancel_r_list subst_atm_mset_lists_comp_substs subst_atm_mset_lists_id_subst) + by (metis inv_renaming_cancel_r_list subst_atm_mset_lists_comp_substs + subst_atm_mset_lists_id_subst) lemma is_renaming_inv_renaming_cancel_lit[simp]: "is_renaming \ \ (L \l \) \l inv_renaming \ = L" by (metis inv_renaming_cancel_r subst_lit_comp_subst subst_lit_id_subst) lemma is_renaming_inv_renaming_cancel_cls[simp]: "is_renaming \ \ C \ \ \ inv_renaming \ = C" by (metis inv_renaming_cancel_r subst_cls_comp_subst subst_cls_id_subst) -lemma is_renaming_inv_renaming_cancel_clss[simp]: "is_renaming \ \ CC \cs \ \cs inv_renaming \ = CC" +lemma is_renaming_inv_renaming_cancel_clss[simp]: + "is_renaming \ \ CC \cs \ \cs inv_renaming \ = CC" by (metis inv_renaming_cancel_r subst_clss_id_subst subst_clsscomp_subst) -lemma is_renaming_inv_renaming_cancel_cls_list[simp]: "is_renaming \ \ Cs \cl \ \cl inv_renaming \ = Cs" +lemma is_renaming_inv_renaming_cancel_cls_list[simp]: + "is_renaming \ \ Cs \cl \ \cl inv_renaming \ = Cs" by (metis inv_renaming_cancel_r subst_cls_list_comp_subst subst_cls_list_id_subst) lemma is_renaming_list_inv_renaming_cancel_cls_list[simp]: "length Cs = length \s \ is_renaming_list \s \ Cs \\cl \s \\cl map inv_renaming \s = Cs" by (metis inv_renaming_cancel_r_list subst_cls_lists_comp_substs subst_cls_lists_id_subst) -lemma is_renaming_inv_renaming_cancel_cls_mset[simp]: "is_renaming \ \ CC \cm \ \cm inv_renaming \ = CC" +lemma is_renaming_inv_renaming_cancel_cls_mset[simp]: + "is_renaming \ \ CC \cm \ \cm inv_renaming \ = CC" by (metis inv_renaming_cancel_r subst_cls_mset_comp_subst subst_cls_mset_id_subst) subsubsection \Monotonicity\ lemma subst_cls_mono: "set_mset C \ set_mset D \ set_mset (C \ \) \ set_mset (D \ \)" by force lemma subst_cls_mono_mset: "C \# D \ C \ \ \# D \ \" unfolding subst_clss_def by (metis mset_subset_eq_exists_conv subst_cls_union) lemma subst_subset_mono: "D \# C \ D \ \ \# C \ \" unfolding subst_cls_def by (simp add: image_mset_subset_mono) subsubsection \Size after Substitution\ lemma size_subst[simp]: "size (D \ \) = size D" unfolding subst_cls_def by auto lemma subst_atm_list_length[simp]: "length (As \al \) = length As" unfolding subst_atm_list_def by auto lemma length_subst_atm_mset_list[simp]: "length (AAs \aml \) = length AAs" unfolding subst_atm_mset_list_def by auto lemma subst_atm_mset_lists_length[simp]: "length (AAs \\aml \s) = min (length AAs) (length \s)" unfolding subst_atm_mset_lists_def by auto lemma subst_cls_list_length[simp]: "length (Cs \cl \) = length Cs" unfolding subst_cls_list_def by auto lemma comp_substs_length[simp]: "length (\s \s \s) = min (length \s) (length \s)" unfolding comp_substs_def by auto lemma subst_cls_lists_length[simp]: "length (Cs \\cl \s) = min (length Cs) (length \s)" unfolding subst_cls_lists_def by auto subsubsection \Variable Disjointness\ lemma var_disjoint_clauses: assumes "var_disjoint Cs" shows "\\s. length \s = length Cs \ (\\. Cs \\cl \s = Cs \cl \)" proof clarify fix \s :: "'s list" assume a: "length \s = length Cs" then obtain \ where "\i < length Cs. \S. S \# Cs ! i \ S \ \s ! i = S \ \" using assms unfolding var_disjoint_def by blast then have "\i < length Cs. (Cs ! i) \ \s ! i = (Cs ! i) \ \" by auto then have "Cs \\cl \s = Cs \cl \" using a by (auto intro: nth_equalityI) then show "\\. Cs \\cl \s = Cs \cl \" by auto qed subsubsection \Ground Expressions and Substitutions\ lemma ex_ground_subst: "\\. is_ground_subst \" using make_ground_subst[of "{#}"] by (simp add: is_ground_cls_def) lemma is_ground_cls_list_Cons[simp]: "is_ground_cls_list (C # Cs) = (is_ground_cls C \ is_ground_cls_list Cs)" unfolding is_ground_cls_list_def by auto paragraph \Ground union\ lemma is_ground_atms_union[simp]: "is_ground_atms (AA \ BB) \ is_ground_atms AA \ is_ground_atms BB" unfolding is_ground_atms_def by auto lemma is_ground_atm_mset_union[simp]: "is_ground_atm_mset (AA + BB) \ is_ground_atm_mset AA \ is_ground_atm_mset BB" unfolding is_ground_atm_mset_def by auto lemma is_ground_cls_union[simp]: "is_ground_cls (C + D) \ is_ground_cls C \ is_ground_cls D" unfolding is_ground_cls_def by auto lemma is_ground_clss_union[simp]: "is_ground_clss (CC \ DD) \ is_ground_clss CC \ is_ground_clss DD" unfolding is_ground_clss_def by auto lemma is_ground_cls_list_is_ground_cls_sum_list[simp]: "is_ground_cls_list Cs \ is_ground_cls (sum_list Cs)" by (meson in_mset_sum_list2 is_ground_cls_def is_ground_cls_list_def) paragraph \Ground mono\ lemma is_ground_cls_mono: "C \# D \ is_ground_cls D \ is_ground_cls C" unfolding is_ground_cls_def by (metis set_mset_mono subsetD) lemma is_ground_clss_mono: "CC \ DD \ is_ground_clss DD \ is_ground_clss CC" unfolding is_ground_clss_def by blast lemma grounding_of_clss_mono: "CC \ DD \ grounding_of_clss CC \ grounding_of_clss DD" using grounding_of_clss_def by auto lemma sum_list_subseteq_mset_is_ground_cls_list[simp]: "sum_list Cs \# sum_list Ds \ is_ground_cls_list Ds \ is_ground_cls_list Cs" by (meson in_mset_sum_list is_ground_cls_def is_ground_cls_list_is_ground_cls_sum_list is_ground_cls_mono is_ground_cls_list_def) paragraph \Substituting on ground expression preserves ground\ lemma is_ground_comp_subst[simp]: "is_ground_subst \ \ is_ground_subst (\ \ \)" unfolding is_ground_subst_def is_ground_atm_def by auto lemma ground_subst_ground_atm[simp]: "is_ground_subst \ \ is_ground_atm (A \a \)" by (simp add: is_ground_subst_def) lemma ground_subst_ground_lit[simp]: "is_ground_subst \ \ is_ground_lit (L \l \)" unfolding is_ground_lit_def subst_lit_def by (cases L) auto lemma ground_subst_ground_cls[simp]: "is_ground_subst \ \ is_ground_cls (C \ \)" unfolding is_ground_cls_def by auto lemma ground_subst_ground_clss[simp]: "is_ground_subst \ \ is_ground_clss (CC \cs \)" unfolding is_ground_clss_def subst_clss_def by auto lemma ground_subst_ground_cls_list[simp]: "is_ground_subst \ \ is_ground_cls_list (Cs \cl \)" unfolding is_ground_cls_list_def subst_cls_list_def by auto lemma ground_subst_ground_cls_lists[simp]: "\\ \ set \s. is_ground_subst \ \ is_ground_cls_list (Cs \\cl \s)" unfolding is_ground_cls_list_def subst_cls_lists_def by (auto simp: set_zip) paragraph \Substituting on ground expression has no effect\ lemma is_ground_subst_atm[simp]: "is_ground_atm A \ A \a \ = A" unfolding is_ground_atm_def by simp lemma is_ground_subst_atms[simp]: "is_ground_atms AA \ AA \as \ = AA" unfolding is_ground_atms_def subst_atms_def image_def by auto lemma is_ground_subst_atm_mset[simp]: "is_ground_atm_mset AA \ AA \am \ = AA" unfolding is_ground_atm_mset_def subst_atm_mset_def by auto lemma is_ground_subst_atm_list[simp]: "is_ground_atm_list As \ As \al \ = As" unfolding is_ground_atm_list_def subst_atm_list_def by (auto intro: nth_equalityI) lemma is_ground_subst_atm_list_member[simp]: "is_ground_atm_list As \ i < length As \ As ! i \a \ = As ! i" unfolding is_ground_atm_list_def by auto lemma is_ground_subst_lit[simp]: "is_ground_lit L \ L \l \ = L" unfolding is_ground_lit_def subst_lit_def by (cases L) simp_all lemma is_ground_subst_cls[simp]: "is_ground_cls C \ C \ \ = C" unfolding is_ground_cls_def subst_cls_def by simp lemma is_ground_subst_clss[simp]: "is_ground_clss CC \ CC \cs \ = CC" unfolding is_ground_clss_def subst_clss_def image_def by auto lemma is_ground_subst_cls_lists[simp]: assumes "length P = length Cs" and "is_ground_cls_list Cs" shows "Cs \\cl P = Cs" using assms by (metis is_ground_cls_list_def is_ground_subst_cls min.idem nth_equalityI nth_mem subst_cls_lists_nth subst_cls_lists_length) lemma is_ground_subst_lit_iff: "is_ground_lit L \ (\\. L = L \l \)" using is_ground_atm_def is_ground_lit_def subst_lit_def by (cases L) auto lemma is_ground_subst_cls_iff: "is_ground_cls C \ (\\. C = C \ \)" by (metis ex_ground_subst ground_subst_ground_cls is_ground_subst_cls) paragraph \Members of ground expressions are ground\ lemma is_ground_cls_as_atms: "is_ground_cls C \ (\A \ atms_of C. is_ground_atm A)" by (auto simp: atms_of_def is_ground_cls_def is_ground_lit_def) lemma is_ground_cls_imp_is_ground_lit: "L \# C \ is_ground_cls C \ is_ground_lit L" by (simp add: is_ground_cls_def) lemma is_ground_cls_imp_is_ground_atm: "A \ atms_of C \ is_ground_cls C \ is_ground_atm A" by (simp add: is_ground_cls_as_atms) lemma is_ground_cls_is_ground_atms_atms_of[simp]: "is_ground_cls C \ is_ground_atms (atms_of C)" by (simp add: is_ground_cls_imp_is_ground_atm is_ground_atms_def) lemma grounding_ground: "C \ grounding_of_clss M \ is_ground_cls C" unfolding grounding_of_clss_def grounding_of_cls_def by auto lemma in_subset_eq_grounding_of_clss_is_ground_cls[simp]: "C \ CC \ CC \ grounding_of_clss DD \ is_ground_cls C" unfolding grounding_of_clss_def grounding_of_cls_def by auto lemma is_ground_cls_empty[simp]: "is_ground_cls {#}" unfolding is_ground_cls_def by simp lemma grounding_of_cls_ground: "is_ground_cls C \ grounding_of_cls C = {C}" unfolding grounding_of_cls_def by (simp add: ex_ground_subst) lemma grounding_of_cls_empty[simp]: "grounding_of_cls {#} = {{#}}" by (simp add: grounding_of_cls_ground) subsubsection \Subsumption\ lemma subsumes_empty_left[simp]: "subsumes {#} C" unfolding subsumes_def subst_cls_def by simp lemma strictly_subsumes_empty_left[simp]: "strictly_subsumes {#} C \ C \ {#}" unfolding strictly_subsumes_def subsumes_def subst_cls_def by simp subsubsection \Unifiers\ lemma card_le_one_alt: "finite X \ card X \ 1 \ X = {} \ (\x. X = {x})" by (induct rule: finite_induct) auto lemma is_unifier_subst_atm_eqI: assumes "finite AA" shows "is_unifier \ AA \ A \ AA \ B \ AA \ A \a \ = B \a \" unfolding is_unifier_def subst_atms_def card_le_one_alt[OF finite_imageI[OF assms]] by (metis equals0D imageI insert_iff) lemma is_unifier_alt: assumes "finite AA" shows "is_unifier \ AA \ (\A \ AA. \B \ AA. A \a \ = B \a \)" unfolding is_unifier_def subst_atms_def card_le_one_alt[OF finite_imageI[OF assms(1)]] by (rule iffI, metis empty_iff insert_iff insert_image, blast) lemma is_unifiers_subst_atm_eqI: assumes "finite AA" "is_unifiers \ AAA" "AA \ AAA" "A \ AA" "B \ AA" shows "A \a \ = B \a \" by (metis assms is_unifiers_def is_unifier_subst_atm_eqI) theorem is_unifiers_comp: "is_unifiers \ (set_mset ` set (map2 add_mset As Bs) \ass \) \ is_unifiers (\ \ \) (set_mset ` set (map2 add_mset As Bs))" unfolding is_unifiers_def is_unifier_def subst_atmss_def by auto subsubsection \Most General Unifier\ lemma is_mgu_is_unifiers: "is_mgu \ AAA \ is_unifiers \ AAA" using is_mgu_def by blast lemma is_mgu_is_most_general: "is_mgu \ AAA \ is_unifiers \ AAA \ \\. \ = \ \ \" using is_mgu_def by blast lemma is_unifiers_is_unifier: "is_unifiers \ AAA \ AA \ AAA \ is_unifier \ AA" using is_unifiers_def by simp subsubsection \Generalization and Subsumption\ lemma variants_iff_subsumes: "variants C D \ subsumes C D \ subsumes D C" proof assume "variants C D" then show "subsumes C D \ subsumes D C" unfolding variants_def generalizes_cls_def subsumes_def by (metis subset_mset.order.refl) next assume sub: "subsumes C D \ subsumes D C" then have "size C = size D" unfolding subsumes_def by (metis antisym size_mset_mono size_subst) then show "variants C D" using sub unfolding subsumes_def variants_def generalizes_cls_def by (metis leD mset_subset_size size_mset_mono size_subst subset_mset.order.not_eq_order_implies_strict) qed lemma wf_strictly_generalizes_cls: "wfP strictly_generalizes_cls" proof - { assume "\C_at. \i. strictly_generalizes_cls (C_at (Suc i)) (C_at i)" then obtain C_at :: "nat \ 'a clause" where sg_C: "\i. strictly_generalizes_cls (C_at (Suc i)) (C_at i)" by blast define n :: nat where "n = size (C_at 0)" have sz_C: "size (C_at i) = n" for i proof (induct i) case (Suc i) then show ?case using sg_C[of i] unfolding strictly_generalizes_cls_def generalizes_cls_def subst_cls_def by (metis size_image_mset) qed (simp add: n_def) obtain \_at :: "nat \ 's" where C_\: "\i. image_mset (\L. L \l \_at i) (C_at (Suc i)) = C_at i" using sg_C[unfolded strictly_generalizes_cls_def generalizes_cls_def subst_cls_def] by metis define Ls_at :: "nat \ 'a literal list" where "Ls_at = rec_nat (SOME Ls. mset Ls = C_at 0) (\i Lsi. SOME Ls. mset Ls = C_at (Suc i) \ map (\L. L \l \_at i) Ls = Lsi)" have Ls_at_0: "Ls_at 0 = (SOME Ls. mset Ls = C_at 0)" and Ls_at_Suc: "\i. Ls_at (Suc i) = (SOME Ls. mset Ls = C_at (Suc i) \ map (\L. L \l \_at i) Ls = Ls_at i)" unfolding Ls_at_def by simp+ have mset_Lt_at_0: "mset (Ls_at 0) = C_at 0" unfolding Ls_at_0 by (rule someI_ex) (metis list_of_mset_exi) have "mset (Ls_at (Suc i)) = C_at (Suc i) \ map (\L. L \l \_at i) (Ls_at (Suc i)) = Ls_at i" for i proof (induct i) case 0 then show ?case by (simp add: Ls_at_Suc, rule someI_ex, metis C_\ image_mset_of_subset_list mset_Lt_at_0) next case Suc then show ?case by (subst (1 2) Ls_at_Suc) (rule someI_ex, metis C_\ image_mset_of_subset_list) qed note mset_Ls = this[THEN conjunct1] and Ls_\ = this[THEN conjunct2] have len_Ls: "\i. length (Ls_at i) = n" by (metis mset_Ls mset_Lt_at_0 not0_implies_Suc size_mset sz_C) have is_pos_Ls: "\i j. j < n \ is_pos (Ls_at (Suc i) ! j) \ is_pos (Ls_at i ! j)" using Ls_\ len_Ls by (metis literal.map_disc_iff nth_map subst_lit_def) have Ls_\_strict_lit: "\i \. map (\L. L \l \) (Ls_at i) \ Ls_at (Suc i)" by (metis C_\ mset_Ls Ls_\ mset_map sg_C generalizes_cls_def strictly_generalizes_cls_def subst_cls_def) have Ls_\_strict_tm: "map ((\t. t \a \) \ atm_of) (Ls_at i) \ map atm_of (Ls_at (Suc i))" for i \ proof - obtain j :: nat where j_lt: "j < n" and j_\: "Ls_at i ! j \l \ \ Ls_at (Suc i) ! j" using Ls_\_strict_lit[of \ i] len_Ls by (metis (no_types, lifting) length_map list_eq_iff_nth_eq nth_map) have "atm_of (Ls_at i ! j) \a \ \ atm_of (Ls_at (Suc i) ! j)" using j_\ is_pos_Ls[OF j_lt] by (metis (mono_guards) literal.expand literal.map_disc_iff literal.map_sel subst_lit_def) then show ?thesis using j_lt len_Ls by (metis nth_map o_apply) qed define tm_at :: "nat \ 'a" where "\i. tm_at i = atm_of_atms (map atm_of (Ls_at i))" have "\i. generalizes_atm (tm_at (Suc i)) (tm_at i)" unfolding tm_at_def generalizes_atm_def atm_of_atms_subst using Ls_\[THEN arg_cong, of "map atm_of"] by (auto simp: comp_def) moreover have "\i. \ generalizes_atm (tm_at i) (tm_at (Suc i))" unfolding tm_at_def generalizes_atm_def atm_of_atms_subst by (simp add: Ls_\_strict_tm) ultimately have "\i. strictly_generalizes_atm (tm_at (Suc i)) (tm_at i)" unfolding strictly_generalizes_atm_def by blast then have False using wf_strictly_generalizes_atm[unfolded wfP_def wf_iff_no_infinite_down_chain] by blast } then show "wfP (strictly_generalizes_cls :: 'a clause \ _ \ _)" unfolding wfP_def by (blast intro: wf_iff_no_infinite_down_chain[THEN iffD2]) qed lemma strict_subset_subst_strictly_subsumes: assumes c\_sub: "C \ \ \# D" shows "strictly_subsumes C D" by (metis c\_sub leD mset_subset_size size_mset_mono size_subst strictly_subsumes_def subset_mset.dual_order.strict_implies_order substitution_ops.subsumes_def) +lemma subsumes_refl: "subsumes C C" + unfolding subsumes_def by (rule exI[of _ id_subst]) auto + lemma subsumes_trans: "subsumes C D \ subsumes D E \ subsumes C E" unfolding subsumes_def by (metis (no_types) subset_mset.order.trans subst_cls_comp_subst subst_cls_mono_mset) +lemma strictly_subsumes_irrefl: "\ strictly_subsumes C C" + unfolding strictly_subsumes_def by blast + +lemma strictly_subsumes_antisym: "strictly_subsumes C D \ \ strictly_subsumes D C" + unfolding strictly_subsumes_def by blast + +lemma strictly_subsumes_trans: + "strictly_subsumes C D \ strictly_subsumes D E \ strictly_subsumes C E" + unfolding strictly_subsumes_def using subsumes_trans by blast + lemma subset_strictly_subsumes: "C \# D \ strictly_subsumes C D" using strict_subset_subst_strictly_subsumes[of C id_subst] by auto lemma strictly_subsumes_neq: "strictly_subsumes D' D \ D' \ D \ \" unfolding strictly_subsumes_def subsumes_def by blast lemma strictly_subsumes_has_minimum: assumes "CC \ {}" shows "\C \ CC. \D \ CC. \ strictly_subsumes D C" proof (rule ccontr) assume "\ (\C \ CC. \D\CC. \ strictly_subsumes D C)" then have "\C \ CC. \D \ CC. strictly_subsumes D C" by blast then obtain f where f_p: "\C \ CC. f C \ CC \ strictly_subsumes (f C) C" by metis from assms obtain C where C_p: "C \ CC" by auto define c :: "nat \ 'a clause" where "\n. c n = (f ^^ n) C" have incc: "c i \ CC" for i by (induction i) (auto simp: c_def f_p C_p) have ps: "\i. strictly_subsumes (c (Suc i)) (c i)" using incc f_p unfolding c_def by auto have "\i. size (c i) \ size (c (Suc i))" using ps unfolding strictly_subsumes_def subsumes_def by (metis size_mset_mono size_subst) then have lte: "\i. (size \ c) i \ (size \ c) (Suc i)" unfolding comp_def . then have "\l. \l' \ l. size (c l') = size (c (Suc l'))" using f_Suc_decr_eventually_const comp_def by auto then obtain l where l_p: "\l' \ l. size (c l') = size (c (Suc l'))" by metis then have "\l' \ l. strictly_generalizes_cls (c (Suc l')) (c l')" using ps unfolding strictly_generalizes_cls_def generalizes_cls_def - by (metis size_subst less_irrefl strictly_subsumes_def mset_subset_size - subset_mset_def subsumes_def strictly_subsumes_neq) + by (metis size_subst less_irrefl strictly_subsumes_def mset_subset_size subset_mset_def + subsumes_def strictly_subsumes_neq) then have "\i. strictly_generalizes_cls (c (Suc i + l)) (c (i + l))" unfolding strictly_generalizes_cls_def generalizes_cls_def by auto then have "\f. \i. strictly_generalizes_cls (f (Suc i)) (f i)" by (rule exI[of _ "\x. c (x + l)"]) then show False using wf_strictly_generalizes_cls wf_iff_no_infinite_down_chain[of "{(x, y). strictly_generalizes_cls x y}"] unfolding wfP_def by auto qed +lemma wf_strictly_subsumes: "wfP strictly_subsumes" + using strictly_subsumes_has_minimum by (metis equals0D wfP_eq_minimal) + end subsection \Most General Unifiers\ locale mgu = substitution subst_atm id_subst comp_subst renamings_apart atm_of_atms for subst_atm :: "'a \ 's \ 'a" and id_subst :: 's and comp_subst :: "'s \ 's \ 's" and atm_of_atms :: "'a list \ 'a" and renamings_apart :: "'a literal multiset list \ 's list" + fixes mgu :: "'a set set \ 's option" assumes mgu_sound: "finite AAA \ (\AA \ AAA. finite AA) \ mgu AAA = Some \ \ is_mgu \ AAA" and mgu_complete: "finite AAA \ (\AA \ AAA. finite AA) \ is_unifiers \ AAA \ \\. mgu AAA = Some \" begin lemmas is_unifiers_mgu = mgu_sound[unfolded is_mgu_def, THEN conjunct1] lemmas is_mgu_most_general = mgu_sound[unfolded is_mgu_def, THEN conjunct2] lemma mgu_unifier: assumes aslen: "length As = n" and aaslen: "length AAs = n" and mgu: "Some \ = mgu (set_mset ` set (map2 add_mset As AAs))" and i_lt: "i < n" and a_in: "A \# AAs ! i" shows "A \a \ = As ! i \a \" proof - from mgu have "is_mgu \ (set_mset ` set (map2 add_mset As AAs))" using mgu_sound by auto then have "is_unifiers \ (set_mset ` set (map2 add_mset As AAs))" using is_mgu_is_unifiers by auto then have "is_unifier \ (set_mset (add_mset (As ! i) (AAs ! i)))" using i_lt aslen aaslen unfolding is_unifiers_def is_unifier_def by simp (metis length_zip min.idem nth_mem nth_zip prod.case set_mset_add_mset_insert) then show ?thesis using aslen aaslen a_in is_unifier_subst_atm_eqI by (metis finite_set_mset insertCI set_mset_add_mset_insert) qed end end