1 (* Title: HOL/Subst/Unify.thy |
|
2 Author: Konrad Slind, Cambridge University Computer Laboratory |
|
3 Copyright 1997 University of Cambridge |
|
4 *) |
|
5 |
|
6 header {* Unification Algorithm *} |
|
7 |
|
8 theory Unify |
|
9 imports Unifier "~~/src/HOL/Library/Old_Recdef" |
|
10 begin |
|
11 |
|
12 subsection {* Substitution and Unification in Higher-Order Logic. *} |
|
13 |
|
14 text {* |
|
15 NB: This theory is already quite old. |
|
16 You might want to look at the newer Isar formalization of |
|
17 unification in HOL/ex/Unification.thy. |
|
18 |
|
19 Implements Manna and Waldinger's formalization, with Paulson's simplifications, |
|
20 and some new simplifications by Slind. |
|
21 |
|
22 Z Manna and R Waldinger, Deductive Synthesis of the Unification Algorithm. |
|
23 SCP 1 (1981), 5-48 |
|
24 |
|
25 L C Paulson, Verifying the Unification Algorithm in LCF. SCP 5 (1985), 143-170 |
|
26 *} |
|
27 |
|
28 definition |
|
29 unifyRel :: "(('a uterm * 'a uterm) * ('a uterm * 'a uterm)) set" where |
|
30 "unifyRel = inv_image (finite_psubset <*lex*> measure uterm_size) |
|
31 (%(M,N). (vars_of M Un vars_of N, M))" |
|
32 --{*Termination relation for the Unify function: |
|
33 either the set of variables decreases, |
|
34 or the first argument does (in fact, both do) *} |
|
35 |
|
36 |
|
37 text{* Wellfoundedness of unifyRel *} |
|
38 lemma wf_unifyRel [iff]: "wf unifyRel" |
|
39 by (simp add: unifyRel_def wf_lex_prod wf_finite_psubset) |
|
40 |
|
41 consts unify :: "'a uterm * 'a uterm => ('a * 'a uterm) list option" |
|
42 recdef (permissive) unify "unifyRel" |
|
43 unify_CC: "unify(Const m, Const n) = (if (m=n) then Some[] else None)" |
|
44 unify_CB: "unify(Const m, Comb M N) = None" |
|
45 unify_CV: "unify(Const m, Var v) = Some[(v,Const m)]" |
|
46 unify_V: "unify(Var v, M) = (if (Var v \<prec> M) then None else Some[(v,M)])" |
|
47 unify_BC: "unify(Comb M N, Const x) = None" |
|
48 unify_BV: "unify(Comb M N, Var v) = (if (Var v \<prec> Comb M N) then None |
|
49 else Some[(v,Comb M N)])" |
|
50 unify_BB: |
|
51 "unify(Comb M1 N1, Comb M2 N2) = |
|
52 (case unify(M1,M2) |
|
53 of None => None |
|
54 | Some theta => (case unify(N1 \<lhd> theta, N2 \<lhd> theta) |
|
55 of None => None |
|
56 | Some sigma => Some (theta \<lozenge> sigma)))" |
|
57 (hints recdef_wf: wf_unifyRel) |
|
58 |
|
59 |
|
60 text{* This file defines a nested unification algorithm, then proves that it |
|
61 terminates, then proves 2 correctness theorems: that when the algorithm |
|
62 succeeds, it 1) returns an MGU; and 2) returns an idempotent substitution. |
|
63 Although the proofs may seem long, they are actually quite direct, in that |
|
64 the correctness and termination properties are not mingled as much as in |
|
65 previous proofs of this algorithm.*} |
|
66 |
|
67 (*--------------------------------------------------------------------------- |
|
68 * Our approach for nested recursive functions is as follows: |
|
69 * |
|
70 * 0. Prove the wellfoundedness of the termination relation. |
|
71 * 1. Prove the non-nested termination conditions. |
|
72 * 2. Eliminate (0) and (1) from the recursion equations and the |
|
73 * induction theorem. |
|
74 * 3. Prove the nested termination conditions by using the induction |
|
75 * theorem from (2) and by using the recursion equations from (2). |
|
76 * These are constrained by the nested termination conditions, but |
|
77 * things work out magically (by wellfoundedness of the termination |
|
78 * relation). |
|
79 * 4. Eliminate the nested TCs from the results of (2). |
|
80 * 5. Prove further correctness properties using the results of (4). |
|
81 * |
|
82 * Deeper nestings require iteration of steps (3) and (4). |
|
83 *---------------------------------------------------------------------------*) |
|
84 |
|
85 text{*The non-nested TC (terminiation condition).*} |
|
86 recdef_tc unify_tc1: unify (1) |
|
87 by (auto simp: unifyRel_def finite_psubset_def finite_vars_of) |
|
88 |
|
89 |
|
90 text{*Termination proof.*} |
|
91 |
|
92 lemma trans_unifyRel: "trans unifyRel" |
|
93 by (simp add: unifyRel_def measure_def trans_inv_image trans_lex_prod |
|
94 trans_finite_psubset) |
|
95 |
|
96 |
|
97 text{*The following lemma is used in the last step of the termination proof |
|
98 for the nested call in Unify. Loosely, it says that unifyRel doesn't care |
|
99 about term structure.*} |
|
100 lemma Rassoc: |
|
101 "((X,Y), (Comb A (Comb B C), Comb D (Comb E F))) \<in> unifyRel ==> |
|
102 ((X,Y), (Comb (Comb A B) C, Comb (Comb D E) F)) \<in> unifyRel" |
|
103 by (simp add: less_eq add_assoc Un_assoc unifyRel_def lex_prod_def) |
|
104 |
|
105 |
|
106 text{*This lemma proves the nested termination condition for the base cases |
|
107 * 3, 4, and 6.*} |
|
108 lemma var_elimR: |
|
109 "~(Var x \<prec> M) ==> |
|
110 ((N1 \<lhd> [(x,M)], N2 \<lhd> [(x,M)]), (Comb M N1, Comb(Var x) N2)) \<in> unifyRel |
|
111 & ((N1 \<lhd> [(x,M)], N2 \<lhd> [(x,M)]), (Comb(Var x) N1, Comb M N2)) \<in> unifyRel" |
|
112 apply (case_tac "Var x = M", clarify, simp) |
|
113 apply (case_tac "x \<in> (vars_of N1 Un vars_of N2)") |
|
114 txt{*@{text uterm_less} case*} |
|
115 apply (simp add: less_eq unifyRel_def lex_prod_def) |
|
116 apply blast |
|
117 txt{*@{text finite_psubset} case*} |
|
118 apply (simp add: unifyRel_def lex_prod_def) |
|
119 apply (simp add: finite_psubset_def finite_vars_of psubset_eq) |
|
120 apply blast |
|
121 txt{*Final case, also @{text finite_psubset}*} |
|
122 apply (simp add: finite_vars_of unifyRel_def finite_psubset_def lex_prod_def) |
|
123 apply (cut_tac s = "[(x,M)]" and v = x and t = N2 in Var_elim) |
|
124 apply (cut_tac [3] s = "[(x,M)]" and v = x and t = N1 in Var_elim) |
|
125 apply (simp_all (no_asm_simp) add: srange_iff vars_iff_occseq) |
|
126 apply (auto elim!: Var_intro [THEN disjE] simp add: srange_iff) |
|
127 done |
|
128 |
|
129 |
|
130 text{*Eliminate tc1 from the recursion equations and the induction theorem.*} |
|
131 |
|
132 lemmas unify_nonrec [simp] = |
|
133 unify_CC unify_CB unify_CV unify_V unify_BC unify_BV |
|
134 |
|
135 lemmas unify_simps0 = unify_nonrec unify_BB [OF unify_tc1] |
|
136 |
|
137 lemmas unify_induct0 = unify.induct [OF unify_tc1] |
|
138 |
|
139 text{*The nested TC. The (2) requests the second one. |
|
140 Proved by recursion induction.*} |
|
141 recdef_tc unify_tc2: unify (2) |
|
142 txt{*The extracted TC needs the scope of its quantifiers adjusted, so our |
|
143 first step is to restrict the scopes of N1 and N2.*} |
|
144 apply (subgoal_tac "\<forall>M1 M2 theta. unify (M1, M2) = Some theta --> |
|
145 (\<forall>N1 N2.((N1\<lhd>theta, N2\<lhd>theta), (Comb M1 N1, Comb M2 N2)) \<in> unifyRel)") |
|
146 apply blast |
|
147 apply (rule allI) |
|
148 apply (rule allI) |
|
149 txt{*Apply induction on this still-quantified formula*} |
|
150 apply (rule_tac u = M1 and v = M2 in unify_induct0) |
|
151 apply (simp_all (no_asm_simp) add: var_elimR unify_simps0) |
|
152 txt{*Const-Const case*} |
|
153 apply (simp add: unifyRel_def lex_prod_def less_eq) |
|
154 txt{*Comb-Comb case*} |
|
155 apply (simp (no_asm_simp) split add: option.split) |
|
156 apply (intro strip) |
|
157 apply (rule trans_unifyRel [THEN transD], blast) |
|
158 apply (simp only: subst_Comb [symmetric]) |
|
159 apply (rule Rassoc, blast) |
|
160 done |
|
161 |
|
162 |
|
163 text{* Now for elimination of nested TC from unify.simps and induction.*} |
|
164 |
|
165 text{*Desired rule, copied from the theory file.*} |
|
166 lemma unifyCombComb [simp]: |
|
167 "unify(Comb M1 N1, Comb M2 N2) = |
|
168 (case unify(M1,M2) |
|
169 of None => None |
|
170 | Some theta => (case unify(N1 \<lhd> theta, N2 \<lhd> theta) |
|
171 of None => None |
|
172 | Some sigma => Some (theta \<lozenge> sigma)))" |
|
173 by (simp add: unify_tc2 unify_simps0 split add: option.split) |
|
174 |
|
175 lemma unify_induct: |
|
176 "(\<And>m n. P (Const m) (Const n)) \<Longrightarrow> |
|
177 (\<And>m M N. P (Const m) (Comb M N)) \<Longrightarrow> |
|
178 (\<And>m v. P (Const m) (Var v)) \<Longrightarrow> |
|
179 (\<And>v M. P (Var v) M) \<Longrightarrow> |
|
180 (\<And>M N x. P (Comb M N) (Const x)) \<Longrightarrow> |
|
181 (\<And>M N v. P (Comb M N) (Var v)) \<Longrightarrow> |
|
182 (\<And>M1 N1 M2 N2. |
|
183 \<forall>theta. unify (M1, M2) = Some theta \<longrightarrow> P (N1 \<lhd> theta) (N2 \<lhd> theta) \<Longrightarrow> |
|
184 P M1 M2 \<Longrightarrow> P (Comb M1 N1) (Comb M2 N2)) \<Longrightarrow> |
|
185 P u v" |
|
186 by (rule unify_induct0) (simp_all add: unify_tc2) |
|
187 |
|
188 text{*Correctness. Notice that idempotence is not needed to prove that the |
|
189 algorithm terminates and is not needed to prove the algorithm correct, if you |
|
190 are only interested in an MGU. This is in contrast to the approach of M&W, |
|
191 who used idempotence and MGU-ness in the termination proof.*} |
|
192 |
|
193 theorem unify_gives_MGU [rule_format]: |
|
194 "\<forall>theta. unify(M,N) = Some theta --> MGUnifier theta M N" |
|
195 apply (rule_tac u = M and v = N in unify_induct0) |
|
196 apply (simp_all (no_asm_simp)) |
|
197 txt{*Const-Const case*} |
|
198 apply (simp add: MGUnifier_def Unifier_def) |
|
199 txt{*Const-Var case*} |
|
200 apply (subst mgu_sym) |
|
201 apply (simp add: MGUnifier_Var) |
|
202 txt{*Var-M case*} |
|
203 apply (simp add: MGUnifier_Var) |
|
204 txt{*Comb-Var case*} |
|
205 apply (subst mgu_sym) |
|
206 apply (simp add: MGUnifier_Var) |
|
207 txt{*Comb-Comb case*} |
|
208 apply (simp add: unify_tc2) |
|
209 apply (simp (no_asm_simp) split add: option.split) |
|
210 apply (intro strip) |
|
211 apply (simp add: MGUnifier_def Unifier_def MoreGeneral_def) |
|
212 apply (safe, rename_tac theta sigma gamma) |
|
213 apply (erule_tac x = gamma in allE, erule (1) notE impE) |
|
214 apply (erule exE, rename_tac delta) |
|
215 apply (erule_tac x = delta in allE) |
|
216 apply (subgoal_tac "N1 \<lhd> theta \<lhd> delta = N2 \<lhd> theta \<lhd> delta") |
|
217 apply (blast intro: subst_trans intro!: subst_cong comp_assoc[THEN subst_sym]) |
|
218 apply (simp add: subst_eq_iff) |
|
219 done |
|
220 |
|
221 |
|
222 text{*Unify returns idempotent substitutions, when it succeeds.*} |
|
223 theorem unify_gives_Idem [rule_format]: |
|
224 "\<forall>theta. unify(M,N) = Some theta --> Idem theta" |
|
225 apply (rule_tac u = M and v = N in unify_induct0) |
|
226 apply (simp_all add: Var_Idem unify_tc2 split add: option.split) |
|
227 txt{*Comb-Comb case*} |
|
228 apply safe |
|
229 apply (drule spec, erule (1) notE impE)+ |
|
230 apply (safe dest!: unify_gives_MGU [unfolded MGUnifier_def]) |
|
231 apply (rule Idem_comp, assumption+) |
|
232 apply (force simp add: MoreGeneral_def subst_eq_iff Idem_def) |
|
233 done |
|
234 |
|
235 end |
|