412 |_ => fm; |
413 |_ => fm; |
413 |
414 |
414 (* ------------------------------------------------------------------------- *) |
415 (* ------------------------------------------------------------------------- *) |
415 (* Evaluation of constant expressions. *) |
416 (* Evaluation of constant expressions. *) |
416 (* ------------------------------------------------------------------------- *) |
417 (* ------------------------------------------------------------------------- *) |
417 |
418 |
|
419 (* An other implementation of divides, that covers more cases*) |
|
420 |
|
421 exception DVD_UNKNOWN |
|
422 |
|
423 fun dvd_op (d, t) = |
|
424 if not(is_numeral d) then raise DVD_UNKNOWN |
|
425 else let |
|
426 val dn = dest_numeral d |
|
427 fun coeffs_of x = case x of |
|
428 Const(p,_) $ tl $ tr => |
|
429 if p = "op +" then (coeffs_of tl) union (coeffs_of tr) |
|
430 else if p = "op *" |
|
431 then if (is_numeral tr) |
|
432 then [(dest_numeral tr) * (dest_numeral tl)] |
|
433 else [dest_numeral tl] |
|
434 else [] |
|
435 |_ => if (is_numeral t) then [dest_numeral t] else [] |
|
436 val ts = coeffs_of t |
|
437 in case ts of |
|
438 [] => raise DVD_UNKNOWN |
|
439 |_ => foldr (fn(k,r) => r andalso (k mod dn = 0)) (ts,true) |
|
440 end; |
|
441 |
|
442 |
418 val operations = |
443 val operations = |
419 [("op =",op=), ("op <",op<), ("op >",op>), ("op <=",op<=) , ("op >=",op>=), |
444 [("op =",op=), ("op <",op<), ("op >",op>), ("op <=",op<=) , ("op >=",op>=), |
420 ("Divides.op dvd",fn (x,y) =>((y mod x) = 0))]; |
445 ("Divides.op dvd",fn (x,y) =>((y mod x) = 0))]; |
421 |
446 |
422 fun applyoperation (Some f) (a,b) = f (a, b) |
447 fun applyoperation (Some f) (a,b) = f (a, b) |
423 |applyoperation _ (_, _) = false; |
448 |applyoperation _ (_, _) = false; |
424 |
449 |
425 (*Evaluation of constant atomic formulas*) |
450 (*Evaluation of constant atomic formulas*) |
426 |
451 (*FIXME : This is an optimation but still incorrect !! *) |
|
452 (* |
427 fun evalc_atom at = case at of |
453 fun evalc_atom at = case at of |
428 (Const (p,_) $ s $ t) =>( |
454 (Const (p,_) $ s $ t) => |
429 case assoc (operations,p) of |
455 (if p="Divides.op dvd" then |
430 Some f => ((if (f ((dest_numeral s),(dest_numeral t))) then HOLogic.true_const else HOLogic.false_const) |
456 ((if dvd_op(s,t) then HOLogic.true_const |
431 handle _ => at) |
457 else HOLogic.false_const) |
432 | _ => at) |
458 handle _ => at) |
433 |Const("Not",_)$(Const (p,_) $ s $ t) =>( |
459 else |
434 case assoc (operations,p) of |
460 case assoc (operations,p) of |
435 Some f => ((if (f ((dest_numeral s),(dest_numeral t))) then |
461 Some f => ((if (f ((dest_numeral s),(dest_numeral t))) then HOLogic.true_const else HOLogic.false_const) |
436 HOLogic.false_const else HOLogic.true_const) |
462 handle _ => at) |
437 handle _ => at) |
463 | _ => at) |
438 | _ => at) |
464 |Const("Not",_)$(Const (p,_) $ s $ t) =>( |
439 | _ => at; |
465 case assoc (operations,p) of |
440 |
466 Some f => ((if (f ((dest_numeral s),(dest_numeral t))) then |
441 (*Function onatoms apllys function f on the atomic formulas involved in a.*) |
467 HOLogic.false_const else HOLogic.true_const) |
|
468 handle _ => at) |
|
469 | _ => at) |
|
470 | _ => at; |
|
471 |
|
472 *) |
|
473 |
|
474 fun evalc_atom at = case at of |
|
475 (Const (p,_) $ s $ t) => |
|
476 ( case assoc (operations,p) of |
|
477 Some f => ((if (f ((dest_numeral s),(dest_numeral t))) then HOLogic.true_const else HOLogic.false_const) |
|
478 handle _ => at) |
|
479 | _ => at) |
|
480 |Const("Not",_)$(Const (p,_) $ s $ t) =>( |
|
481 case assoc (operations,p) of |
|
482 Some f => ((if (f ((dest_numeral s),(dest_numeral t))) then |
|
483 HOLogic.false_const else HOLogic.true_const) |
|
484 handle _ => at) |
|
485 | _ => at) |
|
486 | _ => at; |
|
487 |
|
488 (*Function onatoms apllys function f on the atomic formulas involved in a.*) |
442 |
489 |
443 fun onatoms f a = if (is_arith_rel a) then f a else case a of |
490 fun onatoms f a = if (is_arith_rel a) then f a else case a of |
444 |
491 |
445 (Const ("Not",_) $ p) => if is_arith_rel p then HOLogic.Not $ (f p) |
492 (Const ("Not",_) $ p) => if is_arith_rel p then HOLogic.Not $ (f p) |
446 |
493 |
650 fun stage j = list_disj (linrep vars x (mk_numeral j) p_inf :: map (p_element j) aset) |
697 fun stage j = list_disj (linrep vars x (mk_numeral j) p_inf :: map (p_element j) aset) |
651 in (list_disj (map stage js)) |
698 in (list_disj (map stage js)) |
652 end |
699 end |
653 | _ => error "cooper: not an existential formula"; |
700 | _ => error "cooper: not an existential formula"; |
654 |
701 |
|
702 |
|
703 (* Try to find a withness for the formula *) |
|
704 |
|
705 fun inf_w mi d vars x p = |
|
706 let val f = if mi then minusinf else plusinf in |
|
707 case (simpl (minusinf x p)) of |
|
708 Const("True",_) => (Some (mk_numeral 1), HOLogic.true_const) |
|
709 |Const("False",_) => (None,HOLogic.false_const) |
|
710 |F => |
|
711 let |
|
712 fun h n = |
|
713 case ((simpl o evalc) (linrep vars x (mk_numeral n) F)) of |
|
714 Const("True",_) => (Some (mk_numeral n),HOLogic.true_const) |
|
715 |F' => if n=1 then (None,F') |
|
716 else let val (rw,rf) = h (n-1) in |
|
717 (rw,HOLogic.mk_disj(F',rf)) |
|
718 end |
|
719 |
|
720 in (h d) |
|
721 end |
|
722 end; |
|
723 |
|
724 fun set_w d b st vars x p = let |
|
725 fun h ns = case ns of |
|
726 [] => (None,HOLogic.false_const) |
|
727 |n::nl => ( case ((simpl o evalc) (linrep vars x n p)) of |
|
728 Const("True",_) => (Some n,HOLogic.true_const) |
|
729 |F' => let val (rw,rf) = h nl |
|
730 in (rw,HOLogic.mk_disj(F',rf)) |
|
731 end) |
|
732 val f = if b then linear_add else linear_sub |
|
733 val p_elements = foldr (fn (i,l) => l union (map (fn e => f [] e (mk_numeral i)) st)) (1 upto d,[]) |
|
734 in h p_elements |
|
735 end; |
|
736 |
|
737 fun withness d b st vars x p = case (inf_w b d vars x p) of |
|
738 (Some n,_) => (Some n,HOLogic.true_const) |
|
739 |(None,Pinf) => (case (set_w d b st vars x p) of |
|
740 (Some n,_) => (Some n,HOLogic.true_const) |
|
741 |(_,Pst) => (None,HOLogic.mk_disj(Pinf,Pst))); |
|
742 |
|
743 |
655 |
744 |
656 |
745 |
657 (*Cooper main procedure*) |
746 (*Cooper main procedure*) |
658 |
747 |
659 fun cooper vars1 fm = |
748 fun cooper vars1 fm = |
676 in (list_disj (map stage js)) |
765 in (list_disj (map stage js)) |
677 end |
766 end |
678 | _ => error "cooper: not an existential formula"; |
767 | _ => error "cooper: not an existential formula"; |
679 |
768 |
680 |
769 |
|
770 (* A Version of cooper that returns a withness *) |
|
771 fun cooper_w vars1 fm = |
|
772 case fm of |
|
773 Const ("Ex",_) $ Abs(x0,T,p0) => let |
|
774 val (xn,p1) = variant_abs (x0,T,p0) |
|
775 val x = Free (xn,T) |
|
776 val vars = (xn::vars1) |
|
777 (* val p = unitycoeff x (posineq (simpl p1)) *) |
|
778 val p = unitycoeff x p1 |
|
779 val ast = aset x p |
|
780 val bst = bset x p |
|
781 val d = divlcm x p |
|
782 val (p_inf,S ) = |
|
783 if (length bst) <= (length ast) |
|
784 then (true,bst) |
|
785 else (false,ast) |
|
786 in withness d p_inf S vars x p |
|
787 (* fun p_element j a = linrep vars x (f vars a (mk_numeral j)) p |
|
788 fun stage j = list_disj (linrep vars x (mk_numeral j) p_inf :: map (p_element j) S) |
|
789 in (list_disj (map stage js)) |
|
790 *) |
|
791 end |
|
792 | _ => error "cooper: not an existential formula"; |
681 |
793 |
682 |
794 |
683 (*Function itlist applys a double parametred function f : 'a->'b->b iteratively to a List l : 'a |
795 (*Function itlist applys a double parametred function f : 'a->'b->b iteratively to a List l : 'a |
684 list With End condition b. ict calculates f(e1,f(f(e2,f(e3,...(...f(en,b))..))))) |
796 list With End condition b. ict calculates f(e1,f(f(e2,f(e3,...(...f(en,b))..))))) |
685 assuming l = [e1,e2,...,en]*) |
797 assuming l = [e1,e2,...,en]*) |