464 |
464 |
465 fun simp thm = |
465 fun simp thm = |
466 let val thm' = trace_thm "Simplified:" (full_simplify simpset' thm) |
466 let val thm' = trace_thm "Simplified:" (full_simplify simpset' thm) |
467 in if LA_Logic.is_False thm' then raise FalseE thm' else thm' end |
467 in if LA_Logic.is_False thm' then raise FalseE thm' else thm' end |
468 |
468 |
469 fun mk (Asm i) = trace_thm "Asm" (nth asms i) |
469 fun mk (Asm i) = trace_thm "Asm" (nth asms i) |
470 | mk (Nat i) = trace_thm "Nat" (LA_Logic.mk_nat_thm sg (nth atoms i)) |
470 | mk (Nat i) = trace_thm "Nat" (LA_Logic.mk_nat_thm sg (nth atoms i)) |
471 | mk (LessD(j)) = trace_thm "L" (hd([mk j] RL lessD)) |
471 | mk (LessD j) = trace_thm "L" (hd ([mk j] RL lessD)) |
472 | mk (NotLeD(j)) = trace_thm "NLe" (mk j RS LA_Logic.not_leD) |
472 | mk (NotLeD j) = trace_thm "NLe" (mk j RS LA_Logic.not_leD) |
473 | mk (NotLeDD(j)) = trace_thm "NLeD" (hd([mk j RS LA_Logic.not_leD] RL lessD)) |
473 | mk (NotLeDD j) = trace_thm "NLeD" (hd ([mk j RS LA_Logic.not_leD] RL lessD)) |
474 | mk (NotLessD(j)) = trace_thm "NL" (mk j RS LA_Logic.not_lessD) |
474 | mk (NotLessD j) = trace_thm "NL" (mk j RS LA_Logic.not_lessD) |
475 | mk (Added(j1,j2)) = simp (trace_thm "+" (addthms (mk j1) (mk j2))) |
475 | mk (Added (j1, j2)) = simp (trace_thm "+" (addthms (mk j1) (mk j2))) |
476 | mk (Multiplied(n,j)) = (trace_msg("*"^IntInf.toString n); trace_thm "*" (multn(n,mk j))) |
476 | mk (Multiplied (n, j)) = (trace_msg ("*" ^ IntInf.toString n); trace_thm "*" (multn (n, mk j))) |
477 | mk (Multiplied2(n,j)) = simp (trace_msg("**"^IntInf.toString n); trace_thm "**" (multn2(n,mk j))) |
477 | mk (Multiplied2 (n, j)) = simp (trace_msg ("**" ^ IntInf.toString n); trace_thm "**" (multn2 (n, mk j))) |
478 |
478 |
479 in trace_msg "mkthm"; |
479 in trace_msg "mkthm"; |
480 let val thm = trace_thm "Final thm:" (mk just) |
480 let val thm = trace_thm "Final thm:" (mk just) |
481 in let val fls = simplify simpset' thm |
481 in let val fls = simplify simpset' thm |
482 in trace_thm "After simplification:" fls; |
482 in trace_thm "After simplification:" fls; |
588 (* should be intertwined: separate the first (fully split) case, *) |
588 (* should be intertwined: separate the first (fully split) case, *) |
589 (* refute it, continue with splitting and refuting. Terminate with *) |
589 (* refute it, continue with splitting and refuting. Terminate with *) |
590 (* failure as soon as a case could not be refuted; i.e. delay further *) |
590 (* failure as soon as a case could not be refuted; i.e. delay further *) |
591 (* splitting until after a refutation for other cases has been found. *) |
591 (* splitting until after a refutation for other cases has been found. *) |
592 |
592 |
593 (* Theory.theory -> bool -> typ list * term list -> (typ list * (decompT * int) list) list *) |
593 (* Theory.theory -> typ list * term list -> (typ list * (decompT * int) list) list *) |
594 |
594 |
595 fun split_items sg do_pre (Ts, terms) = |
595 fun split_items sg (Ts, terms) = |
596 let |
596 let |
597 (* |
597 (* |
598 val _ = trace_msg ("split_items: do_pre is " ^ Bool.toString do_pre ^ "\n" ^ |
598 val _ = trace_msg ("split_items: Ts = " ^ string_of_list (Sign.string_of_typ sg) Ts ^ "\n" ^ |
599 " Ts = " ^ string_of_list (Sign.string_of_typ sg) Ts ^ "\n" ^ |
599 " terms = " ^ string_of_list (Sign.string_of_term sg) terms) |
600 " terms = " ^ string_of_list (Sign.string_of_term sg) terms) |
|
601 *) |
600 *) |
602 (* splits inequalities '~=' into '<' and '>'; this corresponds to *) |
601 (* splits inequalities '~=' into '<' and '>'; this corresponds to *) |
603 (* 'REPEAT_DETERM (eresolve_tac neqE i)' at the theorem/tactic *) |
602 (* 'REPEAT_DETERM (eresolve_tac neqE i)' at the theorem/tactic *) |
604 (* level *) |
603 (* level *) |
605 (* decompT option list -> decompT option list list *) |
604 (* decompT option list -> decompT option list list *) |
614 | number_hyps n (NONE::xs) = number_hyps (n+1) xs |
613 | number_hyps n (NONE::xs) = number_hyps (n+1) xs |
615 | number_hyps n ((SOME x)::xs) = (x, n) :: number_hyps (n+1) xs |
614 | number_hyps n ((SOME x)::xs) = (x, n) :: number_hyps (n+1) xs |
616 |
615 |
617 val result = (Ts, terms) |> (* user-defined preprocessing of the subgoal *) |
616 val result = (Ts, terms) |> (* user-defined preprocessing of the subgoal *) |
618 (* (typ list * term list) list *) |
617 (* (typ list * term list) list *) |
619 (if do_pre then LA_Data.pre_decomp sg else Library.single) |
618 LA_Data.pre_decomp sg |
620 |> (* compute the internal encoding of (in-)equalities *) |
619 |> (* compute the internal encoding of (in-)equalities *) |
621 (* (typ list * decompT option list) list *) |
620 (* (typ list * decompT option list) list *) |
622 map (apsnd (map (LA_Data.decomp sg))) |
621 map (apsnd (map (LA_Data.decomp sg))) |
623 |> (* splitting of inequalities *) |
622 |> (* splitting of inequalities *) |
624 (* (typ list * decompT option list) list list *) |
623 (* (typ list * decompT option list) list list *) |
693 | refute [] js = SOME js |
692 | refute [] js = SOME js |
694 in refute end; |
693 in refute end; |
695 |
694 |
696 (* Theory.theory -> (string * Term.typ) list -> bool -> bool -> term list -> injust list option *) |
695 (* Theory.theory -> (string * Term.typ) list -> bool -> bool -> term list -> injust list option *) |
697 |
696 |
698 fun refute sg params show_ex do_pre terms = |
697 fun refute sg params show_ex terms = |
699 refutes sg params show_ex (split_items sg do_pre (map snd params, terms)) []; |
698 refutes sg params show_ex (split_items sg (map snd params, terms)) []; |
700 |
|
701 (* MetaSimplifier.simpset -> int * injust list -> Tactical.tactic *) |
|
702 |
|
703 fun refute_tac ss (i, justs) = |
|
704 fn state => |
|
705 let val _ = trace_thm ("refute_tac (on subgoal " ^ Int.toString i ^ ", with " ^ Int.toString (length justs) ^ " justification(s)):") state |
|
706 val sg = theory_of_thm state |
|
707 val {neqE, ...} = Data.get sg |
|
708 fun just1 j = |
|
709 REPEAT_DETERM (eresolve_tac neqE i) THEN (* eliminate inequalities *) |
|
710 METAHYPS (fn asms => rtac (mkthm (sg, ss) asms j) 1) i (* use theorems generated from the actual justifications *) |
|
711 in DETERM (resolve_tac [LA_Logic.notI, LA_Logic.ccontr] i) THEN (* rewrite "[| A1; ...; An |] ==> B" to "[| A1; ...; An; ~B |] ==> False" *) |
|
712 DETERM (LA_Data.pre_tac i) THEN (* user-defined preprocessing of the subgoal *) |
|
713 PRIMITIVE (trace_thm "State after pre_tac:") THEN |
|
714 EVERY (map just1 justs) (* prove every resulting subgoal, using its justification *) |
|
715 end state; |
|
716 |
699 |
717 (* ('a -> bool) -> 'a list -> int *) |
700 (* ('a -> bool) -> 'a list -> int *) |
718 |
701 |
719 fun count P xs = length (List.filter P xs); |
702 fun count P xs = length (List.filter P xs); |
720 |
703 |
739 if count is_neq (map (LA_Data.decomp sg) Hs') |
722 if count is_neq (map (LA_Data.decomp sg) Hs') |
740 > !fast_arith_neq_limit then ( |
723 > !fast_arith_neq_limit then ( |
741 trace_msg ("fast_arith_neq_limit exceeded (current value is " ^ string_of_int (!fast_arith_neq_limit) ^ ")"); |
724 trace_msg ("fast_arith_neq_limit exceeded (current value is " ^ string_of_int (!fast_arith_neq_limit) ^ ")"); |
742 NONE |
725 NONE |
743 ) else |
726 ) else |
744 refute sg params show_ex do_pre Hs' |
727 refute sg params show_ex Hs' |
745 end; |
728 end; |
|
729 |
|
730 (* MetaSimplifier.simpset -> int * injust list -> Tactical.tactic *) |
|
731 |
|
732 fun refute_tac ss (i, justs) = |
|
733 fn state => |
|
734 let val _ = trace_thm ("refute_tac (on subgoal " ^ Int.toString i ^ ", with " ^ Int.toString (length justs) ^ " justification(s)):") state |
|
735 val sg = theory_of_thm state |
|
736 val {neqE, ...} = Data.get sg |
|
737 fun just1 j = |
|
738 REPEAT_DETERM (eresolve_tac neqE i) THEN (* eliminate inequalities *) |
|
739 METAHYPS (fn asms => rtac (mkthm (sg, ss) asms j) 1) i (* use theorems generated from the actual justifications *) |
|
740 in DETERM (resolve_tac [LA_Logic.notI, LA_Logic.ccontr] i) THEN (* rewrite "[| A1; ...; An |] ==> B" to "[| A1; ...; An; ~B |] ==> False" *) |
|
741 DETERM (LA_Data.pre_tac i) THEN (* user-defined preprocessing of the subgoal *) |
|
742 PRIMITIVE (trace_thm "State after pre_tac:") THEN |
|
743 EVERY (map just1 justs) (* prove every resulting subgoal, using its justification *) |
|
744 end state; |
746 |
745 |
747 (* |
746 (* |
748 Fast but very incomplete decider. Only premises and conclusions |
747 Fast but very incomplete decider. Only premises and conclusions |
749 that are already (negated) (in)equations are taken into account. |
748 that are already (negated) (in)equations are taken into account. |
750 *) |
749 *) |
751 fun simpset_lin_arith_tac ss show_ex i st = SUBGOAL (fn (A,_) => |
750 fun simpset_lin_arith_tac ss show_ex i st = SUBGOAL (fn (A,_) => |
752 let val params = rev (Logic.strip_params A) |
751 let val params = rev (Logic.strip_params A) |
753 val Hs = Logic.strip_assums_hyp A |
752 val Hs = Logic.strip_assums_hyp A |
754 val concl = Logic.strip_assums_concl A |
753 val concl = Logic.strip_assums_concl A |
755 in trace_thm ("Trying to refute subgoal " ^ string_of_int i) st; |
754 in trace_thm ("Trying to refute subgoal " ^ string_of_int i) st; |
756 case prove (Thm.sign_of_thm st) params show_ex true Hs concl of |
755 case prove (Thm.sign_of_thm st) params show_ex Hs concl of |
757 NONE => (trace_msg "Refutation failed."; no_tac) |
756 NONE => (trace_msg "Refutation failed."; no_tac) |
758 | SOME js => (trace_msg "Refutation succeeded."; refute_tac ss (i, js)) |
757 | SOME js => (trace_msg "Refutation succeeded."; refute_tac ss (i, js)) |
759 end) i st; |
758 end) i st; |
760 |
759 |
761 fun lin_arith_tac show_ex i st = |
760 fun lin_arith_tac show_ex i st = |
766 cut_facts_tac (Simplifier.prems_of_ss ss) i THEN |
765 cut_facts_tac (Simplifier.prems_of_ss ss) i THEN |
767 simpset_lin_arith_tac ss false i; |
766 simpset_lin_arith_tac ss false i; |
768 |
767 |
769 (** Forward proof from theorems **) |
768 (** Forward proof from theorems **) |
770 |
769 |
771 (* More tricky code. Needs to arrange the proofs of the multiple cases (due |
|
772 to splits of ~= premises) such that it coincides with the order of the cases |
|
773 generated by function split_items. *) |
|
774 |
|
775 datatype splittree = Tip of thm list |
|
776 | Spl of thm * cterm * splittree * cterm * splittree |
|
777 |
|
778 (* the cterm "(ct1 ==> ?R) ==> (ct2 ==> ?R) ==> ?R" is taken to (ct1, ct2) *) |
|
779 |
|
780 (* Thm.cterm -> Thm.cterm * Thm.cterm *) |
|
781 |
|
782 fun extract imp = |
|
783 let val (Il, r) = Thm.dest_comb imp |
|
784 val (_, imp1) = Thm.dest_comb Il |
|
785 val (Ict1, _) = Thm.dest_comb imp1 |
|
786 val (_, ct1) = Thm.dest_comb Ict1 |
|
787 val (Ir, _) = Thm.dest_comb r |
|
788 val (_, Ict2r) = Thm.dest_comb Ir |
|
789 val (Ict2, _) = Thm.dest_comb Ict2r |
|
790 val (_, ct2) = Thm.dest_comb Ict2 |
|
791 in (ct1, ct2) end; |
|
792 |
|
793 (* Theory.theory -> Thm.thm list -> splittree *) |
|
794 |
|
795 fun splitasms sg asms = |
|
796 let val {neqE, ...} = Data.get sg |
|
797 fun elim_neq (asms', []) = Tip (rev asms') |
|
798 | elim_neq (asms', asm::asms) = |
|
799 (case get_first (fn th => SOME (asm COMP th) handle THM _ => NONE) neqE of |
|
800 SOME spl => |
|
801 let val (ct1, ct2) = extract (cprop_of spl) |
|
802 val thm1 = assume ct1 |
|
803 val thm2 = assume ct2 |
|
804 in Spl (spl, ct1, elim_neq (asms', asms@[thm1]), ct2, elim_neq (asms', asms@[thm2])) |
|
805 end |
|
806 | NONE => elim_neq (asm::asms', asms)) |
|
807 in elim_neq ([], asms) end; |
|
808 |
|
809 (* Theory.theory * MetaSimplifier.simpset -> splittree -> injust list -> (Thm.thm, injust list) *) |
|
810 |
|
811 fun fwdproof ctxt (Tip asms) (j::js) = (mkthm ctxt asms j, js) |
|
812 | fwdproof ctxt (Spl (thm, ct1, tree1, ct2, tree2)) js = |
|
813 let val (thm1, js1) = fwdproof ctxt tree1 js |
|
814 val (thm2, js2) = fwdproof ctxt tree2 js1 |
|
815 val thm1' = implies_intr ct1 thm1 |
|
816 val thm2' = implies_intr ct2 thm2 |
|
817 in (thm2' COMP (thm1' COMP thm), js2) end; |
|
818 (* needs handle THM _ => NONE ? *) |
|
819 |
|
820 (* Theory.theory * MetaSimplifier.simpset -> Thm.thm list -> Term.term -> injust list -> bool -> Thm.thm option *) |
770 (* Theory.theory * MetaSimplifier.simpset -> Thm.thm list -> Term.term -> injust list -> bool -> Thm.thm option *) |
821 |
771 |
822 fun prover (ctxt as (sg, ss)) thms Tconcl js pos = |
772 fun prover (ctxt as (sg, ss)) thms Tconcl js pos = |
823 let |
773 let |
824 (* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv *) |
|
825 (* Use this code instead if lin_arith_prover calls prove with do_pre set to true *) |
|
826 (* There is no "forward version" of 'pre_tac'. Therefore we combine the *) |
774 (* There is no "forward version" of 'pre_tac'. Therefore we combine the *) |
827 (* available theorems into a single proof state and perform "backward proof" *) |
775 (* available theorems into a single proof state and perform "backward proof" *) |
828 (* using 'refute_tac'. *) |
776 (* using 'refute_tac'. *) |
829 (* |
|
830 val Hs = map prop_of thms |
777 val Hs = map prop_of thms |
831 val Prop = fold (curry Logic.mk_implies) (rev Hs) Tconcl |
778 val Prop = fold (curry Logic.mk_implies) (rev Hs) Tconcl |
832 val cProp = cterm_of sg Prop |
779 val cProp = cterm_of sg Prop |
833 val concl = Goal.init cProp |
780 val concl = Goal.init cProp |
834 |> refute_tac ss (1, js) |
781 |> refute_tac ss (1, js) |
835 |> Seq.hd |
782 |> Seq.hd |
836 |> Goal.finish |
783 |> Goal.finish |
837 |> fold (fn thA => fn thAB => implies_elim thAB thA) thms |
784 |> fold (fn thA => fn thAB => implies_elim thAB thA) thms |
838 *) |
|
839 (* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *) |
|
840 val nTconcl = LA_Logic.neg_prop Tconcl |
|
841 val cnTconcl = cterm_of sg nTconcl |
|
842 val nTconclthm = assume cnTconcl |
|
843 val tree = splitasms sg (thms @ [nTconclthm]) |
|
844 val (Falsethm, _) = fwdproof ctxt tree js |
|
845 val contr = if pos then LA_Logic.ccontr else LA_Logic.notI |
|
846 val concl = implies_intr cnTconcl Falsethm COMP contr |
|
847 in SOME (trace_thm "Proved by lin. arith. prover:" |
785 in SOME (trace_thm "Proved by lin. arith. prover:" |
848 (LA_Logic.mk_Eq concl)) end |
786 (LA_Logic.mk_Eq concl)) end |
849 (* in case concl contains ?-var, which makes assume fail: *) |
787 (* in case concl contains ?-var, which makes assume fail: *) |
850 handle THM _ => NONE; |
788 handle THM _ => NONE; |
851 |
789 |