src/Provers/splitter.ML
changeset 17881 2b3709f5e477
parent 17325 d9d50222808e
child 17959 8db36a108213
equal deleted inserted replaced
17880:4494c023bf2a 17881:2b3709f5e477
    10 
    10 
    11 infix 4 addsplits delsplits;
    11 infix 4 addsplits delsplits;
    12 
    12 
    13 signature SPLITTER_DATA =
    13 signature SPLITTER_DATA =
    14 sig
    14 sig
    15   structure Simplifier: SIMPLIFIER
       
    16   val mk_eq         : thm -> thm
    15   val mk_eq         : thm -> thm
    17   val meta_eq_to_iff: thm (* "x == y ==> x = y"                    *)
    16   val meta_eq_to_iff: thm (* "x == y ==> x = y"                    *)
    18   val iffD          : thm (* "[| P = Q; Q |] ==> P"                *)
    17   val iffD          : thm (* "[| P = Q; Q |] ==> P"                *)
    19   val disjE         : thm (* "[| P | Q; P ==> R; Q ==> R |] ==> R" *)
    18   val disjE         : thm (* "[| P | Q; P ==> R; Q ==> R |] ==> R" *)
    20   val conjE         : thm (* "[| P & Q; [| P; Q |] ==> R |] ==> R" *)
    19   val conjE         : thm (* "[| P & Q; [| P; Q |] ==> R |] ==> R" *)
    24   val notnotD       : thm (* "~ ~ P ==> P"                         *)
    23   val notnotD       : thm (* "~ ~ P ==> P"                         *)
    25 end
    24 end
    26 
    25 
    27 signature SPLITTER =
    26 signature SPLITTER =
    28 sig
    27 sig
    29   type simpset
       
    30   val split_tac       : thm list -> int -> tactic
    28   val split_tac       : thm list -> int -> tactic
    31   val split_inside_tac: thm list -> int -> tactic
    29   val split_inside_tac: thm list -> int -> tactic
    32   val split_asm_tac   : thm list -> int -> tactic
    30   val split_asm_tac   : thm list -> int -> tactic
    33   val addsplits       : simpset * thm list -> simpset
    31   val addsplits       : simpset * thm list -> simpset
    34   val delsplits       : simpset * thm list -> simpset
    32   val delsplits       : simpset * thm list -> simpset
    41   val split_modifiers : (Args.T list -> (Method.modifier * Args.T list)) list
    39   val split_modifiers : (Args.T list -> (Method.modifier * Args.T list)) list
    42   val setup: (theory -> theory) list
    40   val setup: (theory -> theory) list
    43 end;
    41 end;
    44 
    42 
    45 functor SplitterFun(Data: SPLITTER_DATA): SPLITTER =
    43 functor SplitterFun(Data: SPLITTER_DATA): SPLITTER =
    46 struct 
    44 struct
    47 
       
    48 structure Simplifier = Data.Simplifier;
       
    49 type simpset = Simplifier.simpset;
       
    50 
    45 
    51 val Const ("==>", _) $ (Const ("Trueprop", _) $
    46 val Const ("==>", _) $ (Const ("Trueprop", _) $
    52          (Const (const_not, _) $ _    )) $ _ = #prop (rep_thm(Data.notnotD));
    47          (Const (const_not, _) $ _    )) $ _ = #prop (rep_thm(Data.notnotD));
    53 
    48 
    54 val Const ("==>", _) $ (Const ("Trueprop", _) $
    49 val Const ("==>", _) $ (Const ("Trueprop", _) $
    84 
    79 
    85 val trlift = lift RS transitive_thm;
    80 val trlift = lift RS transitive_thm;
    86 val _ $ (P $ _) $ _ = concl_of trlift;
    81 val _ $ (P $ _) $ _ = concl_of trlift;
    87 
    82 
    88 
    83 
    89 (************************************************************************ 
    84 (************************************************************************
    90    Set up term for instantiation of P in the lift-theorem
    85    Set up term for instantiation of P in the lift-theorem
    91    
    86 
    92    Ts    : types of parameters (i.e. variables bound by meta-quantifiers)
    87    Ts    : types of parameters (i.e. variables bound by meta-quantifiers)
    93    t     : lefthand side of meta-equality in subgoal
    88    t     : lefthand side of meta-equality in subgoal
    94            the lift theorem is applied to (see select)
    89            the lift theorem is applied to (see select)
    95    pos   : "path" leading to abstraction, coded as a list
    90    pos   : "path" leading to abstraction, coded as a list
    96    T     : type of body of P(...)
    91    T     : type of body of P(...)
   107                 val v2 = ListPair.map var (us, (i+p) upto (i+length(ts)-2))
   102                 val v2 = ListPair.map var (us, (i+p) upto (i+length(ts)-2))
   108       in list_comb(h,v1@[down ps u (i+length ts)]@v2) end;
   103       in list_comb(h,v1@[down ps u (i+length ts)]@v2) end;
   109   in Abs("", T, down (rev pos) t maxi) end;
   104   in Abs("", T, down (rev pos) t maxi) end;
   110 
   105 
   111 
   106 
   112 (************************************************************************ 
   107 (************************************************************************
   113    Set up term for instantiation of P in the split-theorem
   108    Set up term for instantiation of P in the split-theorem
   114    P(...) == rhs
   109    P(...) == rhs
   115 
   110 
   116    t     : lefthand side of meta-equality in subgoal
   111    t     : lefthand side of meta-equality in subgoal
   117            the split theorem is applied to (see select)
   112            the split theorem is applied to (see select)
   149    T     : type of P(...)
   144    T     : type of P(...)
   150    T'    : type of term to be scanned
   145    T'    : type of term to be scanned
   151    n     : number of arguments expected by Const(key,...)
   146    n     : number of arguments expected by Const(key,...)
   152    ts    : list of arguments actually found
   147    ts    : list of arguments actually found
   153    apsns : list of tuples of the form (T,U,pos), one tuple for each
   148    apsns : list of tuples of the form (T,U,pos), one tuple for each
   154            abstraction that is encountered on the way to the position where 
   149            abstraction that is encountered on the way to the position where
   155            Const(key, ...) $ ...  occurs, where
   150            Const(key, ...) $ ...  occurs, where
   156            T   : type of the variable bound by the abstraction
   151            T   : type of the variable bound by the abstraction
   157            U   : type of the abstraction's body
   152            U   : type of the abstraction's body
   158            pos : "path" leading to the body of the abstraction
   153            pos : "path" leading to the body of the abstraction
   159    pos   : "path" leading to the position where Const(key, ...) $ ...  occurs.
   154    pos   : "path" leading to the position where Const(key, ...) $ ...  occurs.
   164    (thm, apsns, pos, TB, tt)
   159    (thm, apsns, pos, TB, tt)
   165    Note : apsns is reversed, so that the outermost quantifier's position
   160    Note : apsns is reversed, so that the outermost quantifier's position
   166           comes first ! If the terms in ts don't contain variables bound
   161           comes first ! If the terms in ts don't contain variables bound
   167           by other than meta-quantifiers, apsns is empty, because no further
   162           by other than meta-quantifiers, apsns is empty, because no further
   168           lifting is required before applying the split-theorem.
   163           lifting is required before applying the split-theorem.
   169 ******************************************************************************) 
   164 ******************************************************************************)
   170 
   165 
   171 fun mk_split_pack(thm, T, T', n, ts, apsns, pos, TB, t) =
   166 fun mk_split_pack(thm, T, T', n, ts, apsns, pos, TB, t) =
   172   if n > length ts then []
   167   if n > length ts then []
   173   else let val lev = length apsns
   168   else let val lev = length apsns
   174            val lbnos = Library.foldl add_lbnos ([],Library.take(n,ts))
   169            val lbnos = Library.foldl add_lbnos ([],Library.take(n,ts))
   285 **************************************************************)
   280 **************************************************************)
   286 
   281 
   287 fun inst_lift Ts t (T, U, pos) state i =
   282 fun inst_lift Ts t (T, U, pos) state i =
   288   let
   283   let
   289     val cert = cterm_of (sign_of_thm state);
   284     val cert = cterm_of (sign_of_thm state);
   290     val cntxt = mk_cntxt Ts t pos (T --> U) (#maxidx(rep_thm trlift));    
   285     val cntxt = mk_cntxt Ts t pos (T --> U) (#maxidx(rep_thm trlift));
   291   in cterm_instantiate [(cert P, cert cntxt)] trlift
   286   in cterm_instantiate [(cert P, cert cntxt)] trlift
   292   end;
   287   end;
   293 
   288 
   294 
   289 
   295 (*************************************************************
   290 (*************************************************************
   304    state : current proof state
   299    state : current proof state
   305    i     : number of subgoal
   300    i     : number of subgoal
   306 **************************************************************)
   301 **************************************************************)
   307 
   302 
   308 fun inst_split Ts t tt thm TB state i =
   303 fun inst_split Ts t tt thm TB state i =
   309   let 
   304   let
   310     val thm' = Thm.lift_rule (state, i) thm;
   305     val thm' = Thm.lift_rule (state, i) thm;
   311     val (P, _) = strip_comb (fst (Logic.dest_equals
   306     val (P, _) = strip_comb (fst (Logic.dest_equals
   312       (Logic.strip_assums_concl (#prop (rep_thm thm')))));
   307       (Logic.strip_assums_concl (#prop (rep_thm thm')))));
   313     val cert = cterm_of (sign_of_thm state);
   308     val cert = cterm_of (sign_of_thm state);
   314     val cntxt = mk_cntxt_splitthm t tt TB;
   309     val cntxt = mk_cntxt_splitthm t tt TB;
   317   end;
   312   end;
   318 
   313 
   319 
   314 
   320 (*****************************************************************************
   315 (*****************************************************************************
   321    The split-tactic
   316    The split-tactic
   322    
   317 
   323    splits : list of split-theorems to be tried
   318    splits : list of split-theorems to be tried
   324    i      : number of subgoal the tactic should be applied to
   319    i      : number of subgoal the tactic should be applied to
   325 *****************************************************************************)
   320 *****************************************************************************)
   326 
   321 
   327 fun split_tac [] i = no_tac
   322 fun split_tac [] i = no_tac
   348                       [] => compose_tac (false, inst_split Ts t tt thm TB state i, 0) i state
   343                       [] => compose_tac (false, inst_split Ts t tt thm TB state i, 0) i state
   349                     | p::_ => EVERY [lift_tac Ts t p,
   344                     | p::_ => EVERY [lift_tac Ts t p,
   350                                      rtac reflexive_thm (i+1),
   345                                      rtac reflexive_thm (i+1),
   351                                      lift_split_tac] state)
   346                                      lift_split_tac] state)
   352             end
   347             end
   353   in COND (has_fewer_prems i) no_tac 
   348   in COND (has_fewer_prems i) no_tac
   354           (rtac meta_iffD i THEN lift_split_tac)
   349           (rtac meta_iffD i THEN lift_split_tac)
   355   end;
   350   end;
   356 
   351 
   357 in split_tac end;
   352 in split_tac end;
   358 
   353 
   362 val split_inside_tac = mk_case_split_tac (rev_order o int_ord);
   357 val split_inside_tac = mk_case_split_tac (rev_order o int_ord);
   363 
   358 
   364 
   359 
   365 (*****************************************************************************
   360 (*****************************************************************************
   366    The split-tactic for premises
   361    The split-tactic for premises
   367    
   362 
   368    splits : list of split-theorems to be tried
   363    splits : list of split-theorems to be tried
   369 ****************************************************************************)
   364 ****************************************************************************)
   370 fun split_asm_tac []     = K no_tac
   365 fun split_asm_tac []     = K no_tac
   371   | split_asm_tac splits = 
   366   | split_asm_tac splits =
   372 
   367 
   373   let val cname_list = map (fst o fst o split_thm_info) splits;
   368   let val cname_list = map (fst o fst o split_thm_info) splits;
   374       fun is_case (a,_) = a mem cname_list;
   369       fun is_case (a,_) = a mem cname_list;
   375       fun tac (t,i) = 
   370       fun tac (t,i) =
   376 	  let val n = find_index (exists_Const is_case) 
   371           let val n = find_index (exists_Const is_case)
   377 				 (Logic.strip_assums_hyp t);
   372                                  (Logic.strip_assums_hyp t);
   378 	      fun first_prem_is_disj (Const ("==>", _) $ (Const ("Trueprop", _)
   373               fun first_prem_is_disj (Const ("==>", _) $ (Const ("Trueprop", _)
   379 				 $ (Const (s, _) $ _ $ _ )) $ _ ) = (s=const_or)
   374                                  $ (Const (s, _) $ _ $ _ )) $ _ ) = (s=const_or)
   380 	      |   first_prem_is_disj (Const("all",_)$Abs(_,_,t)) = 
   375               |   first_prem_is_disj (Const("all",_)$Abs(_,_,t)) =
   381 					first_prem_is_disj t
   376                                         first_prem_is_disj t
   382 	      |   first_prem_is_disj _ = false;
   377               |   first_prem_is_disj _ = false;
   383       (* does not work properly if the split variable is bound by a quantfier *)
   378       (* does not work properly if the split variable is bound by a quantfier *)
   384 	      fun flat_prems_tac i = SUBGOAL (fn (t,i) => 
   379               fun flat_prems_tac i = SUBGOAL (fn (t,i) =>
   385 			   (if first_prem_is_disj t
   380                            (if first_prem_is_disj t
   386 			    then EVERY[etac Data.disjE i,rotate_tac ~1 i,
   381                             then EVERY[etac Data.disjE i,rotate_tac ~1 i,
   387 				       rotate_tac ~1  (i+1),
   382                                        rotate_tac ~1  (i+1),
   388 				       flat_prems_tac (i+1)]
   383                                        flat_prems_tac (i+1)]
   389 			    else all_tac) 
   384                             else all_tac)
   390 			   THEN REPEAT (eresolve_tac [Data.conjE,Data.exE] i)
   385                            THEN REPEAT (eresolve_tac [Data.conjE,Data.exE] i)
   391 			   THEN REPEAT (dresolve_tac [Data.notnotD]   i)) i;
   386                            THEN REPEAT (dresolve_tac [Data.notnotD]   i)) i;
   392 	  in if n<0 then no_tac else DETERM (EVERY'
   387           in if n<0 then no_tac else DETERM (EVERY'
   393 		[rotate_tac n, etac Data.contrapos2,
   388                 [rotate_tac n, etac Data.contrapos2,
   394 		 split_tac splits, 
   389                  split_tac splits,
   395 		 rotate_tac ~1, etac Data.contrapos, rotate_tac ~1, 
   390                  rotate_tac ~1, etac Data.contrapos, rotate_tac ~1,
   396 		 flat_prems_tac] i)
   391                  flat_prems_tac] i)
   397 	  end;
   392           end;
   398   in SUBGOAL tac
   393   in SUBGOAL tac
   399   end;
   394   end;
   400 
   395 
   401 fun gen_split_tac [] = K no_tac
   396 fun gen_split_tac [] = K no_tac
   402   | gen_split_tac (split::splits) =
   397   | gen_split_tac (split::splits) =
   411 
   406 
   412 fun string_of_typ (Type (s, Ts)) = (if null Ts then ""
   407 fun string_of_typ (Type (s, Ts)) = (if null Ts then ""
   413       else enclose "(" ")" (commas (map string_of_typ Ts))) ^ s
   408       else enclose "(" ")" (commas (map string_of_typ Ts))) ^ s
   414   | string_of_typ _ = "_";
   409   | string_of_typ _ = "_";
   415 
   410 
   416 fun split_name (name, T) asm = "split " ^ 
   411 fun split_name (name, T) asm = "split " ^
   417   (if asm then "asm " else "") ^ name ^ " :: " ^ string_of_typ T;
   412   (if asm then "asm " else "") ^ name ^ " :: " ^ string_of_typ T;
   418 
   413 
   419 fun ss addsplits splits =
   414 fun ss addsplits splits =
   420   let fun addsplit (ss,split) =
   415   let fun addsplit (ss,split) =
   421         let val (name,asm) = split_thm_info split
   416         let val (name,asm) = split_thm_info split
   422         in Simplifier.addloop (ss, (split_name name asm,
   417         in Simplifier.addloop (ss, (split_name name asm,
   423 		       (if asm then split_asm_tac else split_tac) [split])) end
   418                        (if asm then split_asm_tac else split_tac) [split])) end
   424   in Library.foldl addsplit (ss,splits) end;
   419   in Library.foldl addsplit (ss,splits) end;
   425 
   420 
   426 fun ss delsplits splits =
   421 fun ss delsplits splits =
   427   let fun delsplit(ss,split) =
   422   let fun delsplit(ss,split) =
   428         let val (name,asm) = split_thm_info split
   423         let val (name,asm) = split_thm_info split
   429         in Simplifier.delloop (ss, split_name name asm)
   424         in Simplifier.delloop (ss, split_name name asm)
   430   end in Library.foldl delsplit (ss,splits) end;
   425   end in Library.foldl delsplit (ss,splits) end;
   431 
   426 
   432 fun Addsplits splits = (Simplifier.simpset_ref() := 
   427 fun Addsplits splits = (change_simpset (fn ss => ss addsplits splits));
   433 			Simplifier.simpset() addsplits splits);
   428 fun Delsplits splits = (change_simpset (fn ss => ss delsplits splits));
   434 fun Delsplits splits = (Simplifier.simpset_ref() := 
       
   435 			Simplifier.simpset() delsplits splits);
       
   436 
   429 
   437 
   430 
   438 (* attributes *)
   431 (* attributes *)
   439 
   432 
   440 val splitN = "split";
   433 val splitN = "split";