700 |
699 |
701 local |
700 local |
702 fun count_rules ptab = |
701 fun count_rules ptab = |
703 let |
702 let |
704 fun count (_, Unproved _) (solved, total) = (solved, total + 1) |
703 fun count (_, Unproved _) (solved, total) = (solved, total + 1) |
705 | count (_, Sequent _) (solved, total) = (solved + 1, total + 1) |
704 | count (_, Proved _) (solved, total) = (solved + 1, total + 1) |
706 in Inttab.fold count ptab (0, 0) end |
705 in Inttab.fold count ptab (0, 0) end |
707 |
706 |
708 fun header idx r (solved, total) = |
707 fun header idx r (solved, total) = |
709 "Z3: #" ^ string_of_int idx ^ ": " ^ P.string_of_rule r ^ " (goal " ^ |
708 "Z3: #" ^ string_of_int idx ^ ": " ^ P.string_of_rule r ^ " (goal " ^ |
710 string_of_int (solved + 1) ^ " of " ^ string_of_int total ^ ")" |
709 string_of_int (solved + 1) ^ " of " ^ string_of_int total ^ ")" |
711 |
710 |
712 fun check ctxt idx r ps ct ((_, p), _) = |
711 fun check ctxt idx r ps ct p = |
713 let val thm = thm_of p |> tap (Thm.join_proofs o single) |
712 let val thm = thm_of p |> tap (Thm.join_proofs o single) |
714 in |
713 in |
715 if (Thm.cprop_of thm) aconvc ct then () |
714 if (Thm.cprop_of thm) aconvc ct then () |
716 else z3_exn (Pretty.string_of (Pretty.big_list ("proof step failed: " ^ |
715 else z3_exn (Pretty.string_of (Pretty.big_list ("proof step failed: " ^ |
717 quote (P.string_of_rule r) ^ " (#" ^ string_of_int idx ^ ")") |
716 quote (P.string_of_rule r) ^ " (#" ^ string_of_int idx ^ ")") |
718 (pretty_goal ctxt (map (thm_of o fst) ps) (Thm.prop_of thm) @ |
717 (pretty_goal ctxt (map (thm_of o fst) ps) (Thm.prop_of thm) @ |
719 [Pretty.block [Pretty.str "expected: ", |
718 [Pretty.block [Pretty.str "expected: ", |
720 Syntax.pretty_term ctxt (Thm.term_of ct)]]))) |
719 Syntax.pretty_term ctxt (Thm.term_of ct)]]))) |
721 end |
720 end |
722 in |
721 in |
723 fun trace_rule ctxt idx prove r ps ct ptab = |
722 fun trace_rule idx prove r ps ct (cxp as (ctxt, ptab)) = |
724 let |
723 let |
725 val _ = SMT_Solver.trace_msg ctxt (header idx r o count_rules) ptab |
724 val _ = SMT_Solver.trace_msg ctxt (header idx r o count_rules) ptab |
726 val result = prove r ps ct ptab |
725 val result as (p, cxp' as (ctxt', _)) = prove r ps ct cxp |
727 val _ = if not (Config.get ctxt SMT_Solver.trace) then () |
726 val _ = if not (Config.get ctxt' SMT_Solver.trace) then () |
728 else check ctxt idx r ps ct result |
727 else check ctxt' idx r ps ct p |
729 in result end |
728 in result end |
730 end |
729 end |
731 |
730 |
732 |
731 |
733 (* overall reconstruction procedure *) |
732 (* overall reconstruction procedure *) |
734 |
733 |
735 fun not_supported r = |
734 fun not_supported r = |
736 z3_exn ("proof rule not implemented: " ^ quote (P.string_of_rule r)) |
735 raise Fail ("Z3: proof rule not implemented: " ^ quote (P.string_of_rule r)) |
737 |
736 |
738 fun prove ctxt unfolds assms vars = |
737 fun prove ctxt unfolds assms vars = |
739 let |
738 let |
740 val assms' = Option.map (prepare_assms unfolds) assms |
739 val assms' = Option.map (prepare_assms unfolds) assms |
741 val simpset = T.make_simpset ctxt (Z3_Simps.get ctxt) |
740 val simpset = T.make_simpset ctxt (Z3_Simps.get ctxt) |
742 |
741 |
743 fun step r ps ct ptab = |
742 fun step r ps ct (cxp as (cx, ptab)) = |
744 (case (r, ps) of |
743 (case (r, ps) of |
745 (* core rules *) |
744 (* core rules *) |
746 (P.TrueAxiom, _) => (([], Thm L.true_thm), ptab) |
745 (P.TrueAxiom, _) => (Thm L.true_thm, cxp) |
747 | (P.Asserted, _) => (([], asserted ctxt assms' ct), ptab) |
746 | (P.Asserted, _) => (asserted cx assms' ct, cxp) |
748 | (P.Goal, _) => (([], asserted ctxt assms' ct), ptab) |
747 | (P.Goal, _) => (asserted cx assms' ct, cxp) |
749 | (P.ModusPonens, [(p, _), (q, _)]) => (([], mp q (thm_of p)), ptab) |
748 | (P.ModusPonens, [(p, _), (q, _)]) => (mp q (thm_of p), cxp) |
750 | (P.ModusPonensOeq, [(p, _), (q, _)]) => (([], mp q (thm_of p)), ptab) |
749 | (P.ModusPonensOeq, [(p, _), (q, _)]) => (mp q (thm_of p), cxp) |
751 | (P.AndElim, [(p, i)]) => apfst (pair []) (and_elim (p, i) ct ptab) |
750 | (P.AndElim, [(p, i)]) => and_elim (p, i) ct ptab ||> pair cx |
752 | (P.NotOrElim, [(p, i)]) => apfst (pair []) (not_or_elim (p, i) ct ptab) |
751 | (P.NotOrElim, [(p, i)]) => not_or_elim (p, i) ct ptab ||> pair cx |
753 | (P.Hypothesis, _) => (([], Thm (Thm.assume ct)), ptab) |
752 | (P.Hypothesis, _) => (Thm (Thm.assume ct), cxp) |
754 | (P.Lemma, [(p, _)]) => (([], lemma (thm_of p) ct), ptab) |
753 | (P.Lemma, [(p, _)]) => (lemma (thm_of p) ct, cxp) |
755 | (P.UnitResolution, (p, _) :: ps) => |
754 | (P.UnitResolution, (p, _) :: ps) => |
756 (([], unit_resolution (thm_of p) (map (thm_of o fst) ps) ct), ptab) |
755 (unit_resolution (thm_of p) (map (thm_of o fst) ps) ct, cxp) |
757 | (P.IffTrue, [(p, _)]) => (([], iff_true (thm_of p)), ptab) |
756 | (P.IffTrue, [(p, _)]) => (iff_true (thm_of p), cxp) |
758 | (P.IffFalse, [(p, _)]) => (([], iff_false (thm_of p)), ptab) |
757 | (P.IffFalse, [(p, _)]) => (iff_false (thm_of p), cxp) |
759 | (P.Distributivity, _) => (([], distributivity ctxt ct), ptab) |
758 | (P.Distributivity, _) => (distributivity cx ct, cxp) |
760 | (P.DefAxiom, _) => (([], def_axiom ctxt ct), ptab) |
759 | (P.DefAxiom, _) => (def_axiom cx ct, cxp) |
761 | (P.IntroDef, _) => (intro_def ct, ptab) |
760 | (P.IntroDef, _) => intro_def ct cx ||> rpair ptab |
762 | (P.ApplyDef, [(p, _)]) => (([], apply_def (thm_of p)), ptab) |
761 | (P.ApplyDef, [(p, _)]) => (apply_def (thm_of p), cxp) |
763 | (P.IffOeq, [(p, _)]) => (([], p), ptab) |
762 | (P.IffOeq, [(p, _)]) => (p, cxp) |
764 | (P.NnfPos, _) => (([], nnf ctxt vars (map fst ps) ct), ptab) |
763 | (P.NnfPos, _) => (nnf cx vars (map fst ps) ct, cxp) |
765 | (P.NnfNeg, _) => (([], nnf ctxt vars (map fst ps) ct), ptab) |
764 | (P.NnfNeg, _) => (nnf cx vars (map fst ps) ct, cxp) |
766 |
765 |
767 (* equality rules *) |
766 (* equality rules *) |
768 | (P.Reflexivity, _) => (([], refl ct), ptab) |
767 | (P.Reflexivity, _) => (refl ct, cxp) |
769 | (P.Symmetry, [(p, _)]) => (([], symm p), ptab) |
768 | (P.Symmetry, [(p, _)]) => (symm p, cxp) |
770 | (P.Transitivity, [(p, _), (q, _)]) => (([], trans p q), ptab) |
769 | (P.Transitivity, [(p, _), (q, _)]) => (trans p q, cxp) |
771 | (P.Monotonicity, _) => (([], monotonicity (map fst ps) ct), ptab) |
770 | (P.Monotonicity, _) => (monotonicity (map fst ps) ct, cxp) |
772 | (P.Commutativity, _) => (([], commutativity ct), ptab) |
771 | (P.Commutativity, _) => (commutativity ct, cxp) |
773 |
772 |
774 (* quantifier rules *) |
773 (* quantifier rules *) |
775 | (P.QuantIntro, [(p, _)]) => (([], quant_intro vars p ct), ptab) |
774 | (P.QuantIntro, [(p, _)]) => (quant_intro vars p ct, cxp) |
776 | (P.PullQuant, _) => (([], pull_quant ctxt ct), ptab) |
775 | (P.PullQuant, _) => (pull_quant cx ct, cxp) |
777 | (P.PushQuant, _) => (([], push_quant ctxt ct), ptab) |
776 | (P.PushQuant, _) => (push_quant cx ct, cxp) |
778 | (P.ElimUnusedVars, _) => (([], elim_unused_vars ctxt ct), ptab) |
777 | (P.ElimUnusedVars, _) => (elim_unused_vars cx ct, cxp) |
779 | (P.DestEqRes, _) => (([], dest_eq_res ctxt ct), ptab) |
778 | (P.DestEqRes, _) => (dest_eq_res cx ct, cxp) |
780 | (P.QuantInst, _) => (([], quant_inst ct), ptab) |
779 | (P.QuantInst, _) => (quant_inst ct, cxp) |
781 | (P.Skolemize, _) => (skolemize ctxt ct, ptab) |
780 | (P.Skolemize, _) => skolemize ct cx ||> rpair ptab |
782 |
781 |
783 (* theory rules *) |
782 (* theory rules *) |
784 | (P.ThLemma, _) => |
783 | (P.ThLemma, _) => |
785 (([], th_lemma ctxt simpset (map (thm_of o fst) ps) ct), ptab) |
784 (th_lemma cx simpset (map (thm_of o fst) ps) ct, cxp) |
786 | (P.Rewrite, _) => (([], rewrite ctxt simpset [] ct), ptab) |
785 | (P.Rewrite, _) => (rewrite cx simpset [] ct, cxp) |
787 | (P.RewriteStar, ps) => |
786 | (P.RewriteStar, ps) => |
788 (([], rewrite ctxt simpset (map fst ps) ct), ptab) |
787 (rewrite cx simpset (map fst ps) ct, cxp) |
789 |
788 |
790 | (P.NnfStar, _) => not_supported r |
789 | (P.NnfStar, _) => not_supported r |
791 | (P.CnfStar, _) => not_supported r |
790 | (P.CnfStar, _) => not_supported r |
792 | (P.TransitivityStar, _) => not_supported r |
791 | (P.TransitivityStar, _) => not_supported r |
793 | (P.PullQuantStar, _) => not_supported r |
792 | (P.PullQuantStar, _) => not_supported r |
794 |
793 |
795 | _ => z3_exn ("Proof rule " ^ quote (P.string_of_rule r) ^ |
794 | _ => raise Fail ("Z3: proof rule " ^ quote (P.string_of_rule r) ^ |
796 " has an unexpected number of arguments.")) |
795 " has an unexpected number of arguments.")) |
797 |
796 |
798 fun eq_hyp_def (ct, cu) = Thm.dest_arg1 ct aconvc Thm.dest_arg1 cu |
797 fun conclude idx rule prop (ps, cxp) = |
799 (* compare only the defined Frees, not the whole definitions *) |
798 trace_rule idx step rule ps prop cxp |
800 |
799 |-> (fn p => apsnd (Inttab.update (idx, Proved p)) #> pair p) |
801 fun conclude idx rule prop ((hypss, ps), ptab) = |
800 |
802 trace_rule ctxt idx step rule ps prop ptab |
801 fun lookup idx (cxp as (cx, ptab)) = |
803 |>> apfst (distinct eq_hyp_def o fold append hypss) |
|
804 |
|
805 fun add_sequent idx (hyps, thm) ptab = |
|
806 ((hyps, thm), Inttab.update (idx, Sequent {hyps=hyps, thm=thm}) ptab) |
|
807 |
|
808 fun lookup idx ptab = |
|
809 (case Inttab.lookup ptab idx of |
802 (case Inttab.lookup ptab idx of |
810 SOME (Unproved (P.Proof_Step {rule, prems, prop})) => |
803 SOME (Unproved (P.Proof_Step {rule, prems, prop})) => |
811 fold_map lookup prems ptab |
804 fold_map lookup prems cxp |
812 |>> split_list |
805 |>> map2 rpair prems |
813 |>> apsnd (fn ps => ps ~~ prems) |
|
814 |> conclude idx rule prop |
806 |> conclude idx rule prop |
815 |-> add_sequent idx |
807 | SOME (Proved p) => (p, cxp) |
816 | SOME (Sequent {hyps, thm}) => ((hyps, thm), ptab) |
|
817 | NONE => z3_exn ("unknown proof id: " ^ quote (string_of_int idx))) |
808 | NONE => z3_exn ("unknown proof id: " ^ quote (string_of_int idx))) |
818 |
809 |
819 fun result (hyps, thm) = |
810 fun result (p, (cx, _)) = (thm_of p, cx) |
820 fold SMT_Normalize.discharge_definition hyps (thm_of thm) |
|
821 in |
811 in |
822 (fn (idx, ptab) => result (fst (lookup idx (Inttab.map Unproved ptab)))) |
812 (fn (idx, ptab) => result (lookup idx (ctxt, Inttab.map Unproved ptab))) |
823 end |
813 end |
824 |
814 |
825 fun reconstruct ctxt {typs, terms, unfolds, assms} output = |
815 fun reconstruct (output, {typs, terms, unfolds, assms}) ctxt = |
826 P.parse ctxt typs terms output |
816 P.parse ctxt typs terms output |
827 |> (fn (idx, (ptab, vars, cx)) => prove cx unfolds assms vars (idx, ptab)) |
817 |> (fn (idx, (ptab, vars, cx)) => prove cx unfolds assms vars (idx, ptab)) |
828 |
818 |
829 val setup = trace_assms_setup #> z3_rules_setup #> Z3_Simps.setup |
819 val setup = trace_assms_setup #> z3_rules_setup #> Z3_Simps.setup |
830 |
820 |