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; |