TFL/casesplit.ML
changeset 15531 08c8dad8e399
parent 15252 d4f1b11c336b
child 15570 8d8c70b41bab
equal deleted inserted replaced
15530:6f43714517ee 15531:08c8dad8e399
    70       string * Term.typ -> int -> Thm.thm -> Thm.thm Seq.seq
    70       string * Term.typ -> int -> Thm.thm -> Thm.thm Seq.seq
    71   val casesplit_name : string -> int -> Thm.thm -> Thm.thm Seq.seq
    71   val casesplit_name : string -> int -> Thm.thm -> Thm.thm Seq.seq
    72 
    72 
    73   (* finding a free var to split *)
    73   (* finding a free var to split *)
    74   val find_term_split :
    74   val find_term_split :
    75       Term.term * Term.term -> (string * Term.typ) Library.option
    75       Term.term * Term.term -> (string * Term.typ) option
    76   val find_thm_split :
    76   val find_thm_split :
    77       Thm.thm -> int -> Thm.thm -> (string * Term.typ) Library.option
    77       Thm.thm -> int -> Thm.thm -> (string * Term.typ) option
    78   val find_thms_split :
    78   val find_thms_split :
    79       Thm.thm list -> int -> Thm.thm -> (string * Term.typ) Library.option
    79       Thm.thm list -> int -> Thm.thm -> (string * Term.typ) option
    80 
    80 
    81   (* try to recursively split conjectured thm to given list of thms *)
    81   (* try to recursively split conjectured thm to given list of thms *)
    82   val splitto : Thm.thm list -> Thm.thm -> Thm.thm
    82   val splitto : Thm.thm list -> Thm.thm -> Thm.thm
    83 
    83 
    84   (* for use with the recdef package *)
    84   (* for use with the recdef package *)
   127                    | TFree(s,_)  => raise ERROR_MESSAGE 
   127                    | TFree(s,_)  => raise ERROR_MESSAGE 
   128                                             ("Free type: " ^ s)   
   128                                             ("Free type: " ^ s)   
   129                    | TVar((s,i),_) => raise ERROR_MESSAGE 
   129                    | TVar((s,i),_) => raise ERROR_MESSAGE 
   130                                             ("Free variable: " ^ s)   
   130                                             ("Free variable: " ^ s)   
   131       val dt = case (Symtab.lookup (dtypestab,ty_str))
   131       val dt = case (Symtab.lookup (dtypestab,ty_str))
   132                 of Some dt => dt
   132                 of SOME dt => dt
   133                  | None => raise ERROR_MESSAGE ("Not a Datatype: " ^ ty_str)
   133                  | NONE => raise ERROR_MESSAGE ("Not a Datatype: " ^ ty_str)
   134     in
   134     in
   135       cases_thm_of_induct_thm (#induction dt)
   135       cases_thm_of_induct_thm (#induction dt)
   136     end;
   136     end;
   137 
   137 
   138 (* 
   138 (* 
   204 
   204 
   205       val freets = Term.term_frees gt;
   205       val freets = Term.term_frees gt;
   206       fun getter x = 
   206       fun getter x = 
   207           let val (n,ty) = Term.dest_Free x in 
   207           let val (n,ty) = Term.dest_Free x in 
   208             (if vstr = n orelse vstr = Syntax.dest_skolem n 
   208             (if vstr = n orelse vstr = Syntax.dest_skolem n 
   209              then Some (n,ty) else None )
   209              then SOME (n,ty) else NONE )
   210             handle LIST _ => None
   210             handle LIST _ => NONE
   211           end;
   211           end;
   212       val (n,ty) = case Library.get_first getter freets 
   212       val (n,ty) = case Library.get_first getter freets 
   213                 of Some (n, ty) => (n, ty)
   213                 of SOME (n, ty) => (n, ty)
   214                  | _ => raise ERROR_MESSAGE ("no such variable " ^ vstr);
   214                  | _ => raise ERROR_MESSAGE ("no such variable " ^ vstr);
   215       val sgn = Thm.sign_of_thm th;
   215       val sgn = Thm.sign_of_thm th;
   216 
   216 
   217       val splitter_thm = mk_casesplit_goal_thm sgn (n,ty) gt;
   217       val splitter_thm = mk_casesplit_goal_thm sgn (n,ty) gt;
   218       val nsplits = Thm.nprems_of splitter_thm;
   218       val nsplits = Thm.nprems_of splitter_thm;
   245 
   245 
   246 (* assuming two twems are identical except for a free in one at a
   246 (* assuming two twems are identical except for a free in one at a
   247 subterm, or constant in another, ie assume that one term is a plit of
   247 subterm, or constant in another, ie assume that one term is a plit of
   248 another, then gives back the free variable that has been split. *)
   248 another, then gives back the free variable that has been split. *)
   249 exception find_split_exp of string
   249 exception find_split_exp of string
   250 fun find_term_split (Free v, _ $ _) = Some v
   250 fun find_term_split (Free v, _ $ _) = SOME v
   251   | find_term_split (Free v, Const _) = Some v
   251   | find_term_split (Free v, Const _) = SOME v
   252   | find_term_split (Free v, Abs _) = Some v (* do we really want this case? *)
   252   | find_term_split (Free v, Abs _) = SOME v (* do we really want this case? *)
   253   | find_term_split (Free v, Var _) = None (* keep searching *)
   253   | find_term_split (Free v, Var _) = NONE (* keep searching *)
   254   | find_term_split (a $ b, a2 $ b2) = 
   254   | find_term_split (a $ b, a2 $ b2) = 
   255     (case find_term_split (a, a2) of 
   255     (case find_term_split (a, a2) of 
   256        None => find_term_split (b,b2)  
   256        NONE => find_term_split (b,b2)  
   257      | vopt => vopt)
   257      | vopt => vopt)
   258   | find_term_split (Abs(_,ty,t1), Abs(_,ty2,t2)) = 
   258   | find_term_split (Abs(_,ty,t1), Abs(_,ty2,t2)) = 
   259     find_term_split (t1, t2)
   259     find_term_split (t1, t2)
   260   | find_term_split (Const (x,ty), Const(x2,ty2)) = 
   260   | find_term_split (Const (x,ty), Const(x2,ty2)) = 
   261     if x = x2 then None else (* keep searching *)
   261     if x = x2 then NONE else (* keep searching *)
   262     raise find_split_exp (* stop now *)
   262     raise find_split_exp (* stop now *)
   263             "Terms are not identical upto a free varaible! (Consts)"
   263             "Terms are not identical upto a free varaible! (Consts)"
   264   | find_term_split (Bound i, Bound j) =     
   264   | find_term_split (Bound i, Bound j) =     
   265     if i = j then None else (* keep searching *)
   265     if i = j then NONE else (* keep searching *)
   266     raise find_split_exp (* stop now *)
   266     raise find_split_exp (* stop now *)
   267             "Terms are not identical upto a free varaible! (Bound)"
   267             "Terms are not identical upto a free varaible! (Bound)"
   268   | find_term_split (a, b) = 
   268   | find_term_split (a, b) = 
   269     raise find_split_exp (* stop now *)
   269     raise find_split_exp (* stop now *)
   270             "Terms are not identical upto a free varaible! (Other)";
   270             "Terms are not identical upto a free varaible! (Other)";
   272 (* assume that "splitth" is a case split form of subgoal i of "genth",
   272 (* assume that "splitth" is a case split form of subgoal i of "genth",
   273 then look for a free variable to split, breaking the subgoal closer to
   273 then look for a free variable to split, breaking the subgoal closer to
   274 splitth. *)
   274 splitth. *)
   275 fun find_thm_split splitth i genth =
   275 fun find_thm_split splitth i genth =
   276     find_term_split (Logic.get_goal (Thm.prop_of genth) i, 
   276     find_term_split (Logic.get_goal (Thm.prop_of genth) i, 
   277                      Thm.concl_of splitth) handle find_split_exp _ => None;
   277                      Thm.concl_of splitth) handle find_split_exp _ => NONE;
   278 
   278 
   279 (* as above but searches "splitths" for a theorem that suggest a case split *)
   279 (* as above but searches "splitths" for a theorem that suggest a case split *)
   280 fun find_thms_split splitths i genth =
   280 fun find_thms_split splitths i genth =
   281     Library.get_first (fn sth => find_thm_split sth i genth) splitths;
   281     Library.get_first (fn sth => find_thm_split sth i genth) splitths;
   282 
   282 
   302       fun solve_by_splitth th split = 
   302       fun solve_by_splitth th split = 
   303           Thm.biresolution false [(false,split)] 1 th;
   303           Thm.biresolution false [(false,split)] 1 th;
   304 
   304 
   305       fun split th = 
   305       fun split th = 
   306           (case find_thms_split splitths 1 th of 
   306           (case find_thms_split splitths 1 th of 
   307              None => 
   307              NONE => 
   308              (writeln "th:";
   308              (writeln "th:";
   309               Display.print_thm th; writeln "split ths:";
   309               Display.print_thm th; writeln "split ths:";
   310               Display.print_thms splitths; writeln "\n--";
   310               Display.print_thms splitths; writeln "\n--";
   311               raise ERROR_MESSAGE "splitto: cannot find variable to split on")
   311               raise ERROR_MESSAGE "splitto: cannot find variable to split on")
   312             | Some v => 
   312             | SOME v => 
   313              let 
   313              let 
   314                val gt = Data.dest_Trueprop (nth_elem(0, Thm.prems_of th));
   314                val gt = Data.dest_Trueprop (nth_elem(0, Thm.prems_of th));
   315                val split_thm = mk_casesplit_goal_thm sgn v gt;
   315                val split_thm = mk_casesplit_goal_thm sgn v gt;
   316                val (subthms, expf) = IsaND.fixed_subgoal_thms split_thm;
   316                val (subthms, expf) = IsaND.fixed_subgoal_thms split_thm;
   317              in 
   317              in 
   320 
   320 
   321       and recsplitf th = 
   321       and recsplitf th = 
   322           (* note: multiple unifiers! we only take the first element,
   322           (* note: multiple unifiers! we only take the first element,
   323              probably fine -- there is probably only one anyway. *)
   323              probably fine -- there is probably only one anyway. *)
   324           (case Library.get_first (Seq.pull o solve_by_splitth th) splitths of
   324           (case Library.get_first (Seq.pull o solve_by_splitth th) splitths of
   325              None => split th
   325              NONE => split th
   326            | Some (solved_th, more) => solved_th)
   326            | SOME (solved_th, more) => solved_th)
   327     in
   327     in
   328       recsplitf genth
   328       recsplitf genth
   329     end;
   329     end;
   330 
   330 
   331 
   331 
   338 
   338 
   339 (* derive eqs, assuming strict, ie the rules have no assumptions = all
   339 (* derive eqs, assuming strict, ie the rules have no assumptions = all
   340    the well-foundness conditions have been solved. *)
   340    the well-foundness conditions have been solved. *)
   341 local
   341 local
   342   fun get_related_thms i = 
   342   fun get_related_thms i = 
   343       mapfilter ((fn (r,x) => if x = i then Some r else None));
   343       mapfilter ((fn (r,x) => if x = i then SOME r else NONE));
   344       
   344       
   345   fun solve_eq (th, [], i) = 
   345   fun solve_eq (th, [], i) = 
   346       raise ERROR_MESSAGE "derive_init_eqs: missing rules"
   346       raise ERROR_MESSAGE "derive_init_eqs: missing rules"
   347     | solve_eq (th, [a], i) = (a, i)
   347     | solve_eq (th, [a], i) = (a, i)
   348     | solve_eq (th, splitths as (_ :: _), i) = (splitto splitths th,i);
   348     | solve_eq (th, splitths as (_ :: _), i) = (splitto splitths th,i);