src/HOL/Tools/TFL/casesplit.ML
author wenzelm
Wed, 15 Feb 2012 20:28:19 +0100
changeset 46489 2accd201e5bc
parent 45701 615da8b8d758
child 49340 25fc6e0da459
permissions -rw-r--r--
removed dead code;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
23150
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
     1
(*  Title:      HOL/Tools/TFL/casesplit.ML
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
     2
    Author:     Lucas Dixon, University of Edinburgh
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
     3
41840
f69045fdc836 removed dead code/unused exports/speculative generality
krauss
parents: 41228
diff changeset
     4
Extra case splitting for TFL.
23150
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
     5
*)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
     6
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
     7
signature CASE_SPLIT =
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
     8
sig
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
     9
  (* try to recursively split conjectured thm to given list of thms *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    10
  val splitto : thm list -> thm -> thm
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    11
end;
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    12
41840
f69045fdc836 removed dead code/unused exports/speculative generality
krauss
parents: 41228
diff changeset
    13
structure CaseSplit: CASE_SPLIT =
23150
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    14
struct
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    15
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    16
(* beta-eta contract the theorem *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    17
fun beta_eta_contract thm =
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    18
    let
36945
9bec62c10714 less pervasive names from structure Thm;
wenzelm
parents: 32952
diff changeset
    19
      val thm2 = Thm.equal_elim (Thm.beta_conversion true (Thm.cprop_of thm)) thm
9bec62c10714 less pervasive names from structure Thm;
wenzelm
parents: 32952
diff changeset
    20
      val thm3 = Thm.equal_elim (Thm.eta_conversion (Thm.cprop_of thm2)) thm2
23150
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    21
    in thm3 end;
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    22
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    23
(* make a casethm from an induction thm *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    24
val cases_thm_of_induct_thm =
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    25
     Seq.hd o (ALLGOALS (fn i => REPEAT (etac Drule.thin_rl i)));
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    26
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    27
(* get the case_thm (my version) from a type *)
31784
bd3486c57ba3 tuned interfaces of datatype module
haftmann
parents: 31723
diff changeset
    28
fun case_thm_of_ty thy ty  =
23150
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    29
    let
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    30
      val ty_str = case ty of
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    31
                     Type(ty_str, _) => ty_str
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    32
                   | TFree(s,_)  => error ("Free type: " ^ s)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    33
                   | TVar((s,i),_) => error ("Free variable: " ^ s)
45701
615da8b8d758 discontinued obsolete datatype "alt_names";
wenzelm
parents: 44121
diff changeset
    34
      val {induct, ...} = Datatype.the_info thy ty_str
23150
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    35
    in
45701
615da8b8d758 discontinued obsolete datatype "alt_names";
wenzelm
parents: 44121
diff changeset
    36
      cases_thm_of_induct_thm induct
23150
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    37
    end;
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    38
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    39
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    40
(* for use when there are no prems to the subgoal *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    41
(* does a case split on the given variable *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    42
fun mk_casesplit_goal_thm sgn (vstr,ty) gt =
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    43
    let
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    44
      val x = Free(vstr,ty)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    45
      val abst = Abs(vstr, ty, Term.abstract_over (x, gt));
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    46
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    47
      val ctermify = Thm.cterm_of sgn;
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    48
      val ctypify = Thm.ctyp_of sgn;
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    49
      val case_thm = case_thm_of_ty sgn ty;
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    50
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    51
      val abs_ct = ctermify abst;
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    52
      val free_ct = ctermify x;
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    53
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    54
      val (Pv, Dv, type_insts) =
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    55
          case (Thm.concl_of case_thm) of
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    56
            (_ $ ((Pv as Var(P,Pty)) $ (Dv as Var(D, Dty)))) =>
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    57
            (Pv, Dv,
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    58
             Sign.typ_match sgn (Dty, ty) Vartab.empty)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    59
          | _ => error "not a valid case thm";
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    60
      val type_cinsts = map (fn (ixn, (S, T)) => (ctypify (TVar (ixn, S)), ctypify T))
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    61
        (Vartab.dest type_insts);
32035
8e77b6a250d5 tuned/modernized Envir.subst_XXX;
wenzelm
parents: 31784
diff changeset
    62
      val cPv = ctermify (Envir.subst_term_types type_insts Pv);
8e77b6a250d5 tuned/modernized Envir.subst_XXX;
wenzelm
parents: 31784
diff changeset
    63
      val cDv = ctermify (Envir.subst_term_types type_insts Dv);
23150
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    64
    in
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    65
      (beta_eta_contract
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    66
         (case_thm
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    67
            |> Thm.instantiate (type_cinsts, [])
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    68
            |> Thm.instantiate ([], [(cPv, abs_ct), (cDv, free_ct)])))
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    69
    end;
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    70
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    71
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    72
(* the find_XXX_split functions are simply doing a lightwieght (I
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    73
think) term matching equivalent to find where to do the next split *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    74
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    75
(* assuming two twems are identical except for a free in one at a
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    76
subterm, or constant in another, ie assume that one term is a plit of
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    77
another, then gives back the free variable that has been split. *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    78
exception find_split_exp of string
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    79
fun find_term_split (Free v, _ $ _) = SOME v
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    80
  | find_term_split (Free v, Const _) = SOME v
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    81
  | find_term_split (Free v, Abs _) = SOME v (* do we really want this case? *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    82
  | find_term_split (Free v, Var _) = NONE (* keep searching *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    83
  | find_term_split (a $ b, a2 $ b2) =
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    84
    (case find_term_split (a, a2) of
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    85
       NONE => find_term_split (b,b2)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    86
     | vopt => vopt)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    87
  | find_term_split (Abs(_,ty,t1), Abs(_,ty2,t2)) =
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    88
    find_term_split (t1, t2)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    89
  | find_term_split (Const (x,ty), Const(x2,ty2)) =
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    90
    if x = x2 then NONE else (* keep searching *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    91
    raise find_split_exp (* stop now *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    92
            "Terms are not identical upto a free varaible! (Consts)"
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    93
  | find_term_split (Bound i, Bound j) =
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    94
    if i = j then NONE else (* keep searching *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    95
    raise find_split_exp (* stop now *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    96
            "Terms are not identical upto a free varaible! (Bound)"
46489
2accd201e5bc removed dead code;
wenzelm
parents: 45701
diff changeset
    97
  | find_term_split _ =
23150
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    98
    raise find_split_exp (* stop now *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
    99
            "Terms are not identical upto a free varaible! (Other)";
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   100
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   101
(* assume that "splitth" is a case split form of subgoal i of "genth",
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   102
then look for a free variable to split, breaking the subgoal closer to
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   103
splitth. *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   104
fun find_thm_split splitth i genth =
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   105
    find_term_split (Logic.get_goal (Thm.prop_of genth) i,
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   106
                     Thm.concl_of splitth) handle find_split_exp _ => NONE;
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   107
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   108
(* as above but searches "splitths" for a theorem that suggest a case split *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   109
fun find_thms_split splitths i genth =
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   110
    Library.get_first (fn sth => find_thm_split sth i genth) splitths;
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   111
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   112
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   113
(* split the subgoal i of "genth" until we get to a member of
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   114
splitths. Assumes that genth will be a general form of splitths, that
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   115
can be case-split, as needed. Otherwise fails. Note: We assume that
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   116
all of "splitths" are split to the same level, and thus it doesn't
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   117
matter which one we choose to look for the next split. Simply add
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   118
search on splitthms and split variable, to change this.  *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   119
(* Note: possible efficiency measure: when a case theorem is no longer
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   120
useful, drop it? *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   121
(* Note: This should not be a separate tactic but integrated into the
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   122
case split done during recdef's case analysis, this would avoid us
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   123
having to (re)search for variables to split. *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   124
fun splitto splitths genth =
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   125
    let
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   126
      val _ = not (null splitths) orelse error "splitto: no given splitths";
42364
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   127
      val thy = Thm.theory_of_thm genth;
23150
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   128
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   129
      (* check if we are a member of splitths - FIXME: quicker and
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   130
      more flexible with discrim net. *)
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   131
      fun solve_by_splitth th split =
42364
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   132
        Thm.biresolution false [(false,split)] 1 th;
23150
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   133
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   134
      fun split th =
42364
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   135
        (case find_thms_split splitths 1 th of
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   136
          NONE =>
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   137
           (writeln (cat_lines
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   138
            (["th:", Display.string_of_thm_without_context th, "split ths:"] @
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   139
              map Display.string_of_thm_without_context splitths @ ["\n--"]));
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   140
            error "splitto: cannot find variable to split on")
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   141
        | SOME v =>
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   142
            let
42365
bfd28ba57859 more direct Logic.dest_implies (with exception TERM instead of Subscript);
wenzelm
parents: 42364
diff changeset
   143
              val gt = HOLogic.dest_Trueprop (#1 (Logic.dest_implies (Thm.prop_of th)));
42364
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   144
              val split_thm = mk_casesplit_goal_thm thy v gt;
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   145
              val (subthms, expf) = IsaND.fixed_subgoal_thms split_thm;
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   146
            in
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   147
              expf (map recsplitf subthms)
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   148
            end)
23150
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   149
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   150
      and recsplitf th =
42364
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   151
        (* note: multiple unifiers! we only take the first element,
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   152
           probably fine -- there is probably only one anyway. *)
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   153
        (case get_first (Seq.pull o solve_by_splitth th) splitths of
8c674b3b8e44 eliminated old List.nth;
wenzelm
parents: 41840
diff changeset
   154
          NONE => split th
46489
2accd201e5bc removed dead code;
wenzelm
parents: 45701
diff changeset
   155
        | SOME (solved_th, _) => solved_th);
23150
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   156
    in
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   157
      recsplitf genth
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   158
    end;
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   159
073a65f0bc40 moved TFL files to canonical place;
wenzelm
parents:
diff changeset
   160
end;