diff --git a/thys/First_Order_Terms/Term.thy b/thys/First_Order_Terms/Term.thy --- a/thys/First_Order_Terms/Term.thy +++ b/thys/First_Order_Terms/Term.thy @@ -1,499 +1,551 @@ (* Author: Christian Sternagel Author: René Thiemann License: LGPL *) section \First-Order Terms\ theory Term imports Main begin datatype (funs_term : 'f, vars_term : 'v) "term" = is_Var: Var (the_Var: 'v) | Fun 'f (args : "('f, 'v) term list") where "args (Var _) = []" abbreviation "is_Fun t \ \ is_Var t" lemma is_VarE [elim]: "is_Var t \ (\x. t = Var x \ P) \ P" by (cases t) auto lemma is_FunE [elim]: "is_Fun t \ (\f ts. t = Fun f ts \ P) \ P" by (cases t) auto text \Reorient equations of the form @{term "Var x = t"} and @{term "Fun f ss = t"} to facilitate simplification.\ setup \ Reorient_Proc.add (fn Const (@{const_name Var}, _) $ _ => true | _ => false) #> Reorient_Proc.add (fn Const (@{const_name Fun}, _) $ _ $ _ => true | _ => false) \ simproc_setup reorient_Var ("Var x = t") = Reorient_Proc.proc simproc_setup reorient_Fun ("Fun f ss = t") = Reorient_Proc.proc text \The \emph{root symbol} of a term is defined by:\ fun root :: "('f, 'v) term \ ('f \ nat) option" where "root (Var x) = None" | "root (Fun f ts) = Some (f, length ts)" lemma finite_vars_term [simp]: "finite (vars_term t)" by (induct t) simp_all lemma finite_Union_vars_term: "finite (\t \ set ts. vars_term t)" by auto text \A substitution is a mapping \\\ from variables to terms. We call a substitution that alters the type of variables a generalized substitution, since it does not have all properties that are expected of (standard) substitutions (e.g., there is no empty substitution).\ type_synonym ('f, 'v, 'w) gsubst = "'v \ ('f, 'w) term" type_synonym ('f, 'v) subst = "('f, 'v, 'v) gsubst" fun subst_apply_term :: "('f, 'v) term \ ('f, 'v, 'w) gsubst \ ('f, 'w) term" (infixl "\" 67) where "Var x \ \ = \ x" | "Fun f ss \ \ = Fun f (map (\t. t \ \) ss)" definition subst_compose :: "('f, 'u, 'v) gsubst \ ('f, 'v, 'w) gsubst \ ('f, 'u, 'w) gsubst" (infixl "\\<^sub>s" 75) where "\ \\<^sub>s \ = (\x. (\ x) \ \)" lemma subst_subst_compose [simp]: "t \ (\ \\<^sub>s \) = t \ \ \ \" by (induct t \ rule: subst_apply_term.induct) (simp_all add: subst_compose_def) lemma subst_compose_assoc: "\ \\<^sub>s \ \\<^sub>s \ = \ \\<^sub>s (\ \\<^sub>s \)" proof (rule ext) fix x show "(\ \\<^sub>s \ \\<^sub>s \) x = (\ \\<^sub>s (\ \\<^sub>s \)) x" proof - have "(\ \\<^sub>s \ \\<^sub>s \) x = \(x) \ \ \ \" by (simp add: subst_compose_def) also have "\ = \(x) \ (\ \\<^sub>s \)" by simp finally show ?thesis by (simp add: subst_compose_def) qed qed lemma subst_apply_term_empty [simp]: "t \ Var = t" proof (induct t) case (Fun f ts) from map_ext [rule_format, of ts _ id, OF Fun] show ?case by simp qed simp interpretation subst_monoid_mult: monoid_mult "Var" "(\\<^sub>s)" by (unfold_locales) (simp add: subst_compose_assoc, simp_all add: subst_compose_def) lemma term_subst_eq: assumes "\x. x \ vars_term t \ \ x = \ x" shows "t \ \ = t \ \" using assms by (induct t) (auto) lemma term_subst_eq_rev: "t \ \ = t \ \ \ \x \ vars_term t. \ x = \ x" by (induct t) simp_all lemma term_subst_eq_conv: "t \ \ = t \ \ \ (\x \ vars_term t. \ x = \ x)" using term_subst_eq [of t \ \] and term_subst_eq_rev [of t \ \] by auto lemma subst_term_eqI: assumes "(\t. t \ \ = t \ \)" shows "\ = \" using assms [of "Var x" for x] by (intro ext) simp definition subst_domain :: "('f, 'v) subst \ 'v set" where "subst_domain \ = {x. \ x \ Var x}" fun subst_range :: "('f, 'v) subst \ ('f, 'v) term set" where "subst_range \ = \ ` subst_domain \" text \The variables introduced by a substitution.\ definition range_vars :: "('f, 'v) subst \ 'v set" where "range_vars \ = \(vars_term ` subst_range \)" lemma subst_domain_Var [simp]: "subst_domain Var = {}" by (simp add: subst_domain_def) lemma subst_range_Var[simp]: \<^marker>\contributor \Martin Desharnais\\ "subst_range Var = {}" by simp lemma range_vars_Var[simp]: \<^marker>\contributor \Martin Desharnais\\ "range_vars Var = {}" by (simp add: range_vars_def) lemma subst_apply_term_ident: \<^marker>\contributor \Martin Desharnais\\ "vars_term t \ subst_domain \ = {} \ t \ \ = t" proof (induction t) case (Var x) thus ?case by (simp add: subst_domain_def) next case (Fun f ts) thus ?case by (auto intro: list.map_ident_strong) qed lemma vars_term_subst_apply_term: \<^marker>\contributor \Martin Desharnais\\ "vars_term (t \ \) = (\x \ vars_term t. vars_term (\ x))" by (induction t) (auto simp add: insert_Diff_if subst_domain_def) corollary vars_term_subst_apply_term_subset: \<^marker>\contributor \Martin Desharnais\\ "vars_term (t \ \) \ vars_term t - subst_domain \ \ range_vars \" unfolding vars_term_subst_apply_term proof (induction t) case (Var x) show ?case by (cases "\ x = Var x") (auto simp add: range_vars_def subst_domain_def) next case (Fun f xs) thus ?case by auto qed definition is_renaming :: "('f, 'v) subst \ bool" where "is_renaming \ \ (\x. is_Var (\ x)) \ inj_on \ (subst_domain \)" lemma inv_renaming_sound: \<^marker>\contributor \Martin Desharnais\\ assumes is_var_\: "\x. is_Var (\ x)" and "inj \" shows "\ \\<^sub>s (Var \ (inv (the_Var \ \))) = Var" proof - define \' where "\' = the_Var \ \" have \_def: "\ = Var \ \'" unfolding \'_def using is_var_\ by auto from is_var_\ \inj \\ have "inj \'" unfolding inj_def \_def comp_def by fast hence "inv \' \ \' = id" using inv_o_cancel[of \'] by simp hence "Var \ (inv \' \ \') = Var" by simp hence "\x. (Var \ (inv \' \ \')) x = Var x" by metis hence "\x. ((Var \ \') \\<^sub>s (Var \ (inv \'))) x = Var x" unfolding subst_compose_def by auto thus "\ \\<^sub>s (Var \ (inv \')) = Var" using \_def by auto qed lemma ex_inverse_of_renaming: \<^marker>\contributor \Martin Desharnais\\ assumes "\x. is_Var (\ x)" and "inj \" shows "\\. \ \\<^sub>s \ = Var" using inv_renaming_sound[OF assms] by blast lemma vars_term_subst: "vars_term (t \ \) = \(vars_term ` \ ` vars_term t)" by (induct t) simp_all lemma range_varsE [elim]: assumes "x \ range_vars \" and "\t. x \ vars_term t \ t \ subst_range \ \ P" shows "P" using assms by (auto simp: range_vars_def) lemma range_vars_subst_compose_subset: "range_vars (\ \\<^sub>s \) \ (range_vars \ - subst_domain \) \ range_vars \" (is "?L \ ?R") proof fix x assume "x \ ?L" then obtain y where "y \ subst_domain (\ \\<^sub>s \)" and "x \ vars_term ((\ \\<^sub>s \) y)" by (auto simp: range_vars_def) then show "x \ ?R" proof (cases) assume "y \ subst_domain \" and "x \ vars_term ((\ \\<^sub>s \) y)" moreover then obtain v where "v \ vars_term (\ y)" and "x \ vars_term (\ v)" by (auto simp: subst_compose_def vars_term_subst) ultimately show ?thesis by (cases "v \ subst_domain \") (auto simp: range_vars_def subst_domain_def) qed (auto simp: range_vars_def subst_compose_def subst_domain_def) qed definition "subst x t = Var (x := t)" lemma subst_simps [simp]: "subst x t x = t" "subst x (Var x) = Var" by (auto simp: subst_def) lemma subst_subst_domain [simp]: "subst_domain (subst x t) = (if t = Var x then {} else {x})" proof - { fix y have "y \ {y. subst x t y \ Var y} \ y \ (if t = Var x then {} else {x})" by (cases "x = y", auto simp: subst_def) } then show ?thesis by (simp add: subst_domain_def) qed lemma subst_subst_range [simp]: "subst_range (subst x t) = (if t = Var x then {} else {t})" by (cases "t = Var x") (auto simp: subst_domain_def subst_def) lemma subst_apply_left_idemp [simp]: assumes "\ x = t \ \" shows "s \ subst x t \ \ = s \ \" using assms by (induct s) (auto simp: subst_def) lemma subst_compose_left_idemp [simp]: assumes "\ x = t \ \" shows "subst x t \\<^sub>s \ = \" by (rule subst_term_eqI) (simp add: assms) lemma subst_ident [simp]: assumes "x \ vars_term t" shows "t \ subst x u = t" proof - have "t \ subst x u = t \ Var" by (rule term_subst_eq) (auto simp: assms subst_def) then show ?thesis by simp qed lemma subst_self_idemp [simp]: "x \ vars_term t \ subst x t \\<^sub>s subst x t = subst x t" by (metis subst_simps(1) subst_compose_left_idemp subst_ident) type_synonym ('f, 'v) terms = "('f, 'v) term set" text \Applying a substitution to every term of a given set.\ abbreviation subst_apply_set :: "('f, 'v) terms \ ('f, 'v, 'w) gsubst \ ('f, 'w) terms" (infixl "\\<^sub>s\<^sub>e\<^sub>t" 60) where "T \\<^sub>s\<^sub>e\<^sub>t \ \ (\t. t \ \) ` T" text \Composition of substitutions\ lemma subst_compose: "(\ \\<^sub>s \) x = \ x \ \" by (auto simp: subst_compose_def) lemmas subst_subst = subst_subst_compose [symmetric] lemma subst_apply_eq_Var: assumes "s \ \ = Var x" obtains y where "s = Var y" and "\ y = Var x" using assms by (induct s) auto lemma subst_domain_subst_compose: "subst_domain (\ \\<^sub>s \) = (subst_domain \ - {x. \y. \ x = Var y \ \ y = Var x}) \ (subst_domain \ - subst_domain \)" by (auto simp: subst_domain_def subst_compose_def elim: subst_apply_eq_Var) text \A substitution is idempotent iff the variables in its range are disjoint from its domain. (See also "Term Rewriting and All That" \cite[Lemma 4.5.7]{AllThat}.)\ lemma subst_idemp_iff: "\ \\<^sub>s \ = \ \ subst_domain \ \ range_vars \ = {}" proof assume "\ \\<^sub>s \ = \" then have "\x. \ x \ \ = \ x \ Var" by simp (metis subst_compose_def) then have *: "\x. \y\vars_term (\ x). \ y = Var y" unfolding term_subst_eq_conv by simp { fix x y assume "\ x \ Var x" and "x \ vars_term (\ y)" with * [of y] have False by simp } then show "subst_domain \ \ range_vars \ = {}" by (auto simp: subst_domain_def range_vars_def) next assume "subst_domain \ \ range_vars \ = {}" then have *: "\x y. \ x = Var x \ \ y = Var y \ x \ vars_term (\ y)" by (auto simp: subst_domain_def range_vars_def) have "\x. \y\vars_term (\ x). \ y = Var y" proof fix x y assume "y \ vars_term (\ x)" with * [of y x] show "\ y = Var y" by auto qed then show "\ \\<^sub>s \ = \" by (simp add: subst_compose_def term_subst_eq_conv [symmetric]) qed lemma subst_compose_apply_eq_apply_lhs: \<^marker>\contributor \Martin Desharnais\\ assumes "range_vars \ \ subst_domain \ = {}" "x \ subst_domain \" shows "(\ \\<^sub>s \) x = \ x" proof (cases "\ x") case (Var y) show ?thesis proof (cases "x = y") case True with Var have \\ x = Var x\ by simp moreover from \x \ subst_domain \\ have "\ x = Var x" by (simp add: disjoint_iff subst_domain_def) ultimately show ?thesis by (simp add: subst_compose_def) next case False have "y \ range_vars \" unfolding range_vars_def UN_iff proof (rule bexI) show "y \ vars_term (Var y)" by simp next from Var False show "Var y \ subst_range \" by (simp_all add: subst_domain_def) qed hence "y \ subst_domain \" using \range_vars \ \ subst_domain \ = {}\ by (simp add: disjoint_iff) with Var show ?thesis unfolding subst_compose_def by (simp add: subst_domain_def) qed next case (Fun f ys) hence "Fun f ys \ subst_range \ \ (\y\set ys. y \ subst_range \)" using subst_domain_def by fastforce hence "\x \ vars_term (Fun f ys). x \ range_vars \" by (metis UN_I range_vars_def term.distinct(1) term.sel(4) term.set_cases(2)) hence "Fun f ys \ \ = Fun f ys \ Var" unfolding term_subst_eq_conv using \range_vars \ \ subst_domain \ = {}\ by (simp add: disjoint_iff subst_domain_def) hence "Fun f ys \ \ = Fun f ys" by simp with Fun show ?thesis by (simp add: subst_compose_def) qed lemma subst_apply_term_subst_apply_term_eq_subst_apply_term_lhs: \<^marker>\contributor \Martin Desharnais\\ assumes "range_vars \ \ subst_domain \ = {}" and "vars_term t \ subst_domain \ = {}" shows "t \ \ \ \ = t \ \" proof - from assms have "\x. x \ vars_term t \ (\ \\<^sub>s \) x = \ x" using subst_compose_apply_eq_apply_lhs by fastforce hence "t \ \ \\<^sub>s \ = t \ \" using term_subst_eq_conv[of t "\ \\<^sub>s \" \] by metis thus ?thesis by simp qed fun num_funs :: "('f, 'v) term \ nat" where "num_funs (Var x) = 0" | "num_funs (Fun f ts) = Suc (sum_list (map num_funs ts))" lemma num_funs_0: assumes "num_funs t = 0" obtains x where "t = Var x" using assms by (induct t) auto lemma num_funs_subst: "num_funs (t \ \) \ num_funs t" by (induct t) (simp_all, metis comp_apply sum_list_mono) lemma sum_list_map_num_funs_subst: assumes "sum_list (map (num_funs \ (\t. t \ \)) ts) = sum_list (map num_funs ts)" shows "\i < length ts. num_funs (ts ! i \ \) = num_funs (ts ! i)" using assms proof (induct ts) case (Cons t ts) then have "num_funs (t \ \) + sum_list (map (num_funs \ (\t. t \ \)) ts) = num_funs t + sum_list (map num_funs ts)" by (simp add: o_def) moreover have "num_funs (t \ \) \ num_funs t" by (metis num_funs_subst) moreover have "sum_list (map (num_funs \ (\t. t \ \)) ts) \ sum_list (map num_funs ts)" using num_funs_subst [of _ \] by (induct ts) (auto intro: add_mono) ultimately show ?case using Cons by (auto) (case_tac i, auto) qed simp lemma is_Fun_num_funs_less: assumes "x \ vars_term t" and "is_Fun t" shows "num_funs (\ x) < num_funs (t \ \)" using assms proof (induct t) case (Fun f ts) then obtain u where u: "u \ set ts" "x \ vars_term u" by auto then have "num_funs (u \ \) \ sum_list (map (num_funs \ (\t. t \ \)) ts)" by (intro member_le_sum_list) simp moreover have "num_funs (\ x) \ num_funs (u \ \)" using Fun.hyps [OF u] and u by (cases u; simp) ultimately show ?case by simp qed simp lemma finite_subst_domain_subst: "finite (subst_domain (subst x y))" by simp lemma subst_domain_compose: "subst_domain (\ \\<^sub>s \) \ subst_domain \ \ subst_domain \" by (auto simp: subst_domain_def subst_compose_def) lemma vars_term_disjoint_imp_unifier: fixes \ :: "('f, 'v, 'w) gsubst" assumes "vars_term s \ vars_term t = {}" and "s \ \ = t \ \" shows "\\ :: ('f, 'v, 'w) gsubst. s \ \ = t \ \" proof - let ?\ = "\x. if x \ vars_term s then \ x else \ x" have "s \ \ = s \ ?\" unfolding term_subst_eq_conv by (induct s) (simp_all) moreover have "t \ \ = t \ ?\" using assms(1) unfolding term_subst_eq_conv by (induct s arbitrary: t) (auto) ultimately have "s \ ?\ = t \ ?\" using assms(2) by simp then show ?thesis by blast qed lemma vars_term_subset_subst_eq: assumes "vars_term t \ vars_term s" and "s \ \ = s \ \" shows "t \ \ = t \ \" using assms by (induct t) (induct s, auto) subsection \Rename the Domain of a Substitution\ definition rename_subst_domain where \<^marker>\contributor \Martin Desharnais\\ "rename_subst_domain \ \ x = (if Var x \ \ ` subst_domain \ then \ (the_inv \ (Var x)) else Var x)" lemma rename_subst_domain_Var_rhs: \<^marker>\contributor \Martin Desharnais\\ "rename_subst_domain \ Var = Var" by (rule ext) (simp add: rename_subst_domain_def) lemma renaming_cancels_rename_subst_domain: \<^marker>\contributor \Martin Desharnais\\ assumes is_var_\: "\x. is_Var (\ x)" and "inj \" and vars_t: "vars_term t \ subst_domain \" shows "t \ \ \ rename_subst_domain \ \ = t \ \" unfolding subst_subst proof (intro term_subst_eq ballI) fix x assume "x \ vars_term t" with vars_t have x_in: "x \ subst_domain \" by blast obtain x' where \_x: "\ x = Var x'" using is_var_\ by (meson is_Var_def) with x_in have x'_in: "Var x' \ \ ` subst_domain \" by (metis image_eqI) have "(\ \\<^sub>s rename_subst_domain \ \) x = \ x \ rename_subst_domain \ \" by (simp add: subst_compose_def) also have "\ = rename_subst_domain \ \ x'" using \_x by simp also have "\ = \ (the_inv \ (Var x'))" by (simp add: rename_subst_domain_def if_P[OF x'_in]) also have "\ = \ (the_inv \ (\ x))" by (simp add: \_x) also have "\ = \ x" using \inj \\ by (simp add: the_inv_f_f) finally show "(\ \\<^sub>s rename_subst_domain \ \) x = \ x" by simp qed + +subsection \Rename the Domain and Range of a Substitution\ + +definition rename_subst_domain_range where \<^marker>\contributor \Martin Desharnais\\ + "rename_subst_domain_range \ \ x = + (if Var x \ \ ` subst_domain \ then + ((Var o the_inv \) \\<^sub>s \ \\<^sub>s \) (Var x) + else + Var x)" + +lemma subst_compose_renaming_rename_subst_domain_range: \<^marker>\contributor \Martin Desharnais\\ + fixes \ \ :: "('f, 'v) subst" + assumes is_var_\: "\x. is_Var (\ x)" and "inj \" + shows "\ \\<^sub>s rename_subst_domain_range \ \ = \ \\<^sub>s \" +proof (rule ext) + fix x + from is_var_\ obtain x' where "\ x = Var x'" + by (meson is_Var_def is_renaming_def) + with \inj \\ have inv_\_x': "the_inv \ (Var x') = x" + by (metis the_inv_f_f) + + show "(\ \\<^sub>s rename_subst_domain_range \ \) x = (\ \\<^sub>s \) x" + proof (cases "x \ subst_domain \") + case True + hence "Var x' \ \ ` subst_domain \" + using \\ x = Var x'\ by (metis imageI) + thus ?thesis + by (simp add: \\ x = Var x'\ rename_subst_domain_range_def subst_compose_def inv_\_x') + next + case False + hence "Var x' \ \ ` subst_domain \" + proof (rule contrapos_nn) + assume "Var x' \ \ ` subst_domain \" + hence "\ x \ \ ` subst_domain \" + unfolding \\ x = Var x'\ . + thus "x \ subst_domain \" + unfolding inj_image_mem_iff[OF \inj \\] . + qed + with False \\ x = Var x'\ show ?thesis + by (simp add: subst_compose_def subst_domain_def rename_subst_domain_range_def) + qed +qed + +corollary subst_apply_term_renaming_rename_subst_domain_range: \<^marker>\contributor \Martin Desharnais\\ + \ \This might be easier to find with @{command find_theorems}.\ + fixes t :: "('f, 'v) term" and \ \ :: "('f, 'v) subst" + assumes is_var_\: "\x. is_Var (\ x)" and "inj \" + shows "t \ \ \ rename_subst_domain_range \ \ = t \ \ \ \" + unfolding subst_subst + unfolding subst_compose_renaming_rename_subst_domain_range[OF assms] + by (rule refl) + end diff --git a/thys/First_Order_Terms/Unifiers.thy b/thys/First_Order_Terms/Unifiers.thy --- a/thys/First_Order_Terms/Unifiers.thy +++ b/thys/First_Order_Terms/Unifiers.thy @@ -1,217 +1,277 @@ (* Author: Christian Sternagel Author: René Thiemann License: LGPL *) section \Unification\ subsection \Unifiers\ text \Definition and properties of (most general) unifiers\ theory Unifiers imports Term begin (*TODO: move*) lemma map_eq_set_zipD [dest]: assumes "map f xs = map f ys" and "(x, y) \ set (zip xs ys)" shows "f x = f y" using assms proof (induct xs arbitrary: ys) case (Cons x xs) then show ?case by (cases ys) auto qed simp type_synonym ('f, 'v) equation = "('f, 'v) term \ ('f, 'v) term" type_synonym ('f, 'v) equations = "('f, 'v) equation set" text \The set of unifiers for a given set of equations.\ definition unifiers :: "('f, 'v) equations \ ('f, 'v) subst set" where "unifiers E = {\. \p\E. fst p \ \ = snd p \ \}" text \Check whether a set of equations is unifiable.\ definition "unifiable E \ (\\. \ \ unifiers E)" lemma in_unifiersE [elim]: "\\ \ unifiers E; (\e. e \ E \ fst e \ \ = snd e \ \) \ P\ \ P" by (force simp: unifiers_def) text \Applying a substitution to a set of equations.\ definition subst_set :: "('f, 'v) subst \ ('f, 'v) equations \ ('f, 'v) equations" where "subst_set \ E = (\e. (fst e \ \, snd e \ \)) ` E" text \Check whether a substitution is a most-general unifier (mgu) of a set of equations.\ definition is_mgu :: "('f, 'v) subst \ ('f, 'v) equations \ bool" where "is_mgu \ E \ \ \ unifiers E \ (\\ \ unifiers E. (\\. \ = \ \\<^sub>s \))" text \The following property characterizes idempotent mgus, that is, mgus \<^term>\\\ for which \<^prop>\\ \\<^sub>s \ = \\ holds.\ definition is_imgu :: "('f, 'v) subst \ ('f, 'v) equations \ bool" where "is_imgu \ E \ \ \ unifiers E \ (\\ \ unifiers E. \ = \ \\<^sub>s \)" subsubsection \Properties of sets of unifiers\ lemma unifiers_Un [simp]: "unifiers (s \ t) = unifiers s \ unifiers t" by (auto simp: unifiers_def) lemma unifiers_empty [simp]: "unifiers {} = UNIV" by (auto simp: unifiers_def) lemma unifiers_insert: (* "simp not added for readability (and termination)" *) "unifiers (insert p t) = {\. fst p \ \ = snd p \ \} \ unifiers t" by (auto simp: unifiers_def) lemma unifiers_insert_ident [simp]: "unifiers (insert (t, t) E) = unifiers E" by (auto simp: unifiers_insert) lemma unifiers_insert_swap: "unifiers (insert (s, t) E) = unifiers (insert (t, s) E)" by (auto simp: unifiers_insert) lemma unifiers_insert_Var_swap [simp]: "unifiers (insert (t, Var x) E) = unifiers (insert (Var x, t) E)" by (rule unifiers_insert_swap) lemma unifiers_subst_set [simp]: "\ \ unifiers (subst_set \ E) \ \ \\<^sub>s \ \ unifiers E" by (auto simp: unifiers_def subst_set_def) lemma unifiers_insert_VarD: shows "\ \ unifiers (insert (Var x, t) E) \ subst x t \\<^sub>s \ = \" and "\ \ unifiers (insert (t, Var x) E) \ subst x t \\<^sub>s \ = \" by (auto simp: unifiers_def) lemma unifiers_insert_Var_left: "\ \ unifiers (insert (Var x, t) E) \ \ \ unifiers (subst_set (subst x t) E)" by (auto simp: unifiers_def subst_set_def) lemma unifiers_set_zip [simp]: assumes "length ss = length ts" shows "unifiers (set (zip ss ts)) = {\. map (\t. t \ \) ss = map (\t. t \ \) ts}" using assms by (induct ss ts rule: list_induct2) (auto simp: unifiers_def) lemma unifiers_Fun [simp]: "\ \ unifiers {(Fun f ss, Fun g ts)} \ length ss = length ts \ f = g \ \ \ unifiers (set (zip ss ts))" by (auto simp: unifiers_def dest: map_eq_imp_length_eq) (induct ss ts rule: list_induct2, simp_all) lemma unifiers_occur_left_is_Fun: fixes t :: "('f, 'v) term" assumes "x \ vars_term t" and "is_Fun t" shows "unifiers (insert (Var x, t) E) = {}" proof (rule ccontr) assume "\ ?thesis" then obtain \ :: "('f, 'v) subst" where "\ x = t \ \" by (auto simp: unifiers_def) with is_Fun_num_funs_less [OF assms, of \] show False by auto qed lemma unifiers_occur_left_not_Var: "x \ vars_term t \ t \ Var x \ unifiers (insert (Var x, t) E) = {}" using unifiers_occur_left_is_Fun [of x t] by (cases t) simp_all lemma unifiers_occur_left_Fun: "x \ (\t\set ts. vars_term t) \ unifiers (insert (Var x, Fun f ts) E) = {}" using unifiers_occur_left_is_Fun [of x "Fun f ts"] by simp lemmas unifiers_occur_left_simps [simp] = unifiers_occur_left_is_Fun unifiers_occur_left_not_Var unifiers_occur_left_Fun subsubsection \Properties of unifiability\ lemma in_vars_is_Fun_not_unifiable: assumes "x \ vars_term t" and "is_Fun t" shows "\ unifiable {(Var x, t)}" proof assume "unifiable {(Var x, t)}" then obtain \ where "\ \ unifiers {(Var x, t)}" by (auto simp: unifiable_def) then have "\ x = t \ \" by (auto) moreover have "num_funs (\ x) < num_funs (t \ \)" using is_Fun_num_funs_less [OF assms] by auto ultimately show False by auto qed lemma unifiable_insert_swap: "unifiable (insert (s, t) E) = unifiable (insert (t, s) E)" by (auto simp: unifiable_def unifiers_insert_swap) lemma subst_set_reflects_unifiable: fixes \ :: "('f, 'v) subst" assumes "unifiable (subst_set \ E)" shows "unifiable E" proof - { fix \ :: "('f, 'v) subst" assume "\p\E. fst p \ \ \ \ = snd p \ \ \ \" then have "\\ :: ('f, 'v) subst. \p\E. fst p \ \ = snd p \ \" by (intro exI [of _ "\ \\<^sub>s \"]) auto } then show ?thesis using assms by (auto simp: unifiable_def unifiers_def subst_set_def) qed subsubsection \Properties of \<^term>\is_mgu\\ lemma is_mgu_empty [simp]: "is_mgu Var {}" by (auto simp: is_mgu_def) lemma is_mgu_insert_trivial [simp]: "is_mgu \ (insert (t, t) E) = is_mgu \ E" by (auto simp: is_mgu_def) lemma is_mgu_insert_decomp [simp]: assumes "length ss = length ts" shows "is_mgu \ (insert (Fun f ss, Fun f ts) E) \ is_mgu \ (E \ set (zip ss ts))" using assms by (auto simp: is_mgu_def unifiers_insert) lemma is_mgu_insert_swap: "is_mgu \ (insert (s, t) E) = is_mgu \ (insert (t, s) E)" by (auto simp: is_mgu_def unifiers_def) lemma is_mgu_insert_Var_swap [simp]: "is_mgu \ (insert (t, Var x) E) = is_mgu \ (insert (Var x, t) E)" by (rule is_mgu_insert_swap) lemma is_mgu_subst_set_subst: assumes "x \ vars_term t" and "is_mgu \ (subst_set (subst x t) E)" (is "is_mgu \ ?E") shows "is_mgu (subst x t \\<^sub>s \) (insert (Var x, t) E)" (is "is_mgu ?\ ?E'") proof - from \is_mgu \ ?E\ have "?\ \ unifiers E" and *: "\\. (subst x t \\<^sub>s \) \ unifiers E \ (\\. \ = \ \\<^sub>s \)" by (auto simp: is_mgu_def) then have "?\ \ unifiers ?E'" using assms by (simp add: unifiers_insert subst_compose) moreover have "\\. \ \ unifiers ?E' \ (\\. \ = ?\ \\<^sub>s \)" proof (intro allI impI) fix \ assume **: "\ \ unifiers ?E'" then have [simp]: "subst x t \\<^sub>s \ = \" by (blast dest: unifiers_insert_VarD) from unifiers_insert_Var_left [OF **] have "subst x t \\<^sub>s \ \ unifiers E" by (simp) with * obtain \ where "\ = \ \\<^sub>s \" by blast then have "subst x t \\<^sub>s \ = subst x t \\<^sub>s \ \\<^sub>s \" by (auto simp: ac_simps) then show "\\. \ = subst x t \\<^sub>s \ \\<^sub>s \" by auto qed ultimately show "is_mgu ?\ ?E'" by (simp add: is_mgu_def) qed lemma is_imgu_imp_is_mgu: assumes "is_imgu \ E" shows "is_mgu \ E" using assms by (auto simp: is_imgu_def is_mgu_def) + +subsection \Properties of \<^term>\is_imgu\\ + +lemma rename_subst_domain_range_preserves_is_imgu: \<^marker>\contributor \Martin Desharnais\\ + fixes E :: "('f, 'v) equations" and \ \ :: "('f, 'v) subst" + assumes imgu_\: "is_imgu \ E" and is_var_\: "\x. is_Var (\ x)" and "inj \" + shows "is_imgu (rename_subst_domain_range \ \) (subst_set \ E)" +proof (unfold is_imgu_def, intro conjI ballI) + from imgu_\ have unif_\: "\ \ unifiers E" + by (simp add: is_imgu_def) + + show "rename_subst_domain_range \ \ \ unifiers (subst_set \ E)" + unfolding unifiers_subst_set unifiers_def mem_Collect_eq + proof (rule ballI) + fix e\<^sub>\ assume "e\<^sub>\ \ subst_set \ E" + then obtain e where "e \ E" and "e\<^sub>\ = (fst e \ \, snd e \ \)" + by (auto simp: subst_set_def) + then show "fst e\<^sub>\ \ rename_subst_domain_range \ \ = snd e\<^sub>\ \ rename_subst_domain_range \ \" + using unif_\ subst_apply_term_renaming_rename_subst_domain_range[OF is_var_\ \inj \\, of _ \] + by (simp add: unifiers_def) + qed +next + fix \ :: "('f, 'v) subst" + assume "\ \ unifiers (subst_set \ E)" + hence "(\ \\<^sub>s \) \ unifiers E" + by (simp add: subst_set_def unifiers_def) + with imgu_\ have \_\_\: "\ \\<^sub>s \ \\<^sub>s \ = \ \\<^sub>s \" + by (simp add: is_imgu_def subst_compose_assoc) + + show "\ = rename_subst_domain_range \ \ \\<^sub>s \" + proof (rule ext) + fix x + show "\ x = (rename_subst_domain_range \ \ \\<^sub>s \) x" + proof (cases "Var x \ \ ` subst_domain \") + case True + hence "(rename_subst_domain_range \ \ \\<^sub>s \) x = (\ \\<^sub>s \ \\<^sub>s \) (the_inv \ (Var x))" + by (simp add: rename_subst_domain_range_def subst_compose_def) + also have "\ = (\ \\<^sub>s \) (the_inv \ (Var x))" + by (simp add: \_\_\) + also have "\ = (\ (the_inv \ (Var x))) \ \" + by (simp add: subst_compose) + also have "\ = Var x \ \" + using True f_the_inv_into_f[OF \inj \\, of "Var x"] by force + finally show ?thesis + by simp + next + case False + thus ?thesis + by (simp add: rename_subst_domain_range_def subst_compose) + qed + qed +qed + +corollary rename_subst_domain_range_preserves_is_imgu_singleton: \<^marker>\contributor \Martin Desharnais\\ + fixes t u :: "('f, 'v) term" and \ \ :: "('f, 'v) subst" + assumes imgu_\: "is_imgu \ {(t, u)}" and is_var_\: "\x. is_Var (\ x)" and "inj \" + shows "is_imgu (rename_subst_domain_range \ \) {(t \ \, u \ \)}" + by (rule rename_subst_domain_range_preserves_is_imgu[OF imgu_\ is_var_\ \inj \\, + unfolded subst_set_def, simplified]) + end