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