bulwahn@41460: (* krauss@22999: Author: Alexander Krauss, Technische Universitaet Muenchen krauss@22999: *) krauss@22999: krauss@22999: header {* Case study: Unification Algorithm *} krauss@22999: wenzelm@23219: theory Unification krauss@22999: imports Main wenzelm@23219: begin krauss@22999: krauss@22999: text {* krauss@22999: This is a formalization of a first-order unification krauss@22999: algorithm. It uses the new "function" package to define recursive krauss@22999: functions, which allows a better treatment of nested recursion. krauss@22999: krauss@22999: This is basically a modernized version of a previous formalization krauss@22999: by Konrad Slind (see: HOL/Subst/Unify.thy), which itself builds on wenzelm@23219: previous work by Paulson and Manna \& Waldinger (for details, see krauss@22999: there). krauss@22999: krauss@22999: Unlike that formalization, where the proofs of termination and krauss@22999: some partial correctness properties are intertwined, we can prove krauss@22999: partial correctness and termination separately. krauss@22999: *} krauss@22999: wenzelm@23219: krauss@44368: subsection {* Terms *} krauss@44368: krauss@44368: text {* Binary trees with leaves that are constants or variables. *} krauss@22999: krauss@22999: datatype 'a trm = krauss@22999: Var 'a krauss@22999: | Const 'a krauss@44367: | Comb "'a trm" "'a trm" (infix "\" 60) krauss@22999: krauss@44368: primrec vars_of :: "'a trm \ 'a set" krauss@44368: where krauss@44368: "vars_of (Var v) = {v}" krauss@44368: | "vars_of (Const c) = {}" krauss@44368: | "vars_of (M \ N) = vars_of M \ vars_of N" krauss@44368: krauss@44368: fun occs :: "'a trm \ 'a trm \ bool" (infixl "\" 54) krauss@44368: where krauss@44369: "u \ Var v \ False" krauss@44369: | "u \ Const c \ False" krauss@44369: | "u \ M \ N \ u = M \ u = N \ u \ M \ u \ N" krauss@44368: krauss@44368: krauss@44368: lemma finite_vars_of[intro]: "finite (vars_of t)" krauss@44368: by (induct t) simp_all krauss@44368: krauss@44368: lemma vars_var_iff: "v \ vars_of (Var w) \ w = v" krauss@44368: by auto krauss@44368: krauss@44368: lemma vars_iff_occseq: "x \ vars_of t \ Var x \ t \ Var x = t" krauss@44368: by (induct t) auto krauss@44368: krauss@44368: lemma occs_vars_subset: "M \ N \ vars_of M \ vars_of N" krauss@44368: by (induct N) auto krauss@44368: krauss@44368: krauss@44368: subsection {* Substitutions *} krauss@44368: wenzelm@42463: type_synonym 'a subst = "('a \ 'a trm) list" krauss@22999: krauss@22999: text {* Applying a substitution to a variable: *} krauss@22999: krauss@22999: fun assoc :: "'a \ 'b \ ('a \ 'b) list \ 'b" krauss@22999: where krauss@22999: "assoc x d [] = d" krauss@22999: | "assoc x d ((p,q)#t) = (if x = p then q else assoc x d t)" krauss@22999: krauss@22999: text {* Applying a substitution to a term: *} krauss@22999: krauss@44367: primrec subst :: "'a trm \ 'a subst \ 'a trm" (infixl "\" 55) krauss@22999: where krauss@44367: "(Var v) \ s = assoc v (Var v) s" krauss@44367: | "(Const c) \ s = (Const c)" krauss@44367: | "(M \ N) \ s = (M \ s) \ (N \ s)" krauss@22999: krauss@44368: definition subst_eq (infixr "\" 52) krauss@44368: where krauss@44368: "s1 \ s2 \ (\t. t \ s1 = t \ s2)" krauss@22999: krauss@44368: fun comp :: "'a subst \ 'a subst \ 'a subst" (infixl "\" 56) krauss@22999: where krauss@44367: "[] \ bl = bl" krauss@44367: | "((a,b) # al) \ bl = (a, b \ bl) # (al \ bl)" krauss@22999: krauss@44368: krauss@44368: subsection {* Basic Laws *} krauss@44368: krauss@44368: lemma subst_Nil[simp]: "t \ [] = t" krauss@44368: by (induct t) auto krauss@44368: krauss@44368: lemma subst_mono: "t \ u \ t \ s \ u \ s" krauss@44368: by (induct u) auto krauss@44368: krauss@44368: lemma agreement: "(t \ r = t \ s) \ (\v \ vars_of t. Var v \ r = Var v \ s)" krauss@44368: by (induct t) auto krauss@44368: krauss@44368: lemma repl_invariance: "v \ vars_of t \ t \ (v,u) # s = t \ s" krauss@44368: by (simp add: agreement) krauss@22999: krauss@44368: lemma Var_in_subst: krauss@44368: "v \ vars_of t \ w \ vars_of (t \ (v, Var(w)) # s)" krauss@44368: by (induct t) auto krauss@44368: krauss@44370: lemma remove_var: "v \ vars_of s \ v \ vars_of (t \ [(v, s)])" krauss@44370: by (induct t) simp_all krauss@44370: krauss@44368: lemma subst_refl[iff]: "s \ s" krauss@44368: by (auto simp:subst_eq_def) krauss@44368: krauss@44368: lemma subst_sym[sym]: "\s1 \ s2\ \ s2 \ s1" krauss@44368: by (auto simp:subst_eq_def) krauss@44368: krauss@44368: lemma subst_trans[trans]: "\s1 \ s2; s2 \ s3\ \ s1 \ s3" krauss@44368: by (auto simp:subst_eq_def) krauss@44368: krauss@44371: lemma subst_no_occs: "\ Var v \ t \ Var v \ t krauss@44371: \ t \ [(v,s)] = t" krauss@44371: by (induct t) auto krauss@44370: krauss@44368: text {* Composition of Substitutions *} krauss@22999: krauss@44368: lemma comp_Nil[simp]: "\ \ [] = \" krauss@22999: by (induct \) auto krauss@22999: krauss@44368: lemma subst_comp[simp]: "t \ (r \ s) = t \ r \ s" krauss@22999: proof (induct t) krauss@22999: case (Var v) thus ?case krauss@44368: by (induct r) auto krauss@44368: qed auto krauss@22999: krauss@44368: lemma subst_eq_intro[intro]: "(\t. t \ \ = t \ \) \ \ \ \" krauss@44367: by (auto simp:subst_eq_def) krauss@22999: krauss@44368: lemma subst_eq_dest[dest]: "s1 \ s2 \ t \ s1 = t \ s2" krauss@44367: by (auto simp:subst_eq_def) krauss@22999: krauss@44368: lemma comp_assoc: "(a \ b) \ c \ a \ (b \ c)" krauss@44368: by auto krauss@22999: krauss@44368: lemma subst_cong: "\\ \ \'; \ \ \'\ \ (\ \ \) \ (\' \ \')" krauss@44368: by (auto simp: subst_eq_def) krauss@22999: krauss@44370: lemma var_self: "[(v, Var v)] \ []" krauss@44370: proof krauss@44370: fix t show "t \ [(v, Var v)] = t \ []" krauss@44370: by (induct t) simp_all krauss@44370: qed krauss@44370: krauss@44370: lemma var_same[simp]: "[(v, t)] \ [] \ t = Var v" krauss@44370: by (metis assoc.simps(2) subst.simps(1) subst_eq_def var_self) krauss@22999: wenzelm@23219: krauss@22999: subsection {* Specification: Most general unifiers *} krauss@22999: krauss@44368: definition Unifier :: "'a subst \ 'a trm \ 'a trm \ bool" krauss@44368: where "Unifier \ t u \ (t \ \ = u \ \)" krauss@22999: krauss@44368: definition MGU :: "'a subst \ 'a trm \ 'a trm \ bool" where krauss@44368: "MGU \ t u \ krauss@44368: Unifier \ t u \ (\\. Unifier \ t u \ (\\. \ \ \ \ \))" krauss@22999: krauss@22999: lemma MGUI[intro]: krauss@44367: "\t \ \ = u \ \; \\. t \ \ = u \ \ \ \\. \ \ \ \ \\ krauss@22999: \ MGU \ t u" krauss@22999: by (simp only:Unifier_def MGU_def, auto) krauss@22999: krauss@22999: lemma MGU_sym[sym]: krauss@22999: "MGU \ s t \ MGU \ t s" krauss@22999: by (auto simp:MGU_def Unifier_def) krauss@22999: krauss@44371: lemma MGU_is_Unifier: "MGU \ t u \ Unifier \ t u" krauss@44371: unfolding MGU_def by (rule conjunct1) krauss@44371: krauss@44370: lemma MGU_Var: krauss@44370: assumes "\ Var v \ t" krauss@44370: shows "MGU [(v,t)] (Var v) t" krauss@44370: proof (intro MGUI exI) krauss@44370: show "Var v \ [(v,t)] = t \ [(v,t)]" using assms krauss@44370: by (metis assoc.simps(2) repl_invariance subst.simps(1) subst_Nil vars_iff_occseq) krauss@44370: next krauss@44370: fix \ assume th: "Var v \ \ = t \ \" krauss@44370: show "\ \ [(v,t)] \ \" krauss@44370: proof krauss@44370: fix s show "s \ \ = s \ [(v,t)] \ \" using th krauss@44370: by (induct s) auto krauss@44370: qed krauss@44370: qed krauss@44370: krauss@44370: lemma MGU_Const: "MGU [] (Const c) (Const d) \ c = d" krauss@44370: by (auto simp: MGU_def Unifier_def) krauss@44370: krauss@22999: krauss@44368: definition Idem :: "'a subst \ bool" krauss@44368: where "Idem s \ (s \ s) \ s" krauss@44368: krauss@44368: krauss@44368: krauss@22999: subsection {* The unification algorithm *} krauss@22999: krauss@22999: krauss@22999: text {* The unification algorithm: *} krauss@22999: krauss@22999: function unify :: "'a trm \ 'a trm \ 'a subst option" krauss@22999: where krauss@22999: "unify (Const c) (M \ N) = None" krauss@22999: | "unify (M \ N) (Const c) = None" krauss@22999: | "unify (Const c) (Var v) = Some [(v, Const c)]" krauss@44369: | "unify (M \ N) (Var v) = (if Var v \ M \ N krauss@22999: then None krauss@22999: else Some [(v, M \ N)])" krauss@44369: | "unify (Var v) M = (if Var v \ M krauss@22999: then None krauss@22999: else Some [(v, M)])" krauss@22999: | "unify (Const c) (Const d) = (if c=d then Some [] else None)" krauss@22999: | "unify (M \ N) (M' \ N') = (case unify M M' of krauss@22999: None \ None | krauss@44367: Some \ \ (case unify (N \ \) (N' \ \) krauss@22999: of None \ None | krauss@44367: Some \ \ Some (\ \ \)))" krauss@22999: by pat_completeness auto krauss@22999: krauss@22999: subsection {* Properties used in termination proof *} krauss@22999: krauss@22999: krauss@22999: text {* Elimination of variables by a substitution: *} krauss@22999: krauss@22999: definition krauss@44367: "elim \ v \ \t. v \ vars_of (t \ \)" krauss@22999: krauss@44367: lemma elim_intro[intro]: "(\t. v \ vars_of (t \ \)) \ elim \ v" krauss@22999: by (auto simp:elim_def) krauss@22999: krauss@44367: lemma elim_dest[dest]: "elim \ v \ v \ vars_of (t \ \)" krauss@22999: by (auto simp:elim_def) krauss@22999: krauss@44370: lemma elim_eq: "\ \ \ \ elim \ x = elim \ x" krauss@44367: by (auto simp:elim_def subst_eq_def) krauss@22999: krauss@44369: lemma occs_elim: "\ Var v \ t krauss@44367: \ elim [(v,t)] v \ [(v,t)] \ []" krauss@44370: by (metis elim_intro remove_var var_same vars_iff_occseq) krauss@22999: krauss@22999: text {* The result of a unification never introduces new variables: *} krauss@22999: krauss@44370: declare unify.psimps[simp] krauss@44370: krauss@22999: lemma unify_vars: krauss@22999: assumes "unify_dom (M, N)" krauss@22999: assumes "unify M N = Some \" krauss@44367: shows "vars_of (t \ \) \ vars_of M \ vars_of N \ vars_of t" krauss@22999: (is "?P M N \ t") wenzelm@24444: using assms krauss@22999: proof (induct M N arbitrary:\ t) krauss@22999: case (3 c v) krauss@22999: hence "\ = [(v, Const c)]" by simp wenzelm@24444: thus ?case by (induct t) auto krauss@22999: next krauss@22999: case (4 M N v) krauss@44369: hence "\ Var v \ M \ N" by auto wenzelm@24444: with 4 have "\ = [(v, M\N)]" by simp wenzelm@24444: thus ?case by (induct t) auto krauss@22999: next krauss@22999: case (5 v M) krauss@44369: hence "\ Var v \ M" by auto wenzelm@24444: with 5 have "\ = [(v, M)]" by simp wenzelm@24444: thus ?case by (induct t) auto krauss@22999: next krauss@22999: case (7 M N M' N' \) krauss@22999: then obtain \1 \2 krauss@22999: where "unify M M' = Some \1" krauss@44367: and "unify (N \ \1) (N' \ \1) = Some \2" krauss@44367: and \: "\ = \1 \ \2" krauss@22999: and ih1: "\t. ?P M M' \1 t" krauss@44367: and ih2: "\t. ?P (N\\1) (N'\\1) \2 t" krauss@22999: by (auto split:option.split_asm) krauss@22999: krauss@22999: show ?case krauss@22999: proof krauss@44367: fix v assume a: "v \ vars_of (t \ \)" krauss@22999: krauss@22999: show "v \ vars_of (M \ N) \ vars_of (M' \ N') \ vars_of t" krauss@22999: proof (cases "v \ vars_of M \ v \ vars_of M' wenzelm@32960: \ v \ vars_of N \ v \ vars_of N'") krauss@22999: case True krauss@44367: with ih1 have l:"\t. v \ vars_of (t \ \1) \ v \ vars_of t" wenzelm@32960: by auto krauss@22999: krauss@44367: from a and ih2[where t="t \ \1"] krauss@44367: have "v \ vars_of (N \ \1) \ vars_of (N' \ \1) krauss@44367: \ v \ vars_of (t \ \1)" unfolding \ wenzelm@32960: by auto krauss@22999: hence "v \ vars_of t" krauss@22999: proof krauss@44367: assume "v \ vars_of (N \ \1) \ vars_of (N' \ \1)" wenzelm@32960: with True show ?thesis by (auto dest:l) krauss@22999: next krauss@44367: assume "v \ vars_of (t \ \1)" wenzelm@32960: thus ?thesis by (rule l) krauss@22999: qed krauss@22999: krauss@22999: thus ?thesis by auto krauss@22999: qed auto krauss@22999: qed krauss@22999: qed (auto split: split_if_asm) krauss@22999: krauss@22999: krauss@22999: text {* The result of a unification is either the identity krauss@22999: substitution or it eliminates a variable from one of the terms: *} krauss@22999: krauss@22999: lemma unify_eliminates: krauss@22999: assumes "unify_dom (M, N)" krauss@22999: assumes "unify M N = Some \" krauss@44367: shows "(\v\vars_of M \ vars_of N. elim \ v) \ \ \ []" krauss@22999: (is "?P M N \") wenzelm@24444: using assms krauss@22999: proof (induct M N arbitrary:\) krauss@22999: case 1 thus ?case by simp krauss@22999: next krauss@22999: case 2 thus ?case by simp krauss@22999: next krauss@22999: case (3 c v) krauss@44369: have no_occs: "\ Var v \ Const c" by simp wenzelm@24444: with 3 have "\ = [(v, Const c)]" by simp krauss@44367: with occs_elim[OF no_occs] krauss@22999: show ?case by auto krauss@22999: next krauss@22999: case (4 M N v) krauss@44369: hence no_occs: "\ Var v \ M \ N" by auto wenzelm@24444: with 4 have "\ = [(v, M\N)]" by simp krauss@44367: with occs_elim[OF no_occs] krauss@22999: show ?case by auto krauss@22999: next krauss@22999: case (5 v M) krauss@44369: hence no_occs: "\ Var v \ M" by auto wenzelm@24444: with 5 have "\ = [(v, M)]" by simp krauss@44367: with occs_elim[OF no_occs] krauss@22999: show ?case by auto krauss@22999: next krauss@22999: case (6 c d) thus ?case krauss@22999: by (cases "c = d") auto krauss@22999: next krauss@22999: case (7 M N M' N' \) krauss@22999: then obtain \1 \2 krauss@22999: where "unify M M' = Some \1" krauss@44367: and "unify (N \ \1) (N' \ \1) = Some \2" krauss@44367: and \: "\ = \1 \ \2" krauss@22999: and ih1: "?P M M' \1" krauss@44367: and ih2: "?P (N\\1) (N'\\1) \2" krauss@22999: by (auto split:option.split_asm) krauss@22999: krauss@22999: from `unify_dom (M \ N, M' \ N')` krauss@22999: have "unify_dom (M, M')" berghofe@23777: by (rule accp_downward) (rule unify_rel.intros) krauss@22999: hence no_new_vars: krauss@44367: "\t. vars_of (t \ \1) \ vars_of M \ vars_of M' \ vars_of t" wenzelm@23373: by (rule unify_vars) (rule `unify M M' = Some \1`) krauss@22999: krauss@22999: from ih2 show ?case krauss@22999: proof krauss@44367: assume "\v\vars_of (N \ \1) \ vars_of (N' \ \1). elim \2 v" krauss@22999: then obtain v krauss@44367: where "v\vars_of (N \ \1) \ vars_of (N' \ \1)" krauss@22999: and el: "elim \2 v" by auto krauss@22999: with no_new_vars show ?thesis unfolding \ krauss@22999: by (auto simp:elim_def) krauss@22999: next krauss@44367: assume empty[simp]: "\2 \ []" krauss@22999: krauss@44367: have "\ \ (\1 \ [])" unfolding \ krauss@44368: by (rule subst_cong) auto krauss@44367: also have "\ \ \1" by auto krauss@44367: finally have "\ \ \1" . krauss@22999: krauss@22999: from ih1 show ?thesis krauss@22999: proof krauss@22999: assume "\v\vars_of M \ vars_of M'. elim \1 v" krauss@44370: with elim_eq[OF `\ \ \1`] krauss@22999: show ?thesis by auto krauss@22999: next krauss@44367: note `\ \ \1` krauss@44367: also assume "\1 \ []" krauss@22999: finally show ?thesis .. krauss@22999: qed krauss@22999: qed krauss@22999: qed krauss@22999: krauss@44370: declare unify.psimps[simp del] krauss@22999: krauss@22999: subsection {* Termination proof *} krauss@22999: krauss@22999: termination unify krauss@22999: proof krauss@22999: let ?R = "measures [\(M,N). card (vars_of M \ vars_of N), krauss@22999: \(M, N). size M]" krauss@22999: show "wf ?R" by simp krauss@22999: krauss@44370: fix M N M' N' :: "'a trm" krauss@22999: show "((M, M'), (M \ N, M' \ N')) \ ?R" -- "Inner call" krauss@22999: by (rule measures_lesseq) (auto intro: card_mono) krauss@22999: krauss@22999: fix \ -- "Outer call" krauss@22999: assume inner: "unify_dom (M, M')" krauss@22999: "unify M M' = Some \" krauss@22999: krauss@22999: from unify_eliminates[OF inner] krauss@44367: show "((N \ \, N' \ \), (M \ N, M' \ N')) \?R" krauss@22999: proof krauss@22999: -- {* Either a variable is eliminated \ldots *} krauss@22999: assume "(\v\vars_of M \ vars_of M'. elim \ v)" krauss@22999: then obtain v wenzelm@32960: where "elim \ v" wenzelm@32960: and "v\vars_of M \ vars_of M'" by auto krauss@22999: with unify_vars[OF inner] krauss@44367: have "vars_of (N\\) \ vars_of (N'\\) wenzelm@32960: \ vars_of (M\N) \ vars_of (M'\N')" wenzelm@32960: by auto krauss@22999: krauss@22999: thus ?thesis krauss@22999: by (auto intro!: measures_less intro: psubset_card_mono) krauss@22999: next krauss@22999: -- {* Or the substitution is empty *} krauss@44367: assume "\ \ []" krauss@44367: hence "N \ \ = N" krauss@44367: and "N' \ \ = N'" by auto krauss@22999: thus ?thesis krauss@22999: by (auto intro!: measures_less intro: psubset_card_mono) krauss@22999: qed krauss@22999: qed krauss@22999: krauss@44370: krauss@44370: subsection {* Other Properties *} krauss@44370: krauss@44370: lemma unify_computes_MGU: krauss@44370: "unify M N = Some \ \ MGU \ M N" krauss@44370: proof (induct M N arbitrary: \ rule: unify.induct) krauss@44370: case (7 M N M' N' \) -- "The interesting case" krauss@44370: krauss@44370: then obtain \1 \2 krauss@44370: where "unify M M' = Some \1" krauss@44370: and "unify (N \ \1) (N' \ \1) = Some \2" krauss@44370: and \: "\ = \1 \ \2" krauss@44370: and MGU_inner: "MGU \1 M M'" krauss@44370: and MGU_outer: "MGU \2 (N \ \1) (N' \ \1)" krauss@44370: by (auto split:option.split_asm) krauss@44370: krauss@44370: show ?case krauss@44370: proof krauss@44370: from MGU_inner and MGU_outer krauss@44370: have "M \ \1 = M' \ \1" krauss@44370: and "N \ \1 \ \2 = N' \ \1 \ \2" krauss@44370: unfolding MGU_def Unifier_def krauss@44370: by auto krauss@44370: thus "M \ N \ \ = M' \ N' \ \" unfolding \ krauss@44370: by simp krauss@44370: next krauss@44370: fix \' assume "M \ N \ \' = M' \ N' \ \'" krauss@44370: hence "M \ \' = M' \ \'" krauss@44370: and Ns: "N \ \' = N' \ \'" by auto krauss@44370: krauss@44370: with MGU_inner obtain \ krauss@44370: where eqv: "\' \ \1 \ \" krauss@44370: unfolding MGU_def Unifier_def krauss@44370: by auto krauss@44370: krauss@44370: from Ns have "N \ \1 \ \ = N' \ \1 \ \" krauss@44370: by (simp add:subst_eq_dest[OF eqv]) krauss@44370: krauss@44370: with MGU_outer obtain \ krauss@44370: where eqv2: "\ \ \2 \ \" krauss@44370: unfolding MGU_def Unifier_def krauss@44370: by auto krauss@44370: krauss@44370: have "\' \ \ \ \" unfolding \ krauss@44370: by (rule subst_eq_intro, auto simp:subst_eq_dest[OF eqv] subst_eq_dest[OF eqv2]) krauss@44370: thus "\\. \' \ \ \ \" .. krauss@44370: qed krauss@44370: qed (auto simp: MGU_Const intro: MGU_Var MGU_Var[symmetric] split: split_if_asm) krauss@44370: krauss@44371: lemma Idem_Nil [iff]: "Idem []" krauss@44371: by (simp add: Idem_def) krauss@44370: krauss@44371: lemma Var_Idem: krauss@44371: assumes "~ (Var v \ t)" shows "Idem [(v,t)]" krauss@44371: unfolding Idem_def krauss@44371: proof krauss@44371: from assms have [simp]: "t \ [(v, t)] = t" krauss@44371: by (metis assoc.simps(2) subst.simps(1) subst_no_occs) krauss@44371: krauss@44371: fix s show "s \ [(v, t)] \ [(v, t)] = s \ [(v, t)]" krauss@44371: by (induct s) auto krauss@44371: qed krauss@44371: krauss@44371: lemma Unifier_Idem_subst: krauss@44371: "Idem(r) \ Unifier s (t \ r) (u \ r) \ krauss@44371: Unifier (r \ s) (t \ r) (u \ r)" krauss@44371: by (simp add: Idem_def Unifier_def subst_eq_def) krauss@44371: krauss@44371: lemma Idem_comp: krauss@44371: "Idem r \ Unifier s (t \ r) (u \ r) \ krauss@44371: (!!q. Unifier q (t \ r) (u \ r) \ s \ q \ q) \ krauss@44371: Idem (r \ s)" krauss@44371: apply (frule Unifier_Idem_subst, blast) krauss@44371: apply (force simp add: Idem_def subst_eq_def) krauss@44371: done krauss@44371: krauss@44371: theorem unify_gives_Idem: krauss@44371: "unify M N = Some \ \ Idem \" krauss@44371: proof (induct M N arbitrary: \ rule: unify.induct) krauss@44371: case (7 M M' N N' \) krauss@44371: krauss@44371: then obtain \1 \2 krauss@44371: where "unify M N = Some \1" krauss@44371: and \2: "unify (M' \ \1) (N' \ \1) = Some \2" krauss@44371: and \: "\ = \1 \ \2" krauss@44371: and "Idem \1" krauss@44371: and "Idem \2" krauss@44371: by (auto split: option.split_asm) krauss@44371: krauss@44371: from \2 have "Unifier \2 (M' \ \1) (N' \ \1)" krauss@44371: by (rule unify_computes_MGU[THEN MGU_is_Unifier]) krauss@44371: krauss@44371: with `Idem \1` krauss@44371: show "Idem \" unfolding \ krauss@44371: proof (rule Idem_comp) krauss@44371: fix \ assume "Unifier \ (M' \ \1) (N' \ \1)" krauss@44371: with \2 obtain \ where \: "\ \ \2 \ \" krauss@44371: using unify_computes_MGU MGU_def by blast krauss@44371: krauss@44371: have "\2 \ \ \ \2 \ (\2 \ \)" by (rule subst_cong) (auto simp: \) krauss@44371: also have "... \ (\2 \ \2) \ \" by (rule comp_assoc[symmetric]) krauss@44371: also have "... \ \2 \ \" by (rule subst_cong) (auto simp: `Idem \2`[unfolded Idem_def]) krauss@44371: also have "... \ \" by (rule \[symmetric]) krauss@44371: finally show "\2 \ \ \ \" . krauss@44371: qed krauss@44371: qed (auto intro!: Var_Idem split: option.splits if_splits) krauss@39754: wenzelm@23219: end