src/Tools/IsaPlanner/rw_inst.ML
author wenzelm
Thu May 31 20:55:29 2007 +0200 (2007-05-31)
changeset 23171 861f63a35d31
child 23175 267ba70e7a9d
permissions -rw-r--r--
moved IsaPlanner from Provers to Tools;
wenzelm@23171
     1
(* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *) 
wenzelm@23171
     2
(*  Title:      Pure/IsaPlanner/rw_inst.ML
wenzelm@23171
     3
    ID:         $Id$
wenzelm@23171
     4
    Author:     Lucas Dixon, University of Edinburgh
wenzelm@23171
     5
                lucas.dixon@ed.ac.uk
wenzelm@23171
     6
    Created:    25 Aug 2004
wenzelm@23171
     7
*)
wenzelm@23171
     8
(* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *) 
wenzelm@23171
     9
(*  DESCRIPTION:
wenzelm@23171
    10
wenzelm@23171
    11
    rewriting using a conditional meta-equality theorem which supports 
wenzelm@23171
    12
    schematic variable instantiation.
wenzelm@23171
    13
wenzelm@23171
    14
*)   
wenzelm@23171
    15
(* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *)
wenzelm@23171
    16
signature RW_INST =
wenzelm@23171
    17
sig
wenzelm@23171
    18
wenzelm@23171
    19
  (* Rewrite: give it instantiation infromation, a rule, and the
wenzelm@23171
    20
  target thm, and it will return the rewritten target thm *)
wenzelm@23171
    21
  val rw :
wenzelm@23171
    22
      ((Term.indexname * (Term.sort * Term.typ)) list *  (* type var instantiations *)
wenzelm@23171
    23
       (Term.indexname * (Term.typ * Term.term)) list)  (* schematic var instantiations *)
wenzelm@23171
    24
      * (string * Term.typ) list           (* Fake named bounds + types *)
wenzelm@23171
    25
      * (string * Term.typ) list           (* names of bound + types *)
wenzelm@23171
    26
      * Term.term ->                       (* outer term for instantiation *)
wenzelm@23171
    27
      Thm.thm ->                           (* rule with indexies lifted *)
wenzelm@23171
    28
      Thm.thm ->                           (* target thm *)
wenzelm@23171
    29
      Thm.thm                              (* rewritten theorem possibly 
wenzelm@23171
    30
                                              with additional premises for 
wenzelm@23171
    31
                                              rule conditions *)
wenzelm@23171
    32
wenzelm@23171
    33
  (* used tools *)
wenzelm@23171
    34
  val mk_abstractedrule :
wenzelm@23171
    35
      (string * Term.typ) list (* faked outer bound *)
wenzelm@23171
    36
      -> (string * Term.typ) list (* hopeful name of outer bounds *)
wenzelm@23171
    37
      -> Thm.thm -> Thm.cterm list * Thm.thm
wenzelm@23171
    38
  val mk_fixtvar_tyinsts :
wenzelm@23171
    39
      (Term.indexname * (Term.sort * Term.typ)) list ->
wenzelm@23171
    40
      Term.term list -> ((string * int) * (Term.sort * Term.typ)) list 
wenzelm@23171
    41
                        * (string * Term.sort) list
wenzelm@23171
    42
  val mk_renamings :
wenzelm@23171
    43
      Term.term -> Thm.thm -> (((string * int) * Term.typ) * Term.term) list
wenzelm@23171
    44
  val new_tfree :
wenzelm@23171
    45
      ((string * int) * Term.sort) *
wenzelm@23171
    46
      (((string * int) * (Term.sort * Term.typ)) list * string list) ->
wenzelm@23171
    47
      ((string * int) * (Term.sort * Term.typ)) list * string list
wenzelm@23171
    48
  val cross_inst : (Term.indexname * (Term.typ * Term.term)) list 
wenzelm@23171
    49
                   -> (Term.indexname *(Term.typ * Term.term)) list
wenzelm@23171
    50
  val cross_inst_typs : (Term.indexname * (Term.sort * Term.typ)) list 
wenzelm@23171
    51
                   -> (Term.indexname * (Term.sort * Term.typ)) list
wenzelm@23171
    52
wenzelm@23171
    53
  val beta_contract : Thm.thm -> Thm.thm
wenzelm@23171
    54
  val beta_eta_contract : Thm.thm -> Thm.thm
wenzelm@23171
    55
wenzelm@23171
    56
end;
wenzelm@23171
    57
wenzelm@23171
    58
structure RWInst 
wenzelm@23171
    59
: RW_INST
wenzelm@23171
    60
= struct
wenzelm@23171
    61
wenzelm@23171
    62
wenzelm@23171
    63
(* beta contract the theorem *)
wenzelm@23171
    64
fun beta_contract thm = 
wenzelm@23171
    65
    equal_elim (Thm.beta_conversion true (Thm.cprop_of thm)) thm;
wenzelm@23171
    66
wenzelm@23171
    67
(* beta-eta contract the theorem *)
wenzelm@23171
    68
fun beta_eta_contract thm = 
wenzelm@23171
    69
    let
wenzelm@23171
    70
      val thm2 = equal_elim (Thm.beta_conversion true (Thm.cprop_of thm)) thm
wenzelm@23171
    71
      val thm3 = equal_elim (Thm.eta_conversion (Thm.cprop_of thm2)) thm2
wenzelm@23171
    72
    in thm3 end;
wenzelm@23171
    73
wenzelm@23171
    74
wenzelm@23171
    75
(* to get the free names of a theorem (including hyps and flexes) *)
wenzelm@23171
    76
fun usednames_of_thm th =
wenzelm@23171
    77
    let val rep = Thm.rep_thm th
wenzelm@23171
    78
      val hyps = #hyps rep
wenzelm@23171
    79
      val (tpairl,tpairr) = Library.split_list (#tpairs rep)
wenzelm@23171
    80
      val prop = #prop rep
wenzelm@23171
    81
    in
wenzelm@23171
    82
      List.foldr Term.add_term_names [] (prop :: (tpairl @ (tpairr @ hyps)))
wenzelm@23171
    83
    end;
wenzelm@23171
    84
wenzelm@23171
    85
(* Given a list of variables that were bound, and a that has been
wenzelm@23171
    86
instantiated with free variable placeholders for the bound vars, it
wenzelm@23171
    87
creates an abstracted version of the theorem, with local bound vars as
wenzelm@23171
    88
lambda-params:
wenzelm@23171
    89
wenzelm@23171
    90
Ts: 
wenzelm@23171
    91
("x", ty)
wenzelm@23171
    92
wenzelm@23171
    93
rule::
wenzelm@23171
    94
C :x ==> P :x = Q :x
wenzelm@23171
    95
wenzelm@23171
    96
results in:
wenzelm@23171
    97
("!! x. C x", (%x. p x = %y. p y) [!! x. C x])
wenzelm@23171
    98
wenzelm@23171
    99
note: assumes rule is instantiated
wenzelm@23171
   100
*)
wenzelm@23171
   101
(* Note, we take abstraction in the order of last abstraction first *)
wenzelm@23171
   102
fun mk_abstractedrule TsFake Ts rule = 
wenzelm@23171
   103
    let 
wenzelm@23171
   104
      val ctermify = Thm.cterm_of (Thm.theory_of_thm rule);
wenzelm@23171
   105
wenzelm@23171
   106
      (* now we change the names of temporary free vars that represent 
wenzelm@23171
   107
         bound vars with binders outside the redex *)
wenzelm@23171
   108
      val prop = Thm.prop_of rule;
wenzelm@23171
   109
      val names = usednames_of_thm rule;
wenzelm@23171
   110
      val (fromnames,tonames,names2,Ts') = 
wenzelm@23171
   111
          Library.foldl (fn ((rnf,rnt,names, Ts''),((faken,_),(n,ty))) => 
wenzelm@23171
   112
                    let val n2 = Name.variant names n in
wenzelm@23171
   113
                      (ctermify (Free(faken,ty)) :: rnf,
wenzelm@23171
   114
                       ctermify (Free(n2,ty)) :: rnt, 
wenzelm@23171
   115
                       n2 :: names,
wenzelm@23171
   116
                       (n2,ty) :: Ts'')
wenzelm@23171
   117
                    end)
wenzelm@23171
   118
                (([],[],names, []), TsFake~~Ts);
wenzelm@23171
   119
wenzelm@23171
   120
      (* rename conflicting free's in the rule to avoid cconflicts
wenzelm@23171
   121
      with introduced vars from bounds outside in redex *)
wenzelm@23171
   122
      val rule' = rule |> Drule.forall_intr_list fromnames
wenzelm@23171
   123
                       |> Drule.forall_elim_list tonames;
wenzelm@23171
   124
      
wenzelm@23171
   125
      (* make unconditional rule and prems *)
wenzelm@23171
   126
      val (uncond_rule, cprems) = IsaND.allify_conditions ctermify (rev Ts') 
wenzelm@23171
   127
                                                          rule';
wenzelm@23171
   128
wenzelm@23171
   129
      (* using these names create lambda-abstracted version of the rule *)
wenzelm@23171
   130
      val abstractions = rev (Ts' ~~ tonames);
wenzelm@23171
   131
      val abstract_rule = Library.foldl (fn (th,((n,ty),ct)) => 
wenzelm@23171
   132
                                    Thm.abstract_rule n ct th)
wenzelm@23171
   133
                                (uncond_rule, abstractions);
wenzelm@23171
   134
    in (cprems, abstract_rule) end;
wenzelm@23171
   135
wenzelm@23171
   136
wenzelm@23171
   137
(* given names to avoid, and vars that need to be fixed, it gives
wenzelm@23171
   138
unique new names to the vars so that they can be fixed as free
wenzelm@23171
   139
variables *)
wenzelm@23171
   140
(* make fixed unique free variable instantiations for non-ground vars *)
wenzelm@23171
   141
(* Create a table of vars to be renamed after instantiation - ie
wenzelm@23171
   142
      other uninstantiated vars in the hyps of the rule 
wenzelm@23171
   143
      ie ?z in C ?z ?x ==> A ?x ?y = B ?x ?y *)
wenzelm@23171
   144
fun mk_renamings tgt rule_inst = 
wenzelm@23171
   145
    let
wenzelm@23171
   146
      val rule_conds = Thm.prems_of rule_inst
wenzelm@23171
   147
      val names = foldr Term.add_term_names [] (tgt :: rule_conds);
wenzelm@23171
   148
      val (conds_tyvs,cond_vs) = 
wenzelm@23171
   149
          Library.foldl (fn ((tyvs, vs), t) => 
wenzelm@23171
   150
                    (Library.union
wenzelm@23171
   151
                       (Term.term_tvars t, tyvs),
wenzelm@23171
   152
                     Library.union 
wenzelm@23171
   153
                       (map Term.dest_Var (Term.term_vars t), vs))) 
wenzelm@23171
   154
                (([],[]), rule_conds);
wenzelm@23171
   155
      val termvars = map Term.dest_Var (Term.term_vars tgt); 
wenzelm@23171
   156
      val vars_to_fix = Library.union (termvars, cond_vs);
wenzelm@23171
   157
      val (renamings, names2) = 
wenzelm@23171
   158
          foldr (fn (((n,i),ty), (vs, names')) => 
wenzelm@23171
   159
                    let val n' = Name.variant names' n in
wenzelm@23171
   160
                      ((((n,i),ty), Free (n', ty)) :: vs, n'::names')
wenzelm@23171
   161
                    end)
wenzelm@23171
   162
                ([], names) vars_to_fix;
wenzelm@23171
   163
    in renamings end;
wenzelm@23171
   164
wenzelm@23171
   165
(* make a new fresh typefree instantiation for the given tvar *)
wenzelm@23171
   166
fun new_tfree (tv as (ix,sort), (pairs,used)) =
wenzelm@23171
   167
      let val v = Name.variant used (string_of_indexname ix)
wenzelm@23171
   168
      in  ((ix,(sort,TFree(v,sort)))::pairs, v::used)  end;
wenzelm@23171
   169
wenzelm@23171
   170
wenzelm@23171
   171
(* make instantiations to fix type variables that are not 
wenzelm@23171
   172
   already instantiated (in ignore_ixs) from the list of terms. *)
wenzelm@23171
   173
fun mk_fixtvar_tyinsts ignore_insts ts = 
wenzelm@23171
   174
    let 
wenzelm@23171
   175
      val ignore_ixs = map fst ignore_insts;
wenzelm@23171
   176
      val (tvars, tfrees) = 
wenzelm@23171
   177
            foldr (fn (t, (varixs, tfrees)) => 
wenzelm@23171
   178
                      (Term.add_term_tvars (t,varixs),
wenzelm@23171
   179
                       Term.add_term_tfrees (t,tfrees)))
wenzelm@23171
   180
                  ([],[]) ts;
wenzelm@23171
   181
        val unfixed_tvars = 
wenzelm@23171
   182
            List.filter (fn (ix,s) => not (member (op =) ignore_ixs ix)) tvars;
wenzelm@23171
   183
        val (fixtyinsts, _) = foldr new_tfree ([], map fst tfrees) unfixed_tvars
wenzelm@23171
   184
    in (fixtyinsts, tfrees) end;
wenzelm@23171
   185
wenzelm@23171
   186
wenzelm@23171
   187
(* cross-instantiate the instantiations - ie for each instantiation
wenzelm@23171
   188
replace all occurances in other instantiations - no loops are possible
wenzelm@23171
   189
and thus only one-parsing of the instantiations is necessary. *)
wenzelm@23171
   190
fun cross_inst insts = 
wenzelm@23171
   191
    let 
wenzelm@23171
   192
      fun instL (ix, (ty,t)) = 
wenzelm@23171
   193
          map (fn (ix2,(ty2,t2)) => 
wenzelm@23171
   194
                  (ix2, (ty2,Term.subst_vars ([], [(ix, t)]) t2)));
wenzelm@23171
   195
wenzelm@23171
   196
      fun cross_instL ([], l) = rev l
wenzelm@23171
   197
        | cross_instL ((ix, t) :: insts, l) = 
wenzelm@23171
   198
          cross_instL (instL (ix, t) insts, (ix, t) :: (instL (ix, t) l));
wenzelm@23171
   199
wenzelm@23171
   200
    in cross_instL (insts, []) end;
wenzelm@23171
   201
wenzelm@23171
   202
(* as above but for types -- I don't know if this is needed, will we ever incur mixed up types? *)
wenzelm@23171
   203
fun cross_inst_typs insts = 
wenzelm@23171
   204
    let 
wenzelm@23171
   205
      fun instL (ix, (srt,ty)) = 
wenzelm@23171
   206
          map (fn (ix2,(srt2,ty2)) => 
wenzelm@23171
   207
                  (ix2, (srt2,Term.typ_subst_TVars [(ix, ty)] ty2)));
wenzelm@23171
   208
wenzelm@23171
   209
      fun cross_instL ([], l) = rev l
wenzelm@23171
   210
        | cross_instL ((ix, t) :: insts, l) = 
wenzelm@23171
   211
          cross_instL (instL (ix, t) insts, (ix, t) :: (instL (ix, t) l));
wenzelm@23171
   212
wenzelm@23171
   213
    in cross_instL (insts, []) end;
wenzelm@23171
   214
wenzelm@23171
   215
wenzelm@23171
   216
(* assume that rule and target_thm have distinct var names. THINK:
wenzelm@23171
   217
efficient version with tables for vars for: target vars, introduced
wenzelm@23171
   218
vars, and rule vars, for quicker instantiation?  The outerterm defines
wenzelm@23171
   219
which part of the target_thm was modified.  Note: we take Ts in the
wenzelm@23171
   220
upterm order, ie last abstraction first., and with an outeterm where
wenzelm@23171
   221
the abstracted subterm has the arguments in the revered order, ie
wenzelm@23171
   222
first abstraction first.  FakeTs has abstractions using the fake name
wenzelm@23171
   223
- ie the name distinct from all other abstractions. *)
wenzelm@23171
   224
wenzelm@23171
   225
fun rw ((nonfixed_typinsts, unprepinsts), FakeTs, Ts, outerterm) rule target_thm = 
wenzelm@23171
   226
    let 
wenzelm@23171
   227
      (* general signature info *)
wenzelm@23171
   228
      val target_sign = (Thm.theory_of_thm target_thm);
wenzelm@23171
   229
      val ctermify = Thm.cterm_of target_sign;
wenzelm@23171
   230
      val ctypeify = Thm.ctyp_of target_sign;
wenzelm@23171
   231
wenzelm@23171
   232
      (* fix all non-instantiated tvars *)
wenzelm@23171
   233
      val (fixtyinsts, othertfrees) = 
wenzelm@23171
   234
          mk_fixtvar_tyinsts nonfixed_typinsts
wenzelm@23171
   235
                             [Thm.prop_of rule, Thm.prop_of target_thm];
wenzelm@23171
   236
      val new_fixed_typs = map (fn ((s,i),(srt,ty)) => (Term.dest_TFree ty))
wenzelm@23171
   237
                               fixtyinsts;
wenzelm@23171
   238
      val typinsts = cross_inst_typs (nonfixed_typinsts @ fixtyinsts);
wenzelm@23171
   239
wenzelm@23171
   240
      (* certified instantiations for types *)
wenzelm@23171
   241
      val ctyp_insts = 
wenzelm@23171
   242
          map (fn (ix,(s,ty)) => (ctypeify (TVar (ix,s)), ctypeify ty)) 
wenzelm@23171
   243
              typinsts;
wenzelm@23171
   244
wenzelm@23171
   245
      (* type instantiated versions *)
wenzelm@23171
   246
      val tgt_th_tyinst = Thm.instantiate (ctyp_insts,[]) target_thm;
wenzelm@23171
   247
      val rule_tyinst =  Thm.instantiate (ctyp_insts,[]) rule;
wenzelm@23171
   248
wenzelm@23171
   249
      val term_typ_inst = map (fn (ix,(srt,ty)) => (ix,ty)) typinsts;
wenzelm@23171
   250
      (* type instanitated outer term *)
wenzelm@23171
   251
      val outerterm_tyinst = Term.subst_TVars term_typ_inst outerterm;
wenzelm@23171
   252
wenzelm@23171
   253
      val FakeTs_tyinst = map (apsnd (Term.typ_subst_TVars term_typ_inst)) 
wenzelm@23171
   254
                              FakeTs;
wenzelm@23171
   255
      val Ts_tyinst = map (apsnd (Term.typ_subst_TVars term_typ_inst)) 
wenzelm@23171
   256
                          Ts;
wenzelm@23171
   257
wenzelm@23171
   258
      (* type-instantiate the var instantiations *)
wenzelm@23171
   259
      val insts_tyinst = foldr (fn ((ix,(ty,t)),insts_tyinst) => 
wenzelm@23171
   260
                            (ix, (Term.typ_subst_TVars term_typ_inst ty, 
wenzelm@23171
   261
                                  Term.subst_TVars term_typ_inst t))
wenzelm@23171
   262
                            :: insts_tyinst)
wenzelm@23171
   263
                        [] unprepinsts;
wenzelm@23171
   264
wenzelm@23171
   265
      (* cross-instantiate *)
wenzelm@23171
   266
      val insts_tyinst_inst = cross_inst insts_tyinst;
wenzelm@23171
   267
wenzelm@23171
   268
      (* create certms of instantiations *)
wenzelm@23171
   269
      val cinsts_tyinst = 
wenzelm@23171
   270
          map (fn (ix,(ty,t)) => (ctermify (Var (ix, ty)), 
wenzelm@23171
   271
                                  ctermify t)) insts_tyinst_inst;
wenzelm@23171
   272
wenzelm@23171
   273
      (* The instantiated rule *)
wenzelm@23171
   274
      val rule_inst = rule_tyinst |> Thm.instantiate ([], cinsts_tyinst);
wenzelm@23171
   275
wenzelm@23171
   276
      (* Create a table of vars to be renamed after instantiation - ie
wenzelm@23171
   277
      other uninstantiated vars in the hyps the *instantiated* rule 
wenzelm@23171
   278
      ie ?z in C ?z ?x ==> A ?x ?y = B ?x ?y *)
wenzelm@23171
   279
      val renamings = mk_renamings (Thm.prop_of tgt_th_tyinst) 
wenzelm@23171
   280
                                   rule_inst;
wenzelm@23171
   281
      val cterm_renamings = 
wenzelm@23171
   282
          map (fn (x,y) => (ctermify (Var x), ctermify y)) renamings;
wenzelm@23171
   283
wenzelm@23171
   284
      (* Create the specific version of the rule for this target application *)
wenzelm@23171
   285
      val outerterm_inst = 
wenzelm@23171
   286
          outerterm_tyinst 
wenzelm@23171
   287
            |> Term.subst_Vars (map (fn (ix,(ty,t)) => (ix,t)) insts_tyinst_inst)
wenzelm@23171
   288
            |> Term.subst_Vars (map (fn ((ix,ty),t) => (ix,t)) renamings);
wenzelm@23171
   289
      val couter_inst = Thm.reflexive (ctermify outerterm_inst);
wenzelm@23171
   290
      val (cprems, abstract_rule_inst) = 
wenzelm@23171
   291
          rule_inst |> Thm.instantiate ([], cterm_renamings)
wenzelm@23171
   292
                    |> mk_abstractedrule FakeTs_tyinst Ts_tyinst;
wenzelm@23171
   293
      val specific_tgt_rule = 
wenzelm@23171
   294
          beta_eta_contract
wenzelm@23171
   295
            (Thm.combination couter_inst abstract_rule_inst);
wenzelm@23171
   296
wenzelm@23171
   297
      (* create an instantiated version of the target thm *)
wenzelm@23171
   298
      val tgt_th_inst = 
wenzelm@23171
   299
          tgt_th_tyinst |> Thm.instantiate ([], cinsts_tyinst)
wenzelm@23171
   300
                        |> Thm.instantiate ([], cterm_renamings);
wenzelm@23171
   301
wenzelm@23171
   302
      val (vars,frees_of_fixed_vars) = Library.split_list cterm_renamings;
wenzelm@23171
   303
wenzelm@23171
   304
    in
wenzelm@23171
   305
      (beta_eta_contract tgt_th_inst)
wenzelm@23171
   306
        |> Thm.equal_elim specific_tgt_rule
wenzelm@23171
   307
        |> Drule.implies_intr_list cprems
wenzelm@23171
   308
        |> Drule.forall_intr_list frees_of_fixed_vars
wenzelm@23171
   309
        |> Drule.forall_elim_list vars
wenzelm@23171
   310
        |> Thm.varifyT' othertfrees
wenzelm@23171
   311
        |-> K Drule.zero_var_indexes
wenzelm@23171
   312
    end;
wenzelm@23171
   313
wenzelm@23171
   314
wenzelm@23171
   315
end; (* struct *)