src/Tools/IsaPlanner/isand.ML
author wenzelm
Wed Sep 12 23:18:26 2012 +0200 (2012-09-12)
changeset 49340 25fc6e0da459
parent 49339 d1fcb4de8349
child 52242 2d634bfa1bbf
permissions -rw-r--r--
observe context more carefully when producing "fresh" variables -- for increased chances that method "subst" works in local context (including that of forked proofs);
wenzelm@23175
     1
(*  Title:      Tools/IsaPlanner/isand.ML
wenzelm@23171
     2
    Author:     Lucas Dixon, University of Edinburgh
wenzelm@23175
     3
wenzelm@23175
     4
Natural Deduction tools.
wenzelm@23171
     5
wenzelm@23175
     6
For working with Isabelle theorems in a natural detuction style.
wenzelm@23175
     7
ie, not having to deal with meta level quantified varaibles,
wenzelm@23175
     8
instead, we work with newly introduced frees, and hide the
wenzelm@23175
     9
"all"'s, exporting results from theorems proved with the frees, to
wenzelm@23175
    10
solve the all cases of the previous goal. This allows resolution
wenzelm@49339
    11
to do proof search normally.
wenzelm@23171
    12
wenzelm@23175
    13
Note: A nice idea: allow exporting to solve any subgoal, thus
wenzelm@23175
    14
allowing the interleaving of proof, or provide a structure for the
wenzelm@23175
    15
ordering of proof, thus allowing proof attempts in parrell, but
wenzelm@23175
    16
recording the order to apply things in.
wenzelm@23171
    17
wenzelm@23175
    18
THINK: are we really ok with our varify name w.r.t the prop - do
wenzelm@23175
    19
we also need to avoid names in the hidden hyps? What about
wenzelm@23175
    20
unification contraints in flex-flex pairs - might they also have
wenzelm@23175
    21
extra free vars?
wenzelm@23171
    22
*)
wenzelm@23171
    23
wenzelm@23171
    24
signature ISA_ND =
wenzelm@23171
    25
sig
wenzelm@23171
    26
  (* inserting meta level params for frees in the conditions *)
wenzelm@49339
    27
  val allify_conditions : (term -> cterm) -> (string * typ) list -> thm -> thm * cterm list
wenzelm@23171
    28
wenzelm@49340
    29
  val variant_names : Proof.context -> term list -> string list -> string list
wenzelm@49340
    30
wenzelm@23171
    31
  (* meta level fixed params (i.e. !! vars) *)
wenzelm@49340
    32
  val fix_alls_term : Proof.context -> int -> term -> term * term list
wenzelm@23171
    33
wenzelm@49339
    34
  val unfix_frees : cterm list -> thm -> thm
wenzelm@23171
    35
wenzelm@23171
    36
  (* assumptions/subgoals *)
wenzelm@49340
    37
  val fixed_subgoal_thms : Proof.context -> thm -> thm list * (thm list -> thm)
wenzelm@23171
    38
end
wenzelm@23171
    39
wenzelm@49339
    40
structure IsaND : ISA_ND =
wenzelm@49339
    41
struct
wenzelm@23171
    42
wenzelm@23171
    43
(* Given ctertmify function, (string,type) pairs capturing the free
wenzelm@23171
    44
vars that need to be allified in the assumption, and a theorem with
wenzelm@23171
    45
assumptions possibly containing the free vars, then we give back the
wenzelm@49339
    46
assumptions allified as hidden hyps.
wenzelm@23171
    47
wenzelm@49339
    48
Given: x
wenzelm@49339
    49
th: A vs ==> B vs
wenzelm@23171
    50
Results in: "B vs" [!!x. A x]
wenzelm@23171
    51
*)
wenzelm@49339
    52
fun allify_conditions ctermify Ts th =
wenzelm@49339
    53
    let
wenzelm@23171
    54
      val premts = Thm.prems_of th;
wenzelm@49339
    55
wenzelm@49339
    56
      fun allify_prem_var (vt as (n,ty),t)  =
wenzelm@46217
    57
          (Logic.all_const ty) $ (Abs(n,ty,Term.abstract_over (Free vt, t)))
wenzelm@23171
    58
wenzelm@30190
    59
      fun allify_prem Ts p = List.foldr allify_prem_var p Ts
wenzelm@23171
    60
wenzelm@23171
    61
      val cTs = map (ctermify o Free) Ts
wenzelm@23171
    62
      val cterm_asms = map (ctermify o allify_prem Ts) premts
wenzelm@23171
    63
      val allifyied_asm_thms = map (Drule.forall_elim_list cTs o Thm.assume) cterm_asms
wenzelm@49339
    64
    in
wenzelm@23171
    65
      (Library.foldl (fn (x,y) => y COMP x) (th, allifyied_asm_thms), cterm_asms)
wenzelm@23171
    66
    end;
wenzelm@23171
    67
wenzelm@23171
    68
(* make free vars into schematic vars with index zero *)
wenzelm@49339
    69
fun unfix_frees frees =
wenzelm@46777
    70
     fold (K (Thm.forall_elim_var 0)) frees
wenzelm@23171
    71
     o Drule.forall_intr_list frees;
wenzelm@23171
    72
wenzelm@23171
    73
(* datatype to capture an exported result, ie a fix or assume. *)
wenzelm@49339
    74
datatype export =
wenzelm@23171
    75
         export of {fixes : Thm.cterm list, (* fixed vars *)
wenzelm@23171
    76
                    assumes : Thm.cterm list, (* hidden hyps/assumed prems *)
wenzelm@23171
    77
                    sgid : int,
wenzelm@23171
    78
                    gth :  Thm.thm}; (* subgoal/goalthm *)
wenzelm@23171
    79
wenzelm@23171
    80
(* exporting function that takes a solution to the fixed/assumed goal,
wenzelm@23171
    81
and uses this to solve the subgoal in the main theorem *)
wenzelm@23171
    82
fun export_solution (export {fixes = cfvs, assumes = hcprems,
wenzelm@49339
    83
                             sgid = i, gth = gth}) solth =
wenzelm@49339
    84
    let
wenzelm@49339
    85
      val solth' =
wenzelm@23171
    86
          solth |> Drule.implies_intr_list hcprems
wenzelm@23171
    87
                |> Drule.forall_intr_list cfvs
wenzelm@23171
    88
    in Drule.compose_single (solth', i, gth) end;
wenzelm@23171
    89
wenzelm@49340
    90
fun variant_names ctxt ts xs =
wenzelm@49340
    91
  let
wenzelm@49340
    92
    val names =
wenzelm@49340
    93
      Variable.names_of ctxt
wenzelm@49340
    94
      |> (fold o fold_aterms)
wenzelm@49340
    95
          (fn Var ((a, _), _) => Name.declare a
wenzelm@49340
    96
            | Free (a, _) => Name.declare a
wenzelm@49340
    97
            | _ => I) ts;
wenzelm@49340
    98
  in fst (fold_map Name.variant xs names) end;
wenzelm@23171
    99
wenzelm@23171
   100
(* fix parameters of a subgoal "i", as free variables, and create an
wenzelm@23171
   101
exporting function that will use the result of this proved goal to
wenzelm@49339
   102
show the goal in the original theorem.
wenzelm@23171
   103
wenzelm@23171
   104
Note, an advantage of this over Isar is that it supports instantiation
wenzelm@23171
   105
of unkowns in the earlier theorem, ie we can do instantiation of meta
wenzelm@49339
   106
vars!
wenzelm@23171
   107
wenzelm@49339
   108
avoids constant, free and vars names.
wenzelm@23171
   109
wenzelm@23171
   110
loosely corresponds to:
wenzelm@23171
   111
Given "[| SG0; ... !! x. As ==> SGi x; ... SGm |] ==> G" : thm
wenzelm@49339
   112
Result:
wenzelm@49339
   113
  ("(As ==> SGi x') ==> (As ==> SGi x')" : thm,
wenzelm@49339
   114
   expf :
wenzelm@49339
   115
     ("As ==> SGi x'" : thm) ->
wenzelm@23171
   116
     ("[| SG0; ... SGi-1; SGi+1; ... SGm |] ==> G") : thm)
wenzelm@23171
   117
*)
wenzelm@49340
   118
fun fix_alls_term ctxt i t =
wenzelm@23171
   119
    let
wenzelm@23171
   120
      val gt = Logic.get_goal t i;
wenzelm@23171
   121
      val body = Term.strip_all_body gt;
wenzelm@23171
   122
      val alls = rev (Term.strip_all_vars gt);
wenzelm@49340
   123
      val xs = variant_names ctxt [t] (map fst alls);
wenzelm@49340
   124
      val fvs = map Free (xs ~~ map snd alls);
wenzelm@23171
   125
    in ((subst_bounds (fvs,body)), fvs) end;
wenzelm@23171
   126
wenzelm@49340
   127
fun fix_alls_cterm ctxt i th =
wenzelm@23171
   128
    let
wenzelm@23171
   129
      val ctermify = Thm.cterm_of (Thm.theory_of_thm th);
wenzelm@49340
   130
      val (fixedbody, fvs) = fix_alls_term ctxt i (Thm.prop_of th);
wenzelm@23171
   131
      val cfvs = rev (map ctermify fvs);
wenzelm@23171
   132
      val ct_body = ctermify fixedbody
wenzelm@23171
   133
    in
wenzelm@23171
   134
      (ct_body, cfvs)
wenzelm@23171
   135
    end;
wenzelm@23171
   136
wenzelm@49340
   137
fun fix_alls' ctxt i = apfst Thm.trivial o fix_alls_cterm ctxt i;
wenzelm@23171
   138
wenzelm@23171
   139
wenzelm@49339
   140
(* hide other goals *)
wenzelm@23171
   141
(* note the export goal is rotated by (i - 1) and will have to be
wenzelm@23171
   142
unrotated to get backto the originial position(s) *)
wenzelm@49339
   143
fun hide_other_goals th =
wenzelm@23171
   144
    let
wenzelm@23171
   145
      (* tl beacuse fst sg is the goal we are interested in *)
wenzelm@23171
   146
      val cprems = tl (Drule.cprems_of th)
wenzelm@23171
   147
      val aprems = map Thm.assume cprems
wenzelm@23171
   148
    in
wenzelm@49339
   149
      (Drule.implies_elim_list (Drule.rotate_prems 1 th) aprems,
wenzelm@23171
   150
       cprems)
wenzelm@23171
   151
    end;
wenzelm@23171
   152
wenzelm@23171
   153
(* a nicer version of the above that leaves only a single subgoal (the
wenzelm@23171
   154
other subgoals are hidden hyps, that the exporter suffles about)
wenzelm@23171
   155
namely the subgoal that we were trying to solve. *)
wenzelm@23171
   156
(* loosely corresponds to:
wenzelm@23171
   157
Given "[| SG0; ... !! x. As ==> SGi x; ... SGm |] ==> G" : thm
wenzelm@49339
   158
Result:
wenzelm@49339
   159
  ("(As ==> SGi x') ==> SGi x'" : thm,
wenzelm@49339
   160
   expf :
wenzelm@49339
   161
     ("SGi x'" : thm) ->
wenzelm@23171
   162
     ("[| SG0; ... SGi-1; SGi+1; ... SGm |] ==> G") : thm)
wenzelm@23171
   163
*)
wenzelm@49340
   164
fun fix_alls ctxt i th =
wenzelm@49339
   165
    let
wenzelm@49340
   166
      val (fixed_gth, fixedvars) = fix_alls' ctxt i th
wenzelm@23171
   167
      val (sml_gth, othergoals) = hide_other_goals fixed_gth
wenzelm@23171
   168
    in
wenzelm@49339
   169
      (sml_gth, export {fixes = fixedvars,
wenzelm@49339
   170
                        assumes = othergoals,
wenzelm@23171
   171
                        sgid = i, gth = th})
wenzelm@23171
   172
    end;
wenzelm@23171
   173
wenzelm@23171
   174
wenzelm@23171
   175
(* Fixme: allow different order of subgoals given to expf *)
wenzelm@23171
   176
(* make each subgoal into a separate thm that needs to be proved *)
wenzelm@23171
   177
(* loosely corresponds to:
wenzelm@49339
   178
Given
wenzelm@23171
   179
  "[| SG0; ... SGm |] ==> G" : thm
wenzelm@49339
   180
Result:
wenzelm@23171
   181
(["SG0 ==> SG0", ... ,"SGm ==> SGm"] : thm list, -- goals
wenzelm@23171
   182
 ["SG0", ..., "SGm"] : thm list ->   -- export function
wenzelm@23171
   183
   "G" : thm)
wenzelm@23171
   184
*)
wenzelm@49339
   185
fun subgoal_thms th =
wenzelm@49339
   186
    let
wenzelm@49339
   187
      val t = (prop_of th);
wenzelm@23171
   188
wenzelm@23171
   189
      val prems = Logic.strip_imp_prems t;
wenzelm@23171
   190
wenzelm@23171
   191
      val sgn = Thm.theory_of_thm th;
wenzelm@23171
   192
      val ctermify = Thm.cterm_of sgn;
wenzelm@23171
   193
wenzelm@23171
   194
      val aprems = map (Thm.trivial o ctermify) prems;
wenzelm@23171
   195
wenzelm@49339
   196
      fun explortf premths =
wenzelm@23171
   197
          Drule.implies_elim_list th premths
wenzelm@23171
   198
    in
wenzelm@23171
   199
      (aprems, explortf)
wenzelm@23171
   200
    end;
wenzelm@23171
   201
wenzelm@23171
   202
wenzelm@23171
   203
(* Fixme: allow different order of subgoals in exportf *)
wenzelm@23171
   204
(* as above, but also fix all parameters in all subgoals, and uses
wenzelm@23171
   205
fix_alls, not fix_alls', ie doesn't leave extra asumptions as apparent
wenzelm@23171
   206
subgoals. *)
wenzelm@23171
   207
(* loosely corresponds to:
wenzelm@49339
   208
Given
wenzelm@49339
   209
  "[| !! x0s. A0s x0s ==> SG0 x0s;
wenzelm@23171
   210
      ...; !! xms. Ams xms ==> SGm xms|] ==> G" : thm
wenzelm@49339
   211
Result:
wenzelm@49339
   212
(["(A0s x0s' ==> SG0 x0s') ==> SG0 x0s'",
wenzelm@23171
   213
  ... ,"(Ams xms' ==> SGm xms') ==> SGm xms'"] : thm list, -- goals
wenzelm@23171
   214
 ["SG0 x0s'", ..., "SGm xms'"] : thm list ->   -- export function
wenzelm@23171
   215
   "G" : thm)
wenzelm@23171
   216
*)
wenzelm@23171
   217
(* requires being given solutions! *)
wenzelm@49340
   218
fun fixed_subgoal_thms ctxt th =
wenzelm@49339
   219
    let
wenzelm@23171
   220
      val (subgoals, expf) = subgoal_thms th;
wenzelm@23171
   221
(*       fun export_sg (th, exp) = exp th; *)
wenzelm@49339
   222
      fun export_sgs expfs solthms =
wenzelm@23171
   223
          expf (map2 (curry (op |>)) solthms expfs);
wenzelm@23171
   224
(*           expf (map export_sg (ths ~~ expfs)); *)
wenzelm@49339
   225
    in
wenzelm@49339
   226
      apsnd export_sgs (Library.split_list (map (apsnd export_solution o
wenzelm@49340
   227
                                                 fix_alls ctxt 1) subgoals))
wenzelm@23171
   228
    end;
wenzelm@23171
   229
wenzelm@23171
   230
end;