src/Provers/Arith/fast_lin_arith.ML
changeset 9420 d4e9f60fe25a
parent 9073 40d8dfac96b8
child 10575 c78d26d5c3c1
equal deleted inserted replaced
9419:e46de4af70e4 9420:d4e9f60fe25a
    50 mk_nat_thm(t) = "0 <= t"
    50 mk_nat_thm(t) = "0 <= t"
    51 *)
    51 *)
    52 
    52 
    53 signature LIN_ARITH_DATA =
    53 signature LIN_ARITH_DATA =
    54 sig
    54 sig
    55   val add_mono_thms:    thm list ref
       
    56                             (* [| i rel1 j; m rel2 n |] ==> i + m rel3 j + n *)
       
    57   val lessD:            thm list ref (* m < n ==> m+1 <= n *)
       
    58   val decomp:
    55   val decomp:
    59     term -> ((term*int)list * int * string * (term*int)list * int * bool)option
    56     Sign.sg -> term -> ((term*int)list * int * string * (term*int)list * int * bool)option
    60   val ss_ref: simpset ref
       
    61 end;
    57 end;
    62 (*
    58 (*
    63 decomp(`x Rel y') should yield (p,i,Rel,q,j,d)
    59 decomp(`x Rel y') should yield (p,i,Rel,q,j,d)
    64    where Rel is one of "<", "~<", "<=", "~<=" and "=" and
    60    where Rel is one of "<", "~<", "<=", "~<=" and "=" and
    65          p/q is the decomposition of the sum terms x/y into a list
    61          p/q is the decomposition of the sum terms x/y into a list
    66          of summand * multiplicity pairs and a constant summand and
    62          of summand * multiplicity pairs and a constant summand and
    67          d indicates if the domain is discrete.
    63          d indicates if the domain is discrete.
    68 
    64 
    69 ss_ref must reduce contradictory <= to False.
    65 ss must reduce contradictory <= to False.
    70    It should also cancel common summands to keep <= reduced;
    66    It should also cancel common summands to keep <= reduced;
    71    otherwise <= can grow to massive proportions.
    67    otherwise <= can grow to massive proportions.
    72 *)
    68 *)
    73 
    69 
    74 signature FAST_LIN_ARITH =
    70 signature FAST_LIN_ARITH =
    75 sig
    71 sig
       
    72   val setup: (theory -> theory) list
       
    73   val map_data: ({add_mono_thms: thm list, lessD: thm list, simpset: Simplifier.simpset}
       
    74     -> {add_mono_thms: thm list, lessD: thm list, simpset: Simplifier.simpset})
       
    75     -> theory -> theory
    76   val trace           : bool ref
    76   val trace           : bool ref
    77   val lin_arith_prover: Sign.sg -> thm list -> term -> thm option
    77   val lin_arith_prover: Sign.sg -> thm list -> term -> thm option
    78   val     lin_arith_tac:             int -> tactic
    78   val     lin_arith_tac:             int -> tactic
    79   val cut_lin_arith_tac: thm list -> int -> tactic
    79   val cut_lin_arith_tac: thm list -> int -> tactic
    80 end;
    80 end;
    81 
    81 
    82 functor Fast_Lin_Arith(structure LA_Logic:LIN_ARITH_LOGIC 
    82 functor Fast_Lin_Arith(structure LA_Logic:LIN_ARITH_LOGIC 
    83                        and       LA_Data:LIN_ARITH_DATA) : FAST_LIN_ARITH =
    83                        and       LA_Data:LIN_ARITH_DATA) : FAST_LIN_ARITH =
    84 struct
    84 struct
       
    85 
       
    86 
       
    87 (** theory data **)
       
    88 
       
    89 (* data kind 'Provers/fast_lin_arith' *)
       
    90 
       
    91 structure DataArgs =
       
    92 struct
       
    93   val name = "Provers/fast_lin_arith";
       
    94   type T = {add_mono_thms: thm list, lessD: thm list, simpset: Simplifier.simpset};
       
    95 
       
    96   val empty = {add_mono_thms = [], lessD = [], simpset = Simplifier.empty_ss};
       
    97   val copy = I;
       
    98   val prep_ext = I;
       
    99 
       
   100   fun merge ({add_mono_thms = add_mono_thms1, lessD = lessD1, simpset = simpset1},
       
   101       {add_mono_thms = add_mono_thms2, lessD = lessD2, simpset = simpset2}) =
       
   102     {add_mono_thms = Drule.merge_rules (add_mono_thms1, add_mono_thms2),
       
   103       lessD = Drule.merge_rules (lessD1, lessD2),
       
   104       simpset = Simplifier.merge_ss (simpset1, simpset2)};
       
   105 
       
   106   fun print _ _ = ();
       
   107 end;
       
   108 
       
   109 structure Data = TheoryDataFun(DataArgs);
       
   110 val map_data = Data.map;
       
   111 val setup = [Data.init];
       
   112 
       
   113 
    85 
   114 
    86 (*** A fast decision procedure ***)
   115 (*** A fast decision procedure ***)
    87 (*** Code ported from HOL Light ***)
   116 (*** Code ported from HOL Light ***)
    88 (* possible optimizations:
   117 (* possible optimizations:
    89    use (var,coeff) rep or vector rep  tp save space;
   118    use (var,coeff) rep or vector rep  tp save space;
   261 *)
   290 *)
   262 local
   291 local
   263  exception FalseE of thm
   292  exception FalseE of thm
   264 in
   293 in
   265 fun mkthm sg asms just =
   294 fun mkthm sg asms just =
   266   let val atoms = foldl (fn (ats,(lhs,_,_,rhs,_,_)) =>
   295   let val {add_mono_thms, lessD, simpset} = Data.get_sg sg;
       
   296       val atoms = foldl (fn (ats,(lhs,_,_,rhs,_,_)) =>
   267                             map fst lhs  union  (map fst rhs  union  ats))
   297                             map fst lhs  union  (map fst rhs  union  ats))
   268                         ([], mapfilter (LA_Data.decomp o concl_of) asms)
   298                         ([], mapfilter (LA_Data.decomp sg o concl_of) asms)
   269 
   299 
   270       fun addthms thm1 thm2 =
   300       fun addthms thm1 thm2 =
   271         let val conj = thm1 RS (thm2 RS LA_Logic.conjI)
   301         let val conj = thm1 RS (thm2 RS LA_Logic.conjI)
   272         in the(get_first (fn th => Some(conj RS th) handle _ => None)
   302         in the(get_first (fn th => Some(conj RS th) handle _ => None) add_mono_thms)
   273                          (!LA_Data.add_mono_thms))
       
   274         end;
   303         end;
   275 
   304 
   276       fun multn(n,thm) =
   305       fun multn(n,thm) =
   277         let fun mul(i,th) = if i=1 then th else mul(i-1, addthms thm th)
   306         let fun mul(i,th) = if i=1 then th else mul(i-1, addthms thm th)
   278         in if n < 0 then mul(~n,thm) RS LA_Logic.sym else mul(n,thm) end;
   307         in if n < 0 then mul(~n,thm) RS LA_Logic.sym else mul(n,thm) end;
   279 
   308 
   280       fun simp thm =
   309       fun simp thm =
   281         let val thm' = simplify (!LA_Data.ss_ref) thm
   310         let val thm' = simplify simpset thm
   282         in if LA_Logic.is_False thm' then raise FalseE thm' else thm' end
   311         in if LA_Logic.is_False thm' then raise FalseE thm' else thm' end
   283 
   312 
   284       fun mk(Asm i) = trace_thm "Asm" (nth_elem(i,asms))
   313       fun mk(Asm i) = trace_thm "Asm" (nth_elem(i,asms))
   285         | mk(Nat(i)) = (trace_msg "Nat";
   314         | mk(Nat(i)) = (trace_msg "Nat";
   286 			LA_Logic.mk_nat_thm sg (nth_elem(i,atoms)))
   315 			LA_Logic.mk_nat_thm sg (nth_elem(i,atoms)))
   287         | mk(LessD(j)) = trace_thm "L" (hd([mk j] RL !LA_Data.lessD))
   316         | mk(LessD(j)) = trace_thm "L" (hd([mk j] RL lessD))
   288         | mk(NotLeD(j)) = trace_thm "NLe" (mk j RS LA_Logic.not_leD)
   317         | mk(NotLeD(j)) = trace_thm "NLe" (mk j RS LA_Logic.not_leD)
   289         | mk(NotLeDD(j)) = trace_thm "NLeD" (hd([mk j RS LA_Logic.not_leD] RL 
   318         | mk(NotLeDD(j)) = trace_thm "NLeD" (hd([mk j RS LA_Logic.not_leD] RL lessD))
   290 						!LA_Data.lessD))
       
   291         | mk(NotLessD(j)) = trace_thm "NL" (mk j RS LA_Logic.not_lessD)
   319         | mk(NotLessD(j)) = trace_thm "NL" (mk j RS LA_Logic.not_lessD)
   292         | mk(Added(j1,j2)) = simp (trace_thm "+" (addthms (mk j1) (mk j2)))
   320         | mk(Added(j1,j2)) = simp (trace_thm "+" (addthms (mk j1) (mk j2)))
   293         | mk(Multiplied(n,j)) = (trace_msg "*"; multn(n,mk j))
   321         | mk(Multiplied(n,j)) = (trace_msg "*"; multn(n,mk j))
   294 
   322 
   295   in trace_msg "mkthm";
   323   in trace_msg "mkthm";
   296      simplify (!LA_Data.ss_ref) (mk just) handle FalseE thm => thm end
   324      simplify simpset (mk just) handle FalseE thm => thm end
   297 end;
   325 end;
   298 
   326 
   299 fun coeff poly atom = case assoc(poly,atom) of None => 0 | Some i => i;
   327 fun coeff poly atom = case assoc(poly,atom) of None => 0 | Some i => i;
   300 
   328 
   301 fun mklineq atoms =
   329 fun mklineq atoms =
   365        METAHYPS (fn asms => rtac (mkthm sg asms just1) 1) i THEN
   393        METAHYPS (fn asms => rtac (mkthm sg asms just1) 1) i THEN
   366        METAHYPS (fn asms => rtac (mkthm sg asms just2) 1) i
   394        METAHYPS (fn asms => rtac (mkthm sg asms just2) 1) i
   367     end
   395     end
   368     state;
   396     state;
   369 
   397 
   370 fun prove(pTs,Hs,concl) =
   398 fun prove sg (pTs,Hs,concl) =
   371 let val nHs = length Hs
   399 let val nHs = length Hs
   372     val ixHs = Hs ~~ (0 upto (nHs-1))
   400     val ixHs = Hs ~~ (0 upto (nHs-1))
   373     val Hitems = mapfilter (fn (h,i) => case LA_Data.decomp h of
   401     val Hitems = mapfilter (fn (h,i) => case LA_Data.decomp sg h of
   374                                  None => None | Some(it) => Some(it,i)) ixHs
   402                                  None => None | Some(it) => Some(it,i)) ixHs
   375 in case LA_Data.decomp concl of
   403 in case LA_Data.decomp sg concl of
   376      None => if null Hitems then [] else refute1(pTs,Hitems)
   404      None => if null Hitems then [] else refute1(pTs,Hitems)
   377    | Some(citem as (r,i,rel,l,j,d)) =>
   405    | Some(citem as (r,i,rel,l,j,d)) =>
   378        if rel = "="
   406        if rel = "="
   379        then refute2(pTs,Hitems,citem,nHs)
   407        then refute2(pTs,Hitems,citem,nHs)
   380        else let val neg::rel0 = explode rel
   408        else let val neg::rel0 = explode rel
   384 
   412 
   385 (*
   413 (*
   386 Fast but very incomplete decider. Only premises and conclusions
   414 Fast but very incomplete decider. Only premises and conclusions
   387 that are already (negated) (in)equations are taken into account.
   415 that are already (negated) (in)equations are taken into account.
   388 *)
   416 *)
   389 val lin_arith_tac = SUBGOAL (fn (A,n) =>
   417 fun lin_arith_tac i st = SUBGOAL (fn (A,n) =>
   390   let val pTs = rev(map snd (Logic.strip_params A))
   418   let val pTs = rev(map snd (Logic.strip_params A))
   391       val Hs = Logic.strip_assums_hyp A
   419       val Hs = Logic.strip_assums_hyp A
   392       val concl = Logic.strip_assums_concl A
   420       val concl = Logic.strip_assums_concl A
   393   in case prove(pTs,Hs,concl) of
   421   in case prove (Thm.sign_of_thm st) (pTs,Hs,concl) of
   394        [j] => refute1_tac(n,j)
   422        [j] => refute1_tac(n,j)
   395      | [j1,j2] => refute2_tac(n,j1,j2)
   423      | [j1,j2] => refute2_tac(n,j1,j2)
   396      | _ => no_tac
   424      | _ => no_tac
   397   end);
   425   end) i st;
   398 
   426 
   399 fun cut_lin_arith_tac thms i = cut_facts_tac thms i THEN lin_arith_tac i;
   427 fun cut_lin_arith_tac thms i = cut_facts_tac thms i THEN lin_arith_tac i;
   400 
   428 
   401 fun prover1(just,sg,thms,concl,pos) =
   429 fun prover1(just,sg,thms,concl,pos) =
   402 let val nconcl = LA_Logic.neg_prop concl
   430 let val nconcl = LA_Logic.neg_prop concl
   425 
   453 
   426 (* PRE: concl is not negated! *)
   454 (* PRE: concl is not negated! *)
   427 fun lin_arith_prover sg thms concl =
   455 fun lin_arith_prover sg thms concl =
   428 let val Hs = map (#prop o rep_thm) thms
   456 let val Hs = map (#prop o rep_thm) thms
   429     val Tconcl = LA_Logic.mk_Trueprop concl
   457     val Tconcl = LA_Logic.mk_Trueprop concl
   430 in case prove([],Hs,Tconcl) of
   458 in case prove sg ([],Hs,Tconcl) of
   431      [j] => prover1(j,sg,thms,Tconcl,true)
   459      [j] => prover1(j,sg,thms,Tconcl,true)
   432    | [j1,j2] => prover2(j1,j2,sg,thms,Tconcl)
   460    | [j1,j2] => prover2(j1,j2,sg,thms,Tconcl)
   433    | _ => let val nTconcl = LA_Logic.neg_prop Tconcl
   461    | _ => let val nTconcl = LA_Logic.neg_prop Tconcl
   434           in case prove([],Hs,nTconcl) of
   462           in case prove sg ([],Hs,nTconcl) of
   435                [j] => prover1(j,sg,thms,nTconcl,false)
   463                [j] => prover1(j,sg,thms,nTconcl,false)
   436                (* [_,_] impossible because of negation *)
   464                (* [_,_] impossible because of negation *)
   437              | _ => None
   465              | _ => None
   438           end
   466           end
   439 end;
   467 end;