src/Provers/splitter.ML
changeset 1721 445654b6cb95
parent 1686 c67d543bc395
child 2143 093bbe6d333b
equal deleted inserted replaced
1720:4d34973672d6 1721:445654b6cb95
    14 where splits = [P(elim(...)) == rhs, ...]
    14 where splits = [P(elim(...)) == rhs, ...]
    15       iffD  = [| P <-> Q; Q |] ==> P (* is called iffD2 in HOL *)
    15       iffD  = [| P <-> Q; Q |] ==> P (* is called iffD2 in HOL *)
    16 
    16 
    17 *)
    17 *)
    18 
    18 
    19 fun mk_case_split_tac iffD =
    19 local
       
    20 
       
    21 fun mk_case_split_tac_2 iffD order =
    20 let
    22 let
    21 
    23 
    22 
    24 
    23 (************************************************************
    25 (************************************************************
    24    Create lift-theorem "trlift" :
    26    Create lift-theorem "trlift" :
    67    P(...) == rhs
    69    P(...) == rhs
    68 
    70 
    69    Ts    : types of parameters (i.e. variables bound by meta-quantifiers)
    71    Ts    : types of parameters (i.e. variables bound by meta-quantifiers)
    70    t     : lefthand side of meta-equality in subgoal
    72    t     : lefthand side of meta-equality in subgoal
    71            the split theorem is applied to (see select)
    73            the split theorem is applied to (see select)
    72    pos   : "path" leading to body of P(...), coded as a list
       
    73    T     : type of body of P(...)
    74    T     : type of body of P(...)
       
    75    tt    : the term  Const(..,..) $ ...
    74    maxi  : maximum index of Vars
    76    maxi  : maximum index of Vars
    75 
    77 
    76    bvars : type of variables bound by other than meta-quantifiers
    78    lev   : abstraction level
    77 *************************************************************************)
    79 *************************************************************************)
    78 
    80 
    79 fun mk_cntxt_splitthm Ts t pos T maxi =
    81 fun mk_cntxt_splitthm Ts t tt T maxi =
    80   let fun down [] t i bvars = Bound (length bvars)
    82   let fun down lev (Abs(v,T2,t)) = Abs(v,T2,down (lev+1) t)
    81         | down (p::ps) (Abs(v,T2,t)) i bvars = Abs(v,T2,down ps t i (T2::bvars))
    83         | down lev (Bound i) = if i >= lev
    82         | down (p::ps) t i bvars =
    84                                then Var(("X",maxi+i-lev),nth_elem(i-lev,Ts))
    83             let val vars = map Bound (0 upto ((length bvars)-1))
    85                                else Bound i 
    84                 val (h,ts) = strip_comb t
    86         | down lev t = 
    85                 fun var (t,i) = list_comb(Var(("X",i),bvars ---> (type_of1(bvars @ Ts,t))),vars);
    87             let val (h,ts) = strip_comb t
    86                 val v1 = map var (take(p,ts) ~~ (i upto (i+p-1)))
    88                 val h2 = (case h of Bound _ => down lev h | _ => h)
    87                 val u::us = drop(p,ts)
    89             in if incr_bv(lev,0,tt)=t 
    88                 val v2 = map var (us ~~ ((i+p) upto (i+length(ts)-2)))
    90                then
    89             in list_comb(h,v1@[down ps u (i+length ts) bvars]@v2) end;
    91                  Bound (lev)
    90   in Abs("",T,down (rev pos) t maxi []) end;
    92                else
       
    93                  list_comb(h2,map (down lev) ts)
       
    94             end;
       
    95   in Abs("",T,down 0 t) end;
    91 
    96 
    92 
    97 
    93 (* add all loose bound variables in t to list is *)
    98 (* add all loose bound variables in t to list is *)
    94 fun add_lbnos(is,t) = add_loose_bnos(t,0,is);
    99 fun add_lbnos(is,t) = add_loose_bnos(t,0,is);
    95 
   100 
   115            T   : type of the variable bound by the abstraction
   120            T   : type of the variable bound by the abstraction
   116            U   : type of the abstraction's body
   121            U   : type of the abstraction's body
   117            pos : "path" leading to the body of the abstraction
   122            pos : "path" leading to the body of the abstraction
   118    pos   : "path" leading to the position where Const(key, ...) $ ...  occurs.
   123    pos   : "path" leading to the position where Const(key, ...) $ ...  occurs.
   119    TB    : type of  Const(key,...) $ t_1 $ ... $ t_n
   124    TB    : type of  Const(key,...) $ t_1 $ ... $ t_n
       
   125    t     : the term Const(key,...) $ t_1 $ ... $ t_n
   120 
   126 
   121    A split pack is a tuple of the form
   127    A split pack is a tuple of the form
   122    (thm, apsns, pos, TB)
   128    (thm, apsns, pos, TB)
   123    Note : apsns is reversed, so that the outermost quantifier's position
   129    Note : apsns is reversed, so that the outermost quantifier's position
   124           comes first ! If the terms in ts don't contain variables bound
   130           comes first ! If the terms in ts don't contain variables bound
   125           by other than meta-quantifiers, apsns is empty, because no further
   131           by other than meta-quantifiers, apsns is empty, because no further
   126           lifting is required before applying the split-theorem.
   132           lifting is required before applying the split-theorem.
   127 ******************************************************************************) 
   133 ******************************************************************************) 
   128 
   134 
   129 fun mk_split_pack(thm,T,n,ts,apsns,pos,TB) =
   135 fun mk_split_pack(thm,T,n,ts,apsns,pos,TB,t) =
   130   if n > length ts then []
   136   if n > length ts then []
   131   else let val lev = length apsns
   137   else let val lev = length apsns
   132            val lbnos = foldl add_lbnos ([],take(n,ts))
   138            val lbnos = foldl add_lbnos ([],take(n,ts))
   133            val flbnos = filter (fn i => i < lev) lbnos
   139            val flbnos = filter (fn i => i < lev) lbnos
   134        in if null flbnos then [(thm,[],pos,TB)]
   140            val tt = incr_bv(~lev,0,t)
   135           else if type_test(T,flbnos,apsns) then [(thm, rev apsns,pos,TB)] else []
   141        in if null flbnos then [(thm,[],pos,TB,tt)]
       
   142           else if type_test(T,flbnos,apsns) then [(thm, rev apsns,pos,TB,tt)] else []
   136        end;
   143        end;
   137 
   144 
   138 
   145 
   139 (****************************************************************************
   146 (****************************************************************************
   140    Recursively scans term for occurences of Const(key,...) $ ...
   147    Recursively scans term for occurences of Const(key,...) $ ...
   158             let val (h,ts) = strip_comb t
   165             let val (h,ts) = strip_comb t
   159                 fun iter((i,a),t) = (i+1, (posns Ts (i::pos) apsns t) @ a);
   166                 fun iter((i,a),t) = (i+1, (posns Ts (i::pos) apsns t) @ a);
   160                 val a = case h of
   167                 val a = case h of
   161                   Const(c,_) =>
   168                   Const(c,_) =>
   162                     (case assoc(cmap,c) of
   169                     (case assoc(cmap,c) of
   163                        Some(thm,T,n) => mk_split_pack(thm,T,n,ts,apsns,pos,type_of1(Ts,t))
   170                        Some(thm,T,n) => mk_split_pack(thm,T,n,ts,apsns,pos,type_of1(Ts,t),t)
   164                      | None => [])
   171                      | None => [])
   165                 | _ => []
   172                 | _ => []
   166              in snd(foldl iter ((0,a),ts)) end
   173              in snd(foldl iter ((0,a),ts)) end
   167   in posns Ts [] [] t end;
   174   in posns Ts [] [] t end;
   168 
   175 
   169 
   176 
   170 fun nth_subgoal i thm = nth_elem(i-1,prems_of thm);
   177 fun nth_subgoal i thm = nth_elem(i-1,prems_of thm);
   171 
   178 
   172 fun shorter((_,ps,pos,_),(_,qs,qos,_)) =
   179 fun shorter((_,ps,pos,_,_),(_,qs,qos,_,_)) =
   173   let val ms = length ps and ns = length qs
   180   let val ms = length ps and ns = length qs
   174   in ms < ns orelse (ms = ns andalso length pos >= length qos) end;
   181   in ms < ns orelse (ms = ns andalso order(length pos,length qos)) end;
   175 
   182 
   176 
   183 
   177 (************************************************************
   184 (************************************************************
   178    call split_posns with appropriate parameters
   185    call split_posns with appropriate parameters
   179 *************************************************************)
   186 *************************************************************)
   225    thm   : the split theorem
   232    thm   : the split theorem
   226    TB    : type of body of P(...)
   233    TB    : type of body of P(...)
   227    state : current proof state
   234    state : current proof state
   228 **************************************************************)
   235 **************************************************************)
   229 
   236 
   230 fun inst_split Ts t pos thm TB state =
   237 fun inst_split Ts t tt thm TB state =
   231   let val _$((Var(P2,PT2))$_)$_ = concl_of thm
   238   let val _$((Var(P2,PT2))$_)$_ = concl_of thm
   232       val sg = #sign(rep_thm state)
   239       val sg = #sign(rep_thm state)
   233       val tsig = #tsig(Sign.rep_sg sg)
   240       val tsig = #tsig(Sign.rep_sg sg)
   234       val cntxt = mk_cntxt_splitthm Ts t pos TB (#maxidx(rep_thm thm))
   241       val cntxt = mk_cntxt_splitthm Ts t tt TB (#maxidx(rep_thm thm))
   235       val cu = cterm_of sg cntxt
   242       val cu = cterm_of sg cntxt
   236       val uT = #T(rep_cterm cu)
   243       val uT = #T(rep_cterm cu)
   237       val cP' = cterm_of sg (Var(P2,uT))
   244       val cP' = cterm_of sg (Var(P2,uT))
   238       val ixnTs = Type.typ_match tsig ([],(PT2,uT));
   245       val ixnTs = Type.typ_match tsig ([],(PT2,uT));
   239       val ixncTs = map (fn (x,y) => (x,ctyp_of sg y)) ixnTs;
   246       val ixncTs = map (fn (x,y) => (x,ctyp_of sg y)) ixnTs;
   256       fun lift Ts t p state = rtac (inst_lift Ts t p state trlift i) i
   263       fun lift Ts t p state = rtac (inst_lift Ts t p state trlift i) i
   257       fun lift_split state =
   264       fun lift_split state =
   258             let val (Ts,t,splits) = select cmap state i
   265             let val (Ts,t,splits) = select cmap state i
   259             in case splits of
   266             in case splits of
   260                  [] => no_tac
   267                  [] => no_tac
   261                | (thm,apsns,pos,TB)::_ =>
   268                | (thm,apsns,pos,TB,tt)::_ =>
   262                    (case apsns of
   269                    (case apsns of
   263                       [] => STATE(fn state => rtac (inst_split Ts t pos thm TB state) i)
   270                       [] => STATE(fn state => rtac (inst_split Ts t tt thm TB state) i)
   264                     | p::_ => EVERY[STATE(lift Ts t p),
   271                     | p::_ => EVERY[STATE(lift Ts t p),
   265                                     rtac reflexive_thm (i+1),
   272                                     rtac reflexive_thm (i+1),
   266                                     STATE lift_split])
   273                                     STATE lift_split])
   267             end
   274             end
   268   in STATE(fn thm =>
   275   in STATE(fn thm =>
   269        if i <= nprems_of thm then rtac iffD i THEN STATE lift_split
   276        if i <= nprems_of thm then rtac iffD i THEN STATE lift_split
   270        else no_tac)
   277        else no_tac)
   271   end;
   278   end;
   272 
   279 
   273 in split_tac end;
   280 in split_tac end;
       
   281 
       
   282 in
       
   283 
       
   284 fun mk_case_split_tac iffD = mk_case_split_tac_2 iffD (op <=) ;
       
   285 
       
   286 fun mk_case_split_inside_tac iffD = mk_case_split_tac_2 iffD (op >=) ;
       
   287 
       
   288 end;