src/HOL/Subst/Unify.thy
changeset 44374 0b217404522a
parent 44373 7321d628b57d
child 44375 dfc2e722fe47
equal deleted inserted replaced
44373:7321d628b57d 44374:0b217404522a
     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