diff --git a/thys/SuperCalc/terms.thy b/thys/SuperCalc/terms.thy --- a/thys/SuperCalc/terms.thy +++ b/thys/SuperCalc/terms.thy @@ -1,1332 +1,1340 @@ theory terms (* N. Peltier - http://membres-lig.imag.fr/peltier/ *) imports "HOL-ex.Unification" begin section \Terms\ subsection \Basic Syntax\ text \We use the same term representation as in the Unification theory provided in Isabelle. Terms are represented by binary trees built on variables and constant symbols.\ fun is_a_variable where "(is_a_variable (Var x)) = True" | "(is_a_variable (Const x)) = False" | "(is_a_variable (Comb x y)) = False" fun is_a_constant where "(is_a_constant (Var x)) = False" | "(is_a_constant (Const x)) = True" | "(is_a_constant (Comb x y)) = False" fun is_compound where "(is_compound (Var x)) = False" | "(is_compound (Const x)) = False" | "(is_compound (Comb x y)) = True" definition ground_term :: "'a trm \ bool" where "(ground_term t) = (vars_of t = {})" lemma constants_are_not_variables : assumes "is_a_constant x" shows "\ (is_a_variable x)" by (metis assms is_a_constant.elims(2) is_a_variable.elims(2) trm.distinct(2)) lemma constants_are_ground : assumes "is_a_constant x" shows "ground_term x" proof - from assms obtain y where "x = (Const y)" using is_a_constant.elims(2) by auto then show ?thesis by (simp add: ground_term_def) qed subsection \Positions\ text \We define the notion of a position together with functions to access to subterms and replace them. We establish some basic properties of these functions.\ text \Since terms are binary trees, positions are sequences of binary digits.\ datatype indices = Left | Right type_synonym position = "indices list" fun left_app where "left_app x = Left # x" fun right_app where "right_app x = Right # x" definition strict_prefix where "strict_prefix p q = (\r. (r \ []) \ (q = (append p r)))" fun subterm :: "'a trm \ position \ 'a trm \ bool" where "(subterm T [] S) = (T = S)" | "(subterm (Var v) (first # next) S) = False" | "(subterm (Const c) (first # next) S) = False" | "(subterm (Comb x y) (Left # next) S) = (subterm x next S)" | "(subterm (Comb x y) (Right # next) S) = (subterm y next S)" definition occurs_in :: "'a trm \ 'a trm \ bool" where "occurs_in t s = (\p. subterm s p t)" definition position_in :: "position \ 'a trm \ bool" where "position_in p s = (\t. subterm s p t)" fun subterms_of where "subterms_of t = { s. (occurs_in s t) }" fun proper_subterms_of where "proper_subterms_of t = { s. \p. (p \ Nil \ (subterm t p s)) }" fun pos_of where "pos_of t = { p. (position_in p t) }" fun replace_subterm :: "'a trm \ position \ 'a trm \ 'a trm \ bool" where "(replace_subterm T [] u S) = (S = u) " | "(replace_subterm (Var x) (first # next) u S) = False" | "(replace_subterm (Const c) (first # next) u S) = False" | "(replace_subterm (Comb x y) (Left # next) u S) = (\S1. (replace_subterm x next u S1) \ (S = Comb S1 y))" | "(replace_subterm (Comb x y) (Right # next) u S) = (\S2. (replace_subterm y next u S2) \ (S = Comb x S2))" lemma replace_subterm_is_a_function: shows "\t u v. subterm t p u \ \s. replace_subterm t p v s" proof (induction p,auto) next case (Cons i q) from \subterm t (Cons i q) u\ obtain t1 t2 where "t = (Comb t1 t2)" using subterm.elims(2) by blast have "i = Right \ i = Left" using indices.exhaust by auto then show ?case proof assume "i = Right" from this and \t = (Comb t1 t2)\ and \subterm t (Cons i q) u\ have "subterm t2 q u" by auto from this obtain s where "replace_subterm t2 q v s" using Cons.IH [of t2 u] by auto from this and \t = (Comb t1 t2)\ and \i = Right\ have "replace_subterm t (Cons i q) v (Comb t1 s)" by auto from this show ?case by auto next assume "i = Left" from this and \t = (Comb t1 t2)\ and \subterm t (Cons i q) u\ have "subterm t1 q u" by auto from this obtain s where "replace_subterm t1 q v s" using Cons.IH [of t1 u] by auto from this and \t = (Comb t1 t2)\ and \i = Left\ have "replace_subterm t (Cons i q) v (Comb s t2)" by auto from this show ?case by auto qed qed text \We prove some useful lemmata concerning the set of variables or subterms occurring in a term.\ lemma root_subterm: shows "t \ (subterms_of t)" by (metis mem_Collect_eq occurs_in_def subterm.simps(1) subterms_of.simps) lemma root_position: shows "Nil \ (pos_of t)" by (metis mem_Collect_eq subterm.simps(1) position_in_def pos_of.simps) lemma subterms_of_an_atomic_term: assumes "is_a_variable t \ is_a_constant t" shows "subterms_of t = { t }" proof show "subterms_of t \ { t }" proof fix x assume "x \ subterms_of t" then have "occurs_in x t" by auto then have "\p. (subterm t p x)" unfolding occurs_in_def by auto from this and assms have "x = t" by (metis is_a_constant.simps(3) is_a_variable.simps(3) subterm.elims(2)) thus "x \ { t }" by auto qed next show "{ t } \ subterms_of t" proof fix x assume "x \ { t }" then show "x \ subterms_of t" using root_subterm by auto qed qed lemma positions_of_an_atomic_term: assumes "is_a_variable t \ is_a_constant t" shows "pos_of t = { Nil }" proof show "pos_of t \ { Nil }" proof fix x assume "x \ pos_of t" then have "position_in x t" by auto then have "\s. (subterm t x s)" unfolding position_in_def by auto from this and assms have "x = Nil" by (metis is_a_constant.simps(3) is_a_variable.simps(3) subterm.elims(2)) thus "x \ { Nil }" by auto qed next show "{ Nil } \ pos_of t" proof fix x :: "indices list" assume "x \ { Nil }" then show "x \ pos_of t" using root_position by auto qed qed lemma subterm_of_a_subterm_is_a_subterm : assumes "subterm u q v" shows "\ t. subterm t p u \ subterm t (append p q) v" proof (induction p) case Nil show "?case" using Nil.prems assms by auto next case (Cons i p') from \subterm t (Cons i p') u\ obtain t1 t2 where "t = (Comb t1 t2)" using subterm.elims(2) by blast have "i = Right \ i = Left" using indices.exhaust by auto then show ?case proof assume "i = Right" from this and \subterm t (Cons i p') u\ and \t = (Comb t1 t2)\ have "subterm t2 p' u" by auto from this have "subterm t2 (append p' q) v" by (simp add: Cons.IH) from this and \t = (Comb t1 t2)\ and \i = Right\ show "subterm t (append (Cons i p') q) v" by simp next assume "i = Left" from this and \subterm t (Cons i p') u\ and \t = (Comb t1 t2)\ have "subterm t1 p' u" by auto from this have "subterm t1 (append p' q) v" by (simp add: Cons.IH) from this and \t = (Comb t1 t2)\ and \i = Left\ show "subterm t (append (Cons i p') q) v" by simp qed qed lemma occur_in_subterm: assumes "occurs_in u t" assumes "occurs_in t s" shows "occurs_in u s" by (meson assms(1) assms(2) occurs_in_def subterm_of_a_subterm_is_a_subterm) lemma vars_of_subterm : assumes "x \ vars_of s" shows "\ t. subterm t p s \ x \ vars_of t" proof (induction p) case Nil show "?case" using Nil.prems assms by auto next case (Cons i p') from \subterm t (Cons i p') s\ obtain t1 t2 where "t = (Comb t1 t2)" using subterm.elims(2) by blast have "i = Right \ i = Left" using indices.exhaust by auto then show ?case proof assume "i = Right" from this and \subterm t (Cons i p') s\ and \t = (Comb t1 t2)\ have "subterm t2 p' s" by auto from this have "x \ vars_of t2" by (simp add: Cons.IH) from this and \t = (Comb t1 t2)\ and \i = Right\ show ?case by simp next assume "i = Left" from this and \subterm t (Cons i p') s\ and \t = (Comb t1 t2)\ have "subterm t1 p' s" by auto from this have "x \ vars_of t1" by (simp add: Cons.IH) from this and \t = (Comb t1 t2)\ and \i = Left\ show ?case by simp qed qed lemma vars_subterm : assumes "subterm t p s" shows "vars_of s \ vars_of t" by (meson assms subsetI vars_of_subterm) lemma vars_subterms_of : assumes "s \ subterms_of t" shows "vars_of s \ vars_of t" using assms occurs_in_def vars_subterm by fastforce lemma subterms_of_a_non_atomic_term: shows "subterms_of (Comb t1 t2) = (subterms_of t1) \ (subterms_of t2) \ { (Comb t1 t2) }" proof show "subterms_of (Comb t1 t2) \ (subterms_of t1) \ (subterms_of t2) \ { (Comb t1 t2) }" proof fix x assume "x \ (subterms_of (Comb t1 t2))" then have "occurs_in x (Comb t1 t2)" by auto then obtain p where "subterm (Comb t1 t2) p x" unfolding occurs_in_def by auto have "p = [] \ (\i q. p = i #q)" using neq_Nil_conv by blast then show "x \ (subterms_of t1) \ (subterms_of t2) \ { (Comb t1 t2) }" proof assume "p = []" from this and \subterm (Comb t1 t2) p x\ show ?thesis by auto next assume "\i q. p = i #q" then obtain i q where "p = i # q" by auto have "i = Left \ i = Right" using indices.exhaust by blast then show "x \ (subterms_of t1) \ (subterms_of t2) \ { (Comb t1 t2) }" proof assume "i = Left" from this and \p = i # q\ and \subterm (Comb t1 t2) p x\ have "subterm t1 q x" by auto then have "occurs_in x t1" unfolding occurs_in_def by auto then show "x \ (subterms_of t1) \ (subterms_of t2) \ { (Comb t1 t2) }" by auto next assume "i = Right" from this and \p = i # q\ and \subterm (Comb t1 t2) p x\ have "subterm t2 q x" by auto then have "occurs_in x t2" unfolding occurs_in_def by auto then show "x \ (subterms_of t1) \ (subterms_of t2) \ { (Comb t1 t2) }" by auto qed qed qed next show "(subterms_of t1) \ (subterms_of t2) \ { (Comb t1 t2) } \ subterms_of (Comb t1 t2)" proof fix x assume "x \ (subterms_of t1) \ (subterms_of t2) \ { (Comb t1 t2) }" then have "x \ (subterms_of t1) \ (x \ (subterms_of t2) \ x = (Comb t1 t2))" by auto thus "x \ subterms_of (Comb t1 t2)" proof assume "x \ (subterms_of t1)" then have "occurs_in x t1" by auto then obtain p where "subterm t1 p x" unfolding occurs_in_def by auto then have "subterm (Comb t1 t2) (Left # p) x" by auto then have "occurs_in x (Comb t1 t2)" using occurs_in_def by blast then show "x \ subterms_of (Comb t1 t2)" by auto next assume "(x \ (subterms_of t2) \ x = (Comb t1 t2))" then show "x \ subterms_of (Comb t1 t2)" proof assume "x \ (subterms_of t2)" then have "occurs_in x t2" by auto then obtain p where "subterm t2 p x" unfolding occurs_in_def by auto then have "subterm (Comb t1 t2) (Right # p) x" by auto then have "occurs_in x (Comb t1 t2)" using occurs_in_def by blast then show "x \ subterms_of (Comb t1 t2)" by auto next assume "x = (Comb t1 t2)" show "x \ subterms_of (Comb t1 t2)" using \x = t1 \ t2\ root_subterm by blast qed qed qed qed lemma positions_of_a_non_atomic_term: shows "pos_of (Comb t1 t2) = (left_app ` (pos_of t1)) \ (right_app ` (pos_of t2)) \ { Nil }" proof show "pos_of (Comb t1 t2) \ (left_app ` (pos_of t1)) \ (right_app ` (pos_of t2)) \ { Nil }" proof fix x assume "x \ pos_of (Comb t1 t2)" then have "position_in x (Comb t1 t2)" by auto then obtain s where "subterm (Comb t1 t2) x s" unfolding position_in_def by auto have "x = [] \ (\i q. x = i #q)" using neq_Nil_conv by blast then show "x \ (left_app ` (pos_of t1)) \ (right_app ` (pos_of t2)) \ { Nil }" proof assume "x = []" from this and \subterm (Comb t1 t2) x s\ show ?thesis by auto next assume "\i q. x = i #q" then obtain i q where "x = i # q" by auto have "i = Left \ i = Right" using indices.exhaust by blast then show "x \ (left_app ` (pos_of t1)) \ (right_app ` (pos_of t2)) \ { Nil }" proof assume "i = Left" from this and \x = i # q\ and \subterm (Comb t1 t2) x s\ have "subterm t1 q s" by auto then have "position_in q t1" unfolding position_in_def by auto from this and \x = i # q\ \i = Left\ show "x \ (left_app ` (pos_of t1)) \ (right_app ` (pos_of t2)) \ { Nil }" by auto next assume "i = Right" from this and \x = i # q\ and \subterm (Comb t1 t2) x s\ have "subterm t2 q s" by auto then have "position_in q t2" unfolding position_in_def by auto from this and \x = i # q\ \i = Right\ show "x \ (left_app ` (pos_of t1)) \ (right_app ` (pos_of t2)) \ { Nil }" by auto qed qed qed next show "(left_app ` (pos_of t1)) \ (right_app ` (pos_of t2)) \ { Nil } \ pos_of (Comb t1 t2)" proof fix x assume "x \ (left_app ` (pos_of t1)) \ (right_app ` (pos_of t2)) \ { Nil }" then have "(x \ left_app ` (pos_of t1)) \ ((x \ (right_app ` (pos_of t2))) \ (x = Nil))" by auto thus "x \ pos_of (Comb t1 t2)" proof assume "x \ left_app ` (pos_of t1)" then obtain q where "x = Left # q" and "position_in q t1" by auto then obtain s where "subterm t1 q s" unfolding position_in_def by auto then have "subterm (Comb t1 t2) (Left # q) s" by auto from this and \x = Left # q\ have "position_in x (Comb t1 t2)" using position_in_def by blast then show "x \ pos_of (Comb t1 t2)" by auto next assume "(x \ (right_app ` (pos_of t2))) \ (x = Nil)" then show "x \ pos_of (Comb t1 t2)" proof assume "x \ right_app ` (pos_of t2)" then obtain q where "x = Right # q" and "position_in q t2" by auto then obtain s where "subterm t2 q s" unfolding position_in_def by auto then have "subterm (Comb t1 t2) (Right # q) s" by auto from this and \x = Right # q\ have "position_in x (Comb t1 t2)" using position_in_def by blast then show "x \ pos_of (Comb t1 t2)" by auto next assume "x = Nil" show "x \ pos_of (Comb t1 t2)" using \x = Nil\ root_position by blast qed qed qed qed lemma set_of_subterms_is_finite : shows "(finite (subterms_of (t :: 'a trm)))" proof (induction t) case (Var x) then show ?case using subterms_of_an_atomic_term [of "Var x"] by simp next case (Const x) then show ?case using subterms_of_an_atomic_term [of "Const x"] by simp next case (Comb t1 t2) assume "finite (subterms_of t1)" and "finite (subterms_of t2)" have "subterms_of (Comb t1 t2) = subterms_of t1 \ subterms_of t2 \ { Comb t1 t2 }" using subterms_of_a_non_atomic_term by auto from this and \finite (subterms_of t1)\ and \finite (subterms_of t2)\ show "finite (subterms_of (Comb t1 t2))" by simp qed lemma set_of_positions_is_finite : shows "(finite (pos_of (t :: 'a trm)))" proof (induction t) case (Var x) then show ?case using positions_of_an_atomic_term [of "Var x"] by simp next case (Const x) then show ?case using positions_of_an_atomic_term [of "Const x"] by simp next case (Comb t1 t2) assume "finite (pos_of t1)" and "finite (pos_of t2)" from \finite (pos_of t1)\ have i: "finite (left_app ` (pos_of t1))" by auto from \finite (pos_of t2)\ have ii: "finite (right_app ` (pos_of t2))" by auto have "pos_of (Comb t1 t2) = (left_app ` (pos_of t1)) \ (right_app ` (pos_of t2)) \ { Nil }" using positions_of_a_non_atomic_term by metis from this and i ii show "finite (pos_of (Comb t1 t2))" by simp qed lemma vars_of_instances: shows "vars_of (subst t \) = \ { V. \x. (x \ (vars_of t)) \ (V = vars_of (subst (Var x) \)) }" proof (induction t) case (Const a) have "vars_of (Const a) = {}" by auto then have rhs_empty: "\ { V. \x. (x \ (vars_of (Const a))) \ (V = vars_of (subst (Var x) \)) } = {}" by auto have lhs_empty: "(subst (Const a) \) = (Const a)" by auto from rhs_empty and lhs_empty show ?case by auto next case (Var a) have "vars_of (Var a) = { a }" by auto then have rhs: "\ { V. \x. (x \ (vars_of (Var a))) \ (V = vars_of (subst (Var x) \)) } = vars_of (subst (Var a) \)" by auto have lhs: "(subst (Var a) \) = (subst (Var a) \)" by auto from rhs and lhs show ?case by auto next case (Comb t1 t2) have "vars_of (Comb t1 t2) = (vars_of t1) \ (vars_of t2)" by auto then have "\ { V. \x. (x \ (vars_of (Comb t1 t2))) \ (V = vars_of (subst (Var x) \)) } = \ { V. \x. (x \ (vars_of t1)) \ (V = vars_of (subst(Var x) \)) } \ \ { V. \x. (x \ (vars_of t2)) \ (V = vars_of (subst (Var x) \)) }" by auto then have rhs: "\ { V. \x. (x \ (vars_of (Comb t1 t2))) \ (V = vars_of (subst (Var x) \)) } = (vars_of (subst t1 \)) \ (vars_of (subst t2 \))" using \vars_of (subst t1 \) = \ { V. \x. (x \ (vars_of t1)) \ (V = vars_of (subst (Var x) \)) }\ and \vars_of (subst t2 \) = \ { V. \x. (x \ (vars_of t2)) \ (V = vars_of (subst (Var x) \)) }\ by auto have "(subst (Comb t1 t2) \) = (Comb (subst t1 \) (subst t2 \))" by auto then have lhs: "(vars_of (subst (Comb t1 t2) \)) = (vars_of (subst t1 \)) \ (vars_of (subst t2 \))" by auto from lhs and rhs show ?case by auto qed lemma subterms_of_instances : "\u v u' s. (u = (subst v s) \ (subterm u p u') \ (\x q1 q2. (is_a_variable x) \ (subterm (subst x s) q1 u') \ (subterm v q2 x) \ (p = (append q2 q1))) \ ((\ v'. ((\ is_a_variable v') \ (subterm v p v') \ (u' = (subst v' s))))))" (is "?prop p") proof (induction p) case Nil show "?case" proof ((rule allI)+,(rule impI)+) fix u ::"'a trm" fix v u' s assume "u = (subst v s)" and "subterm u [] u'" then have "u = u'" by auto show "(\x q1 q2. (is_a_variable x) \ (subterm (subst x s) q1 u') \ (subterm v q2 x) \ ([] = (append q2 q1))) \ ((\ v'. ((\ is_a_variable v') \ (subterm v [] v') \ (u' = (subst v' s)))))" proof (cases) assume "is_a_variable v" from \u = u'\and \u = (subst v s)\ have "(subterm (subst v s) [] u')" by auto have "subterm v [] v" by auto from this and \(subterm (subst v s) [] u')\ and \is_a_variable v\ show ?thesis by auto next assume "\ is_a_variable v" from \u = u'\ and \u = (subst v s)\ have "((subterm v [] v) \ (u' = (subst v s)))" by auto then show ?thesis by auto qed qed next case (Cons i q) show ?case proof ((rule allI)+,(rule impI)+) fix u ::"'a trm" fix v u' s assume "u = (subst v s)" and "subterm u (Cons i q) u'" show "(\x q1 q2. (is_a_variable x) \ (subterm (subst x s) q1 u') \ (subterm v q2 x) \ ((Cons i q) = (append q2 q1))) \ ((\ v'. ((\ is_a_variable v') \ (subterm v (Cons i q) v') \ (u' = (subst v' s)))))" proof (cases v) fix x assume "v = (Var x)" then have "subterm v [] v" by auto from \v = (Var x)\ have "is_a_variable v" by auto have "Cons i q = (append [] (Cons i q))" by auto from \subterm u (Cons i q) u'\ and \u = (subst v s)\ and \v = (Var x)\ have "subterm (subst v s) (Cons i q) u'" by auto from \is_a_variable v\ and \subterm v [] v\ and \Cons i q = (append [] (Cons i q))\ and this show ?thesis by blast next fix x assume "v = (Const x)" from this and \u = (subst v s)\ have "u = v" by auto from this and \v = (Const x)\ and \subterm u (Cons i q) u'\ show ?thesis by auto next fix t1 t2 assume "v = (Comb t1 t2)" from this and \u = (subst v s)\ have "u = (Comb (subst t1 s) (subst t2 s))" by auto have "i = Left \ i = Right" using indices.exhaust by auto from \i = Left \ i = Right\ and \u = (Comb (subst t1 s) (subst t2 s))\ and \subterm u (Cons i q) u'\ obtain ti where "subterm (subst ti s) q u'" and "ti = t1 \ ti = t2" and "subterm v [i] ti" using \v = t1 \ t2\ by auto from \?prop q\ and \subterm (subst ti s) q u'\ have "(\x q1 q2. (is_a_variable x) \ (subterm (subst x s) q1 u') \ (subterm ti q2 x) \ (q = (append q2 q1))) \ ((\ v'. ((\ is_a_variable v') \ (subterm ti q v') \ (u' = (subst v' s)))))" by auto then show ?thesis proof assume "(\x q1 q2. (is_a_variable x) \ (subterm (subst x s) q1 u') \ (subterm ti q2 x) \ (q = (append q2 q1)))" then obtain x q1 q2 where "is_a_variable x" and "subterm (subst x s) q1 u'" and "subterm ti q2 x" and "q = (append q2 q1)" by auto from \subterm ti q2 x\ and \subterm v [i] ti\ have "subterm v (i # q2) x" using \i = indices.Left \ i = indices.Right\ \v = t1 \ t2\ by auto from \q = append q2 q1\ have "i # q = (append (i # q2) q1)" by auto from \i # q = (append (i # q2) q1)\ and \is_a_variable x\ and \subterm (subst x s) q1 u'\ and \subterm v (i # q2) x\ show ?thesis by blast next assume "((\ v'. ((\ is_a_variable v') \ (subterm ti q v') \ (u' = (subst v' s)))))" then obtain v' where "(\ is_a_variable v')" "(subterm ti q v')" and "u' = (subst v' s)" by auto from \subterm ti q v'\ and \subterm v [i] ti\ have "subterm v (i # q) v'" using \i = indices.Left \ i = indices.Right\ \v = t1 \ t2\ by auto from this and \(\ is_a_variable v')\ \subterm ti q v'\ and \u' = (subst v' s)\ show ?thesis by auto qed qed qed qed lemma vars_of_replacement: shows "\ t s. x \ vars_of s \ replace_subterm t p v s \ x \ (vars_of t) \ (vars_of v)" proof (induction p) case Nil from \replace_subterm t Nil v s\ have "s = v" by auto from this and \x \ vars_of s\ show ?case by auto next case (Cons i q) from \replace_subterm t (Cons i q) v s\ obtain t1 t2 where "t = (Comb t1 t2)" by (metis is_a_variable.cases replace_subterm.simps(2) replace_subterm.simps(3)) have "i = Left \ i = Right" using indices.exhaust by blast then show ?case proof assume "i = Left" from this and \t = Comb t1 t2\ and \replace_subterm t (Cons i q) v s\ obtain s1 where "s = Comb s1 t2" and "replace_subterm t1 q v s1" using replace_subterm.simps(4) by auto from \s = Comb s1 t2\ and \x \ vars_of s\ have "x \ vars_of s1 \ x \ vars_of t2" by simp then show ?case proof assume "x \ vars_of s1" from this and Cons.IH [of s1 t1] and \replace_subterm t1 q v s1\ have "x \ (vars_of t1) \ (vars_of v)" by auto from this and \t = (Comb t1 t2)\ show ?case by auto next assume "x \ vars_of t2" from this and \t = (Comb t1 t2)\ show ?case by auto qed next assume "i = Right" from this and \t = Comb t1 t2\ and \replace_subterm t (Cons i q) v s\ obtain s2 where "s = Comb t1 s2" and "replace_subterm t2 q v s2" using replace_subterm.simps by auto from \s = Comb t1 s2\ and \x \ vars_of s\ have "x \ vars_of t1 \ x \ vars_of s2" by simp then show ?case proof assume "x \ vars_of s2" from this and Cons.IH [of s2 t2] and \replace_subterm t2 q v s2\ have "x \ (vars_of t2) \ (vars_of v)" by auto from this and \t = (Comb t1 t2)\ show ?case by auto next assume "x \ vars_of t1" from this and \t = (Comb t1 t2)\ show ?case by auto qed qed qed lemma vars_of_replacement_set: assumes "replace_subterm t p v s" shows "vars_of s \ (vars_of t) \ (vars_of v)" by (meson assms subsetI vars_of_replacement) subsection \Substitutions and Most General Unifiers\ text \Substitutions are defined in the Unification theory. We provide some additional definitions and lemmata.\ fun subst_set :: "'a trm set => 'a subst => 'a trm set" where "(subst_set S \) = { u. \t. u = (subst t \) \ t \ S }" definition subst_codomain where "subst_codomain \ V = { x. \y. (subst (Var y) \) = (Var x) \ (y \ V) }" lemma subst_codomain_is_finite: assumes "finite A" shows "finite (subst_codomain \ A)" proof - have i: "((\x. (Var x)) ` (subst_codomain \ A)) \ ((\x. (subst (Var x) \)) ` A)" proof fix x assume "x \ ((\x. (Var x)) ` (subst_codomain \ A))" from this obtain y where "y \ (subst_codomain \ A)" and "x = (Var y)" by auto from \y \ (subst_codomain \ A)\ obtain z where "(subst (Var z) \) = (Var y)" "(z \ A)" unfolding subst_codomain_def by auto from \(z \ A)\ \x = (Var y)\ \(subst (Var z) \) = (Var y)\ this show "x \ ((\x. (subst (Var x) \)) ` A)"using image_iff by fastforce qed have "inj_on (\x. (Var x)) (subst_codomain \ A)" by (meson inj_onI trm.inject(1)) from assms(1) have "finite ((\x. (subst (Var x) \)) ` A)" by auto from this and i have "finite ((\x. (Var x)) ` (subst_codomain \ A))" using rev_finite_subset by auto from this and \inj_on (\x. (Var x)) (subst_codomain \ A)\ show ?thesis using finite_imageD [of "(\x. (Var x))" "subst_codomain \ A"] by auto qed text \The notions of unifiers, most general unifiers, the unification algorithm and a proof of correctness are provided in the Unification theory. Below, we prove that the algorithm is complete.\ lemma subt_decompose: shows "\t1 t2. Comb t1 t2 \ s \ (t1 \ s \ t2\ s) " proof ((induction s),(simp),(simp)) case (Comb s1 s2) show ?case proof ((rule allI)+,(rule impI)) fix t1 t2 assume "Comb t1 t2 \ Comb s1 s2" show "t1 \ (Comb s1 s2) \ t2 \ (Comb s1 s2)" proof (rule ccontr) assume neg: "\(t1 \ (Comb s1 s2) \ t2 \ (Comb s1 s2))" from \Comb t1 t2 \ Comb s1 s2\ have d: "Comb t1 t2 = s1 \ Comb t1 t2 = s2 \ Comb t1 t2 \ s1 \ Comb t1 t2 \ s2" by auto have i: "\ (Comb t1 t2 = s1)" proof assume "(Comb t1 t2 = s1)" then have "t1 \ s1" and "t2 \ s1" by auto from this and neg show False by auto qed have ii: "\ (Comb t1 t2 = s2)" proof assume "(Comb t1 t2 = s2)" then have "t1 \ s2" and "t2 \ s2" by auto from this and neg show False by auto qed have iii: "\ (Comb t1 t2 \ s1)" proof assume "(Comb t1 t2 \ s1)" then have "t1 \ s1 \ t2 \ s1" using Comb.IH by metis from this and neg show False by auto qed have iv: "\ (Comb t1 t2 \ s2)" proof assume "(Comb t1 t2 \ s2)" then have "t1 \ s2 \ t2 \ s2" using Comb.IH by metis from this and neg show False by auto qed from d and i ii iii iv show False by auto qed qed qed lemma subt_irrefl: shows "\ (s \ s)" proof ((induction s),(simp),(simp)) case (Comb t1 t2) show ?case proof assume "Comb t1 t2 \ Comb t1 t2" then have i: "Comb t1 t2 \ t1" using Comb.IH(1) by fastforce from \Comb t1 t2 \ Comb t1 t2\ have ii: "Comb t1 t2 \ t2" using Comb.IH(2) by fastforce from i ii and \Comb t1 t2 \ Comb t1 t2\ have "Comb t1 t2 \ t1 \ Comb t1 t2 \ t2" by auto then show False proof assume "Comb t1 t2 \ t1" then have "t1 \ t1" using subt_decompose [of t1] by metis from this show False using Comb.IH by auto next assume "Comb t1 t2 \ t2" then have "t2 \ t2" using subt_decompose [of t2] by metis from this show False using Comb.IH by auto qed qed qed lemma MGU_exists: shows "\\. ((subst t \) = (subst s \) \ unify t s \ None)" proof (rule unify.induct) fix x s1 s2 show "\\ :: 'a subst .((subst (Const x) \) = (subst (Comb s1 s2) \) \ unify (Const x) (Comb s1 s2) \ None)" by simp next fix t1 t2 y show "\\ :: 'a subst.(subst (Comb t1 t2) \) = (subst (Const y) \) \ unify (Comb t1 t2) (Const y) \ None" by simp next fix x y show "\\ :: 'a subst.(subst (Const x) \) = (subst (Var y) \) \ unify (Const x) (Var y) \ None" using unify.simps(3) by fastforce next fix t1 t2 y show "\\ :: 'a subst.(subst (Comb t1 t2) \) = (subst (Var y) \) \ unify (Comb t1 t2) (Var y) \ None" by (metis option.distinct(1) subst_mono subt_irrefl unify.simps(4)) next fix x s show "\\ :: 'a subst.(subst (Var x) \) = (subst s \) \ unify (Var x) s \ None" by (metis option.distinct(1) subst_mono subt_irrefl unify.simps(5)) next fix x y show "\\ :: 'a subst.(subst (Const x) \) = (subst (Const y) \) \ unify (Const x) (Const y) \ None" by simp next fix t1 t2 s1 s2 show "\\ :: 'a subst. (subst t1 \ = subst s1 \ \ unify t1 s1 \ None) \ (\x2. unify t1 s1 = Some x2 \ \\. subst (t2 \ x2) \ = subst (s2 \ x2) \ \ unify (t2 \ x2) (s2 \ x2) \ None) \ \\. (subst (t1 \ t2) \ = subst (s1 \ s2) \ \ unify (t1 \ t2) (s1 \ s2) \ None)" proof - assume h1: "\\. (subst t1 \ = subst s1 \ \ unify t1 s1 \ None)" assume h2: "(\x2. unify t1 s1 = Some x2 \ \\. subst (t2 \ x2) \ = subst (s2 \ x2) \ \ unify (t2 \ x2) (s2 \ x2) \ None)" show "\\. (subst (t1 \ t2) \ = subst (s1 \ s2) \ \ unify (t1 \ t2) (s1 \ s2) \ None)" proof ((rule allI),(rule impI)) fix \ assume h3: "subst (t1 \ t2) \ = subst (s1 \ s2) \" from h3 have "subst t1 \ = subst s1 \" by auto from this and h1 have "unify t1 s1 \ None" by auto from this obtain \ where "unify t1 s1 = Some \" and "MGU \ t1 s1" by (meson option.exhaust unify_computes_MGU) from \subst t1 \ = subst s1 \\ have "Unifier \ t1 s1" unfolding Unifier_def by auto from this and \MGU \ t1 s1\ obtain \ where "\ \ \ \ \" using MGU_def by metis from h3 have "subst t2 \ = subst s2 \" by auto from this and \\ \ \ \ \\ have "subst (subst t2 \) \ = subst (subst s2 \) \" by (simp add: subst_eq_def) from this and \unify t1 s1 = Some \\ and h2 [of \] have "unify (t2 \ \) (s2 \ \) \ None" by auto from this show "unify (t1 \ t2) (s1 \ s2) \ None" by (simp add: \unify t1 s1 = Some \\ option.case_eq_if) qed qed qed text \We establish some useful properties of substitutions and instances.\ definition ground_on :: "'a set \ 'a subst \ bool" where "ground_on V \ = (\x \ V. (ground_term (subst (Var x) \)))" lemma comp_subst_terms: assumes "\ \ \ \ \" shows "(subst t \) = (subst (subst t \) \)" proof - from \\ \ \ \ \\ have "((subst t \) = (subst t (\ \ \)))" by auto have "(subst t (\ \ \) = (subst (subst t \) \))" by auto from this and \((subst t \) = (subst t (\ \ \)))\ show ?thesis by auto qed lemma ground_instance: assumes "ground_on (vars_of t) \" shows "ground_term (subst t \)" proof (rule ccontr) assume "\ ground_term (subst t \)" then have "vars_of (subst t \) \ {}" unfolding ground_term_def by auto then obtain x where "x \ vars_of (subst t \)" by auto then have "x \ \ { V. \x. (x \ (vars_of t)) \ (V = vars_of (subst (Var x) \)) }" using vars_of_instances by force then obtain y where "x \ (vars_of (subst (Var y) \))" and "y \ (vars_of t)" by blast from assms(1) and \y \ (vars_of t)\ have "ground_term (subst (Var y) \)" unfolding ground_on_def by auto from this and \x \ (vars_of (subst (Var y) \))\ show False unfolding ground_term_def by auto qed lemma substs_preserve_groundness: assumes "ground_term t" shows "ground_term (subst t \)" by (metis assms equals0D ground_instance ground_on_def ground_term_def) lemma ground_subst_exists : "finite V \ \\. (ground_on V \)" proof (induction rule: finite.induct) case emptyI show ?case unfolding ground_on_def by simp next fix A :: "'a set" and a::'a assume "finite A" assume hyp_ind: "\\. ground_on A \" then obtain \ where "ground_on A \" by auto then show "\\. ground_on (insert a A) \" proof cases assume "a \ A" from this and hyp_ind show "\\. ground_on (insert a A) \" unfolding ground_on_def by auto next assume "a \ A" obtain c where "c = (Const a)" and "is_a_constant c" by auto obtain \ where "\ = (a,c) # \" by auto have "\x. (x \ insert a A \ (ground_term (subst (Var x) \)))" proof ((rule allI)+,(rule impI)+) fix x assume "x \ insert a A" show "ground_term (subst (Var x) \)" proof cases assume "x = a" from this and \\ = (a,c) # \\ have "(subst (Var x) \) = c" by auto from \is_a_constant c\ have "ground_term c" using constants_are_ground by auto from this and \(subst (Var x) \) = c\ show "ground_term (subst (Var x) \)" by auto next assume "x \ a" from \x \ a\ and \x \ insert a A\ have "x \ A" by auto from \x \ a\ and \\ = (a,c) # \\ have "(subst (Var x) \) = (subst (Var x) \)" by auto from this and \x \ A\ and \ground_on A \\ show "ground_term (subst (Var x) \)" unfolding ground_on_def by auto qed qed from this show ?thesis unfolding ground_on_def by auto qed qed lemma substs_preserve_ground_terms : assumes "ground_term t" shows "subst t \ = t" by (metis agreement assms equals0D ground_term_def subst_Nil) lemma substs_preserve_subterms : shows "\ t s. subterm t p s \ subterm (subst t \) p (subst s \)" proof (induction p) case Nil then have "t = s" using subterm.elims(2) by auto from \t = s\ have "(subst t \) = (subst s \)" by auto from this show ?case using Nil.prems by auto next case (Cons i q) from \subterm t (i # q) s\ obtain t1 t2 where "t = (Comb t1 t2)" using subterm.elims(2) by blast have "i = Left \ i = Right" using indices.exhaust by blast then show "subterm (subst t \) (i # q) (subst s \)" proof assume "i = Left" from this and \t = Comb t1 t2\ and \subterm t (i # q) s\ have "subterm t1 q s" by auto from this have "subterm (subst t1 \) q (subst s \)" using Cons.IH by auto from this and \t = Comb t1 t2\ show "subterm (subst t \) (i # q) (subst s \)" by (simp add: \i = indices.Left\) next assume "i = Right" from this and \t = Comb t1 t2\ and \subterm t (i # q) s\ have "subterm t2 q s" by auto from this have "subterm (subst t2 \) q (subst s \)" using Cons.IH by auto from this and \t = Comb t1 t2\ show "subterm (subst t \) (i # q) (subst s \)" by (simp add: \i = indices.Right\) qed qed lemma substs_preserve_occurs_in: assumes "occurs_in s t" shows "occurs_in (subst s \) (subst t \)" using substs_preserve_subterms using assms occurs_in_def by blast definition coincide_on where "coincide_on \ \ V = (\x \ V. (subst (Var x) \) = ( (subst (Var x) \)))" lemma coincide_sym: assumes "coincide_on \ \ V" shows "coincide_on \ \ V" by (metis assms coincide_on_def) lemma coincide_on_term: shows "\ \ \. coincide_on \ \ (vars_of t) \ subst t \ = subst t \" proof (induction t) case (Var x) from this show "subst (Var x) \ = subst (Var x) \" unfolding coincide_on_def by auto next case (Const x) show "subst (Const x) \ = subst (Const x) \" by auto next case (Comb t1 t2) from this show ?case unfolding coincide_on_def by auto qed lemma ground_replacement: assumes "replace_subterm t p v s" assumes "ground_term (subst t \)" assumes "ground_term (subst v \)" shows "ground_term (subst s \)" proof - from assms(1) have "vars_of s \ (vars_of t) \ (vars_of v)" using vars_of_replacement_set [of t p v s] by auto from assms(2) have "ground_on (vars_of t) \" unfolding ground_on_def by (metis contra_subsetD ex_in_conv ground_term_def occs_vars_subset subst_mono vars_iff_occseq) from assms(3) have "ground_on (vars_of v) \" unfolding ground_on_def by (metis contra_subsetD ex_in_conv ground_term_def occs_vars_subset subst_mono vars_iff_occseq) from \vars_of s \ (vars_of t) \ (vars_of v)\ \ground_on (vars_of t) \\ and \ground_on (vars_of v) \\ have "ground_on (vars_of s) \" by (meson UnE ground_on_def rev_subsetD) from this show ?thesis using ground_instance by blast qed text \We now show that two disjoint substitutions can always be fused.\ lemma combine_substs: assumes "finite V1" assumes "V1 \ V2 = {}" assumes "ground_on V1 \1" shows "\\. (coincide_on \ \1 V1) \ (coincide_on \ \2 V2)" proof - have "finite V1 \ ground_on V1 \1 \ V1 \ V2 = {} \ \\. (coincide_on \ \1 V1) \ (coincide_on \ \2 V2)" proof (induction rule: finite.induct) case emptyI show ?case unfolding coincide_on_def by auto next fix V1 :: "'a set" and a::'a assume "finite V1" assume hyp_ind: "ground_on V1 \1 \ V1 \ V2 = {} \ \\. (coincide_on \ \1 V1) \ (coincide_on \ \2 V2)" assume "ground_on (insert a V1) \1" assume "(insert a V1) \ V2 = {}" from this have "V1 \ V2 = {}" by auto from \ground_on (insert a V1) \1\ have "ground_on V1 \1" unfolding ground_on_def by auto from this and hyp_ind and \V1 \ V2 = {}\ obtain \' where c:"(coincide_on \' \1 V1) \ (coincide_on \' \2 V2)" by auto let ?t = "subst (Var a) \1" from assms(2) have "ground_term ?t" by (meson \ground_on (insert a V1) \1\ ground_on_def insertI1) let ?\ = "comp [(a,?t)] \'" have "coincide_on ?\ \1 (insert a V1)" proof (rule ccontr) assume "\coincide_on ?\ \1 (insert a V1)" then obtain x where "x \ (insert a V1)" and "(subst (Var x) ?\) \ ( (subst (Var x) \1))" unfolding coincide_on_def by blast have "subst (Var a) ?\ = subst ?t \'" by simp from \ground_term ?t\ have "subst (Var a) ?\ = ?t" using substs_preserve_ground_terms by auto from this and \(subst (Var x) ?\) \ ( (subst (Var x) \1))\ have "x \ a" by blast from this and \x \ (insert a V1)\ have "x \ V1" by auto from \x \ a\ have "(subst (Var x) ?\) = (subst (Var x) \')" by auto from c and \x \ V1\ have "(subst (Var x) \') = (subst (Var x) \1)" unfolding coincide_on_def by blast from this and \(subst (Var x) ?\) = (subst (Var x) \')\ and \(subst (Var x) ?\) \ ( (subst (Var x) \1))\ show False by auto qed have "coincide_on ?\ \2 V2" proof (rule ccontr) assume "\coincide_on ?\ \2 V2" then obtain x where "x \ V2" and "(subst (Var x) ?\) \ ( (subst (Var x) \2))" unfolding coincide_on_def by blast from \(insert a V1) \ V2 = {}\ and \x \ V2\ have "x \ a" by auto from this have "(subst (Var x) ?\) = (subst (Var x) \')" by auto from c and \x \ V2\ have "(subst (Var x) \') = (subst (Var x) \2)" unfolding coincide_on_def by blast from this and \(subst (Var x) ?\) = (subst (Var x) \')\ and \(subst (Var x) ?\) \ ( (subst (Var x) \2))\ show False by auto qed from \coincide_on ?\ \1 (insert a V1)\ \coincide_on ?\ \2 V2\ show "\\. (coincide_on \ \1 (insert a V1)) \ (coincide_on \ \2 V2)" by auto qed from this and assms show ?thesis by auto qed text \We define a map function for substitutions and prove its correctness.\ fun map_subst where "map_subst f Nil = Nil" | "map_subst f ((x,y) # l) = (x,(f y)) # (map_subst f l)" lemma map_subst_lemma: shows "((subst (Var x) \) \ (Var x) \ (subst (Var x) \) \ (subst (Var x) (map_subst f \))) \ ((subst (Var x) (map_subst f \)) = (f (subst (Var x) \)))" proof (induction \,simp) next case (Cons p \) let ?u = "(fst p)" let ?v = "(snd p)" show ?case proof assume "((subst (Var x) (Cons p \)) \ (Var x) \ (subst (Var x) (Cons p \)) \ (subst (Var x) (map_subst f (Cons p \))))" have "map_subst f (Cons p \) = ( (?u, (f ?v)) # (map_subst f \))" by (metis map_subst.simps(2) prod.collapse) show "(subst (Var x) (map_subst f (Cons p \))) = (f (subst (Var x) (Cons p \)))" proof cases assume "x = ?u" from this have "subst (Var x) (Cons p \) = ?v" by (metis assoc.simps(2) prod.collapse subst.simps(1)) from \map_subst f (Cons p \) = ( (?u, (f ?v)) # (map_subst f \))\ and \x = ?u\ have "subst (Var x) (map_subst f (Cons p \)) = (f ?v)" by simp from \subst (Var x) (Cons p \) = ?v\ \subst (Var x) (map_subst f (Cons p \)) = (f ?v)\ show ?thesis by auto next assume "x \ ?u" from this have "subst (Var x) (Cons p \) = (subst (Var x) \)" by (metis assoc.simps(2) prod.collapse subst.simps(1)) from \map_subst f (Cons p \) = ( (?u, (f ?v)) # (map_subst f \))\ and \x \ ?u\ have "subst (Var x) (map_subst f (Cons p \)) = subst (Var x) (map_subst f \)" by simp from this and "Cons.IH" have "subst (Var x) (map_subst f (Cons p \)) = (f (subst (Var x) \))" using \subst (Var x) (p # \) = subst (Var x) \\ \subst (Var x) (p # \) \ Var x \ subst (Var x) (p # \) \ subst (Var x) (map_subst f (p # \))\ by auto from this and \subst (Var x) (Cons p \) = (subst (Var x) \)\ show ?thesis by auto qed qed qed subsection \Congruences\ text \We now define the notion of a congruence on ground terms, i.e., an equivalence relation that is closed under contextual embedding.\ type_synonym 'a binary_relation_on_trms = "'a trm \ 'a trm \ bool" definition reflexive :: "'a binary_relation_on_trms \ bool" where "(reflexive x) = (\y. (x y y))" definition symmetric :: "'a binary_relation_on_trms \ bool" where "(symmetric x) = (\y. \z. ((x y z) = (x z y)))" definition transitive :: "'a binary_relation_on_trms \ bool" where "(transitive x) = (\y. \z. \u. (x y z) \ (x z u) \ (x y u))" definition equivalence_relation :: "'a binary_relation_on_trms \ bool" where "(equivalence_relation x) = ((reflexive x) \ (symmetric x) \ (transitive x))" definition compatible_with_structure :: "('a binary_relation_on_trms) \ bool" where "(compatible_with_structure x) = (\t1 t2 s1 s2. (x t1 s1) \ (x t2 s2) \ (x (Comb t1 t2) (Comb s1 s2)))" definition congruence :: "'a binary_relation_on_trms \ bool" where "(congruence x) = ((equivalence_relation x) \ (compatible_with_structure x))" lemma replacement_preserves_congruences : shows "\ t s. (congruence I) \ (I (subst u \) (subst v \)) \ subterm t p u \ replace_subterm t p v s \ (I (subst t \) (subst s \))" proof (induction p) case Nil from \subterm t Nil u\ have "t = u" by auto from \replace_subterm t Nil v s\ have "s = v" by auto from \t = u\ and \s = v\ and \(I (subst u \) (subst v \))\ show ?case by auto next case (Cons i q) from \subterm t (i # q) u\ obtain t1 t2 where "t = (Comb t1 t2)" using subterm.elims(2) by blast have "i = Left \ i = Right" using indices.exhaust by blast then show "I (subst t \) (subst s \)" proof assume "i = Left" from this and \t = Comb t1 t2\ and \subterm t (i # q) u\ have "subterm t1 q u" by auto from \i = Left\ and \t = Comb t1 t2\ and \replace_subterm t (i # q) v s\ obtain t1' where "replace_subterm t1 q v t1'" and "s = Comb t1' t2" by auto from \congruence I\ and \(I (subst u \) (subst v \))\ and \subterm t1 q u\ and \replace_subterm t1 q v t1'\ have "I (subst t1 \) (subst t1' \)" using Cons.IH Cons.prems(1) by blast from \congruence I\ have "I (subst t2 \) (subst t2 \)" unfolding congruence_def equivalence_relation_def reflexive_def by auto from \I (subst t1 \) (subst t1' \)\ and \I (subst t2 \) (subst t2 \)\ and \congruence I\ and \t = (Comb t1 t2)\ and \s = (Comb t1' t2)\ show "I (subst t \) (subst s \)" unfolding congruence_def compatible_with_structure_def by auto next assume "i = Right" from this and \t = Comb t1 t2\ and \subterm t (i # q) u\ have "subterm t2 q u" by auto from \i = Right\ and \t = Comb t1 t2\ and \replace_subterm t (i # q) v s\ obtain t2' where "replace_subterm t2 q v t2'" and "s = Comb t1 t2'" by auto from \congruence I\ and \(I (subst u \) (subst v \))\ and \subterm t2 q u\ and \replace_subterm t2 q v t2'\ have "I (subst t2 \) (subst t2' \)" using Cons.IH Cons.prems(1) by blast from \congruence I\ have "I (subst t1 \) (subst t1 \)" unfolding congruence_def equivalence_relation_def reflexive_def by auto from \I (subst t2 \) (subst t2' \)\ and \I (subst t1 \) (subst t1 \)\ and \congruence I\ and \t = (Comb t1 t2)\ and \s = (Comb t1 t2')\ show "I (subst t \) (subst s \)" unfolding congruence_def compatible_with_structure_def by auto qed qed definition equivalent_on where "equivalent_on \ \ V I = (\x \ V. (I (subst (Var x) \) ( (subst (Var x) \))))" lemma equivalent_on_term: assumes "congruence I" shows "\ \ \. equivalent_on \ \ (vars_of t) I \ (I (subst t \) (subst t \))" proof (induction t) case (Var x) from this show "(I (subst (Var x) \) (subst (Var x) \))" unfolding equivalent_on_def by auto next case (Const x) from assms(1) show "(I (subst (Const x) \) (subst (Const x) \))" unfolding congruence_def equivalence_relation_def reflexive_def by auto next case (Comb t1 t2) from this assms(1) show ?case unfolding equivalent_on_def unfolding congruence_def compatible_with_structure_def by auto qed subsection \Renamings\ text \We define the usual notion of a renaming. We show that fresh renamings always exist (provided the set of variables is infinite) and that renamings admit inverses.\ definition renaming where "renaming \ V = (\x \ V. (is_a_variable (subst (Var x) \)) \ (\ x y. ((x \ V) \ (y \ V) \ x \ y \ (subst (Var x) \) \ (subst (Var y) \))))" lemma renamings_admit_inverse: shows "finite V \ renaming \ V \ \ \. (\ x \ V. (subst (subst (Var x) \ ) \) = (Var x)) - \ (\ x. (x \ (subst_codomain \ V) \ (subst (Var x) \) = (Var x)))" + \ (\ x. (x \ (subst_codomain \ V) \ (subst (Var x) \) = (Var x))) + \ (\x. is_a_variable (subst (Var x) \))" proof (induction rule: finite.induct) case emptyI let ?\ = "[]" have i: "(\ x \ {}. (subst (subst (Var x) \ ) ?\) = (Var x))" by auto have ii: "(\ x. (x \ (subst_codomain \ {}) \ (subst (Var x) ?\) = (Var x)))" by auto - from i ii show ?case by metis + have iii: "\x. is_a_variable (subst (Var x) ?\)" by simp + from i ii iii show ?case by metis next fix A :: "'a set" and a::'a assume "finite A" assume hyp_ind: "renaming \ A \ \ \. (\ x \ A. (subst (subst (Var x) \ ) \) = (Var x)) - \ (\ x. (x \ (subst_codomain \ A) \ (subst (Var x) \) = (Var x)))" + \ (\ x. (x \ (subst_codomain \ A) \ (subst (Var x) \) = (Var x))) + \ (\x. is_a_variable (subst (Var x) \))" show "renaming \ (insert a A) \ \ \. (\ x \ (insert a A). (subst (subst (Var x) \ ) \) = (Var x)) - \ (\ x. (x \ (subst_codomain \ (insert a A)) \ (subst (Var x) \) = (Var x)))" + \ (\ x. (x \ (subst_codomain \ (insert a A)) \ (subst (Var x) \) = (Var x))) + \ (\x. is_a_variable (subst (Var x) \))" proof - assume "renaming \ (insert a A)" show "\ \. (\ x \ (insert a A). (subst (subst (Var x) \ ) \) = (Var x)) - \ (\ x. (x \ (subst_codomain \ (insert a A)) \ (subst (Var x) \) = (Var x)))" + \ (\ x. (x \ (subst_codomain \ (insert a A)) \ (subst (Var x) \) = (Var x))) + \ (\x. is_a_variable (subst (Var x) \))" proof (cases) assume "a \ A" from this have "insert a A = A" by auto from this and \renaming \ (insert a A)\ hyp_ind show ?thesis by metis next assume "a \ A" from \renaming \ (insert a A)\ have "renaming \ A" unfolding renaming_def by blast from this and hyp_ind obtain \ where i: "(\ x \ A. (subst (subst (Var x) \ ) \) = (Var x))" and - ii: "(\ x. (x \ (subst_codomain \ A) \ (subst (Var x) \) = (Var x)))" by metis + ii: "(\ x. (x \ (subst_codomain \ A) \ (subst (Var x) \) = (Var x)))" and + iii: "\x. is_a_variable (Var x \ \)" by metis from \renaming \ (insert a A)\ have "is_a_variable (subst (Var a) \)" unfolding renaming_def by blast from this obtain b where "(subst (Var a) \) = (Var b)" using is_a_variable.elims(2) by auto let ?\ = "(b,(Var a)) # \" have i': "(\ x \ (insert a A). (subst (subst (Var x) \ ) ?\) = (Var x))" proof fix x assume "x \ (insert a A)" show "(subst (subst (Var x) \ ) ?\) = (Var x)" proof (cases) assume "x = a" from this have "(subst (Var b) ( (b,(Var a)) # Nil)) = (Var a)" by simp have "b \ (subst_codomain \ A)" proof assume "b \ (subst_codomain \ A)" from this have "\y. (subst (Var y) \) = (Var b) \ (y \ A)" unfolding subst_codomain_def by force then obtain a' where "a' \ A" and "subst (Var a') \ = (Var b)" by metis from \a' \ A\ and \a \ A\ have "a \ a'" by auto have "a \ (insert a A)" by auto from \a \ a'\ and \a' \ A\ and \a \ (insert a A)\ and \renaming \ (insert a A)\ have "(subst (Var a) \ \ (subst (Var a') \))" unfolding renaming_def by blast from this and \subst (Var a') \ = (Var b)\ \(subst (Var a) \) = (Var b)\ show False by auto qed from this and ii have "(subst (Var b) \) = (Var b)" by auto from this and \x = a\ \(subst (Var a) \) = (Var b)\ \(subst (Var b) ( (b,(Var a)) # Nil)) = (Var a)\ show "(subst (subst (Var x) \ ) ?\) = (Var x)" by simp next assume "x \ a" from this and \x \ insert a A\ obtain "x \ A" by auto from this i have "(subst (subst (Var x) \ ) \) = (Var x)" by auto then show "(subst (subst (Var x) \ ) ?\) = (Var x)" by (metis \subst (Var a) \ = Var b\ \renaming \ (insert a A)\ \x \ insert a A\ \x \ a\ insertI1 is_a_variable.elims(2) occs.simps(1) renaming_def repl_invariance vars_iff_occseq) qed qed have ii': "(\ x. (x \ (subst_codomain \ (insert a A)) \ (subst (Var x) ?\) = (Var x)))" proof ((rule allI),(rule impI)) fix x assume "x \ subst_codomain \ (insert a A)" from this \(subst (Var a) \) = (Var b)\ have "x\ b" unfolding subst_codomain_def by auto from this have "(subst (Var x) ?\) = (subst (Var x) \)" by auto from \x \ subst_codomain \ (insert a A)\ have "x \ (subst_codomain \ A)" unfolding subst_codomain_def by auto from this and ii have "(subst (Var x) \) = (Var x)" by auto from \(subst (Var x) ?\) = (subst (Var x) \)\ and \(subst (Var x) \) = (Var x)\ show "(subst (Var x) ?\) = (Var x)" by auto - qed - from i' ii' show ?thesis by auto + qed + have iii': "\x. is_a_variable (subst (Var x) ?\)" + using iii by auto + from i' ii' iii' show ?thesis by auto qed qed qed lemma renaming_exists: assumes "\ finite (Vars :: ('a set))" shows "finite V \ (\V'::'a set. finite V' \ (\\. ((renaming \ V) \ ((subst_codomain \ V) \ V') = {})))" proof (induction rule: finite.induct) case emptyI let ?\ = "[]" show ?case unfolding renaming_def subst_codomain_def by auto next fix A :: "'a set" and a::'a assume "finite A" assume hyp_ind: "\V' :: 'a set. finite V' \ (\\. renaming \ A \ subst_codomain \ A \ V' = {})" show "\V':: 'a set. finite V' \ (\\. renaming \ (insert a A) \ subst_codomain \ (insert a A) \ V' = {})" proof ((rule allI),(rule impI)) fix V':: "'a set" assume "finite V'" from this have "finite (insert a V')" by auto from this and hyp_ind obtain \ where "renaming \ A" and "(subst_codomain \ A) \ (insert a V') = {}" by metis from \finite A\ have "finite (subst_codomain \ A)" using subst_codomain_is_finite by auto from this \finite V'\ have "finite (V' \ (subst_codomain \ A))" by auto from this have "finite ((insert a V') \ (subst_codomain \ A))" by auto from this \\ finite Vars\ have "\ (Vars \ ((insert a V') \ (subst_codomain \ A)))" using rev_finite_subset by metis from this obtain nv where "nv \ Vars" and "nv \ (insert a V')" and "nv \ (subst_codomain \ A)" by auto let ?\ = "(a,(Var nv)) # \" have i: "(\x \ (insert a A). (is_a_variable (subst (Var x) ?\)))" proof (rule ccontr) assume "\ (\x \ (insert a A). (is_a_variable (subst (Var x) ?\)))" then obtain x where "x \ (insert a A)" and "\is_a_variable (subst (Var x) ?\)" by auto from \\is_a_variable (subst (Var x) ?\)\ have "x \ a" by auto from this and \x \ (insert a A)\ have "x \ A" by auto from \x \ a\ have "(subst (Var x) ?\) = (subst (Var x) \)" by auto from \renaming \ A\ and \x \ A\ have "is_a_variable (subst (Var x) \)" unfolding renaming_def by metis from this and \\is_a_variable (subst (Var x) ?\)\ \(subst (Var x) ?\) = (subst (Var x) \)\ show False by auto qed have ii: "(\ x y. ((x \ (insert a A)) \ (y \ (insert a A)) \ x \ y \ (subst (Var x) ?\) \ (subst (Var y) ?\)))" proof (rule ccontr) assume "\(\ x y. ((x \ (insert a A)) \ (y \ (insert a A)) \ x \ y \ (subst (Var x) ?\) \ (subst (Var y) ?\)))" from this obtain x y where "x \ insert a A" "y \ insert a A" "x \ y" "(subst (Var x) ?\) = (subst (Var y) ?\)" by blast from i obtain y' where "(subst (Var y) ?\) = (Var y')" using is_a_variable.simps using \y \ insert a A\ is_a_variable.elims(2) by auto from i obtain x' where "(subst (Var x) ?\) = (Var x')" using is_a_variable.simps using \x \ insert a A\ is_a_variable.elims(2) by auto from \(subst (Var x) ?\) = (Var x')\ \(subst (Var y) ?\) = (Var y')\ \(subst (Var x) ?\) = (subst (Var y) ?\)\ have "x' = y'" by auto have "x \ a" proof assume "x = a" from this and \x \ y\ and \y \ insert a A\ have "y \ A" by auto from this and \x \ y\ and \x = a\ and \(subst (Var y) ?\) = (Var y')\ have "y' \ (subst_codomain \ A)" unfolding subst_codomain_def by auto from \x = a\ and \(subst (Var x) ?\) = (Var x')\ have "x' = nv" by auto from this and \y' \ (subst_codomain \ A)\ and \x' = y'\ and \nv \ (subst_codomain \ A)\ show False by auto qed from this and \x \ insert a A\ have "x \ A" and "(subst (Var x) ?\) = (subst (Var x) \)" by auto have "y \ a" proof assume "y = a" from this and \x \ y\ and \x \ insert a A\ have "x \ A" by auto from this and \x \ y\ and \y = a\ and \(subst (Var x) ?\) = (Var x')\ have "x' \ (subst_codomain \ A)" unfolding subst_codomain_def by auto from \y = a\ and \(subst (Var y) ?\) = (Var y')\ have "y' = nv" by auto from this and \x' \ (subst_codomain \ A)\ and \x' = y'\ and \nv \ (subst_codomain \ A)\ show False by auto qed from this and \y \ insert a A\ have "y \ A" and "(subst (Var y) ?\) = (subst (Var y) \)" by auto from \(subst (Var x) ?\) = (subst (Var x) \)\ \(subst (Var y) ?\) = (subst (Var y) \)\ \(subst (Var x) ?\) = (subst (Var y) ?\)\ have "(subst (Var x) \) = (subst (Var y) \)" by auto from this and \x \ A\ and \y \ A\and \renaming \ A\ and \x \ y\ show False unfolding renaming_def by metis qed from i ii have "renaming ?\ (insert a A)" unfolding renaming_def by auto have "((subst_codomain ?\ (insert a A)) \ V') = {}" proof (rule ccontr) assume "(subst_codomain ?\ (insert a A)) \ V' \ {}" then obtain x where "x \ (subst_codomain ?\ (insert a A))" and "x \ V'" by auto from \x \ (subst_codomain ?\ (insert a A))\ obtain x' where "x' \ (insert a A)" and "subst (Var x') ?\ = (Var x)" unfolding subst_codomain_def by blast have "x' \ a" proof assume "x' = a" from this and \subst (Var x') ?\ = (Var x)\ have "x = nv" by auto from this and \x \ V'\ and \nv \ (insert a V')\ show False by auto qed from this and \x' \ (insert a A)\ have "x' \ A" by auto from \x' \ a\ and \subst (Var x') ?\ = (Var x)\ have "(Var x) = (subst (Var x') \)" by auto from this and \x' \ A\ have "x \ subst_codomain \ A" unfolding subst_codomain_def by auto from \x \ subst_codomain \ A\ and \(subst_codomain \ A) \ (insert a V') = {}\ and \x \ V'\ show False by auto qed from this and \renaming ?\ (insert a A)\ show "\\. renaming \ (insert a A) \ subst_codomain \ (insert a A) \ V' = {}" by auto qed qed end