(* (C) Copyright Andreas Viktor Hess, DTU, 2015-2020 All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *) (* Based on src/HOL/ex/Unification.thy packaged with Isabelle/HOL 2015 having the following license: ISABELLE COPYRIGHT NOTICE, LICENCE AND DISCLAIMER. Copyright (c) 1986-2015, University of Cambridge, Technische Universitaet Muenchen, and contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the University of Cambridge or the Technische Universitaet Muenchen nor the names of their contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *) (* Title: More_Unification.thy Author: Andreas Viktor Hess, DTU Originally based on src/HOL/ex/Unification.thy (Isabelle/HOL 2015) by: Author: Martin Coen, Cambridge University Computer Laboratory Author: Konrad Slind, TUM & Cambridge University Computer Laboratory Author: Alexander Krauss, TUM *) section \Definitions and Properties Related to Substitutions and Unification\ theory More_Unification imports Messages "First_Order_Terms.Unification" begin subsection \Substitutions\ abbreviation subst_apply_list (infix "\\<^sub>l\<^sub>i\<^sub>s\<^sub>t" 51) where "T \\<^sub>l\<^sub>i\<^sub>s\<^sub>t \ \ map (\t. t \ \) T" abbreviation subst_apply_pair (infixl "\\<^sub>p" 60) where "d \\<^sub>p \ \ (case d of (t,t') \ (t \ \, t' \ \))" abbreviation subst_apply_pair_set (infixl "\\<^sub>p\<^sub>s\<^sub>e\<^sub>t" 60) where "M \\<^sub>p\<^sub>s\<^sub>e\<^sub>t \ \ (\d. d \\<^sub>p \) ` M" definition subst_apply_pairs (infix "\\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s" 51) where "F \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \ \ map (\f. f \\<^sub>p \) F" abbreviation subst_more_general_than (infixl "\\<^sub>\" 50) where "\ \\<^sub>\ \ \ \\. \ = \ \\<^sub>s \" abbreviation subst_support (infix "supports" 50) where "\ supports \ \ (\x. \ x \ \ = \ x)" abbreviation rm_var where "rm_var v s \ s(v := Var v)" abbreviation rm_vars where "rm_vars vs \ \ (\v. if v \ vs then Var v else \ v)" definition subst_elim where "subst_elim \ v \ \t. v \ fv (t \ \)" definition subst_idem where "subst_idem s \ s \\<^sub>s s = s" lemma subst_support_def: "\ supports \ \ \ = \ \\<^sub>s \" unfolding subst_compose_def by metis lemma subst_supportD: "\ supports \ \ \ \\<^sub>\ \" using subst_support_def by auto lemma rm_vars_empty[simp]: "rm_vars {} s = s" "rm_vars (set []) s = s" by simp_all lemma rm_vars_singleton: "rm_vars {v} s = rm_var v s" by auto lemma subst_apply_terms_empty: "M \\<^sub>s\<^sub>e\<^sub>t Var = M" by simp lemma subst_agreement: "(t \ r = t \ s) \ (\v \ fv t. Var v \ r = Var v \ s)" by (induct t) auto lemma repl_invariance[dest?]: "v \ fv t \ t \ s(v := u) = t \ s" by (simp add: subst_agreement) lemma subst_idx_map: assumes "\i \ set I. i < length T" shows "(map ((!) T) I) \\<^sub>l\<^sub>i\<^sub>s\<^sub>t \ = map ((!) (map (\t. t \ \) T)) I" using assms by auto lemma subst_idx_map': assumes "\i \ fv\<^sub>s\<^sub>e\<^sub>t (set K). i < length T" shows "(K \\<^sub>l\<^sub>i\<^sub>s\<^sub>t (!) T) \\<^sub>l\<^sub>i\<^sub>s\<^sub>t \ = K \\<^sub>l\<^sub>i\<^sub>s\<^sub>t ((!) (map (\t. t \ \) T))" (is "?A = ?B") proof - have "T ! i \ \ = (map (\t. t \ \) T) ! i" when "i < length T" for i using that by auto hence "T ! i \ \ = (map (\t. t \ \) T) ! i" when "i \ fv\<^sub>s\<^sub>e\<^sub>t (set K)" for i using that assms by auto hence "k \ (!) T \ \ = k \ (!) (map (\t. t \ \) T)" when "fv k \ fv\<^sub>s\<^sub>e\<^sub>t (set K)" for k using that by (induction k) force+ thus ?thesis by auto qed lemma subst_remove_var: "v \ fv s \ v \ fv (t \ Var(v := s))" by (induct t) simp_all lemma subst_set_map: "x \ set X \ x \ s \ set (map (\x. x \ s) X)" by simp lemma subst_set_idx_map: assumes "\i \ I. i < length T" shows "(!) T ` I \\<^sub>s\<^sub>e\<^sub>t \ = (!) (map (\t. t \ \) T) ` I" (is "?A = ?B") proof have *: "T ! i \ \ = (map (\t. t \ \) T) ! i" when "i < length T" for i using that by auto show "?A \ ?B" using * assms by blast show "?B \ ?A" using * assms by auto qed lemma subst_set_idx_map': assumes "\i \ fv\<^sub>s\<^sub>e\<^sub>t K. i < length T" shows "K \\<^sub>s\<^sub>e\<^sub>t (!) T \\<^sub>s\<^sub>e\<^sub>t \ = K \\<^sub>s\<^sub>e\<^sub>t (!) (map (\t. t \ \) T)" (is "?A = ?B") proof have "T ! i \ \ = (map (\t. t \ \) T) ! i" when "i < length T" for i using that by auto hence "T ! i \ \ = (map (\t. t \ \) T) ! i" when "i \ fv\<^sub>s\<^sub>e\<^sub>t K" for i using that assms by auto hence *: "k \ (!) T \ \ = k \ (!) (map (\t. t \ \) T)" when "fv k \ fv\<^sub>s\<^sub>e\<^sub>t K" for k using that by (induction k) force+ show "?A \ ?B" using * by auto show "?B \ ?A" using * by force qed lemma subst_term_list_obtain: assumes "\i < length T. \s. P (T ! i) s \ S ! i = s \ \" and "length T = length S" shows "\U. length T = length U \ (\i < length T. P (T ! i) (U ! i)) \ S = map (\u. u \ \) U" using assms proof (induction T arbitrary: S) case (Cons t T S') then obtain s S where S': "S' = s#S" by (cases S') auto have "\i < length T. \s. P (T ! i) s \ S ! i = s \ \" "length T = length S" using Cons.prems S' by force+ then obtain U where U: "length T = length U" "\i < length T. P (T ! i) (U ! i)" "S = map (\u. u \ \) U" using Cons.IH by moura obtain u where u: "P t u" "s = u \ \" using Cons.prems(1) S' by auto have 1: "length (t#T) = length (u#U)" using Cons.prems(2) U(1) by fastforce have 2: "\i < length (t#T). P ((t#T) ! i) ((u#U) ! i)" using u(1) U(2) by (simp add: nth_Cons') have 3: "S' = map (\u. u \ \) (u#U)" using U u S' by simp show ?case using 1 2 3 by blast qed simp lemma subst_mono: "t \ u \ t \ s \ u \ s" by (induct u) auto lemma subst_mono_fv: "x \ fv t \ s x \ t \ s" by (induct t) auto lemma subst_mono_neq: assumes "t \ u" shows "t \ s \ u \ s" proof (cases u) case (Var v) hence False using \t \ u\ by simp thus ?thesis .. next case (Fun f X) then obtain x where "x \ set X" "t \ x" using \t \ u\ by auto hence "t \ s \ x \ s" using subst_mono by metis obtain Y where "Fun f X \ s = Fun f Y" by auto hence "x \ s \ set Y" using \x \ set X\ by auto hence "x \ s \ Fun f X \ s" using \Fun f X \ s = Fun f Y\ Fun_param_is_subterm by simp hence "t \ s \ Fun f X \ s" using \t \ s \ x \ s\ by (metis term.dual_order.trans term.eq_iff) thus ?thesis using \u = Fun f X\ \t \ u\ by metis qed lemma subst_no_occs[dest]: "\Var v \ t \ t \ Var(v := s) = t" by (induct t) (simp_all add: map_idI) lemma var_comp[simp]: "\ \\<^sub>s Var = \" "Var \\<^sub>s \ = \" unfolding subst_compose_def by simp_all lemma subst_comp_all: "M \\<^sub>s\<^sub>e\<^sub>t (\ \\<^sub>s \) = (M \\<^sub>s\<^sub>e\<^sub>t \) \\<^sub>s\<^sub>e\<^sub>t \" using subst_subst_compose[of _ \ \] by auto lemma subst_all_mono: "M \ M' \ M \\<^sub>s\<^sub>e\<^sub>t s \ M' \\<^sub>s\<^sub>e\<^sub>t s" by auto lemma subst_comp_set_image: "(\ \\<^sub>s \) ` X = \ ` X \\<^sub>s\<^sub>e\<^sub>t \" using subst_compose by fastforce lemma subst_ground_ident[dest?]: "fv t = {} \ t \ s = t" by (induct t, simp, metis subst_agreement empty_iff subst_apply_term_empty) lemma subst_ground_ident_compose: "fv (\ x) = {} \ (\ \\<^sub>s \) x = \ x" "fv (t \ \) = {} \ t \ (\ \\<^sub>s \) = t \ \" using subst_subst_compose[of t \ \] by (simp_all add: subst_compose_def subst_ground_ident) lemma subst_all_ground_ident[dest?]: "ground M \ M \\<^sub>s\<^sub>e\<^sub>t s = M" proof - assume "ground M" hence "\t. t \ M \ fv t = {}" by auto hence "\t. t \ M \ t \ s = t" by (metis subst_ground_ident) moreover have "\t. t \ M \ t \ s \ M \\<^sub>s\<^sub>e\<^sub>t s" by (metis imageI) ultimately show "M \\<^sub>s\<^sub>e\<^sub>t s = M" by (simp add: image_cong) qed lemma subst_eqI[intro]: "(\t. t \ \ = t \ \) \ \ = \" proof - assume "\t. t \ \ = t \ \" hence "\v. Var v \ \ = Var v \ \" by auto thus "\ = \" by auto qed lemma subst_cong: "\\ = \'; \ = \'\ \ (\ \\<^sub>s \) = (\' \\<^sub>s \')" by auto lemma subst_mgt_bot[simp]: "Var \\<^sub>\ \" by simp lemma subst_mgt_refl[simp]: "\ \\<^sub>\ \" by (metis var_comp(1)) lemma subst_mgt_trans: "\\ \\<^sub>\ \; \ \\<^sub>\ \\ \ \ \\<^sub>\ \" by (metis subst_compose_assoc) lemma subst_mgt_comp: "\ \\<^sub>\ \ \\<^sub>s \" by auto lemma subst_mgt_comp': "\ \\<^sub>s \ \\<^sub>\ \ \ \ \\<^sub>\ \" by (metis subst_compose_assoc) lemma var_self: "(\w. if w = v then Var v else Var w) = Var" using subst_agreement by auto lemma var_same[simp]: "Var(v := t) = Var \ t = Var v" by (intro iffI, metis fun_upd_same, simp add: var_self) lemma subst_eq_if_eq_vars: "(\v. (Var v) \ \ = (Var v) \ \) \ \ = \" by (auto simp add: subst_agreement) lemma subst_all_empty[simp]: "{} \\<^sub>s\<^sub>e\<^sub>t \ = {}" by simp lemma subst_all_insert:"(insert t M) \\<^sub>s\<^sub>e\<^sub>t \ = insert (t \ \) (M \\<^sub>s\<^sub>e\<^sub>t \)" by auto lemma subst_apply_fv_subset: "fv t \ V \ fv (t \ \) \ fv\<^sub>s\<^sub>e\<^sub>t (\ ` V)" by (induct t) auto lemma subst_apply_fv_empty: assumes "fv t = {}" shows "fv (t \ \) = {}" using assms subst_apply_fv_subset[of t "{}" \] by auto lemma subst_compose_fv: assumes "fv (\ x) = {}" shows "fv ((\ \\<^sub>s \) x) = {}" using assms subst_apply_fv_empty unfolding subst_compose_def by fast lemma subst_compose_fv': fixes \ \::"('a,'b) subst" assumes "y \ fv ((\ \\<^sub>s \) x)" shows "\z. z \ fv (\ x)" using assms subst_compose_fv by fast lemma subst_apply_fv_unfold: "fv (t \ \) = fv\<^sub>s\<^sub>e\<^sub>t (\ ` fv t)" by (induct t) auto lemma subst_apply_fv_unfold': "fv (t \ \) = (\v \ fv t. fv (\ v))" using subst_apply_fv_unfold by simp lemma subst_apply_fv_union: "fv\<^sub>s\<^sub>e\<^sub>t (\ ` V) \ fv (t \ \) = fv\<^sub>s\<^sub>e\<^sub>t (\ ` (V \ fv t))" proof - have "fv\<^sub>s\<^sub>e\<^sub>t (\ ` (V \ fv t)) = fv\<^sub>s\<^sub>e\<^sub>t (\ ` V) \ fv\<^sub>s\<^sub>e\<^sub>t (\ ` fv t)" by auto thus ?thesis using subst_apply_fv_unfold by metis qed lemma subst_elimI[intro]: "(\t. v \ fv (t \ \)) \ subst_elim \ v" by (auto simp add: subst_elim_def) lemma subst_elimI'[intro]: "(\w. v \ fv (Var w \ \)) \ subst_elim \ v" by (simp add: subst_elim_def subst_apply_fv_unfold') lemma subst_elimD[dest]: "subst_elim \ v \ v \ fv (t \ \)" by (auto simp add: subst_elim_def) lemma subst_elimD'[dest]: "subst_elim \ v \ \ v \ Var v" by (metis subst_elim_def subst_apply_term.simps(1) term.set_intros(3)) lemma subst_elimD''[dest]: "subst_elim \ v \ v \ fv (\ w)" by (metis subst_elim_def subst_apply_term.simps(1)) lemma subst_elim_rm_vars_dest[dest]: "subst_elim (\::('a,'b) subst) v \ v \ vs \ subst_elim (rm_vars vs \) v" proof - assume assms: "subst_elim \ v" "v \ vs" obtain f::"('a, 'b) subst \ 'b \ 'b" where "\\ v. (\w. v \ fv (Var w \ \)) = (v \ fv (Var (f \ v) \ \))" by moura hence *: "\a \. a \ fv (Var (f \ a) \ \) \ subst_elim \ a" by blast have "Var (f (rm_vars vs \) v) \ \ \ Var (f (rm_vars vs \) v) \ rm_vars vs \ \ v \ fv (Var (f (rm_vars vs \) v) \ rm_vars vs \)" using assms(1) by fastforce moreover { assume "Var (f (rm_vars vs \) v) \ \ \ Var (f (rm_vars vs \) v) \ rm_vars vs \" hence "rm_vars vs \ (f (rm_vars vs \) v) \ \ (f (rm_vars vs \) v)" by auto hence "f (rm_vars vs \) v \ vs" by meson hence ?thesis using * assms(2) by force } ultimately show ?thesis using * by blast qed lemma occs_subst_elim: "\Var v \ t \ subst_elim (Var(v := t)) v \ (Var(v := t)) = Var" proof (cases "Var v = t") assume "Var v \ t" "\Var v \ t" hence "v \ fv t" by (simp add: vars_iff_subterm_or_eq) thus ?thesis by (auto simp add: subst_remove_var) qed auto lemma occs_subst_elim': "\Var v \ t \ subst_elim (Var(v := t)) v" proof - assume "\Var v \ t" hence "v \ fv t" by (auto simp add: vars_iff_subterm_or_eq) thus "subst_elim (Var(v := t)) v" by (simp add: subst_elim_def subst_remove_var) qed lemma subst_elim_comp: "subst_elim \ v \ subst_elim (\ \\<^sub>s \) v" by (auto simp add: subst_elim_def) lemma var_subst_idem: "subst_idem Var" by (simp add: subst_idem_def) lemma var_upd_subst_idem: assumes "\Var v \ t" shows "subst_idem (Var(v := t))" unfolding subst_idem_def proof let ?\ = "Var(v := t)" from assms have t_\_id: "t \ ?\ = t" by blast fix s show "s \ (?\ \\<^sub>s ?\) = s \ ?\" unfolding subst_compose_def by (induction s, metis t_\_id fun_upd_def subst_apply_term.simps(1), simp) qed subsection \Lemmata: Domain and Range of Substitutions\ lemma range_vars_alt_def: "range_vars s \ fv\<^sub>s\<^sub>e\<^sub>t (subst_range s)" unfolding range_vars_def by simp lemma subst_dom_var_finite[simp]: "finite (subst_domain Var)" by simp lemma subst_range_Var[simp]: "subst_range Var = {}" by simp lemma range_vars_Var[simp]: "range_vars Var = {}" by fastforce lemma finite_subst_img_if_finite_dom: "finite (subst_domain \) \ finite (range_vars \)" unfolding range_vars_alt_def by auto lemma finite_subst_img_if_finite_dom': "finite (subst_domain \) \ finite (subst_range \)" by auto lemma subst_img_alt_def: "subst_range s = {t. \v. s v = t \ t \ Var v}" by (auto simp add: subst_domain_def) lemma subst_fv_img_alt_def: "range_vars s = (\t \ {t. \v. s v = t \ t \ Var v}. fv t)" unfolding range_vars_alt_def by (auto simp add: subst_domain_def) lemma subst_domI[intro]: "\ v \ Var v \ v \ subst_domain \" by (simp add: subst_domain_def) lemma subst_imgI[intro]: "\ v \ Var v \ \ v \ subst_range \" by (simp add: subst_domain_def) lemma subst_fv_imgI[intro]: "\ v \ Var v \ fv (\ v) \ range_vars \" unfolding range_vars_alt_def by auto lemma subst_domain_subst_Fun_single[simp]: "subst_domain (Var(x := Fun f T)) = {x}" (is "?A = ?B") unfolding subst_domain_def by simp lemma subst_range_subst_Fun_single[simp]: "subst_range (Var(x := Fun f T)) = {Fun f T}" (is "?A = ?B") by simp lemma range_vars_subst_Fun_single[simp]: "range_vars (Var(x := Fun f T)) = fv (Fun f T)" unfolding range_vars_alt_def by force lemma var_renaming_is_Fun_iff: assumes "subst_range \ \ range Var" shows "is_Fun t = is_Fun (t \ \)" proof (cases t) case (Var x) hence "\y. \ x = Var y" using assms by auto thus ?thesis using Var by auto qed simp lemma subst_fv_dom_img_subset: "fv t \ subst_domain \ \ fv (t \ \) \ range_vars \" unfolding range_vars_alt_def by (induct t) auto lemma subst_fv_dom_img_subset_set: "fv\<^sub>s\<^sub>e\<^sub>t M \ subst_domain \ \ fv\<^sub>s\<^sub>e\<^sub>t (M \\<^sub>s\<^sub>e\<^sub>t \) \ range_vars \" proof - assume assms: "fv\<^sub>s\<^sub>e\<^sub>t M \ subst_domain \" obtain f::"'a set \ (('b, 'a) term \ 'a set) \ ('b, 'a) terms \ ('b, 'a) term" where "\x y z. (\v. v \ z \ \ y v \ x) \ (f x y z \ z \ \ y (f x y z) \ x)" by moura hence *: "\T g A. (\ \ (g ` T) \ A \ (\t. t \ T \ g t \ A)) \ (\ (g ` T) \ A \ f A g T \ T \ \ g (f A g T) \ A)" by (metis (no_types) SUP_le_iff) hence **: "\t. t \ M \ fv t \ subst_domain \" by (metis (no_types) assms fv\<^sub>s\<^sub>e\<^sub>t.simps) have "\t::('b, 'a) term. \f T. t \ f ` T \ (\t'::('b, 'a) term. t = f t' \ t' \ T)" by blast hence "f (range_vars \) fv (M \\<^sub>s\<^sub>e\<^sub>t \) \ M \\<^sub>s\<^sub>e\<^sub>t \ \ fv (f (range_vars \) fv (M \\<^sub>s\<^sub>e\<^sub>t \)) \ range_vars \" by (metis (full_types) ** subst_fv_dom_img_subset) thus ?thesis by (metis (no_types) * fv\<^sub>s\<^sub>e\<^sub>t.simps) qed lemma subst_fv_dom_ground_if_ground_img: assumes "fv t \ subst_domain s" "ground (subst_range s)" shows "fv (t \ s) = {}" using subst_fv_dom_img_subset[OF assms(1)] assms(2) by force lemma subst_fv_dom_ground_if_ground_img': assumes "fv t \ subst_domain s" "\x. x \ subst_domain s \ fv (s x) = {}" shows "fv (t \ s) = {}" using subst_fv_dom_ground_if_ground_img[OF assms(1)] assms(2) by auto lemma subst_fv_unfold: "fv (t \ s) = (fv t - subst_domain s) \ fv\<^sub>s\<^sub>e\<^sub>t (s ` (fv t \ subst_domain s))" proof (induction t) case (Var v) thus ?case proof (cases "v \ subst_domain s") case True thus ?thesis by auto next case False hence "fv (Var v \ s) = {v}" "fv (Var v) \ subst_domain s = {}" by auto thus ?thesis by auto qed next case Fun thus ?case by auto qed lemma subst_fv_unfold_ground_img: "range_vars s = {} \ fv (t \ s) = fv t - subst_domain s" using subst_fv_unfold[of t s] unfolding range_vars_alt_def by auto lemma subst_img_update: "\\ v = Var v; t \ Var v\ \ range_vars (\(v := t)) = range_vars \ \ fv t" proof - assume "\ v = Var v" "t \ Var v" hence "(\s \ {s. \w. (\(v := t)) w = s \ s \ Var w}. fv s) = fv t \ range_vars \" unfolding range_vars_alt_def by (auto simp add: subst_domain_def) thus "range_vars (\(v := t)) = range_vars \ \ fv t" by (metis Un_commute subst_fv_img_alt_def) qed lemma subst_dom_update1: "v \ subst_domain \ \ subst_domain (\(v := Var v)) = subst_domain \" by (auto simp add: subst_domain_def) lemma subst_dom_update2: "t \ Var v \ subst_domain (\(v := t)) = insert v (subst_domain \)" by (auto simp add: subst_domain_def) lemma subst_dom_update3: "t = Var v \ subst_domain (\(v := t)) = subst_domain \ - {v}" by (auto simp add: subst_domain_def) lemma var_not_in_subst_dom[elim]: "v \ subst_domain s \ s v = Var v" by (simp add: subst_domain_def) lemma subst_dom_vars_in_subst[elim]: "v \ subst_domain s \ s v \ Var v" by (simp add: subst_domain_def) lemma subst_not_dom_fixed: "\v \ fv t; v \ subst_domain s\ \ v \ fv (t \ s)" by (induct t) auto lemma subst_not_img_fixed: "\v \ fv (t \ s); v \ range_vars s\ \ v \ fv t" unfolding range_vars_alt_def by (induct t) force+ lemma ground_range_vars[intro]: "ground (subst_range s) \ range_vars s = {}" unfolding range_vars_alt_def by metis lemma ground_subst_no_var[intro]: "ground (subst_range s) \ x \ range_vars s" using ground_range_vars[of s] by blast lemma ground_img_obtain_fun: assumes "ground (subst_range s)" "x \ subst_domain s" obtains f T where "s x = Fun f T" "Fun f T \ subst_range s" "fv (Fun f T) = {}" proof - from assms(2) obtain t where t: "s x = t" "t \ subst_range s" by moura hence "fv t = {}" using assms(1) by auto thus ?thesis using t that by (cases t) simp_all qed lemma ground_term_subst_domain_fv_subset: "fv (t \ \) = {} \ fv t \ subst_domain \" by (induct t) auto lemma ground_subst_range_empty_fv: "ground (subst_range \) \ x \ subst_domain \ \ fv (\ x) = {}" by simp lemma subst_Var_notin_img: "x \ range_vars s \ t \ s = Var x \ t = Var x" using subst_not_img_fixed[of x t s] by (induct t) auto lemma fv_in_subst_img: "\s v = t; t \ Var v\ \ fv t \ range_vars s" unfolding range_vars_alt_def by auto lemma empty_dom_iff_empty_subst: "subst_domain \ = {} \ \ = Var" by auto lemma subst_dom_cong: "(\v t. \ v = t \ \ v = t) \ subst_domain \ \ subst_domain \" by (auto simp add: subst_domain_def) lemma subst_img_cong: "(\v t. \ v = t \ \ v = t) \ range_vars \ \ range_vars \" unfolding range_vars_alt_def by (auto simp add: subst_domain_def) lemma subst_dom_elim: "subst_domain s \ range_vars s = {} \ fv (t \ s) \ subst_domain s = {}" proof (induction t) case (Var v) thus ?case using fv_in_subst_img[of s] by (cases "s v = Var v") (auto simp add: subst_domain_def) next case Fun thus ?case by auto qed lemma subst_dom_insert_finite: "finite (subst_domain s) = finite (subst_domain (s(v := t)))" proof assume "finite (subst_domain s)" have "subst_domain (s(v := t)) \ insert v (subst_domain s)" by (auto simp add: subst_domain_def) thus "finite (subst_domain (s(v := t)))" by (meson \finite (subst_domain s)\ finite_insert rev_finite_subset) next assume *: "finite (subst_domain (s(v := t)))" hence "finite (insert v (subst_domain s))" proof (cases "t = Var v") case True hence "finite (subst_domain s - {v})" by (metis * subst_dom_update3) thus ?thesis by simp qed (metis * subst_dom_update2[of t v s]) thus "finite (subst_domain s)" by simp qed lemma trm_subst_disj: "t \ \ = t \ fv t \ subst_domain \ = {}" proof (induction t) case (Fun f X) hence "map (\x. x \ \) X = X" by simp hence "\x. x \ set X \ x \ \ = x" using map_eq_conv by fastforce thus ?case using Fun.IH by auto qed (simp add: subst_domain_def) lemma trm_subst_ident[intro]: "fv t \ subst_domain \ = {} \ t \ \ = t" proof - assume "fv t \ subst_domain \ = {}" hence "\v \ fv t. \w \ subst_domain \. v \ w" by auto thus ?thesis by (metis subst_agreement subst_apply_term.simps(1) subst_apply_term_empty subst_domI) qed lemma trm_subst_ident'[intro]: "v \ subst_domain \ \ (Var v) \ \ = Var v" using trm_subst_ident by (simp add: subst_domain_def) lemma trm_subst_ident''[intro]: "(\x. x \ fv t \ \ x = Var x) \ t \ \ = t" proof - assume "\x. x \ fv t \ \ x = Var x" hence "fv t \ subst_domain \ = {}" by (auto simp add: subst_domain_def) thus ?thesis using trm_subst_ident by auto qed lemma set_subst_ident: "fv\<^sub>s\<^sub>e\<^sub>t M \ subst_domain \ = {} \ M \\<^sub>s\<^sub>e\<^sub>t \ = M" proof - assume "fv\<^sub>s\<^sub>e\<^sub>t M \ subst_domain \ = {}" hence "\t \ M. t \ \ = t" by auto thus ?thesis by force qed lemma trm_subst_ident_subterms[intro]: "fv t \ subst_domain \ = {} \ subterms t \\<^sub>s\<^sub>e\<^sub>t \ = subterms t" using set_subst_ident[of "subterms t" \] fv_subterms[of t] by simp lemma trm_subst_ident_subterms'[intro]: "v \ fv t \ subterms t \\<^sub>s\<^sub>e\<^sub>t Var(v := s) = subterms t" using trm_subst_ident_subterms[of t "Var(v := s)"] by (meson subst_no_occs trm_subst_disj vars_iff_subtermeq) lemma const_mem_subst_cases: assumes "Fun c [] \ M \\<^sub>s\<^sub>e\<^sub>t \" shows "Fun c [] \ M \ Fun c [] \ \ ` fv\<^sub>s\<^sub>e\<^sub>t M" proof - obtain m where m: "m \ M" "m \ \ = Fun c []" using assms by auto thus ?thesis by (cases m) force+ qed lemma const_mem_subst_cases': assumes "Fun c [] \ M \\<^sub>s\<^sub>e\<^sub>t \" shows "Fun c [] \ M \ Fun c [] \ subst_range \" using const_mem_subst_cases[OF assms] by force lemma fv_subterms_substI[intro]: "y \ fv t \ \ y \ subterms t \\<^sub>s\<^sub>e\<^sub>t \" using image_iff vars_iff_subtermeq by fastforce lemma fv_subterms_subst_eq[simp]: "fv\<^sub>s\<^sub>e\<^sub>t (subterms (t \ \)) = fv\<^sub>s\<^sub>e\<^sub>t (subterms t \\<^sub>s\<^sub>e\<^sub>t \)" using fv_subterms by (induct t) force+ lemma fv_subterms_set_subst: "fv\<^sub>s\<^sub>e\<^sub>t (subterms\<^sub>s\<^sub>e\<^sub>t M \\<^sub>s\<^sub>e\<^sub>t \) = fv\<^sub>s\<^sub>e\<^sub>t (subterms\<^sub>s\<^sub>e\<^sub>t (M \\<^sub>s\<^sub>e\<^sub>t \))" using fv_subterms_subst_eq[of _ \] by auto lemma fv_subterms_set_subst': "fv\<^sub>s\<^sub>e\<^sub>t (subterms\<^sub>s\<^sub>e\<^sub>t M \\<^sub>s\<^sub>e\<^sub>t \) = fv\<^sub>s\<^sub>e\<^sub>t (M \\<^sub>s\<^sub>e\<^sub>t \)" using fv_subterms_set[of "M \\<^sub>s\<^sub>e\<^sub>t \"] fv_subterms_set_subst[of \ M] by simp lemma fv_subst_subset: "x \ fv t \ fv (\ x) \ fv (t \ \)" by (metis fv_subset image_eqI subst_apply_fv_unfold) lemma fv_subst_subset': "fv s \ fv t \ fv (s \ \) \ fv (t \ \)" using fv_subst_subset by (induct s) force+ lemma fv_subst_obtain_var: fixes \::"('a,'b) subst" assumes "x \ fv (t \ \)" shows "\y \ fv t. x \ fv (\ y)" using assms by (induct t) force+ lemma set_subst_all_ident: "fv\<^sub>s\<^sub>e\<^sub>t (M \\<^sub>s\<^sub>e\<^sub>t \) \ subst_domain \ = {} \ M \\<^sub>s\<^sub>e\<^sub>t (\ \\<^sub>s \) = M \\<^sub>s\<^sub>e\<^sub>t \" by (metis set_subst_ident subst_comp_all) lemma subterms_subst: "subterms (t \ d) = (subterms t \\<^sub>s\<^sub>e\<^sub>t d) \ subterms\<^sub>s\<^sub>e\<^sub>t (d ` (fv t \ subst_domain d))" by (induct t) (auto simp add: subst_domain_def) lemma subterms_subst': fixes \::"('a,'b) subst" assumes "\x \ fv t. (\f. \ x = Fun f []) \ (\y. \ x = Var y)" shows "subterms (t \ \) = subterms t \\<^sub>s\<^sub>e\<^sub>t \" using assms proof (induction t) case (Var x) thus ?case proof (cases "x \ subst_domain \") case True hence "(\f. \ x = Fun f []) \ (\y. \ x = Var y)" using Var by simp hence "subterms (\ x) = {\ x}" by auto thus ?thesis by simp qed auto qed auto lemma subterms_subst'': fixes \::"('a,'b) subst" assumes "\x \ fv\<^sub>s\<^sub>e\<^sub>t M. (\f. \ x = Fun f []) \ (\y. \ x = Var y)" shows "subterms\<^sub>s\<^sub>e\<^sub>t (M \\<^sub>s\<^sub>e\<^sub>t \) = subterms\<^sub>s\<^sub>e\<^sub>t M \\<^sub>s\<^sub>e\<^sub>t \" using subterms_subst'[of _ \] assms by auto lemma subterms_subst_subterm: fixes \::"('a,'b) subst" assumes "\x \ fv a. (\f. \ x = Fun f []) \ (\y. \ x = Var y)" and "b \ subterms (a \ \)" shows "\c \ subterms a. c \ \ = b" using subterms_subst'[OF assms(1)] assms(2) by auto lemma subterms_subst_subset: "subterms t \\<^sub>s\<^sub>e\<^sub>t \ \ subterms (t \ \)" by (induct t) auto lemma subterms_subst_subset': "subterms\<^sub>s\<^sub>e\<^sub>t M \\<^sub>s\<^sub>e\<^sub>t \ \ subterms\<^sub>s\<^sub>e\<^sub>t (M \\<^sub>s\<^sub>e\<^sub>t \)" using subterms_subst_subset by fast lemma subterms\<^sub>s\<^sub>e\<^sub>t_subst: fixes \::"('a,'b) subst" assumes "t \ subterms\<^sub>s\<^sub>e\<^sub>t (M \\<^sub>s\<^sub>e\<^sub>t \)" shows "t \ subterms\<^sub>s\<^sub>e\<^sub>t M \\<^sub>s\<^sub>e\<^sub>t \ \ (\x \ fv\<^sub>s\<^sub>e\<^sub>t M. t \ subterms (\ x))" using assms subterms_subst[of _ \] by auto lemma rm_vars_dom: "subst_domain (rm_vars V s) = subst_domain s - V" by (auto simp add: subst_domain_def) lemma rm_vars_dom_subset: "subst_domain (rm_vars V s) \ subst_domain s" by (auto simp add: subst_domain_def) lemma rm_vars_dom_eq': "subst_domain (rm_vars (UNIV - V) s) = subst_domain s \ V" using rm_vars_dom[of "UNIV - V" s] by blast lemma rm_vars_img: "subst_range (rm_vars V s) = s ` subst_domain (rm_vars V s)" by (auto simp add: subst_domain_def) lemma rm_vars_img_subset: "subst_range (rm_vars V s) \ subst_range s" by (auto simp add: subst_domain_def) lemma rm_vars_img_fv_subset: "range_vars (rm_vars V s) \ range_vars s" unfolding range_vars_alt_def by (auto simp add: subst_domain_def) lemma rm_vars_fv_obtain: assumes "x \ fv (t \ rm_vars X \) - X" shows "\y \ fv t - X. x \ fv (rm_vars X \ y)" using assms by (induct t) (fastforce, force) lemma rm_vars_apply: "v \ subst_domain (rm_vars V s) \ (rm_vars V s) v = s v" by (auto simp add: subst_domain_def) lemma rm_vars_apply': "subst_domain \ \ vs = {} \ rm_vars vs \ = \" by force lemma rm_vars_ident: "fv t \ vs = {} \ t \ (rm_vars vs \) = t \ \" by (induct t) auto lemma rm_vars_fv_subset: "fv (t \ rm_vars X \) \ fv t \ fv (t \ \)" by (induct t) auto lemma rm_vars_fv_disj: assumes "fv t \ X = {}" "fv (t \ \) \ X = {}" shows "fv (t \ rm_vars X \) \ X = {}" using rm_vars_ident[OF assms(1)] assms(2) by auto lemma rm_vars_ground_supports: assumes "ground (subst_range \)" shows "rm_vars X \ supports \" proof fix x have *: "ground (subst_range (rm_vars X \))" using rm_vars_img_subset[of X \] assms by (auto simp add: subst_domain_def) show "rm_vars X \ x \ \ = \ x " proof (cases "x \ subst_domain (rm_vars X \)") case True hence "fv (rm_vars X \ x) = {}" using * by auto thus ?thesis using True by auto qed (simp add: subst_domain_def) qed lemma rm_vars_split: assumes "ground (subst_range \)" shows "\ = rm_vars X \ \\<^sub>s rm_vars (subst_domain \ - X) \" proof - let ?s1 = "rm_vars X \" let ?s2 = "rm_vars (subst_domain \ - X) \" have doms: "subst_domain ?s1 \ subst_domain \" "subst_domain ?s2 \ subst_domain \" by (auto simp add: subst_domain_def) { fix x assume "x \ subst_domain \" hence "\ x = Var x" "?s1 x = Var x" "?s2 x = Var x" using doms by auto hence "\ x = (?s1 \\<^sub>s ?s2) x" by (simp add: subst_compose_def) } moreover { fix x assume "x \ subst_domain \" "x \ X" hence "?s1 x = Var x" "?s2 x = \ x" using doms by auto hence "\ x = (?s1 \\<^sub>s ?s2) x" by (simp add: subst_compose_def) } moreover { fix x assume "x \ subst_domain \" "x \ X" hence "?s1 x = \ x" "fv (\ x) = {}" using assms doms by auto hence "\ x = (?s1 \\<^sub>s ?s2) x" by (simp add: subst_compose subst_ground_ident) } ultimately show ?thesis by blast qed lemma rm_vars_fv_img_disj: assumes "fv t \ X = {}" "X \ range_vars \ = {}" shows "fv (t \ rm_vars X \) \ X = {}" using assms proof (induction t) case (Var x) hence *: "(rm_vars X \) x = \ x" by auto show ?case proof (cases "x \ subst_domain \") case True hence "\ x \ subst_range \" by auto hence "fv (\ x) \ X = {}" using Var.prems(2) unfolding range_vars_alt_def by fastforce thus ?thesis using * by auto next case False thus ?thesis using Var.prems(1) by auto qed next case Fun thus ?case by auto qed lemma subst_apply_dom_ident: "t \ \ = t \ subst_domain \ \ subst_domain \ \ t \ \ = t" proof (induction t) case (Fun f T) thus ?case by (induct T) auto qed (auto simp add: subst_domain_def) lemma rm_vars_subst_apply_ident: assumes "t \ \ = t" shows "t \ (rm_vars vs \) = t" using rm_vars_dom[of vs \] subst_apply_dom_ident[OF assms, of "rm_vars vs \"] by auto lemma rm_vars_subst_eq: "t \ \ = t \ rm_vars (subst_domain \ - subst_domain \ \ fv t) \" by (auto intro: term_subst_eq) lemma rm_vars_subst_eq': "t \ \ = t \ rm_vars (UNIV - fv t) \" by (auto intro: term_subst_eq) lemma rm_vars_comp: assumes "range_vars \ \ vs = {}" shows "t \ rm_vars vs (\ \\<^sub>s \) = t \ (rm_vars vs \ \\<^sub>s rm_vars vs \)" using assms proof (induction t) case (Var x) thus ?case proof (cases "x \ vs") case True thus ?thesis using Var by auto next case False have "subst_domain (rm_vars vs \) \ vs = {}" by (auto simp add: subst_domain_def) moreover have "fv (\ x) \ vs = {}" using Var False unfolding range_vars_alt_def by force ultimately have "\ x \ (rm_vars vs \) = \ x \ \" using rm_vars_ident by (simp add: subst_domain_def) moreover have "(rm_vars vs (\ \\<^sub>s \)) x = (\ \\<^sub>s \) x" by (metis False) ultimately show ?thesis using subst_compose by auto qed next case Fun thus ?case by auto qed lemma rm_vars_fv\<^sub>s\<^sub>e\<^sub>t_subst: assumes "x \ fv\<^sub>s\<^sub>e\<^sub>t (rm_vars X \ ` Y)" shows "x \ fv\<^sub>s\<^sub>e\<^sub>t (\ ` Y) \ x \ X" using assms by auto lemma disj_dom_img_var_notin: assumes "subst_domain \ \ range_vars \ = {}" "\ v = t" "t \ Var v" shows "v \ fv t" "\v \ fv (t \ \). v \ subst_domain \" proof - have "v \ subst_domain \" "fv t \ range_vars \" using fv_in_subst_img[of \ v t, OF assms(2)] assms(2,3) by (auto simp add: subst_domain_def) thus "v \ fv t" using assms(1) by auto have *: "fv t \ subst_domain \ = {}" using assms(1) \fv t \ range_vars \\ by auto hence "t \ \ = t" by blast thus "\v \ fv (t \ \). v \ subst_domain \" using * by auto qed lemma subst_sends_dom_to_img: "v \ subst_domain \ \ fv (Var v \ \) \ range_vars \" unfolding range_vars_alt_def by auto lemma subst_sends_fv_to_img: "fv (t \ s) \ fv t \ range_vars s" proof (induction t) case (Var v) thus ?case proof (cases "Var v \ s = Var v") case True thus ?thesis by simp next case False hence "v \ subst_domain s" by (meson trm_subst_ident') hence "fv (Var v \ s) \ range_vars s" using subst_sends_dom_to_img by simp thus ?thesis by auto qed next case Fun thus ?case by auto qed lemma ident_comp_subst_trm_if_disj: assumes "subst_domain \ \ range_vars \ = {}" "v \ subst_domain \" shows "(\ \\<^sub>s \) v = \ v" proof - from assms have " subst_domain \ \ fv (\ v) = {}" using fv_in_subst_img unfolding range_vars_alt_def by auto thus "(\ \\<^sub>s \) v = \ v" unfolding subst_compose_def by blast qed lemma ident_comp_subst_trm_if_disj': "fv (\ v) \ subst_domain \ = {} \ (\ \\<^sub>s \) v = \ v" unfolding subst_compose_def by blast lemma subst_idemI[intro]: "subst_domain \ \ range_vars \ = {} \ subst_idem \" using ident_comp_subst_trm_if_disj[of \ \] var_not_in_subst_dom[of _ \] subst_eq_if_eq_vars[of \] by (metis subst_idem_def subst_compose_def var_comp(2)) lemma subst_idemI'[intro]: "ground (subst_range \) \ subst_idem \" proof (intro subst_idemI) assume "ground (subst_range \)" hence "range_vars \ = {}" by (metis ground_range_vars) thus "subst_domain \ \ range_vars \ = {}" by blast qed lemma subst_idemE: "subst_idem \ \ subst_domain \ \ range_vars \ = {}" proof - assume "subst_idem \" hence "\v. fv (\ v) \ subst_domain \ = {}" unfolding subst_idem_def subst_compose_def by (metis trm_subst_disj) thus ?thesis unfolding range_vars_alt_def by auto qed lemma subst_idem_rm_vars: "subst_idem \ \ subst_idem (rm_vars X \)" proof - assume "subst_idem \" hence "subst_domain \ \ range_vars \ = {}" by (metis subst_idemE) moreover have "subst_domain (rm_vars X \) \ subst_domain \" "range_vars (rm_vars X \) \ range_vars \" unfolding range_vars_alt_def by (auto simp add: subst_domain_def) ultimately show ?thesis by blast qed lemma subst_fv_bounded_if_img_bounded: "range_vars \ \ fv t \ V \ fv (t \ \) \ fv t \ V" proof (induction t) case (Var v) thus ?case unfolding range_vars_alt_def by (cases "\ v = Var v") auto qed (metis (no_types, lifting) Un_assoc Un_commute subst_sends_fv_to_img sup.absorb_iff2) lemma subst_fv_bound_singleton: "fv (t \ Var(v := t')) \ fv t \ fv t'" using subst_fv_bounded_if_img_bounded[of "Var(v := t')" t "fv t'"] unfolding range_vars_alt_def by (auto simp add: subst_domain_def) lemma subst_fv_bounded_if_img_bounded': assumes "range_vars \ \ fv\<^sub>s\<^sub>e\<^sub>t M" shows "fv\<^sub>s\<^sub>e\<^sub>t (M \\<^sub>s\<^sub>e\<^sub>t \) \ fv\<^sub>s\<^sub>e\<^sub>t M" proof fix v assume *: "v \ fv\<^sub>s\<^sub>e\<^sub>t (M \\<^sub>s\<^sub>e\<^sub>t \)" obtain t where t: "t \ M" "t \ \ \ M \\<^sub>s\<^sub>e\<^sub>t \" "v \ fv (t \ \)" proof - assume **: "\t. \t \ M; t \ \ \ M \\<^sub>s\<^sub>e\<^sub>t \; v \ fv (t \ \)\ \ thesis" have "v \ \ (fv ` ((\t. t \ \) ` M))" using * by (metis fv\<^sub>s\<^sub>e\<^sub>t.simps) hence "\t. t \ M \ v \ fv (t \ \)" by blast thus ?thesis using ** imageI by blast qed from \t \ M\ obtain M' where "t \ M'" "M = insert t M'" by (meson Set.set_insert) hence "fv\<^sub>s\<^sub>e\<^sub>t M = fv t \ fv\<^sub>s\<^sub>e\<^sub>t M'" by simp hence "fv (t \ \) \ fv\<^sub>s\<^sub>e\<^sub>t M" using subst_fv_bounded_if_img_bounded assms by simp thus "v \ fv\<^sub>s\<^sub>e\<^sub>t M" using assms \v \ fv (t \ \)\ by auto qed lemma ground_img_if_ground_subst: "(\v t. s v = t \ fv t = {}) \ range_vars s = {}" unfolding range_vars_alt_def by auto lemma ground_subst_fv_subset: "ground (subst_range \) \ fv (t \ \) \ fv t" using subst_fv_bounded_if_img_bounded[of \] unfolding range_vars_alt_def by force lemma ground_subst_fv_subset': "ground (subst_range \) \ fv\<^sub>s\<^sub>e\<^sub>t (M \\<^sub>s\<^sub>e\<^sub>t \) \ fv\<^sub>s\<^sub>e\<^sub>t M" using subst_fv_bounded_if_img_bounded'[of \ M] unfolding range_vars_alt_def by auto lemma subst_to_var_is_var[elim]: "t \ s = Var v \ \w. t = Var w" using subst_apply_term.elims by blast lemma subst_dom_comp_inI: assumes "y \ subst_domain \" and "y \ subst_domain \" shows "y \ subst_domain (\ \\<^sub>s \)" using assms subst_domain_subst_compose[of \ \] by blast lemma subst_comp_notin_dom_eq: "x \ subst_domain \1 \ (\1 \\<^sub>s \2) x = \2 x" unfolding subst_compose_def by fastforce lemma subst_dom_comp_eq: assumes "subst_domain \ \ range_vars \ = {}" shows "subst_domain (\ \\<^sub>s \) = subst_domain \ \ subst_domain \" proof (rule ccontr) assume "subst_domain (\ \\<^sub>s \) \ subst_domain \ \ subst_domain \" hence "subst_domain (\ \\<^sub>s \) \ subst_domain \ \ subst_domain \" using subst_domain_compose[of \ \] by (simp add: subst_domain_def) then obtain v where "v \ subst_domain (\ \\<^sub>s \)" "v \ subst_domain \ \ subst_domain \" by auto hence v_in_some_subst: "\ v \ Var v \ \ v \ Var v" and "\ v \ \ = Var v" unfolding subst_compose_def by (auto simp add: subst_domain_def) then obtain w where "\ v = Var w" using subst_to_var_is_var by fastforce show False proof (cases "v = w") case True hence "\ v = Var v" using \\ v = Var w\ by simp hence "\ v \ Var v" using v_in_some_subst by simp thus False using \\ v = Var v\ \\ v \ \ = Var v\ by simp next case False hence "v \ subst_domain \" using v_in_some_subst \\ v \ \ = Var v\ by auto hence "v \ range_vars \" using assms by auto moreover have "\ w = Var v" using \\ v \ \ = Var v\ \\ v = Var w\ by simp hence "v \ range_vars \" using \v \ w\ subst_fv_imgI[of \ w] by simp ultimately show False .. qed qed lemma subst_img_comp_subset[simp]: "range_vars (\1 \\<^sub>s \2) \ range_vars \1 \ range_vars \2" proof let ?img = "range_vars" fix x assume "x \ ?img (\1 \\<^sub>s \2)" then obtain v t where vt: "x \ fv t" "t = (\1 \\<^sub>s \2) v" "t \ Var v" unfolding range_vars_alt_def subst_compose_def by (auto simp add: subst_domain_def) { assume "x \ ?img \1" hence "x \ ?img \2" by (metis (no_types, opaque_lifting) fv_in_subst_img Un_iff subst_compose_def vt subsetCE subst_apply_term.simps(1) subst_sends_fv_to_img) } thus "x \ ?img \1 \ ?img \2" by auto qed lemma subst_img_comp_subset': assumes "t \ subst_range (\1 \\<^sub>s \2)" shows "t \ subst_range \2 \ (\t' \ subst_range \1. t = t' \ \2)" proof - obtain x where x: "x \ subst_domain (\1 \\<^sub>s \2)" "(\1 \\<^sub>s \2) x = t" "t \ Var x" using assms by (auto simp add: subst_domain_def) { assume "x \ subst_domain \1" hence "(\1 \\<^sub>s \2) x = \2 x" unfolding subst_compose_def by auto hence ?thesis using x by auto } moreover { assume "x \ subst_domain \1" hence ?thesis using subst_compose x(2) by fastforce } ultimately show ?thesis by metis qed lemma subst_img_comp_subset'': "subterms\<^sub>s\<^sub>e\<^sub>t (subst_range (\1 \\<^sub>s \2)) \ subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \2) \ ((subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \1)) \\<^sub>s\<^sub>e\<^sub>t \2)" proof fix t assume "t \ subterms\<^sub>s\<^sub>e\<^sub>t (subst_range (\1 \\<^sub>s \2))" then obtain x where x: "x \ subst_domain (\1 \\<^sub>s \2)" "t \ subterms ((\1 \\<^sub>s \2) x)" by auto show "t \ subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \2) \ (subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \1) \\<^sub>s\<^sub>e\<^sub>t \2)" proof (cases "x \ subst_domain \1") case True thus ?thesis using subst_compose[of \1 \2] x(2) subterms_subst by fastforce next case False hence "(\1 \\<^sub>s \2) x = \2 x" unfolding subst_compose_def by auto thus ?thesis using x by (auto simp add: subst_domain_def) qed qed lemma subst_img_comp_subset''': "subterms\<^sub>s\<^sub>e\<^sub>t (subst_range (\1 \\<^sub>s \2)) - range Var \ subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \2) - range Var \ ((subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \1) - range Var) \\<^sub>s\<^sub>e\<^sub>t \2)" proof fix t assume t: "t \ subterms\<^sub>s\<^sub>e\<^sub>t (subst_range (\1 \\<^sub>s \2)) - range Var" then obtain f T where fT: "t = Fun f T" by (cases t) simp_all then obtain x where x: "x \ subst_domain (\1 \\<^sub>s \2)" "Fun f T \ subterms ((\1 \\<^sub>s \2) x)" using t by auto have "Fun f T \ subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \2) \ (subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \1) - range Var \\<^sub>s\<^sub>e\<^sub>t \2)" proof (cases "x \ subst_domain \1") case True hence "Fun f T \ (subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \2)) \ (subterms (\1 x) \\<^sub>s\<^sub>e\<^sub>t \2)" using x(2) subterms_subst[of "\1 x" \2] unfolding subst_compose[of \1 \2 x] by auto moreover have ?thesis when *: "Fun f T \ subterms (\1 x) \\<^sub>s\<^sub>e\<^sub>t \2" proof - obtain s where s: "s \ subterms (\1 x)" "Fun f T = s \ \2" using * by moura show ?thesis proof (cases s) case (Var y) hence "Fun f T \ subst_range \2" using s by force thus ?thesis by blast next case (Fun g S) hence "Fun f T \ (subterms (\1 x) - range Var) \\<^sub>s\<^sub>e\<^sub>t \2" using s by blast thus ?thesis using True by auto qed qed ultimately show ?thesis by blast next case False hence "(\1 \\<^sub>s \2) x = \2 x" unfolding subst_compose_def by auto thus ?thesis using x by (auto simp add: subst_domain_def) qed thus "t \ subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \2) - range Var \ (subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \1) - range Var \\<^sub>s\<^sub>e\<^sub>t \2)" using fT by auto qed lemma subst_img_comp_subset_const: assumes "Fun c [] \ subst_range (\1 \\<^sub>s \2)" shows "Fun c [] \ subst_range \2 \ Fun c [] \ subst_range \1 \ (\x. Var x \ subst_range \1 \ \2 x = Fun c [])" proof (cases "Fun c [] \ subst_range \2") case False then obtain t where t: "t \ subst_range \1" "Fun c [] = t \ \2" using subst_img_comp_subset'[OF assms] by auto thus ?thesis by (cases t) auto qed (simp add: subst_img_comp_subset'[OF assms]) lemma subst_img_comp_subset_const': fixes \ \::"('f,'v) subst" assumes "(\ \\<^sub>s \) x = Fun c []" shows "\ x = Fun c [] \ (\z. \ x = Var z \ \ z = Fun c [])" proof (cases "\ x = Fun c []") case False then obtain t where "\ x = t" "t \ \ = Fun c []" using assms unfolding subst_compose_def by auto thus ?thesis by (cases t) auto qed simp lemma subst_img_comp_subset_ground: assumes "ground (subst_range \1)" shows "subst_range (\1 \\<^sub>s \2) \ subst_range \1 \ subst_range \2" proof fix t assume t: "t \ subst_range (\1 \\<^sub>s \2)" then obtain x where x: "x \ subst_domain (\1 \\<^sub>s \2)" "t = (\1 \\<^sub>s \2) x" by auto show "t \ subst_range \1 \ subst_range \2" proof (cases "x \ subst_domain \1") case True hence "fv (\1 x) = {}" using assms ground_subst_range_empty_fv by fast hence "t = \1 x" using x(2) unfolding subst_compose_def by blast thus ?thesis using True by simp next case False hence "t = \2 x" "x \ subst_domain \2" using x subst_domain_compose[of \1 \2] by (metis subst_comp_notin_dom_eq, blast) thus ?thesis using x by simp qed qed lemma subst_fv_dom_img_single: assumes "v \ fv t" "\ v = t" "\w. v \ w \ \ w = Var w" shows "subst_domain \ = {v}" "range_vars \ = fv t" proof - show "subst_domain \ = {v}" using assms by (fastforce simp add: subst_domain_def) have "fv t \ range_vars \" by (metis fv_in_subst_img assms(1,2) vars_iff_subterm_or_eq) moreover have "\v. \ v \ Var v \ \ v = t" using assms by fastforce ultimately show "range_vars \ = fv t" unfolding range_vars_alt_def by (auto simp add: subst_domain_def) qed lemma subst_comp_upd1: "\(v := t) \\<^sub>s \ = (\ \\<^sub>s \)(v := t \ \)" unfolding subst_compose_def by auto lemma subst_comp_upd2: assumes "v \ subst_domain s" "v \ range_vars s" shows "s(v := t) = s \\<^sub>s (Var(v := t))" unfolding subst_compose_def proof - { fix w have "(s(v := t)) w = s w \ Var(v := t)" proof (cases "w = v") case True hence "s w = Var w" using \v \ subst_domain s\ by (simp add: subst_domain_def) thus ?thesis using \w = v\ by simp next case False hence "(s(v := t)) w = s w" by simp moreover have "s w \ Var(v := t) = s w" using \w \ v\ \v \ range_vars s\ by (metis fv_in_subst_img fun_upd_apply insert_absorb insert_subset repl_invariance subst_apply_term.simps(1) subst_apply_term_empty) ultimately show ?thesis .. qed } thus "s(v := t) = (\w. s w \ Var(v := t))" by auto qed lemma ground_subst_dom_iff_img: "ground (subst_range \) \ x \ subst_domain \ \ \ x \ subst_range \" by (auto simp add: subst_domain_def) lemma finite_dom_subst_exists: "finite S \ \\::('f,'v) subst. subst_domain \ = S" proof (induction S rule: finite.induct) case (insertI A a) then obtain \::"('f,'v) subst" where "subst_domain \ = A" by blast fix f::'f have "subst_domain (\(a := Fun f [])) = insert a A" using \subst_domain \ = A\ by (auto simp add: subst_domain_def) thus ?case by metis qed (auto simp add: subst_domain_def) lemma subst_inj_is_bij_betw_dom_img_if_ground_img: assumes "ground (subst_range \)" shows "inj \ \ bij_betw \ (subst_domain \) (subst_range \)" (is "?A \ ?B") proof show "?A \ ?B" by (metis bij_betw_def injD inj_onI subst_range.simps) next assume ?B hence "inj_on \ (subst_domain \)" unfolding bij_betw_def by auto moreover have "\x. x \ UNIV - subst_domain \ \ \ x = Var x" by auto hence "inj_on \ (UNIV - subst_domain \)" using inj_onI[of "UNIV - subst_domain \"] by (metis term.inject(1)) moreover have "\x y. x \ subst_domain \ \ y \ subst_domain \ \ \ x \ \ y" using assms by (auto simp add: subst_domain_def) ultimately show ?A by (metis injI inj_onD subst_domI term.inject(1)) qed lemma bij_finite_ground_subst_exists: assumes "finite (S::'v set)" "infinite (U::('f,'v) term set)" "ground U" shows "\\::('f,'v) subst. subst_domain \ = S \ bij_betw \ (subst_domain \) (subst_range \) \ subst_range \ \ U" proof - obtain T' where "T' \ U" "card T' = card S" "finite T'" by (meson assms(2) finite_Diff2 infinite_arbitrarily_large) then obtain f::"'v \ ('f,'v) term" where f_bij: "bij_betw f S T'" using finite_same_card_bij[OF assms(1)] by metis hence *: "\v. v \ S \ f v \ Var v" using \ground U\ \T' \ U\ bij_betwE by fastforce let ?\ = "\v. if v \ S then f v else Var v" have "subst_domain ?\ = S" proof show "subst_domain ?\ \ S" by (auto simp add: subst_domain_def) { fix v assume "v \ S" "v \ subst_domain ?\" hence "f v = Var v" by (simp add: subst_domain_def) hence False using *[OF \v \ S\] by metis } thus "S \ subst_domain ?\" by blast qed hence "\v w. \v \ subst_domain ?\; w \ subst_domain ?\\ \ ?\ w \ ?\ v" using \ground U\ bij_betwE[OF f_bij] set_rev_mp[OF _ \T' \ U\] by (metis (no_types, lifting) UN_iff empty_iff vars_iff_subterm_or_eq fv\<^sub>s\<^sub>e\<^sub>t.simps) hence "inj_on ?\ (subst_domain ?\)" using f_bij \subst_domain ?\ = S\ unfolding bij_betw_def inj_on_def by metis hence "bij_betw ?\ (subst_domain ?\) (subst_range ?\)" using inj_on_imp_bij_betw[of ?\] by simp moreover have "subst_range ?\ = T'" using \bij_betw f S T'\ \subst_domain ?\ = S\ unfolding bij_betw_def by auto hence "subst_range ?\ \ U" using \T' \ U\ by auto ultimately show ?thesis using \subst_domain ?\ = S\ by (metis (lifting)) qed lemma bij_finite_const_subst_exists: assumes "finite (S::'v set)" "finite (T::'f set)" "infinite (U::'f set)" shows "\\::('f,'v) subst. subst_domain \ = S \ bij_betw \ (subst_domain \) (subst_range \) \ subst_range \ \ (\c. Fun c []) ` (U - T)" proof - obtain T' where "T' \ U - T" "card T' = card S" "finite T'" by (meson assms(2,3) finite_Diff2 infinite_arbitrarily_large) then obtain f::"'v \ 'f" where f_bij: "bij_betw f S T'" using finite_same_card_bij[OF assms(1)] by metis let ?\ = "\v. if v \ S then Fun (f v) [] else Var v" have "subst_domain ?\ = S" by (simp add: subst_domain_def) moreover have "\v w. \v \ subst_domain ?\; w \ subst_domain ?\\ \ ?\ w \ ?\ v" by auto hence "inj_on ?\ (subst_domain ?\)" using f_bij unfolding bij_betw_def inj_on_def by (metis \subst_domain ?\ = S\ term.inject(2)) hence "bij_betw ?\ (subst_domain ?\) (subst_range ?\)" using inj_on_imp_bij_betw[of ?\] by simp moreover have "subst_range ?\ = ((\c. Fun c []) ` T')" using \bij_betw f S T'\ unfolding bij_betw_def inj_on_def by (auto simp add: subst_domain_def) hence "subst_range ?\ \ ((\c. Fun c []) ` (U - T))" using \T' \ U - T\ by auto ultimately show ?thesis by (metis (lifting)) qed lemma bij_finite_const_subst_exists': assumes "finite (S::'v set)" "finite (T::('f,'v) terms)" "infinite (U::'f set)" shows "\\::('f,'v) subst. subst_domain \ = S \ bij_betw \ (subst_domain \) (subst_range \) \ subst_range \ \ ((\c. Fun c []) ` U) - T" proof - have "finite (\(funs_term ` T))" using assms(2) by auto then obtain \ where \: "subst_domain \ = S" "bij_betw \ (subst_domain \) (subst_range \)" "subst_range \ \ (\c. Fun c []) ` (U - (\(funs_term ` T)))" using bij_finite_const_subst_exists[OF assms(1) _ assms(3)] by blast moreover have "(\c. Fun c []) ` (U - (\(funs_term ` T))) \ ((\c. Fun c []) ` U) - T" by auto ultimately show ?thesis by blast qed lemma bij_betw_iteI: assumes "bij_betw f A B" "bij_betw g C D" "A \ C = {}" "B \ D = {}" shows "bij_betw (\x. if x \ A then f x else g x) (A \ C) (B \ D)" proof - have "bij_betw (\x. if x \ A then f x else g x) A B" by (metis bij_betw_cong[of A f "\x. if x \ A then f x else g x" B] assms(1)) moreover have "bij_betw (\x. if x \ A then f x else g x) C D" using bij_betw_cong[of C g "\x. if x \ A then f x else g x" D] assms(2,3) by force ultimately show ?thesis using bij_betw_combine[OF _ _ assms(4)] by metis qed lemma subst_comp_split: assumes "subst_domain \ \ range_vars \ = {}" shows "\ = (rm_vars (subst_domain \ - V) \) \\<^sub>s (rm_vars V \)" (is ?P) and "\ = (rm_vars V \) \\<^sub>s (rm_vars (subst_domain \ - V) \)" (is ?Q) proof - let ?rm1 = "rm_vars (subst_domain \ - V) \" and ?rm2 = "rm_vars V \" have "subst_domain ?rm2 \ range_vars ?rm1 = {}" "subst_domain ?rm1 \ range_vars ?rm2 = {}" using assms unfolding range_vars_alt_def by (force simp add: subst_domain_def)+ hence *: "\v. v \ subst_domain ?rm1 \ (?rm1 \\<^sub>s ?rm2) v = \ v" "\v. v \ subst_domain ?rm2 \ (?rm2 \\<^sub>s ?rm1) v = \ v" using ident_comp_subst_trm_if_disj[of ?rm2 ?rm1] ident_comp_subst_trm_if_disj[of ?rm1 ?rm2] by (auto simp add: subst_domain_def) hence "\v. v \ subst_domain ?rm1 \ (?rm1 \\<^sub>s ?rm2) v = \ v" "\v. v \ subst_domain ?rm2 \ (?rm2 \\<^sub>s ?rm1) v = \ v" unfolding subst_compose_def by (auto simp add: subst_domain_def) hence "\v. (?rm1 \\<^sub>s ?rm2) v = \ v" "\v. (?rm2 \\<^sub>s ?rm1) v = \ v" using * by blast+ thus ?P ?Q by auto qed lemma subst_comp_eq_if_disjoint_vars: assumes "(subst_domain \ \ range_vars \) \ (subst_domain \ \ range_vars \) = {}" shows "\ \\<^sub>s \ = \ \\<^sub>s \" proof - { fix x assume "x \ subst_domain \" hence "(\ \\<^sub>s \) x = \ x" "(\ \\<^sub>s \) x = \ x" using assms unfolding range_vars_alt_def by (force simp add: subst_compose)+ hence "(\ \\<^sub>s \) x = (\ \\<^sub>s \) x" by metis } moreover { fix x assume "x \ subst_domain \" hence "(\ \\<^sub>s \) x = \ x" "(\ \\<^sub>s \) x = \ x" using assms unfolding range_vars_alt_def by (auto simp add: subst_compose subst_domain_def) hence "(\ \\<^sub>s \) x = (\ \\<^sub>s \) x" by metis } moreover { fix x assume "x \ subst_domain \" "x \ subst_domain \" hence "(\ \\<^sub>s \) x = (\ \\<^sub>s \) x" by (simp add: subst_compose subst_domain_def) } ultimately show ?thesis by auto qed lemma subst_eq_if_disjoint_vars_ground: fixes \ \::"('f,'v) subst" assumes "subst_domain \ \ subst_domain \ = {}" "ground (subst_range \)" "ground (subst_range \)" shows "t \ \ \ \ = t \ \ \ \" by (metis assms subst_comp_eq_if_disjoint_vars range_vars_alt_def subst_subst_compose sup_bot.right_neutral) lemma subst_img_bound: "subst_domain \ \ range_vars \ \ fv t \ range_vars \ \ fv (t \ \)" proof - assume "subst_domain \ \ range_vars \ \ fv t" hence "subst_domain \ \ fv t" by blast thus ?thesis by (metis (no_types) range_vars_alt_def le_iff_sup subst_apply_fv_unfold subst_apply_fv_union subst_range.simps) qed lemma subst_all_fv_subset: "fv t \ fv\<^sub>s\<^sub>e\<^sub>t M \ fv (t \ \) \ fv\<^sub>s\<^sub>e\<^sub>t (M \\<^sub>s\<^sub>e\<^sub>t \)" proof - assume *: "fv t \ fv\<^sub>s\<^sub>e\<^sub>t M" { fix v assume "v \ fv t" hence "v \ fv\<^sub>s\<^sub>e\<^sub>t M" using * by auto then obtain t' where "t' \ M" "v \ fv t'" by auto hence "fv (\ v) \ fv (t' \ \)" by (metis subst_apply_term.simps(1) subst_apply_fv_subset subst_apply_fv_unfold subtermeq_vars_subset vars_iff_subtermeq) hence "fv (\ v) \ fv\<^sub>s\<^sub>e\<^sub>t (M \\<^sub>s\<^sub>e\<^sub>t \)" using \t' \ M\ by auto } thus ?thesis using subst_apply_fv_unfold[of t \] by auto qed lemma subst_support_if_mgt_subst_idem: assumes "\ \\<^sub>\ \" "subst_idem \" shows "\ supports \" proof - from \\ \\<^sub>\ \\ obtain \ where \: "\ = \ \\<^sub>s \" by blast hence "\v. \ v \ \ = Var v \ (\ \\<^sub>s \ \\<^sub>s \)" by simp hence "\v. \ v \ \ = Var v \ (\ \\<^sub>s \)" using \subst_idem \ \ unfolding subst_idem_def by simp hence "\v. \ v \ \ = Var v \ \" using \ by simp thus "\ supports \" by simp qed lemma subst_support_iff_mgt_if_subst_idem: assumes "subst_idem \" shows "\ \\<^sub>\ \ \ \ supports \" proof show "\ \\<^sub>\ \ \ \ supports \" by (fact subst_support_if_mgt_subst_idem[OF _ \subst_idem \\]) show "\ supports \ \ \ \\<^sub>\ \" by (fact subst_supportD) qed lemma subst_support_comp: fixes \ \ \::"('a,'b) subst" assumes "\ supports \" "\ supports \" shows "(\ \\<^sub>s \) supports \" by (metis (no_types) assms subst_agreement subst_apply_term.simps(1) subst_subst_compose) lemma subst_support_comp': fixes \ \ \::"('a,'b) subst" assumes "\ supports \" shows "\ supports (\ \\<^sub>s \)" "\ supports \ \ \ supports (\ \\<^sub>s \)" using assms unfolding subst_support_def by (metis subst_compose_assoc, metis) lemma subst_support_comp_split: fixes \ \ \::"('a,'b) subst" assumes "(\ \\<^sub>s \) supports \" shows "subst_domain \ \ range_vars \ = {} \ \ supports \" and "subst_domain \ \ subst_domain \ = {} \ \ supports \" proof - assume "subst_domain \ \ range_vars \ = {}" hence "subst_idem \" by (metis subst_idemI) have "\ \\<^sub>\ \" using assms subst_compose_assoc[of \ \ \] unfolding subst_compose_def by metis show "\ supports \" using subst_support_if_mgt_subst_idem[OF \\ \\<^sub>\ \\ \subst_idem \\] by auto next assume "subst_domain \ \ subst_domain \ = {}" moreover have "\v \ subst_domain (\ \\<^sub>s \). (\ \\<^sub>s \) v \ \ = \ v" using assms by metis ultimately have "\v \ subst_domain \. \ v \ \ = \ v" using var_not_in_subst_dom unfolding subst_compose_def by (metis IntI empty_iff subst_apply_term.simps(1)) thus "\ supports \" by force qed lemma subst_idem_support: "subst_idem \ \ \ supports \ \\<^sub>s \" unfolding subst_idem_def by (metis subst_support_def subst_compose_assoc) lemma subst_idem_iff_self_support: "subst_idem \ \ \ supports \" using subst_support_def[of \ \] unfolding subst_idem_def by auto lemma subterm_subst_neq: "t \ t' \ t \ s \ t' \ s" by (metis subst_mono_neq) lemma fv_Fun_subst_neq: "x \ fv (Fun f T) \ \ x \ Fun f T \ \" using subterm_subst_neq[of "Var x" "Fun f T"] vars_iff_subterm_or_eq[of x "Fun f T"] by auto lemma subterm_subst_unfold: assumes "t \ s \ \" shows "(\s'. s' \ s \ t = s' \ \) \ (\x \ fv s. t \ \ x)" using assms proof (induction s) case (Fun f T) thus ?case proof (cases "t = Fun f T \ \") case True thus ?thesis using Fun by auto next case False then obtain s' where s': "s' \ set T" "t \ s' \ \" using Fun by auto hence "(\s''. s'' \ s' \ t = s'' \ \) \ (\x \ fv s'. t \ \ x)" by (metis Fun.IH) thus ?thesis using s'(1) by auto qed qed simp lemma subterm_subst_img_subterm: assumes "t \ s \ \" "\s'. s' \ s \ t \ s' \ \" shows "\w \ fv s. t \ \ w" using subterm_subst_unfold[OF assms(1)] assms(2) by force lemma subterm_subst_not_img_subterm: assumes "t \ s \ \" "\(\w \ fv s. t \ \ w)" shows "\f T. Fun f T \ s \ t = Fun f T \ \" proof (rule ccontr) assume "\(\f T. Fun f T \ s \ t = Fun f T \ \)" hence "\f T. Fun f T \ s \ t \ Fun f T \ \" by simp moreover have "\x. Var x \ s \ t \ Var x \ \" using assms(2) vars_iff_subtermeq by force ultimately have "\s'. s' \ s \ t \ s' \ \" by (metis "term.exhaust") thus False using assms subterm_subst_img_subterm by blast qed lemma subst_apply_img_var: assumes "v \ fv (t \ \)" "v \ fv t" obtains w where "w \ fv t" "v \ fv (\ w)" using assms by (induct t) auto lemma subst_apply_img_var': assumes "x \ fv (t \ \)" "x \ fv t" shows "\y \ fv t. x \ fv (\ y)" by (metis assms subst_apply_img_var) lemma nth_map_subst: fixes \::"('f,'v) subst" and T::"('f,'v) term list" and i::nat shows "i < length T \ (map (\t. t \ \) T) ! i = (T ! i) \ \" by (fact nth_map) lemma subst_subterm: assumes "Fun f T \ t \ \" shows "(\S. Fun f S \ t \ Fun f S \ \ = Fun f T) \ (\s \ subst_range \. Fun f T \ s)" using assms subterm_subst_not_img_subterm by (cases "\s \ subst_range \. Fun f T \ s") fastforce+ lemma subst_subterm': assumes "Fun f T \ t \ \" shows "\S. length S = length T \ (Fun f S \ t \ (\s \ subst_range \. Fun f S \ s))" using subst_subterm[OF assms] by auto lemma subst_subterm'': assumes "s \ subterms (t \ \)" shows "(\u \ subterms t. s = u \ \) \ s \ subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \)" proof (cases s) case (Var x) thus ?thesis using assms subterm_subst_not_img_subterm vars_iff_subtermeq by (cases "s = t \ \") fastforce+ next case (Fun f T) thus ?thesis using subst_subterm[of f T t \] assms by fastforce qed subsection \More Small Lemmata\ lemma funs_term_subst: "funs_term (t \ \) = funs_term t \ (\x \ fv t. funs_term (\ x))" by (induct t) auto lemma fv\<^sub>s\<^sub>e\<^sub>t_subst_img_eq: assumes "X \ (subst_domain \ \ range_vars \) = {}" shows "fv\<^sub>s\<^sub>e\<^sub>t (\ ` (Y - X)) = fv\<^sub>s\<^sub>e\<^sub>t (\ ` Y) - X" using assms unfolding range_vars_alt_def by force lemma subst_Fun_index_eq: assumes "i < length T" "Fun f T \ \ = Fun g T' \ \" shows "T ! i \ \ = T' ! i \ \" proof - have "map (\x. x \ \) T = map (\x. x \ \) T'" using assms by simp thus ?thesis by (metis assms(1) length_map nth_map) qed lemma fv_exists_if_unifiable_and_neq: fixes t t'::"('a,'b) term" and \ \::"('a,'b) subst" assumes "t \ t'" "t \ \ = t' \ \" shows "fv t \ fv t' \ {}" proof assume "fv t \ fv t' = {}" hence "fv t = {}" "fv t' = {}" by auto hence "t \ \ = t" "t' \ \ = t'" by auto hence "t = t'" using assms(2) by metis thus False using assms(1) by auto qed lemma const_subterm_subst: "Fun c [] \ t \ Fun c [] \ t \ \" by (induct t) auto lemma const_subterm_subst_var_obtain: assumes "Fun c [] \ t \ \" "\Fun c [] \ t" obtains x where "x \ fv t" "Fun c [] \ \ x" using assms by (induct t) auto lemma const_subterm_subst_cases: assumes "Fun c [] \ t \ \" shows "Fun c [] \ t \ (\x \ fv t. x \ subst_domain \ \ Fun c [] \ \ x)" proof (cases "Fun c [] \ t") case False then obtain x where "x \ fv t" "Fun c [] \ \ x" using const_subterm_subst_var_obtain[OF assms] by moura thus ?thesis by (cases "x \ subst_domain \") auto qed simp lemma fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s_subst_fv_subset: assumes "x \ fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s F" shows "fv (\ x) \ fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s (F \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \)" using assms proof (induction F) case (Cons f F) then obtain t t' where f: "f = (t,t')" by (metis surj_pair) show ?case proof (cases "x \ fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s F") case True thus ?thesis using Cons.IH unfolding subst_apply_pairs_def by auto next case False hence "x \ fv t \ fv t'" using Cons.prems f by simp hence "fv (\ x) \ fv (t \ \) \ fv (t' \ \)" using fv_subst_subset[of x] by force thus ?thesis using f unfolding subst_apply_pairs_def by auto qed qed simp lemma fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s_step_subst: "fv\<^sub>s\<^sub>e\<^sub>t (\ ` fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s F) = fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s (F \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \)" proof (induction F) case (Cons f F) obtain t t' where "f = (t,t')" by moura thus ?case using Cons by (simp add: subst_apply_pairs_def subst_apply_fv_unfold) qed (simp_all add: subst_apply_pairs_def) lemma fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s_subst_obtain_var: fixes \::"('a,'b) subst" assumes "x \ fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s (F \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \)" shows "\y \ fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s F. x \ fv (\ y)" using assms proof (induction F) case (Cons f F) then obtain t s where f: "f = (t,s)" by (metis surj_pair) from Cons.IH show ?case proof (cases "x \ fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s (F \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \)") case False hence "x \ fv (t \ \) \ x \ fv (s \ \)" using f Cons.prems by (simp add: subst_apply_pairs_def) hence "(\y \ fv t. x \ fv (\ y)) \ (\y \ fv s. x \ fv (\ y))" by (metis fv_subst_obtain_var) thus ?thesis using f by (auto simp add: subst_apply_pairs_def) qed (auto simp add: Cons.IH) qed (simp add: subst_apply_pairs_def) lemma pair_subst_ident[intro]: "(fv t \ fv t') \ subst_domain \ = {} \ (t,t') \\<^sub>p \ = (t,t')" by auto lemma pairs_substI[intro]: assumes "subst_domain \ \ (\(s,t) \ M. fv s \ fv t) = {}" shows "M \\<^sub>p\<^sub>s\<^sub>e\<^sub>t \ = M" proof - { fix m assume M: "m \ M" then obtain s t where m: "m = (s,t)" by (metis surj_pair) hence "(fv s \ fv t) \ subst_domain \ = {}" using assms M by auto hence "m \\<^sub>p \ = m" using m by auto } thus ?thesis by (simp add: image_cong) qed lemma fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s_subst: "fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s (F \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \) = fv\<^sub>s\<^sub>e\<^sub>t (\ ` (fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s F))" proof (induction F) case (Cons g G) obtain t t' where "g = (t,t')" by (metis surj_pair) thus ?case using Cons.IH by (simp add: subst_apply_pairs_def subst_apply_fv_unfold) qed (simp add: subst_apply_pairs_def) lemma fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s_subst_subset: assumes "fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s (F \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \) \ subst_domain \" shows "fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s F \ subst_domain \ \ subst_domain \" using assms proof (induction F) case (Cons g G) hence IH: "fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s G \ subst_domain \ \ subst_domain \" by (simp add: subst_apply_pairs_def) obtain t t' where g: "g = (t,t')" by (metis surj_pair) hence "fv (t \ \) \ subst_domain \" "fv (t' \ \) \ subst_domain \" using Cons.prems by (simp_all add: subst_apply_pairs_def) hence "fv t \ subst_domain \ \ subst_domain \" "fv t' \ subst_domain \ \ subst_domain \" using subst_apply_fv_unfold[of _ \] by force+ thus ?case using IH g by (simp add: subst_apply_pairs_def) qed (simp add: subst_apply_pairs_def) lemma pairs_subst_comp: "F \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \ \\<^sub>s \ = ((F \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \) \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \)" by (induct F) (auto simp add: subst_apply_pairs_def) lemma pairs_substI'[intro]: "subst_domain \ \ fv\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s F = {} \ F \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \ = F" by (induct F) (force simp add: subst_apply_pairs_def)+ lemma subst_pair_compose[simp]: "d \\<^sub>p (\ \\<^sub>s \) = d \\<^sub>p \ \\<^sub>p \" proof - obtain t s where "d = (t,s)" by moura thus ?thesis by auto qed lemma subst_pairs_compose[simp]: "D \\<^sub>p\<^sub>s\<^sub>e\<^sub>t (\ \\<^sub>s \) = D \\<^sub>p\<^sub>s\<^sub>e\<^sub>t \ \\<^sub>p\<^sub>s\<^sub>e\<^sub>t \" by auto lemma subst_apply_pair_pair: "(t, s) \\<^sub>p \ = (t \ \, s \ \)" by (rule prod.case) lemma subst_apply_pairs_nil[simp]: "[] \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \ = []" unfolding subst_apply_pairs_def by simp lemma subst_apply_pairs_singleton[simp]: "[(t,s)] \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \ = [(t \ \,s \ \)]" unfolding subst_apply_pairs_def by simp lemma subst_apply_pairs_Var[iff]: "F \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s Var = F" by (simp add: subst_apply_pairs_def) lemma subst_apply_pairs_pset_subst: "set (F \\<^sub>p\<^sub>a\<^sub>i\<^sub>r\<^sub>s \) = set F \\<^sub>p\<^sub>s\<^sub>e\<^sub>t \" unfolding subst_apply_pairs_def by force subsection \Finite Substitutions\ inductive_set fsubst::"('a,'b) subst set" where fvar: "Var \ fsubst" | FUpdate: "\\ \ fsubst; v \ subst_domain \; t \ Var v\ \ \(v := t) \ fsubst" lemma finite_dom_iff_fsubst: "finite (subst_domain \) \ \ \ fsubst" proof assume "finite (subst_domain \)" thus "\ \ fsubst" proof (induction "subst_domain \" arbitrary: \ rule: finite.induct) case emptyI hence "\ = Var" using empty_dom_iff_empty_subst by metis thus ?case using fvar by simp next case (insertI \'\<^sub>d\<^sub>o\<^sub>m v) thus ?case proof (cases "v \ \'\<^sub>d\<^sub>o\<^sub>m") case True hence "\'\<^sub>d\<^sub>o\<^sub>m = subst_domain \" using \insert v \'\<^sub>d\<^sub>o\<^sub>m = subst_domain \\ by auto thus ?thesis using insertI.hyps(2) by metis next case False let ?\' = "\w. if w \ \'\<^sub>d\<^sub>o\<^sub>m then \ w else Var w" have "subst_domain ?\' = \'\<^sub>d\<^sub>o\<^sub>m" using \v \ \'\<^sub>d\<^sub>o\<^sub>m\ \insert v \'\<^sub>d\<^sub>o\<^sub>m = subst_domain \\ by (auto simp add: subst_domain_def) hence "?\' \ fsubst" using insertI.hyps(2) by simp moreover have "?\'(v := \ v) = (\w. if w \ insert v \'\<^sub>d\<^sub>o\<^sub>m then \ w else Var w)" by auto hence "?\'(v := \ v) = \" using \insert v \'\<^sub>d\<^sub>o\<^sub>m = subst_domain \\ by (auto simp add: subst_domain_def) ultimately show ?thesis using FUpdate[of ?\' v "\ v"] False insertI.hyps(3) by (auto simp add: subst_domain_def) qed qed next assume "\ \ fsubst" thus "finite (subst_domain \)" by (induct \, simp, metis subst_dom_insert_finite) qed lemma fsubst_induct[case_names fvar FUpdate, induct set: finite]: assumes "finite (subst_domain \)" "P Var" and "\\ v t. \finite (subst_domain \); v \ subst_domain \; t \ Var v; P \\ \ P (\(v := t))" shows "P \" using assms finite_dom_iff_fsubst fsubst.induct by metis lemma fun_upd_fsubst: "s(v := t) \ fsubst \ s \ fsubst" using subst_dom_insert_finite[of s] finite_dom_iff_fsubst by blast lemma finite_img_if_fsubst: "s \ fsubst \ finite (subst_range s)" using finite_dom_iff_fsubst finite_subst_img_if_finite_dom' by blast subsection \Unifiers and Most General Unifiers (MGUs)\ abbreviation Unifier::"('f,'v) subst \ ('f,'v) term \ ('f,'v) term \ bool" where "Unifier \ t u \ (t \ \ = u \ \)" abbreviation MGU::"('f,'v) subst \ ('f,'v) term \ ('f,'v) term \ bool" where "MGU \ t u \ Unifier \ t u \ (\\. Unifier \ t u \ \ \\<^sub>\ \)" lemma MGUI[intro]: shows "\t \ \ = u \ \; \\::('f,'v) subst. t \ \ = u \ \ \ \ \\<^sub>\ \\ \ MGU \ t u" by auto lemma UnifierD[dest]: fixes \::"('f,'v) subst" and f g::'f and X Y::"('f,'v) term list" assumes "Unifier \ (Fun f X) (Fun g Y)" shows "f = g" "length X = length Y" proof - from assms show "f = g" by auto from assms have "Fun f X \ \ = Fun g Y \ \" by auto hence "length (map (\x. x \ \) X) = length (map (\x. x \ \) Y)" by auto thus "length X = length Y" by auto qed lemma MGUD[dest]: fixes \::"('f,'v) subst" and f g::'f and X Y::"('f,'v) term list" assumes "MGU \ (Fun f X) (Fun g Y)" shows "f = g" "length X = length Y" using assms by (auto intro!: UnifierD[of f X \ g Y]) lemma MGU_sym[sym]: "MGU \ s t \ MGU \ t s" by auto lemma Unifier_sym[sym]: "Unifier \ s t \ Unifier \ t s" by auto lemma MGU_nil: "MGU Var s t \ s = t" by fastforce lemma Unifier_comp: "Unifier (\ \\<^sub>s \) t u \ Unifier \ (t \ \) (u \ \)" by simp lemma Unifier_comp': "Unifier \ (t \ \) (u \ \) \ Unifier (\ \\<^sub>s \) t u" by simp lemma Unifier_excludes_subterm: assumes \: "Unifier \ t u" shows "\t \ u" proof assume "t \ u" hence "t \ \ \ u \ \" using subst_mono_neq by metis hence "t \ \ \ u \ \" by simp moreover from \ have "t \ \ = u \ \" by auto ultimately show False .. qed lemma MGU_is_Unifier: "MGU \ t u \ Unifier \ t u" by (rule conjunct1) lemma MGU_Var1: assumes "\Var v \ t" shows "MGU (Var(v := t)) (Var v) t" proof (intro MGUI exI) show "Var v \ (Var(v := t)) = t \ (Var(v := t))" using assms subst_no_occs by fastforce next fix \::"('a,'b) subst" assume th: "Var v \ \ = t \ \" show "\ = (Var(v := t)) \\<^sub>s \" proof fix s show "s \ \ = s \ ((Var(v := t)) \\<^sub>s \)" using th by (induct s) auto qed qed lemma MGU_Var2: "v \ fv t \ MGU (Var(v := t)) (Var v) t" by (metis (no_types) MGU_Var1 vars_iff_subterm_or_eq) lemma MGU_Var3: "MGU Var (Var v) (Var w) \ v = w" by fastforce lemma MGU_Const1: "MGU Var (Fun c []) (Fun d []) \ c = d" by fastforce lemma MGU_Const2: "MGU \ (Fun c []) (Fun d []) \ c = d" by auto lemma MGU_Fun: assumes "MGU \ (Fun f X) (Fun g Y)" shows "f = g" "length X = length Y" proof - let ?F = "\\ X. map (\x. x \ \) X" from assms have "\f = g; ?F \ X = ?F \ Y; \\'. f = g \ ?F \' X = ?F \' Y \ \ \\<^sub>\ \'\ \ length X = length Y" using map_eq_imp_length_eq by auto thus "f = g" "length X = length Y" using assms by auto qed lemma Unifier_Fun: assumes "Unifier \ (Fun f (x#X)) (Fun g (y#Y))" shows "Unifier \ x y" "Unifier \ (Fun f X) (Fun g Y)" using assms by simp_all lemma Unifier_subst_idem_subst: "subst_idem r \ Unifier s (t \ r) (u \ r) \ Unifier (r \\<^sub>s s) (t \ r) (u \ r)" by (metis (no_types, lifting) subst_idem_def subst_subst_compose) lemma subst_idem_comp: "subst_idem r \ Unifier s (t \ r) (u \ r) \ (\q. Unifier q (t \ r) (u \ r) \ s \\<^sub>s q = q) \ subst_idem (r \\<^sub>s s)" by (frule Unifier_subst_idem_subst, blast, metis subst_idem_def subst_compose_assoc) lemma Unifier_mgt: "\Unifier \ t u; \ \\<^sub>\ \\ \ Unifier \ t u" by auto lemma Unifier_support: "\Unifier \ t u; \ supports \\ \ Unifier \ t u" using subst_supportD Unifier_mgt by metis lemma MGU_mgt: "\MGU \ t u; MGU \ t u\ \ \ \\<^sub>\ \" by auto lemma Unifier_trm_fv_bound: "\Unifier s t u; v \ fv t\ \ v \ subst_domain s \ range_vars s \ fv u" proof (induction t arbitrary: s u) case (Fun f X) hence "v \ fv (u \ s) \ v \ subst_domain s" by (metis subst_not_dom_fixed) thus ?case by (metis (no_types) Un_iff contra_subsetD subst_sends_fv_to_img) qed (metis (no_types) UnI1 UnI2 subsetCE no_var_subterm subst_sends_dom_to_img subst_to_var_is_var trm_subst_ident' vars_iff_subterm_or_eq) lemma Unifier_rm_var: "\Unifier \ s t; v \ fv s \ fv t\ \ Unifier (rm_var v \) s t" by (auto simp add: repl_invariance) lemma Unifier_ground_rm_vars: assumes "ground (subst_range s)" "Unifier (rm_vars X s) t t'" shows "Unifier s t t'" by (rule Unifier_support[OF assms(2) rm_vars_ground_supports[OF assms(1)]]) lemma Unifier_dom_restrict: assumes "Unifier s t t'" "fv t \ fv t' \ S" shows "Unifier (rm_vars (UNIV - S) s) t t'" proof - let ?s = "rm_vars (UNIV - S) s" show ?thesis using term_subst_eq_conv[of t s ?s] term_subst_eq_conv[of t' s ?s] assms by auto qed subsection \Well-formedness of Substitutions and Unifiers\ inductive_set wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set::"('a,'b) subst set" where Empty[simp]: "Var \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set" | Insert[simp]: "\\ \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set; v \ subst_domain \; v \ range_vars \; fv t \ (insert v (subst_domain \)) = {}\ \ \(v := t) \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set" definition wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t::"('a,'b) subst \ bool" where "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \ \ subst_domain \ \ range_vars \ = {} \ finite (subst_domain \)" definition wf\<^sub>M\<^sub>G\<^sub>U::"('a,'b) subst \ ('a,'b) term \ ('a,'b) term \ bool" where "wf\<^sub>M\<^sub>G\<^sub>U \ s t \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \ \ MGU \ s t \ subst_domain \ \ range_vars \ \ fv s \ fv t" lemma wf_subst_subst_idem: "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \ \ subst_idem \" using subst_idemI[of \] unfolding wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def by fast lemma wf_subst_properties: "\ \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set = wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \" proof show "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \ \ \ \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set" unfolding wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def proof - assume "subst_domain \ \ range_vars \ = {} \ finite (subst_domain \)" hence "finite (subst_domain \)" "subst_domain \ \ range_vars \ = {}" by auto thus "\ \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set" proof (induction \ rule: fsubst_induct) case fvar thus ?case by simp next case (FUpdate \ v t) have "subst_domain \ \ subst_domain (\(v := t))" "range_vars \ \ range_vars (\(v := t))" using FUpdate.hyps(2,3) subst_img_update unfolding range_vars_alt_def by (fastforce simp add: subst_domain_def)+ hence "subst_domain \ \ range_vars \ = {}" using FUpdate.prems(1) by blast hence "\ \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set" using FUpdate.IH by metis have *: "range_vars (\(v := t)) = range_vars \ \ fv t" using FUpdate.hyps(2) subst_img_update[OF _ FUpdate.hyps(3)] by fastforce hence "fv t \ insert v (subst_domain \) = {}" using FUpdate.prems subst_dom_update2[OF FUpdate.hyps(3)] by blast moreover have "subst_domain (\(v := t)) = insert v (subst_domain \)" by (meson FUpdate.hyps(3) subst_dom_update2) hence "v \ range_vars \" using FUpdate.prems * by blast ultimately show ?case using Insert[OF \\ \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set\ \v \ subst_domain \\] by metis qed qed show "\ \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \" unfolding wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def proof (induction \ rule: wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set.induct) case Empty thus ?case by simp next case (Insert \ v t) hence 1: "subst_domain \ \ range_vars \ = {}" by simp hence 2: "subst_domain (\(v := t)) \ range_vars \ = {}" using Insert.hyps(3) by (auto simp add: subst_domain_def) have 3: "fv t \ subst_domain (\(v := t)) = {}" using Insert.hyps(4) by (auto simp add: subst_domain_def) have 4: "\ v = Var v" using \v \ subst_domain \\ by (simp add: subst_domain_def) from Insert.IH have "finite (subst_domain \)" by simp hence 5: "finite (subst_domain (\(v := t)))" using subst_dom_insert_finite[of \] by simp have "subst_domain (\(v := t)) \ range_vars (\(v := t)) = {}" proof (cases "t = Var v") case True hence "range_vars (\(v := t)) = range_vars \" using 4 fun_upd_triv term.inject(1) unfolding range_vars_alt_def by (auto simp add: subst_domain_def) thus "subst_domain (\(v := t)) \ range_vars (\(v := t)) = {}" using 1 2 3 by auto next case False hence "range_vars (\(v := t)) = fv t \ (range_vars \)" using 4 subst_img_update[of \ v] by auto thus "subst_domain (\(v := t)) \ range_vars (\(v := t)) = {}" using 1 2 3 by blast qed thus ?case using 5 by blast qed qed lemma wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_induct[consumes 1, case_names Empty Insert]: assumes "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \" "P Var" and "\\ v t. \wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \; P \; v \ subst_domain \; v \ range_vars \; fv t \ insert v (subst_domain \) = {}\ \ P (\(v := t))" shows "P \" proof - from assms(1,3) wf_subst_properties have "\ \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set" "\\ v t. \\ \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set; P \; v \ subst_domain \; v \ range_vars \; fv t \ insert v (subst_domain \) = {}\ \ P (\(v := t))" by blast+ thus "P \" using wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set.induct assms(2) by blast qed lemma wf_subst_fsubst: "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \ \ \ \ fsubst" unfolding wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def using finite_dom_iff_fsubst by blast lemma wf_subst_nil: "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t Var" unfolding wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def by simp lemma wf_MGU_nil: "MGU Var s t \ wf\<^sub>M\<^sub>G\<^sub>U Var s t" using wf_subst_nil subst_domain_Var range_vars_Var unfolding wf\<^sub>M\<^sub>G\<^sub>U_def by fast lemma wf_MGU_dom_bound: "wf\<^sub>M\<^sub>G\<^sub>U \ s t \ subst_domain \ \ fv s \ fv t" unfolding wf\<^sub>M\<^sub>G\<^sub>U_def by blast lemma wf_subst_single: assumes "v \ fv t" "\ v = t" "\w. v \ w \ \ w = Var w" shows "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \" proof - have *: "subst_domain \ = {v}" by (metis subst_fv_dom_img_single(1)[OF assms]) have "subst_domain \ \ range_vars \ = {}" using * assms subst_fv_dom_img_single(2) by (metis inf_bot_left insert_disjoint(1)) moreover have "finite (subst_domain \)" using * by simp ultimately show ?thesis by (metis wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def) qed lemma wf_subst_reduction: "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t s \ wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t (rm_var v s)" proof - assume "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t s" moreover have "subst_domain (rm_var v s) \ subst_domain s" by (auto simp add: subst_domain_def) moreover have "range_vars (rm_var v s) \ range_vars s" unfolding range_vars_alt_def by (auto simp add: subst_domain_def) ultimately have "subst_domain (rm_var v s) \ range_vars (rm_var v s) = {}" by (meson compl_le_compl_iff disjoint_eq_subset_Compl subset_trans wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def) moreover have "finite (subst_domain (rm_var v s))" using \subst_domain (rm_var v s) \ subst_domain s\ \wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t s\ rev_finite_subset unfolding wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def by blast ultimately show "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t (rm_var v s)" by (metis wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def) qed lemma wf_subst_compose: assumes "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \1" "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \2" and "subst_domain \1 \ subst_domain \2 = {}" and "subst_domain \1 \ range_vars \2 = {}" shows "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t (\1 \\<^sub>s \2)" using assms proof (induction \1 rule: wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_induct) case Empty thus ?case unfolding wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def by simp next case (Insert \1 v t) have "t \ Var v" using Insert.hyps(4) by auto hence dom1v_unfold: "subst_domain (\1(v := t)) = insert v (subst_domain \1)" using subst_dom_update2 by metis hence doms_disj: "subst_domain \1 \ subst_domain \2 = {}" using Insert.prems(2) disjoint_insert(1) by blast moreover have dom_img_disj: "subst_domain \1 \ range_vars \2 = {}" using Insert.hyps(2) Insert.prems(3) by (fastforce simp add: subst_domain_def) ultimately have "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t (\1 \\<^sub>s \2)" using Insert.IH[OF \wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \2\] by metis have dom_comp_is_union: "subst_domain (\1 \\<^sub>s \2) = subst_domain \1 \ subst_domain \2" using subst_dom_comp_eq[OF dom_img_disj] . have "v \ subst_domain \2" using Insert.prems(2) \t \ Var v\ by (fastforce simp add: subst_domain_def) hence "\2 v = Var v" "\1 v = Var v" using Insert.hyps(2) by (simp_all add: subst_domain_def) hence "(\1 \\<^sub>s \2) v = Var v" "(\1(v := t) \\<^sub>s \2) v = t \ \2" "((\1 \\<^sub>s \2)(v := t)) v = t" unfolding subst_compose_def by simp_all have fv_t2_bound: "fv (t \ \2) \ fv t \ range_vars \2" by (meson subst_sends_fv_to_img) have 1: "v \ subst_domain (\1 \\<^sub>s \2)" using \(\1 \\<^sub>s \2) v = Var v\ by (auto simp add: subst_domain_def) have "insert v (subst_domain \1) \ range_vars \2 = {}" using Insert.prems(3) dom1v_unfold by blast hence "v \ range_vars \1 \ range_vars \2" using Insert.hyps(3) by blast hence 2: "v \ range_vars (\1 \\<^sub>s \2)" by (meson set_rev_mp subst_img_comp_subset) have "subst_domain \2 \ range_vars \2 = {}" using \wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \2\ unfolding wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def by simp hence "fv (t \ \2) \ subst_domain \2 = {}" using subst_dom_elim unfolding range_vars_alt_def by simp moreover have "v \ range_vars \2" using Insert.prems(3) dom1v_unfold by blast hence "v \ fv t \ range_vars \2" using Insert.hyps(4) by blast hence "v \ fv (t \ \2)" using \fv (t \ \2) \ fv t \ range_vars \2\ by blast moreover have "fv (t \ \2) \ subst_domain \1 = {}" using dom_img_disj fv_t2_bound \fv t \ insert v (subst_domain \1) = {}\ by blast ultimately have 3: "fv (t \ \2) \ insert v (subst_domain (\1 \\<^sub>s \2)) = {}" using dom_comp_is_union by blast have "\1(v := t) \\<^sub>s \2 = (\1 \\<^sub>s \2)(v := t \ \2)" using subst_comp_upd1[of \1 v t \2] . moreover have "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t ((\1 \\<^sub>s \2)(v := t \ \2))" using "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set.Insert"[OF _ 1 2 3] \wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t (\1 \\<^sub>s \2)\ wf_subst_properties by metis ultimately show ?case by presburger qed lemma wf_subst_append: fixes \1 \2::"('f,'v) subst" assumes "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \1" "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \2" and "subst_domain \1 \ subst_domain \2 = {}" and "subst_domain \1 \ range_vars \2 = {}" and "range_vars \1 \ subst_domain \2 = {}" shows "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t (\v. if \1 v = Var v then \2 v else \1 v)" using assms proof (induction \1 rule: wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_induct) case Empty thus ?case unfolding wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def by simp next case (Insert \1 v t) let ?if = "\w. if \1 w = Var w then \2 w else \1 w" let ?if_upd = "\w. if (\1(v := t)) w = Var w then \2 w else (\1(v := t)) w" from Insert.hyps(4) have "?if_upd = ?if(v := t)" by fastforce have dom_insert: "subst_domain (\1(v := t)) = insert v (subst_domain \1)" using Insert.hyps(4) by (auto simp add: subst_domain_def) have "\1 v = Var v" "t \ Var v" using Insert.hyps(2,4) by auto hence img_insert: "range_vars (\1(v := t)) = range_vars \1 \ fv t" using subst_img_update by metis from Insert.prems(2) dom_insert have "subst_domain \1 \ subst_domain \2 = {}" by (auto simp add: subst_domain_def) moreover have "subst_domain \1 \ range_vars \2 = {}" using Insert.prems(3) dom_insert by (simp add: subst_domain_def) moreover have "range_vars \1 \ subst_domain \2 = {}" using Insert.prems(4) img_insert by blast ultimately have "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t ?if" using Insert.IH[OF Insert.prems(1)] by metis have dom_union: "subst_domain ?if = subst_domain \1 \ subst_domain \2" by (auto simp add: subst_domain_def) hence "v \ subst_domain ?if" using Insert.hyps(2) Insert.prems(2) dom_insert by (auto simp add: subst_domain_def) moreover have "v \ range_vars ?if" using Insert.prems(3) Insert.hyps(3) dom_insert unfolding range_vars_alt_def by (auto simp add: subst_domain_def) moreover have "fv t \ insert v (subst_domain ?if) = {}" using Insert.hyps(4) Insert.prems(4) img_insert unfolding range_vars_alt_def by (fastforce simp add: subst_domain_def) ultimately show ?case using wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_set.Insert \wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t ?if\ \?if_upd = ?if(v := t)\ wf_subst_properties by (metis (no_types, lifting)) qed lemma wf_subst_elim_append: assumes "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \" "subst_elim \ v" "v \ fv t" shows "subst_elim (\(w := t)) v" using assms proof (induction \ rule: wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_induct) case (Insert \ v' t') hence "\q. v \ fv (Var q \ \(v' := t'))" using subst_elimD by blast hence "\q. v \ fv (Var q \ \(v' := t', w := t))" using \v \ fv t\ by simp thus ?case by (metis subst_elimI' subst_apply_term.simps(1)) qed (simp add: subst_elim_def) lemma wf_subst_elim_dom: assumes "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \" shows "\v \ subst_domain \. subst_elim \ v" using assms proof (induction \ rule: wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_induct) case (Insert \ w t) have dom_insert: "subst_domain (\(w := t)) \ insert w (subst_domain \)" by (auto simp add: subst_domain_def) hence "\v \ subst_domain \. subst_elim (\(w := t)) v" using Insert.IH Insert.hyps(2,4) by (metis Insert.hyps(1) IntI disjoint_insert(2) empty_iff wf_subst_elim_append) moreover have "w \ fv t" using Insert.hyps(4) by simp hence "\q. w \ fv (Var q \ \(w := t))" by (metis fv_simps(1) fv_in_subst_img Insert.hyps(3) contra_subsetD fun_upd_def singletonD subst_apply_term.simps(1)) hence "subst_elim (\(w := t)) w" by (metis subst_elimI') ultimately show ?case using dom_insert by blast qed simp lemma wf_subst_support_iff_mgt: "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \ \ \ supports \ \ \ \\<^sub>\ \" using subst_support_def subst_support_if_mgt_subst_idem wf_subst_subst_idem by blast subsection \Interpretations\ abbreviation interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t::"('a,'b) subst \ bool" where "interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \ \ subst_domain \ = UNIV \ ground (subst_range \)" lemma interpretation_substI: "(\v. fv (\ v) = {}) \ interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \" proof - assume "\v. fv (\ v) = {}" moreover { fix v assume "fv (\ v) = {}" hence "v \ subst_domain \" by auto } ultimately show ?thesis by auto qed lemma interpretation_grounds[simp]: "interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \ \ fv (t \ \) = {}" using subst_fv_dom_ground_if_ground_img[of t \] by blast lemma interpretation_grounds_all: "interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \ \ (\v. fv (\ v) = {})" by (metis range_vars_alt_def UNIV_I fv_in_subst_img subset_empty subst_dom_vars_in_subst) lemma interpretation_grounds_all': "interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \ \ ground (M \\<^sub>s\<^sub>e\<^sub>t \)" using subst_fv_dom_ground_if_ground_img[of _ \] by simp lemma interpretation_comp: assumes "interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \" shows "interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t (\ \\<^sub>s \)" "interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t (\ \\<^sub>s \)" proof - have \_fv: "fv (\ v) = {}" for v using interpretation_grounds_all[OF assms] by simp hence \_fv': "fv (t \ \) = {}" for t by (metis all_not_in_conv subst_elimD subst_elimI' subst_apply_term.simps(1)) from assms have "(\ \\<^sub>s \) v \ Var v" for v unfolding subst_compose_def by (metis fv_simps(1) \_fv' insert_not_empty) hence "subst_domain (\ \\<^sub>s \) = UNIV" by (simp add: subst_domain_def) moreover have "fv ((\ \\<^sub>s \) v) = {}" for v unfolding subst_compose_def using \_fv' by simp hence "ground (subst_range (\ \\<^sub>s \))" by simp ultimately show "interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t (\ \\<^sub>s \)" .. from assms have "(\ \\<^sub>s \) v \ Var v" for v unfolding subst_compose_def by (metis fv_simps(1) \_fv insert_not_empty subst_to_var_is_var) hence "subst_domain (\ \\<^sub>s \) = UNIV" by (simp add: subst_domain_def) moreover have "fv ((\ \\<^sub>s \) v) = {}" for v unfolding subst_compose_def by (simp add: \_fv trm_subst_ident) hence "ground (subst_range (\ \\<^sub>s \))" by simp ultimately show "interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t (\ \\<^sub>s \)" .. qed lemma interpretation_subst_exists: "\\::('f,'v) subst. interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \" proof - obtain c::"'f" where "c \ UNIV" by simp then obtain \::"('f,'v) subst" where "\v. \ v = Fun c []" by simp hence "subst_domain \ = UNIV" "ground (subst_range \)" by (simp_all add: subst_domain_def) thus ?thesis by auto qed lemma interpretation_subst_exists': "\\::('f,'v) subst. subst_domain \ = X \ ground (subst_range \)" proof - obtain \::"('f,'v) subst" where \: "subst_domain \ = UNIV" "ground (subst_range \)" using interpretation_subst_exists by moura let ?\ = "rm_vars (UNIV - X) \" have 1: "subst_domain ?\ = X" using \ by (auto simp add: subst_domain_def) hence 2: "ground (subst_range ?\)" using \ by force show ?thesis using 1 2 by blast qed lemma interpretation_subst_idem: "interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \ \ subst_idem \" unfolding subst_idem_def using interpretation_grounds_all[of \] trm_subst_ident subst_eq_if_eq_vars by fastforce lemma subst_idem_comp_upd_eq: assumes "v \ subst_domain \" "subst_idem \" shows "\ \\<^sub>s \ = \(v := \ v) \\<^sub>s \" proof - from assms(1) have "(\ \\<^sub>s \) v = \ v" unfolding subst_compose_def by auto moreover have "\w. w \ v \ (\ \\<^sub>s \) w = (\(v := \ v) \\<^sub>s \) w" unfolding subst_compose_def by auto moreover have "(\(v := \ v) \\<^sub>s \) v = \ v" using assms(2) unfolding subst_idem_def subst_compose_def by (metis fun_upd_same) ultimately show ?thesis by (metis fun_upd_same fun_upd_triv subst_comp_upd1) qed lemma interpretation_dom_img_disjoint: "interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \ \ subst_domain \ \ range_vars \ = {}" unfolding range_vars_alt_def by auto subsection \Basic Properties of MGUs\ lemma MGU_is_mgu_singleton: "MGU \ t u = is_mgu \ {(t,u)}" unfolding is_mgu_def unifiers_def by auto lemma Unifier_in_unifiers_singleton: "Unifier \ s t \ \ \ unifiers {(s,t)}" unfolding unifiers_def by auto lemma subst_list_singleton_fv_subset: "(\x \ set (subst_list (subst v t) E). fv (fst x) \ fv (snd x)) \ fv t \ (\x \ set E. fv (fst x) \ fv (snd x))" proof (induction E) case (Cons x E) let ?fvs = "\L. \x \ set L. fv (fst x) \ fv (snd x)" let ?fvx = "fv (fst x) \ fv (snd x)" let ?fvxsubst = "fv (fst x \ Var(v := t)) \ fv (snd x \ Var(v := t))" have "?fvs (subst_list (subst v t) (x#E)) = ?fvxsubst \ ?fvs (subst_list (subst v t) E)" unfolding subst_list_def subst_def by auto hence "?fvs (subst_list (subst v t) (x#E)) \ ?fvxsubst \ fv t \ ?fvs E" using Cons.IH by blast moreover have "?fvs (x#E) = ?fvx \ ?fvs E" by auto moreover have "?fvxsubst \ ?fvx \ fv t" using subst_fv_bound_singleton[of _ v t] by blast ultimately show ?case unfolding range_vars_alt_def by auto qed (simp add: subst_list_def) lemma subst_of_dom_subset: "subst_domain (subst_of L) \ set (map fst L)" proof (induction L rule: List.rev_induct) case (snoc x L) then obtain v t where x: "x = (v,t)" by (metis surj_pair) hence "subst_of (L@[x]) = Var(v := t) \\<^sub>s subst_of L" unfolding subst_of_def subst_def by (induct L) auto hence "subst_domain (subst_of (L@[x])) \ insert v (subst_domain (subst_of L))" using x subst_domain_compose[of "Var(v := t)" "subst_of L"] by (auto simp add: subst_domain_def) thus ?case using snoc.IH x by auto qed simp lemma wf_MGU_is_imgu_singleton: "wf\<^sub>M\<^sub>G\<^sub>U \ s t \ is_imgu \ {(s,t)}" proof - assume 1: "wf\<^sub>M\<^sub>G\<^sub>U \ s t" have 2: "subst_idem \" by (metis wf_subst_subst_idem 1 wf\<^sub>M\<^sub>G\<^sub>U_def) have 3: "\\' \ unifiers {(s,t)}. \ \\<^sub>\ \'" "\ \ unifiers {(s,t)}" by (metis 1 Unifier_in_unifiers_singleton wf\<^sub>M\<^sub>G\<^sub>U_def)+ have "\\ \ unifiers {(s,t)}. \ = \ \\<^sub>s \" by (metis 2 3 subst_idem_def subst_compose_assoc) thus "is_imgu \ {(s,t)}" by (metis is_imgu_def \\ \ unifiers {(s,t)}\) qed lemma mgu_subst_range_vars: assumes "mgu s t = Some \" shows "range_vars \ \ vars_term s \ vars_term t" proof - obtain xs where *: "Unification.unify [(s, t)] [] = Some xs" and [simp]: "subst_of xs = \" using assms by (simp split: option.splits) from unify_Some_UNIF [OF *] obtain ss where "compose ss = \" and "UNIF ss {#(s, t)#} {#}" by auto with UNIF_range_vars_subset [of ss "{#(s, t)#}" "{#}"] show ?thesis by (metis vars_mset_singleton fst_conv snd_conv) qed lemma mgu_subst_domain_range_vars_disjoint: assumes "mgu s t = Some \" shows "subst_domain \ \ range_vars \ = {}" proof - have "is_imgu \ {(s, t)}" using assms mgu_sound by simp hence "\ = \ \\<^sub>s \" unfolding is_imgu_def by blast thus ?thesis by (metis subst_idemp_iff) qed lemma mgu_same_empty: "mgu (t::('a,'b) term) t = Some Var" proof - { fix E::"('a,'b) equation list" and U::"('b \ ('a,'b) term) list" assume "\(s,t) \ set E. s = t" hence "Unification.unify E U = Some U" proof (induction E U rule: Unification.unify.induct) case (2 f S g T E U) hence *: "f = g" "S = T" by auto moreover have "\(s,t) \ set (zip T T). s = t" by (induct T) auto hence "\(s,t) \ set (zip T T@E). s = t" using "2.prems"(1) by auto moreover have "zip_option S T = Some (zip S T)" using \S = T\ by auto hence **: "decompose (Fun f S) (Fun g T) = Some (zip S T)" using \f = g\ unfolding decompose_def by auto ultimately have "Unification.unify (zip S T@E) U = Some U" using "2.IH" * by auto thus ?case using ** by auto qed auto } hence "Unification.unify [(t,t)] [] = Some []" by auto thus ?thesis by auto qed lemma mgu_var: assumes "x \ fv t" shows "mgu (Var x) t = Some (Var(x := t))" proof - have "unify [(Var x,t)] [] = Some [(x,t)]" using assms by (auto simp add: subst_list_def) moreover have "subst_of [(x,t)] = Var(x := t)" unfolding subst_of_def subst_def by simp ultimately show ?thesis by simp qed lemma mgu_gives_wellformed_subst: assumes "mgu s t = Some \" shows "wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \" using mgu_finite_subst_domain[OF assms] mgu_subst_domain_range_vars_disjoint[OF assms] unfolding wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def by auto lemma mgu_gives_wellformed_MGU: assumes "mgu s t = Some \" shows "wf\<^sub>M\<^sub>G\<^sub>U \ s t" using mgu_subst_domain[OF assms] mgu_sound[OF assms] mgu_subst_range_vars [OF assms] MGU_is_mgu_singleton[of s \ t] is_imgu_imp_is_mgu[of \ "{(s,t)}"] mgu_gives_wellformed_subst[OF assms] unfolding wf\<^sub>M\<^sub>G\<^sub>U_def by blast lemma mgu_vars_bounded[dest?]: "mgu M N = Some \ \ subst_domain \ \ range_vars \ \ fv M \ fv N" using mgu_gives_wellformed_MGU unfolding wf\<^sub>M\<^sub>G\<^sub>U_def by blast lemma mgu_gives_subst_idem: "mgu s t = Some \ \ subst_idem \" using mgu_sound[of s t \] unfolding is_imgu_def subst_idem_def by auto lemma mgu_always_unifies: "Unifier \ M N \ \\. mgu M N = Some \" using mgu_complete Unifier_in_unifiers_singleton by blast lemma mgu_gives_MGU: "mgu s t = Some \ \ MGU \ s t" using mgu_sound[of s t \, THEN is_imgu_imp_is_mgu] MGU_is_mgu_singleton by metis lemma mgu_eliminates[dest?]: assumes "mgu M N = Some \" shows "(\v \ fv M \ fv N. subst_elim \ v) \ \ = Var" (is "?P M N \") proof (cases "\ = Var") case False then obtain v where v: "v \ subst_domain \" by auto hence "v \ fv M \ fv N" using mgu_vars_bounded[OF assms] by blast thus ?thesis using wf_subst_elim_dom[OF mgu_gives_wellformed_subst[OF assms]] v by blast qed simp lemma mgu_eliminates_dom: assumes "mgu x y = Some \" "v \ subst_domain \" shows "subst_elim \ v" using mgu_gives_wellformed_subst[OF assms(1)] unfolding wf\<^sub>M\<^sub>G\<^sub>U_def wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def subst_elim_def by (metis disjoint_iff_not_equal subst_dom_elim assms(2)) lemma unify_list_distinct: assumes "Unification.unify E B = Some U" "distinct (map fst B)" and "(\x \ set E. fv (fst x) \ fv (snd x)) \ set (map fst B) = {}" shows "distinct (map fst U)" using assms proof (induction E B arbitrary: U rule: Unification.unify.induct) case 1 thus ?case by simp next case (2 f X g Y E B U) let ?fvs = "\L. \x \ set L. fv (fst x) \ fv (snd x)" from "2.prems"(1) obtain E' where *: "decompose (Fun f X) (Fun g Y) = Some E'" and [simp]: "f = g" "length X = length Y" "E' = zip X Y" and **: "Unification.unify (E'@E) B = Some U" by (auto split: option.splits) hence "\t t'. (t,t') \ set E' \ fv t \ fv (Fun f X) \ fv t' \ fv (Fun g Y)" by (metis zip_arg_subterm subtermeq_vars_subset) hence "?fvs E' \ fv (Fun f X) \ fv (Fun g Y)" by fastforce moreover have "fv (Fun f X) \ set (map fst B) = {}" "fv (Fun g Y) \ set (map fst B) = {}" using "2.prems"(3) by auto ultimately have "?fvs E' \ set (map fst B) = {}" by blast moreover have "?fvs E \ set (map fst B) = {}" using "2.prems"(3) by auto ultimately have "?fvs (E'@E) \ set (map fst B) = {}" by auto thus ?case using "2.IH"[OF * ** "2.prems"(2)] by metis next case (3 v t E B) let ?fvs = "\L. \x \ set L. fv (fst x) \ fv (snd x)" let ?E' = "subst_list (subst v t) E" from "3.prems"(3) have "v \ set (map fst B)" "fv t \ set (map fst B) = {}" by force+ hence *: "distinct (map fst ((v, t)#B))" using "3.prems"(2) by auto show ?case proof (cases "t = Var v") case True thus ?thesis using "3.prems" "3.IH"(1) by auto next case False hence "v \ fv t" using "3.prems"(1) by auto hence "Unification.unify (subst_list (subst v t) E) ((v, t)#B) = Some U" using \t \ Var v\ "3.prems"(1) by auto moreover have "?fvs ?E' \ set (map fst ((v, t)#B)) = {}" proof - have "v \ ?fvs ?E'" unfolding subst_list_def subst_def by (simp add: \v \ fv t\ subst_remove_var) moreover have "?fvs ?E' \ fv t \ ?fvs E" by (metis subst_list_singleton_fv_subset) hence "?fvs ?E' \ set (map fst B) = {}" using "3.prems"(3) by auto ultimately show ?thesis by auto qed ultimately show ?thesis using "3.IH"(2)[OF \t \ Var v\ \v \ fv t\ _ *] by metis qed next case (4 f X v E B U) let ?fvs = "\L. \x \ set L. fv (fst x) \ fv (snd x)" let ?E' = "subst_list (subst v (Fun f X)) E" have *: "?fvs E \ set (map fst B) = {}" using "4.prems"(3) by auto from "4.prems"(1) have "v \ fv (Fun f X)" by force from "4.prems"(3) have **: "v \ set (map fst B)" "fv (Fun f X) \ set (map fst B) = {}" by force+ hence ***: "distinct (map fst ((v, Fun f X)#B))" using "4.prems"(2) by auto from "4.prems"(3) have ****: "?fvs ?E' \ set (map fst ((v, Fun f X)#B)) = {}" proof - have "v \ ?fvs ?E'" unfolding subst_list_def subst_def using \v \ fv (Fun f X)\ subst_remove_var[of v "Fun f X"] by simp moreover have "?fvs ?E' \ fv (Fun f X) \ ?fvs E" by (metis subst_list_singleton_fv_subset) hence "?fvs ?E' \ set (map fst B) = {}" using * ** by blast ultimately show ?thesis by auto qed have "Unification.unify (subst_list (subst v (Fun f X)) E) ((v, Fun f X) # B) = Some U" using \v \ fv (Fun f X)\ "4.prems"(1) by auto thus ?case using "4.IH"[OF \v \ fv (Fun f X)\ _ *** ****] by metis qed lemma mgu_None_is_subst_neq: fixes s t::"('a,'b) term" and \::"('a,'b) subst" assumes "mgu s t = None" shows "s \ \ \ t \ \" using assms mgu_always_unifies by force lemma mgu_None_if_neq_ground: assumes "t \ t'" "fv t = {}" "fv t' = {}" shows "mgu t t' = None" proof (rule ccontr) assume "mgu t t' \ None" then obtain \ where \: "mgu t t' = Some \" by auto hence "t \ \ = t" "t' \ \ = t'" using assms subst_ground_ident by auto thus False using assms(1) MGU_is_Unifier[OF mgu_gives_MGU[OF \]] by auto qed lemma mgu_None_commutes: "mgu s t = None \ mgu t s = None" using mgu_complete[of s t] Unifier_in_unifiers_singleton[of s _ t] Unifier_sym[of t _ s] Unifier_in_unifiers_singleton[of t _ s] mgu_sound[of t s] unfolding is_imgu_def by fastforce lemma mgu_img_subterm_subst: fixes \::"('f,'v) subst" and s t u::"('f,'v) term" assumes "mgu s t = Some \" "u \ subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \) - range Var" shows "u \ ((subterms s \ subterms t) - range Var) \\<^sub>s\<^sub>e\<^sub>t \" proof - define subterms_tuples::"('f,'v) equation list \ ('f,'v) terms" where subtt_def: "subterms_tuples \ \E. subterms\<^sub>s\<^sub>e\<^sub>t (fst ` set E) \ subterms\<^sub>s\<^sub>e\<^sub>t (snd ` set E)" define subterms_img::"('f,'v) subst \ ('f,'v) terms" where subti_def: "subterms_img \ \d. subterms\<^sub>s\<^sub>e\<^sub>t (subst_range d)" define d where "d \ \v t. subst v t::('f,'v) subst" define V where "V \ range Var::('f,'v) terms" define R where "R \ \d::('f,'v) subst. ((subterms s \ subterms t) - V) \\<^sub>s\<^sub>e\<^sub>t d" define M where "M \ \E d. subterms_tuples E \ subterms_img d" define Q where "Q \ (\E d. M E d - V \ R d - V)" define Q' where "Q' \ (\E d d'. (M E d - V) \\<^sub>s\<^sub>e\<^sub>t d' \ (R d - V) \\<^sub>s\<^sub>e\<^sub>t (d'::('f,'v) subst))" have Q_subst: "Q (subst_list (subst v t') E) (subst_of ((v, t')#B))" when v_fv: "v \ fv t'" and Q_assm: "Q ((Var v, t')#E) (subst_of B)" for v t' E B proof - define E' where "E' \ subst_list (subst v t') E" define B' where "B' \ subst_of ((v, t')#B)" have E': "E' = subst_list (d v t') E" and B': "B' = subst_of B \\<^sub>s d v t'" using subst_of_simps(3)[of "(v, t')"] unfolding subst_def E'_def B'_def d_def by simp_all have vt_img_subt: "subterms\<^sub>s\<^sub>e\<^sub>t (subst_range (d v t')) = subterms t'" and vt_dom: "subst_domain (d v t') = {v}" using v_fv by (auto simp add: subst_domain_def d_def subst_def) have *: "subterms u1 \ subterms\<^sub>s\<^sub>e\<^sub>t (fst ` set E)" "subterms u2 \ subterms\<^sub>s\<^sub>e\<^sub>t (snd ` set E)" when "(u1,u2) \ set E" for u1 u2 using that by auto have **: "subterms\<^sub>s\<^sub>e\<^sub>t (d v t' ` (fv u \ subst_domain (d v t'))) \ subterms t'" for u::"('f,'v) term" using vt_dom unfolding d_def by force have 1: "subterms_tuples E' - V \ (subterms t' - V) \ (subterms_tuples E - V \\<^sub>s\<^sub>e\<^sub>t d v t')" (is "?A \ ?B") proof fix u assume "u \ ?A" then obtain u1 u2 where u12: "(u1,u2) \ set E" "u \ (subterms (u1 \ (d v t')) - V) \ (subterms (u2 \ (d v t')) - V)" unfolding subtt_def subst_list_def E'_def d_def by moura hence "u \ (subterms t' - V) \ (((subterms_tuples E) \\<^sub>s\<^sub>e\<^sub>t d v t') - V)" using subterms_subst[of u1 "d v t'"] subterms_subst[of u2 "d v t'"] *[OF u12(1)] **[of u1] **[of u2] unfolding subtt_def subst_list_def by auto moreover have "(subterms_tuples E \\<^sub>s\<^sub>e\<^sub>t d v t') - V \ (subterms_tuples E - V \\<^sub>s\<^sub>e\<^sub>t d v t') \ {t'}" unfolding subst_def subtt_def V_def d_def by force ultimately show "u \ ?B" using u12 v_fv by auto qed have 2: "subterms_img B' - V \ (subterms t' - V) \ (subterms_img (subst_of B) - V \\<^sub>s\<^sub>e\<^sub>t d v t')" using B' vt_img_subt subst_img_comp_subset'''[of "subst_of B" "d v t'"] unfolding subti_def subst_def V_def by argo have 3: "subterms_tuples ((Var v, t')#E) - V = (subterms t' - V) \ (subterms_tuples E - V)" by (auto simp add: subst_def subtt_def V_def) have "fv\<^sub>s\<^sub>e\<^sub>t (subterms t' - V) \ subst_domain (d v t') = {}" using v_fv vt_dom fv_subterms[of t'] by fastforce hence 4: "subterms t' - V \\<^sub>s\<^sub>e\<^sub>t d v t' = subterms t' - V" using set_subst_ident[of "subterms t' - range Var" "d v t'"] by (simp add: V_def) have "M E' B' - V \ M ((Var v, t')#E) (subst_of B) - V \\<^sub>s\<^sub>e\<^sub>t d v t'" using 1 2 3 4 unfolding M_def by blast moreover have "Q' ((Var v, t')#E) (subst_of B) (d v t')" using Q_assm unfolding Q_def Q'_def by auto moreover have "R (subst_of B) \\<^sub>s\<^sub>e\<^sub>t d v t' = R (subst_of ((v,t')#B))" unfolding R_def d_def by auto ultimately have "M (subst_list (d v t') E) (subst_of ((v, t')#B)) - V \ R (subst_of ((v, t')#B)) - V" unfolding Q'_def E'_def B'_def d_def by blast thus ?thesis unfolding Q_def M_def R_def d_def by blast qed have "u \ subterms s \ subterms t - V \\<^sub>s\<^sub>e\<^sub>t subst_of U" when assms': "unify E B = Some U" "u \ subterms\<^sub>s\<^sub>e\<^sub>t (subst_range (subst_of U)) - V" "Q E (subst_of B)" for E B U and T::"('f,'v) term list" using assms' proof (induction E B arbitrary: U rule: Unification.unify.induct) case (1 B) thus ?case by (auto simp add: Q_def M_def R_def subti_def) next case (2 g X h Y E B U) from "2.prems"(1) obtain E' where E': "decompose (Fun g X) (Fun h Y) = Some E'" "g = h" "length X = length Y" "E' = zip X Y" "Unification.unify (E'@E) B = Some U" by (auto split: option.splits) moreover have "subterms_tuples (E'@E) \ subterms_tuples ((Fun g X, Fun h Y)#E)" proof fix u assume "u \ subterms_tuples (E'@E)" then obtain u1 u2 where u12: "(u1,u2) \ set (E'@E)" "u \ subterms u1 \ subterms u2" unfolding subtt_def by fastforce thus "u \ subterms_tuples ((Fun g X, Fun h Y)#E)" proof (cases "(u1,u2) \ set E'") case True hence "subterms u1 \ subterms (Fun g X)" "subterms u2 \ subterms (Fun h Y)" using E'(4) subterms_subset params_subterms subsetCE by (metis set_zip_leftD, metis set_zip_rightD) thus ?thesis using u12 unfolding subtt_def by auto next case False thus ?thesis using u12 unfolding subtt_def by fastforce qed qed hence "Q (E'@E) (subst_of B)" using "2.prems"(3) unfolding Q_def M_def by blast ultimately show ?case using "2.IH"[of E' U] "2.prems" by meson next case (3 v t' E B) show ?case proof (cases "t' = Var v") case True thus ?thesis using "3.prems" "3.IH"(1) unfolding Q_def M_def V_def subtt_def by auto next case False hence 1: "v \ fv t'" using "3.prems"(1) by auto hence "unify (subst_list (subst v t') E) ((v, t')#B) = Some U" using False "3.prems"(1) by auto thus ?thesis using Q_subst[OF 1 "3.prems"(3)] "3.IH"(2)[OF False 1 _ "3.prems"(2)] by metis qed next case (4 g X v E B U) have 1: "v \ fv (Fun g X)" using "4.prems"(1) not_None_eq by fastforce hence 2: "unify (subst_list (subst v (Fun g X)) E) ((v, Fun g X)#B) = Some U" using "4.prems"(1) by auto have 3: "Q ((Var v, Fun g X)#E) (subst_of B)" using "4.prems"(3) unfolding Q_def M_def subtt_def by auto show ?case using Q_subst[OF 1 3] "4.IH"[OF 1 2 "4.prems"(2)] by metis qed moreover obtain D where "unify [(s, t)] [] = Some D" "\ = subst_of D" using assms(1) by (auto split: option.splits) moreover have "Q [(s,t)] (subst_of [])" unfolding Q_def M_def R_def subtt_def subti_def by force ultimately show ?thesis using assms(2) unfolding V_def by auto qed lemma mgu_img_consts: fixes \::"('f,'v) subst" and s t::"('f,'v) term" and c::'f and z::'v assumes "mgu s t = Some \" "Fun c [] \ subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \)" shows "Fun c [] \ subterms s \ subterms t" proof - obtain u where "u \ (subterms s \ subterms t) - range Var" "u \ \ = Fun c []" using mgu_img_subterm_subst[OF assms(1), of "Fun c []"] assms(2) by force thus ?thesis by (cases u) auto qed lemma mgu_img_consts': fixes \::"('f,'v) subst" and s t::"('f,'v) term" and c::'f and z::'v assumes "mgu s t = Some \" "\ z = Fun c []" shows "Fun c [] \ s \ Fun c [] \ t" using mgu_img_consts[OF assms(1)] assms(2) by (metis Un_iff in_subterms_Union subst_imgI term.distinct(1)) lemma mgu_img_composed_var_term: fixes \::"('f,'v) subst" and s t::"('f,'v) term" and f::'f and Z::"'v list" assumes "mgu s t = Some \" "Fun f (map Var Z) \ subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \)" shows "\Z'. map \ Z' = map Var Z \ Fun f (map Var Z') \ subterms s \ subterms t" proof - obtain u where u: "u \ (subterms s \ subterms t) - range Var" "u \ \ = Fun f (map Var Z)" using mgu_img_subterm_subst[OF assms(1), of "Fun f (map Var Z)"] assms(2) by fastforce then obtain T where T: "u = Fun f T" "map (\t. t \ \) T = map Var Z" by (cases u) auto have "\t \ set T. \x. t = Var x" using T(2) by (induct T arbitrary: Z) auto then obtain Z' where Z': "map Var Z' = T" by (metis ex_map_conv) hence "map \ Z' = map Var Z" using T(2) by (induct Z' arbitrary: T Z) auto thus ?thesis using u(1) T(1) Z' by auto qed subsection \Lemmata: The "Inequality Lemmata"\ text \Subterm injectivity (a stronger injectivity property)\ definition subterm_inj_on where "subterm_inj_on f A \ \x\A. \y\A. (\v. v \ f x \ v \ f y) \ x = y" lemma subterm_inj_on_imp_inj_on: "subterm_inj_on f A \ inj_on f A" unfolding subterm_inj_on_def inj_on_def by fastforce lemma subst_inj_on_is_bij_betw: "inj_on \ (subst_domain \) = bij_betw \ (subst_domain \) (subst_range \)" unfolding inj_on_def bij_betw_def by auto lemma subterm_inj_on_alt_def: "subterm_inj_on f A \ (inj_on f A \ (\s \ f`A. \u \ f`A. (\v. v \ s \ v \ u) \ s = u))" (is "?A \ ?B") unfolding subterm_inj_on_def inj_on_def by fastforce lemma subterm_inj_on_alt_def': "subterm_inj_on \ (subst_domain \) \ (inj_on \ (subst_domain \) \ (\s \ subst_range \. \u \ subst_range \. (\v. v \ s \ v \ u) \ s = u))" (is "?A \ ?B") by (metis subterm_inj_on_alt_def subst_range.simps) lemma subterm_inj_on_subset: assumes "subterm_inj_on f A" and "B \ A" shows "subterm_inj_on f B" proof - have "inj_on f A" "\s\f ` A. \u\f ` A. (\v. v \ s \ v \ u) \ s = u" using subterm_inj_on_alt_def[of f A] assms(1) by auto moreover have "f ` B \ f ` A" using assms(2) by auto ultimately have "inj_on f B" "\s\f ` B. \u\f ` B. (\v. v \ s \ v \ u) \ s = u" using inj_on_subset[of f A] assms(2) by blast+ thus ?thesis by (metis subterm_inj_on_alt_def) qed lemma inj_subst_unif_consts: fixes \ \ \::"('f,'v) subst" and s t::"('f,'v) term" assumes \: "subterm_inj_on \ (subst_domain \)" "\x \ (fv s \ fv t) - X. \c. \ x = Fun c []" "subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \) \ (subterms s \ subterms t) = {}" "ground (subst_range \)" "subst_domain \ \ X = {}" and \: "ground (subst_range \)" "subst_domain \ = subst_domain \" and unif: "Unifier \ (s \ \) (t \ \)" shows "\\. Unifier \ (s \ \) (t \ \)" proof - let ?xs = "subst_domain \" let ?ys = "(fv s \ fv t) - ?xs" have "\\::('f,'v) subst. s \ \ = t \ \" by (metis subst_subst_compose unif) then obtain \::"('f,'v) subst" where \: "mgu s t = Some \" using mgu_always_unifies by moura have 1: "\\::('f,'v) subst. s \ \ \ \ = t \ \ \ \" by (metis unif) have 2: "\\::('f,'v) subst. s \ \ \ \ = t \ \ \ \ \ \ \\<^sub>\ \ \\<^sub>s \" using mgu_gives_MGU[OF \] by simp have 3: "\(z::'v) (c::'f). \ z = Fun c [] \ Fun c [] \ s \ Fun c [] \ t" by (rule mgu_img_consts'[OF \]) have 4: "subst_domain \ \ range_vars \ = {}" by (metis mgu_gives_wellformed_subst[OF \] wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def) have 5: "subst_domain \ \ range_vars \ \ fv s \ fv t" by (metis mgu_gives_wellformed_MGU[OF \] wf\<^sub>M\<^sub>G\<^sub>U_def) { fix x and \::"('f,'v) subst" assume "x \ subst_domain \" hence "(\ \\<^sub>s \) x = \ x" using \(4) ident_comp_subst_trm_if_disj[of \ \] unfolding range_vars_alt_def by fast } then obtain \::"('f,'v) subst" where \: "\x \ subst_domain \. \ x = (\ \\<^sub>s \) x" using 1 2 by moura have *: "\x. x \ subst_domain \ \ subst_domain \ \ \y \ ?ys. \ x = Var y" proof - fix x assume "x \ subst_domain \ \ ?xs" hence x: "x \ subst_domain \" "x \ subst_domain \" by auto then obtain c where c: "\ x = Fun c []" using \(2,5) 5 by moura hence *: "(\ \\<^sub>s \) x = Fun c []" using \ x by fastforce hence **: "x \ subst_domain (\ \\<^sub>s \)" "Fun c [] \ subst_range (\ \\<^sub>s \)" by (auto simp add: subst_domain_def) have "\ x = Fun c [] \ (\z. \ x = Var z \ \ z = Fun c [])" by (rule subst_img_comp_subset_const'[OF *]) moreover have "\ x \ Fun c []" proof (rule ccontr) assume "\\ x \ Fun c []" hence "Fun c [] \ s \ Fun c [] \ t" using 3 by metis moreover have "\u \ subst_range \. u \ subterms s \ subterms t" using \(3) by force hence "Fun c [] \ subterms s \ subterms t" by (metis c \ground (subst_range \)\x(2) ground_subst_dom_iff_img) ultimately show False by auto qed moreover have "\x' \ subst_domain \. \ x \ Var x'" proof (rule ccontr) assume "\(\x' \ subst_domain \. \ x \ Var x')" then obtain x' where x': "x' \ subst_domain \" "\ x = Var x'" by moura hence "\ x' = Fun c []" "(\ \\<^sub>s \) x = Fun c []" using * unfolding subst_compose_def by auto moreover have "x \ x'" using x(1) x'(2) 4 by (auto simp add: subst_domain_def) moreover have "x' \ subst_domain \" using x'(2) mgu_eliminates_dom[OF \] by (metis (no_types) subst_elim_def subst_apply_term.simps(1) vars_iff_subterm_or_eq) moreover have "(\ \\<^sub>s \) x = \ x" "(\ \\<^sub>s \) x' = \ x'" using \ x(2) x'(1) by auto ultimately show False using subterm_inj_on_imp_inj_on[OF \(1)] * by (simp add: inj_on_def subst_compose_def x'(2) subst_domain_def) qed ultimately show "\y \ ?ys. \ x = Var y" by (metis 5 x(2) subtermeqI' vars_iff_subtermeq DiffI Un_iff subst_fv_imgI sup.orderE) qed have **: "inj_on \ (subst_domain \ \ ?xs)" proof (intro inj_onI) fix x y assume *: "x \ subst_domain \ \ subst_domain \" "y \ subst_domain \ \ subst_domain \" "\ x = \ y" hence "(\ \\<^sub>s \) x = (\ \\<^sub>s \) y" unfolding subst_compose_def by auto hence "\ x = \ y" using \ * by auto thus "x = y" using inj_onD[OF subterm_inj_on_imp_inj_on[OF \(1)]] *(1,2) by simp qed define \ where "\ = (\y'. if Var y' \ \ ` (subst_domain \ \ ?xs) then Var ((inv_into (subst_domain \ \ ?xs) \) (Var y')) else Var y'::('f,'v) term)" have a1: "Unifier (\ \\<^sub>s \) s t" using mgu_gives_MGU[OF \] by auto define \' where "\' = \ \\<^sub>s \" have d1: "subst_domain \' \ ?ys" proof fix z assume z: "z \ subst_domain \'" have "z \ ?xs \ z \ subst_domain \'" proof (cases "z \ subst_domain \") case True moreover assume "z \ ?xs" ultimately have z_in: "z \ subst_domain \ \ ?xs" by simp then obtain y where y: "\ z = Var y" "y \ ?ys" using * by moura hence "\ y = Var ((inv_into (subst_domain \ \ ?xs) \) (Var y))" using \_def z_in by simp hence "\ y = Var z" by (metis y(1) z_in ** inv_into_f_eq) hence "\' z = Var z" using \'_def y(1) subst_compose_def[of \ \] by simp thus ?thesis by (simp add: subst_domain_def) next case False hence "\ z = Var z" by (simp add: subst_domain_def) moreover assume "z \ ?xs" hence "\ z = Var z" using \_def * by force ultimately show ?thesis using \'_def subst_compose_def[of \ \] by (simp add: subst_domain_def) qed moreover have "subst_domain \ \ range_vars \" unfolding \'_def \_def range_vars_alt_def by (auto simp add: subst_domain_def) hence "subst_domain \' \ subst_domain \ \ range_vars \" using subst_domain_compose[of \ \] unfolding \'_def by blast ultimately show "z \ ?ys" using 5 z by auto qed have d2: "Unifier (\' \\<^sub>s \) s t" using a1 \'_def by auto have d3: "\ \\<^sub>s \' \\<^sub>s \ = \' \\<^sub>s \" proof - { fix z::'v assume z: "z \ ?xs" then obtain u where u: "\ z = u" "fv u = {}" using \ by auto hence "(\ \\<^sub>s \' \\<^sub>s \) z = u" by (simp add: subst_compose subst_ground_ident) moreover have "z \ subst_domain \'" using d1 z by auto hence "\' z = Var z" by (simp add: subst_domain_def) hence "(\' \\<^sub>s \) z = u" using u(1) by (simp add: subst_compose) ultimately have "(\ \\<^sub>s \' \\<^sub>s \) z = (\' \\<^sub>s \) z" by metis } moreover { fix z::'v assume "z \ ?ys" hence "z \ subst_domain \" using \(2) by auto hence "(\ \\<^sub>s \' \\<^sub>s \) z = (\' \\<^sub>s \) z" by (simp add: subst_compose subst_domain_def) } moreover { fix z::'v assume "z \ ?xs" "z \ ?ys" hence "\ z = Var z" "\' z = Var z" using \(2) d1 by blast+ hence "(\ \\<^sub>s \' \\<^sub>s \) z = (\' \\<^sub>s \) z" by (simp add: subst_compose) } ultimately show ?thesis by auto qed from d2 d3 have "Unifier (\' \\<^sub>s \) (s \ \) (t \ \)" by (metis subst_subst_compose) thus ?thesis by metis qed lemma inj_subst_unif_comp_terms: fixes \ \ \::"('f,'v) subst" and s t::"('f,'v) term" assumes \: "subterm_inj_on \ (subst_domain \)" "ground (subst_range \)" "subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \) \ (subterms s \ subterms t) = {}" "(fv s \ fv t) - subst_domain \ \ X" and tfr: "\f U. Fun f U \ subterms s \ subterms t \ U = [] \ (\u \ set U. u \ Var ` X)" and \: "ground (subst_range \)" "subst_domain \ = subst_domain \" and unif: "Unifier \ (s \ \) (t \ \)" shows "\\. Unifier \ (s \ \) (t \ \)" proof - let ?xs = "subst_domain \" let ?ys = "(fv s \ fv t) - ?xs" have "ground (subst_range \)" using \(2) by auto have "\\::('f,'v) subst. s \ \ = t \ \" by (metis subst_subst_compose unif) then obtain \::"('f,'v) subst" where \: "mgu s t = Some \" using mgu_always_unifies by moura have 1: "\\::('f,'v) subst. s \ \ \ \ = t \ \ \ \" by (metis unif) have 2: "\\::('f,'v) subst. s \ \ \ \ = t \ \ \ \ \ \ \\<^sub>\ \ \\<^sub>s \" using mgu_gives_MGU[OF \] by simp have 3: "\(z::'v) (c::'f). Fun c [] \ \ z \ Fun c [] \ s \ Fun c [] \ t" using mgu_img_consts[OF \] by force have 4: "subst_domain \ \ range_vars \ = {}" using mgu_gives_wellformed_subst[OF \] by (metis wf\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t_def) have 5: "subst_domain \ \ range_vars \ \ fv s \ fv t" using mgu_gives_wellformed_MGU[OF \] by (metis wf\<^sub>M\<^sub>G\<^sub>U_def) { fix x and \::"('f,'v) subst" assume "x \ subst_domain \" hence "(\ \\<^sub>s \) x = \ x" using \ground (subst_range \)\ ident_comp_subst_trm_if_disj[of \ \ x] unfolding range_vars_alt_def by blast } then obtain \::"('f,'v) subst" where \: "\x \ subst_domain \. \ x = (\ \\<^sub>s \) x" using 1 2 by moura have ***: "\x. x \ subst_domain \ \ subst_domain \ \ fv (\ x) \ ?ys" proof - fix x assume "x \ subst_domain \ \ ?xs" hence x: "x \ subst_domain \" "x \ subst_domain \" by auto moreover have "\(\x' \ ?xs. x' \ fv (\ x))" proof (rule ccontr) assume "\\(\x' \ ?xs. x' \ fv (\ x))" then obtain x' where x': "x' \ fv (\ x)" "x' \ ?xs" by metis have "x \ x'" "x' \ subst_domain \" "\ x' = Var x'" using 4 x(1) x'(1) unfolding range_vars_alt_def by auto hence "(\ \\<^sub>s \) x' \ (\ \\<^sub>s \) x" "\ x' = (\ \\<^sub>s \) x'" using \ x(2) x'(2) by (metis subst_compose subst_mono vars_iff_subtermeq x'(1), metis subst_apply_term.simps(1) subst_compose_def) hence "\ x' \ \ x" using \ x(2) x'(2) by auto thus False using \(1) x'(2) x(2) \x \ x'\ unfolding subterm_inj_on_def by (meson subtermeqI') qed ultimately show "fv (\ x) \ ?ys" using 5 subst_dom_vars_in_subst[of x \] subst_fv_imgI[of \ x] by blast qed have **: "inj_on \ (subst_domain \ \ ?xs)" proof (intro inj_onI) fix x y assume *: "x \ subst_domain \ \ subst_domain \" "y \ subst_domain \ \ subst_domain \" "\ x = \ y" hence "(\ \\<^sub>s \) x = (\ \\<^sub>s \) y" unfolding subst_compose_def by auto hence "\ x = \ y" using \ * by auto thus "x = y" using inj_onD[OF subterm_inj_on_imp_inj_on[OF \(1)]] *(1,2) by simp qed have *: "\x. x \ subst_domain \ \ subst_domain \ \ \y \ ?ys. \ x = Var y" proof (rule ccontr) fix xi assume xi_assms: "xi \ subst_domain \ \ subst_domain \" "\(\y \ ?ys. \ xi = Var y)" hence xi_\: "xi \ subst_domain \" and \_xi_comp: "\(\y. \ xi = Var y)" using ***[of xi] 5 by auto then obtain f T where f: "\ xi = Fun f T" by (cases "\ xi") moura have "\g Y'. Y' \ [] \ Fun g (map Var Y') \ \ xi \ set Y' \ ?ys" proof - have "\c. Fun c [] \ \ xi \ Fun c [] \ \ xi" using \ xi_\ by (metis const_subterm_subst subst_compose) hence 1: "\c. \(Fun c [] \ \ xi)" using 3[of _ xi] xi_\ \(3) by auto have "\(\x. \ xi = Var x)" using f by auto hence "\g S. Fun g S \ \ xi \ (\s \ set S. (\c. s = Fun c []) \ (\x. s = Var x))" using nonvar_term_has_composed_shallow_term[of "\ xi"] by auto then obtain g S where gS: "Fun g S \ \ xi" "\s \ set S. (\c. s = Fun c []) \ (\x. s = Var x)" by moura have "\s \ set S. \x. s = Var x" using 1 term.order_trans gS by (metis (no_types, lifting) UN_I term.order_refl subsetCE subterms.simps(2) sup_ge2) then obtain S' where 2: "map Var S' = S" by (metis ex_map_conv) have "S \ []" using 1 term.order_trans[OF _ gS(1)] by fastforce hence 3: "S' \ []" "Fun g (map Var S') \ \ xi" using gS(1) 2 by auto have "set S' \ fv (Fun g (map Var S'))" by simp hence 4: "set S' \ fv (\ xi)" using 3(2) fv_subterms by force show ?thesis using ***[OF xi_assms(1)] 2 3 4 by auto qed then obtain g Y' where g: "Y' \ []" "Fun g (map Var Y') \ \ xi" "set Y' \ ?ys" by moura then obtain X where X: "map \ X = map Var Y'" "Fun g (map Var X) \ subterms s \ subterms t" using mgu_img_composed_var_term[OF \, of g Y'] by force hence "\(u::('f,'v) term) \ set (map Var X). u \ Var ` ?ys" using \(4) tfr g(1) by fastforce then obtain j where j: "j < length X" "X ! j \ ?ys" by (metis image_iff[of _ Var "fv s \ fv t - subst_domain \"] nth_map[of _ X Var] in_set_conv_nth[of _ "map Var X"] length_map[of Var X]) define yj' where yj': "yj' \ Y' ! j" define xj where xj: "xj \ X ! j" have "xj \ fv s \ fv t" using j X(1) g(3) 5 xj yj' by (metis length_map nth_map term.simps(1) in_set_conv_nth le_supE subsetCE subst_domI) hence xj_\: "xj \ subst_domain \" using j unfolding xj by simp have len: "length X = length Y'" by (rule map_eq_imp_length_eq[OF X(1)]) have "Var yj' \ \ xi" using term.order_trans[OF _ g(2)] j(1) len unfolding yj' by auto hence "\ yj' \ \ xi" using \ xi_\ by (metis subst_apply_term.simps(1) subst_compose_def subst_mono) moreover have \_xj_var: "Var yj' = \ xj" using X(1) len j(1) nth_map unfolding xj yj' by metis hence "\ yj' = \ xj" using \ xj_\ by (metis subst_apply_term.simps(1) subst_compose_def) moreover have "xi \ xj" using \_xi_comp \_xj_var by auto ultimately show False using \(1) xi_\ xj_\ unfolding subterm_inj_on_def by blast qed define \ where "\ = (\y'. if Var y' \ \ ` (subst_domain \ \ ?xs) then Var ((inv_into (subst_domain \ \ ?xs) \) (Var y')) else Var y'::('f,'v) term)" have a1: "Unifier (\ \\<^sub>s \) s t" using mgu_gives_MGU[OF \] by auto define \' where "\' = \ \\<^sub>s \" have d1: "subst_domain \' \ ?ys" proof fix z assume z: "z \ subst_domain \'" have "z \ ?xs \ z \ subst_domain \'" proof (cases "z \ subst_domain \") case True moreover assume "z \ ?xs" ultimately have z_in: "z \ subst_domain \ \ ?xs" by simp then obtain y where y: "\ z = Var y" "y \ ?ys" using * by moura hence "\ y = Var ((inv_into (subst_domain \ \ ?xs) \) (Var y))" using \_def z_in by simp hence "\ y = Var z" by (metis y(1) z_in ** inv_into_f_eq) hence "\' z = Var z" using \'_def y(1) subst_compose_def[of \ \] by simp thus ?thesis by (simp add: subst_domain_def) next case False hence "\ z = Var z" by (simp add: subst_domain_def) moreover assume "z \ ?xs" hence "\ z = Var z" using \_def * by force ultimately show ?thesis using \'_def subst_compose_def[of \ \] by (simp add: subst_domain_def) qed moreover have "subst_domain \ \ range_vars \" unfolding \'_def \_def range_vars_alt_def subst_domain_def by auto hence "subst_domain \' \ subst_domain \ \ range_vars \" using subst_domain_compose[of \ \] unfolding \'_def by blast ultimately show "z \ ?ys" using 5 z by blast qed have d2: "Unifier (\' \\<^sub>s \) s t" using a1 \'_def by auto have d3: "\ \\<^sub>s \' \\<^sub>s \ = \' \\<^sub>s \" proof - { fix z::'v assume z: "z \ ?xs" then obtain u where u: "\ z = u" "fv u = {}" using \ by auto hence "(\ \\<^sub>s \' \\<^sub>s \) z = u" by (simp add: subst_compose subst_ground_ident) moreover have "z \ subst_domain \'" using d1 z by auto hence "\' z = Var z" by (simp add: subst_domain_def) hence "(\' \\<^sub>s \) z = u" using u(1) by (simp add: subst_compose) ultimately have "(\ \\<^sub>s \' \\<^sub>s \) z = (\' \\<^sub>s \) z" by metis } moreover { fix z::'v assume "z \ ?ys" hence "z \ subst_domain \" using \(2) by auto hence "(\ \\<^sub>s \' \\<^sub>s \) z = (\' \\<^sub>s \) z" by (simp add: subst_compose subst_domain_def) } moreover { fix z::'v assume "z \ ?xs" "z \ ?ys" hence "\ z = Var z" "\' z = Var z" using \(2) d1 by blast+ hence "(\ \\<^sub>s \' \\<^sub>s \) z = (\' \\<^sub>s \) z" by (simp add: subst_compose) } ultimately show ?thesis by auto qed from d2 d3 have "Unifier (\' \\<^sub>s \) (s \ \) (t \ \)" by (metis subst_subst_compose) thus ?thesis by metis qed context begin private lemma sat_ineq_subterm_inj_subst_aux: fixes \::"('f,'v) subst" assumes "Unifier \ (s \ \) (t \ \)" "ground (subst_range \)" "(fv s \ fv t) - X \ subst_domain \" "subst_domain \ \ X = {}" shows "\\::('f,'v) subst. subst_domain \ = X \ ground (subst_range \) \ s \ \ \ \ = t \ \ \ \" proof - have "\\. Unifier \ (s \ \) (t \ \) \ interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \" proof - obtain \'::"('f,'v) subst" where *: "interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \'" using interpretation_subst_exists by metis hence "Unifier (\ \\<^sub>s \') (s \ \) (t \ \)" using assms(1) by simp thus ?thesis using * interpretation_comp by blast qed then obtain \' where \': "Unifier \' (s \ \) (t \ \)" "interpretation\<^sub>s\<^sub>u\<^sub>b\<^sub>s\<^sub>t \'" by moura define \'' where "\'' = rm_vars (UNIV - X) \'" have *: "fv (s \ \) \ X" "fv (t \ \) \ X" using assms(2,3) subst_fv_unfold_ground_img[of \] unfolding range_vars_alt_def by (simp_all add: Diff_subset_conv Un_commute) hence **: "subst_domain \'' = X" "ground (subst_range \'')" using rm_vars_img_subset[of "UNIV - X" \'] rm_vars_dom[of "UNIV - X" \'] \'(2) unfolding \''_def by auto hence "\t. t \ \ \ \'' = t \ \'' \ \" using subst_eq_if_disjoint_vars_ground[OF _ _ assms(2)] assms(4) by blast moreover have "Unifier \'' (s \ \) (t \ \)" using Unifier_dom_restrict[OF \'(1)] \''_def * by blast ultimately show ?thesis using ** by auto qed text \ The "inequality lemma": This lemma gives sufficient syntactic conditions for finding substitutions \\\ under which terms \s\ and \t\ are not unifiable. This is useful later when establishing the typing results since we there want to find well-typed solutions to inequality constraints / "negative checks" constraints, and this lemma gives conditions for protocols under which such constraints are well-typed satisfiable if satisfiable. \ lemma sat_ineq_subterm_inj_subst: fixes \ \ \::"('f,'v) subst" assumes \: "subterm_inj_on \ (subst_domain \)" "ground (subst_range \)" "subst_domain \ \ X = {}" "subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \) \ (subterms s \ subterms t) = {}" "(fv s \ fv t) - subst_domain \ \ X" and tfr: "(\x \ (fv s \ fv t) - X. \c. \ x = Fun c []) \ (\f U. Fun f U \ subterms s \ subterms t \ U = [] \ (\u \ set U. u \ Var ` X))" and \: "\\::('f,'v) subst. subst_domain \ = X \ ground (subst_range \) \ s \ \ \ \ \ t \ \ \ \" "(fv s \ fv t) - X \ subst_domain \" "subst_domain \ \ X = {}" "ground (subst_range \)" "subst_domain \ = subst_domain \" and \: "subst_domain \ = X" "ground (subst_range \)" shows "s \ \ \ \ \ t \ \ \ \" proof - have "\\. \Unifier \ (s \ \) (t \ \)" by (metis \(1) sat_ineq_subterm_inj_subst_aux[OF _ \(4,2,3)]) hence "\Unifier \ (s \ \) (t \ \)" using inj_subst_unif_consts[OF \(1) _ \(4,2,3) \(4,5)] inj_subst_unif_comp_terms[OF \(1,2,4,5) _ \(4,5)] tfr by metis moreover have "subst_domain \ \ subst_domain \ = {}" using \(2,3) \(1) by auto ultimately show ?thesis using \ subst_eq_if_disjoint_vars_ground[OF _ \(2) \(2)] by metis qed end lemma ineq_subterm_inj_cond_subst: assumes "X \ range_vars \ = {}" and "\f T. Fun f T \ subterms\<^sub>s\<^sub>e\<^sub>t S \ T = [] \ (\u \ set T. u \ Var`X)" shows "\f T. Fun f T \ subterms\<^sub>s\<^sub>e\<^sub>t (S \\<^sub>s\<^sub>e\<^sub>t \) \ T = [] \ (\u \ set T. u \ Var`X)" proof (intro allI impI) let ?M = "\S. subterms\<^sub>s\<^sub>e\<^sub>t S \\<^sub>s\<^sub>e\<^sub>t \" let ?N = "\S. subterms\<^sub>s\<^sub>e\<^sub>t (\ ` (fv\<^sub>s\<^sub>e\<^sub>t S \ subst_domain \))" fix f T assume "Fun f T \ subterms\<^sub>s\<^sub>e\<^sub>t (S \\<^sub>s\<^sub>e\<^sub>t \)" hence 1: "Fun f T \ ?M S \ Fun f T \ ?N S" using subterms_subst[of _ \] by auto have 2: "Fun f T \ subterms\<^sub>s\<^sub>e\<^sub>t (subst_range \) \ \u \ set T. u \ Var`X" using fv_subset_subterms[of "Fun f T" "subst_range \"] assms(1) unfolding range_vars_alt_def by force have 3: "\x \ subst_domain \. \ x \ Var`X" proof fix x assume "x \ subst_domain \" hence "fv (\ x) \ range_vars \" using subst_dom_vars_in_subst subst_fv_imgI unfolding range_vars_alt_def by auto thus "\ x \ Var`X" using assms(1) by auto qed show "T = [] \ (\s \ set T. s \ Var`X)" using 1 proof assume "Fun f T \ ?M S" then obtain u where u: "u \ subterms\<^sub>s\<^sub>e\<^sub>t S" "u \ \ = Fun f T" by fastforce show ?thesis proof (cases u) case (Var x) hence "Fun f T \ subst_range \" using u(2) by (simp add: subst_domain_def) hence "\u \ set T. u \ Var`X" using 2 by force thus ?thesis by auto next case (Fun g S) hence "S = [] \ (\u \ set S. u \ Var`X)" using assms(2) u(1) by metis thus ?thesis proof assume "S = []" thus ?thesis using u(2) Fun by simp next assume "\u \ set S. u \ Var`X" then obtain u' where u': "u' \ set S" "u' \ Var`X" by moura hence "u' \ \ \ set T" using u(2) Fun by auto thus ?thesis using u'(2) 3 by (cases u') force+ qed qed next assume "Fun f T \ ?N S" thus ?thesis using 2 by force qed qed subsection \Lemmata: Sufficient Conditions for Term Matching\ text \Injective substitutions from variables to variables are invertible\ definition subst_var_inv where "subst_var_inv \ X \ (\x. if Var x \ \ ` X then Var ((inv_into X \) (Var x)) else Var x)" lemma inj_var_ran_subst_is_invertible: assumes \_inj_on_t: "inj_on \ (fv t)" and \_var_on_t: "\ ` fv t \ range Var" shows "t = t \ \ \\<^sub>s subst_var_inv \ (fv t)" proof - have "\ x \ subst_var_inv \ (fv t) = Var x" when x: "x \ fv t" for x proof - obtain y where y: "\ x = Var y" using x \_var_on_t by auto hence "Var y \ \ ` (fv t)" using x by simp thus ?thesis using y inv_into_f_eq[OF \_inj_on_t x y] unfolding subst_var_inv_def by simp qed thus ?thesis by (simp add: subst_compose_def trm_subst_ident'') qed text \Sufficient conditions for matching unifiable terms\ lemma inj_var_ran_unifiable_has_subst_match: assumes "t \ \ = s \ \" "inj_on \ (fv t)" "\ ` fv t \ range Var" shows "t = s \ \ \\<^sub>s subst_var_inv \ (fv t)" using assms inj_var_ran_subst_is_invertible by fastforce end