18 * rules must not require higher-order unification, e.g. apply_type in ZF |
18 * rules must not require higher-order unification, e.g. apply_type in ZF |
19 + message "Function Var's argument not a bound variable" relates to this |
19 + message "Function Var's argument not a bound variable" relates to this |
20 * its proof strategy is more general but can actually be slower |
20 * its proof strategy is more general but can actually be slower |
21 |
21 |
22 Known problems: |
22 Known problems: |
23 "Recursive" rules such as transitivity can exclude other unsafe formulae |
23 "Recursive" chains of rules can sometimes exclude other unsafe formulae |
24 from expansion. This happens because newly-created formulae always |
24 from expansion. This happens because newly-created formulae always |
25 have priority over existing ones. |
25 have priority over existing ones. But obviously recursive rules |
|
26 such as transitivity are treated specially to prevent this. |
26 |
27 |
27 With overloading: |
28 With overloading: |
28 Overloading can't follow all chains of type dependencies. Cannot |
29 Overloading can't follow all chains of type dependencies. Cannot |
29 prove "In1 x ~: Part A In0" because PartE introducees the polymorphic |
30 prove "In1 x ~: Part A In0" because PartE introducees the polymorphic |
30 equality In1 x = In0 y, when the corresponding rule uses the (distinct) |
31 equality In1 x = In0 y, when the corresponding rule uses the (distinct) |
32 creates new equalities (e.g. PartE in HOL/ex/Simult) |
33 creates new equalities (e.g. PartE in HOL/ex/Simult) |
33 ==> affects freeness reasoning about Sexp constants (since they have |
34 ==> affects freeness reasoning about Sexp constants (since they have |
34 type ... set) |
35 type ... set) |
35 |
36 |
36 With substition for equalities (hyp_subst_tac): |
37 With substition for equalities (hyp_subst_tac): |
37 1. Sometimes hyp_subst_tac will fail due to occurrence of the parameter |
38 When substitution affects a haz formula or literal, it is moved |
38 as the argument of a function variable |
|
39 2. When substitution affects a haz formula or literal, it is moved |
|
40 back to the list of safe formulae. |
39 back to the list of safe formulae. |
41 But there's no way of putting it in the right place. A "moved" or |
40 But there's no way of putting it in the right place. A "moved" or |
42 "no DETERM" flag would prevent proofs failing here. |
41 "no DETERM" flag would prevent proofs failing here. |
43 *) |
42 *) |
44 |
43 |
306 | subst (f$t, lev) = subst(f,lev) $ subst(t,lev) |
298 | subst (f$t, lev) = subst(f,lev) $ subst(t,lev) |
307 | subst (t,lev) = t |
299 | subst (t,lev) = t |
308 in subst (t,0) end; |
300 in subst (t,0) end; |
309 |
301 |
310 |
302 |
311 (*Normalize...but not the bodies of ABSTRACTIONS*) |
303 (*Normalize, INCLUDING bodies of abstractions--this might be slow?*) |
312 fun norm t = case t of |
304 fun norm t = case t of |
313 Skolem (a,args) => Skolem(a, vars_in_vars args) |
305 Skolem (a,args) => Skolem(a, vars_in_vars args) |
314 | (Var (ref None)) => t |
306 | (Var (ref None)) => t |
315 | (Var (ref (Some u))) => norm u |
307 | (Var (ref (Some u))) => norm u |
316 | (f $ u) => (case norm f of |
308 | (f $ u) => (case norm f of |
317 Abs(_,body) => norm (subst_bound (u, body)) |
309 Abs(_,body) => norm (subst_bound (u, body)) |
318 | nf => nf $ norm u) |
310 | nf => nf $ norm u) |
|
311 | Abs (a,body) => Abs (a, norm body) |
319 | _ => t; |
312 | _ => t; |
320 |
313 |
321 |
314 |
322 (*Weak (one-level) normalize for use in unification*) |
315 (*Weak (one-level) normalize for use in unification*) |
323 fun wkNormAux t = case t of |
316 fun wkNormAux t = case t of |
551 |
544 |
552 (** |
545 (** |
553 end; |
546 end; |
554 **) |
547 **) |
555 |
548 |
|
549 |
|
550 (*Pending formulae carry md (may duplicate) flags*) |
|
551 type branch = ((term*bool) list * (*safe formulae on this level*) |
|
552 (term*bool) list) list * (*haz formulae on this level*) |
|
553 term list * (*literals: irreducible formulae*) |
|
554 term option ref list * (*variables occurring in branch*) |
|
555 int; (*resource limit*) |
|
556 |
|
557 val fullTrace = ref[] : branch list list ref; |
|
558 |
|
559 (*Normalize a branch--for tracing*) |
|
560 fun norm2 (G,md) = (norm G, md); |
|
561 |
|
562 fun normLev (Gs,Hs) = (map norm2 Gs, map norm2 Hs); |
|
563 |
|
564 fun normBr (br, lits, vars, lim) = |
|
565 (map normLev br, map norm lits, vars, lim); |
|
566 |
|
567 |
|
568 val dummyVar2 = Term.Var(("var",0), dummyT); |
|
569 |
|
570 (*Convert from prototerms to ordinary terms with dummy types for tracing*) |
|
571 fun showTerm d (Const a) = Term.Const (a,dummyT) |
|
572 | showTerm d (OConst(a,_)) = Term.Const (a,dummyT) |
|
573 | showTerm d (Skolem(a,_)) = Term.Const (a,dummyT) |
|
574 | showTerm d (Free a) = Term.Free (a,dummyT) |
|
575 | showTerm d (Bound i) = Term.Bound i |
|
576 | showTerm d (Var _) = dummyVar2 |
|
577 | showTerm d (Abs(a,t)) = if d=0 then dummyVar |
|
578 else Term.Abs(a, dummyT, showTerm (d-1) t) |
|
579 | showTerm d (f $ u) = if d=0 then dummyVar |
|
580 else Term.$ (showTerm d f, showTerm (d-1) u); |
|
581 |
|
582 |
|
583 fun traceTerm sign t = Sign.string_of_term sign (showTerm 8 (norm t)); |
|
584 |
|
585 |
|
586 (*Print tracing information at each iteration of prover*) |
|
587 fun tracing sign brs = |
|
588 let fun printPairs (((G,_)::_,_)::_) = prs(traceTerm sign G) |
|
589 | printPairs (([],(H,_)::_)::_) = prs(traceTerm sign H ^ "\t (Unsafe)") |
|
590 | printPairs _ = () |
|
591 fun printBrs (brs0 as (pairs, lits, _, lim) :: brs) = |
|
592 (fullTrace := brs0 :: !fullTrace; |
|
593 seq (fn _ => prs "+") brs; |
|
594 prs (" [" ^ Int.toString lim ^ "] "); |
|
595 printPairs pairs; |
|
596 writeln"") |
|
597 in if !trace then printBrs (map normBr brs) else () |
|
598 end; |
|
599 |
|
600 (*Tracing: variables updated in the last branch operation?*) |
|
601 fun traceVars ntrl = |
|
602 if !trace then |
|
603 (case !ntrail-ntrl of |
|
604 0 => writeln"" |
|
605 | 1 => writeln"\t1 variable updated" |
|
606 | n => writeln("\t" ^ Int.toString n ^ " variables updated")) |
|
607 else (); |
|
608 |
|
609 (*Tracing: how many new branches are created?*) |
|
610 fun traceNew prems = |
|
611 if !trace then |
|
612 case length prems of |
|
613 0 => prs"branch closed by rule" |
|
614 | 1 => prs"branch extended (1 new subgoal)" |
|
615 | n => prs("branch split: "^ Int.toString n ^ " new subgoals") |
|
616 else (); |
|
617 |
|
618 |
|
619 |
556 (*** Code for handling equality: naive substitution, like hyp_subst_tac ***) |
620 (*** Code for handling equality: naive substitution, like hyp_subst_tac ***) |
557 |
621 |
558 (*Replace the ATOMIC term "old" by "new" in t*) |
622 (*Replace the ATOMIC term "old" by "new" in t*) |
559 fun subst_atomic (old,new) t = |
623 fun subst_atomic (old,new) t = |
560 let fun subst (Var(ref(Some u))) = subst u |
624 let fun subst (Var(ref(Some u))) = subst u |
591 | occ (Abs(_,u)) = occEq u |
655 | occ (Abs(_,u)) = occEq u |
592 | occ (f$u) = occEq u orelse occEq f |
656 | occ (f$u) = occEq u orelse occEq f |
593 | occ (_) = false; |
657 | occ (_) = false; |
594 in occEq end; |
658 in occEq end; |
595 |
659 |
|
660 exception DEST_EQ; |
|
661 |
|
662 (*Take apart an equality (plain or overloaded). NO constant Trueprop*) |
|
663 fun dest_eq (Const "op =" $ t $ u) = |
|
664 (eta_contract_atom t, eta_contract_atom u) |
|
665 | dest_eq (OConst("op =",_) $ t $ u) = |
|
666 (eta_contract_atom t, eta_contract_atom u) |
|
667 | dest_eq _ = raise DEST_EQ; |
|
668 |
596 fun check (t,u,v) = if substOccur t u then raise DEST_EQ else v; |
669 fun check (t,u,v) = if substOccur t u then raise DEST_EQ else v; |
597 |
670 |
598 (*IF the goal is an equality with a substitutable variable |
671 (*IF the goal is an equality with a substitutable variable |
599 THEN orient that equality ELSE raise exception DEST_EQ*) |
672 THEN orient that equality ELSE raise exception DEST_EQ*) |
600 fun orientGoal (t,u) = |
673 fun orientGoal (t,u) = case (t,u) of |
601 case (eta_contract_atom t, eta_contract_atom u) of |
|
602 (Skolem _, _) => check(t,u,(t,u)) (*eliminates t*) |
674 (Skolem _, _) => check(t,u,(t,u)) (*eliminates t*) |
603 | (_, Skolem _) => check(u,t,(u,t)) (*eliminates u*) |
675 | (_, Skolem _) => check(u,t,(u,t)) (*eliminates u*) |
604 | (Free _, _) => check(t,u,(t,u)) (*eliminates t*) |
676 | (Free _, _) => check(t,u,(t,u)) (*eliminates t*) |
605 | (_, Free _) => check(u,t,(u,t)) (*eliminates u*) |
677 | (_, Free _) => check(u,t,(u,t)) (*eliminates u*) |
606 | _ => raise DEST_EQ; |
678 | _ => raise DEST_EQ; |
607 |
679 |
608 |
|
609 |
|
610 |
|
611 (*Substitute through the branch if an equality goal (else raise DEST_EQ). |
680 (*Substitute through the branch if an equality goal (else raise DEST_EQ). |
612 Moves affected literals back into the branch, but it is not clear where |
681 Moves affected literals back into the branch, but it is not clear where |
613 they should go: this could make proofs fail. ??? *) |
682 they should go: this could make proofs fail. ??? *) |
614 fun equalSubst (G, pairs, lits, vars, lim) = |
683 fun equalSubst sign (G, pairs, lits, vars, lim) = |
615 let val subst = subst_atomic (orientGoal(dest_eq G)) |
684 let val (t,u) = orientGoal(dest_eq G) |
|
685 val subst = subst_atomic (t,u) |
616 fun subst2(G,md) = (subst G, md) |
686 fun subst2(G,md) = (subst G, md) |
617 (*substitute throughout Haz list; move affected ones to Safe part*) |
687 (*substitute throughout Haz list; move affected ones to Safe part*) |
618 fun subHazs ([], Gs, nHs) = (Gs,nHs) |
688 fun subHazs ([], Gs, nHs) = (Gs,nHs) |
619 | subHazs ((H,md)::Hs, Gs, nHs) = |
689 | subHazs ((H,md)::Hs, Gs, nHs) = |
620 let val nH = subst H |
690 let val nH = subst H |
628 | subLits (lit::lits, Gs, nlits) = |
698 | subLits (lit::lits, Gs, nlits) = |
629 let val nlit = subst lit |
699 let val nlit = subst lit |
630 in if nlit aconv lit then subLits (lits, Gs, nlit::nlits) |
700 in if nlit aconv lit then subLits (lits, Gs, nlit::nlits) |
631 else subLits (lits, (nlit,true)::Gs, nlits) |
701 else subLits (lits, (nlit,true)::Gs, nlits) |
632 end |
702 end |
633 in if !trace then writeln "substitution in branch" else (); |
703 in if !trace then writeln ("Substituting " ^ traceTerm sign u ^ |
|
704 " for " ^ traceTerm sign t ^ " in branch" ) |
|
705 else (); |
634 subLits (rev lits, [], []) |
706 subLits (rev lits, [], []) |
635 end; |
707 end; |
636 |
708 |
637 |
709 |
638 exception NEWBRANCHES and CLOSEF; |
710 exception NEWBRANCHES and CLOSEF; |
639 |
|
640 (*Pending formulae carry md (may duplicate) flags*) |
|
641 type branch = ((term*bool) list * (*safe formulae on this level*) |
|
642 (term*bool) list) list * (*haz formulae on this level*) |
|
643 term list * (*literals: irreducible formulae*) |
|
644 term option ref list * (*variables occurring in branch*) |
|
645 int; (*resource limit*) |
|
646 |
|
647 val fullTrace = ref[] : branch list list ref; |
|
648 |
|
649 (*Normalize a branch--for tracing*) |
|
650 fun norm2 (G,md) = (norm G, md); |
|
651 |
|
652 fun normLev (Gs,Hs) = (map norm2 Gs, map norm2 Hs); |
|
653 |
|
654 fun normBr (br, lits, vars, lim) = |
|
655 (map normLev br, map norm lits, vars, lim); |
|
656 |
|
657 |
|
658 val dummyVar2 = Term.Var(("var",0), dummyT); |
|
659 |
|
660 (*Convert from prototerms to ordinary terms with dummy types for tracing*) |
|
661 fun showTerm d (Const a) = Term.Const (a,dummyT) |
|
662 | showTerm d (OConst(a,_)) = Term.Const (a,dummyT) |
|
663 | showTerm d (Skolem(a,_)) = Term.Const (a,dummyT) |
|
664 | showTerm d (Free a) = Term.Free (a,dummyT) |
|
665 | showTerm d (Bound i) = Term.Bound i |
|
666 | showTerm d (Var _) = dummyVar2 |
|
667 | showTerm d (Abs(a,t)) = if d=0 then dummyVar |
|
668 else Term.Abs(a, dummyT, showTerm (d-1) t) |
|
669 | showTerm d (f $ u) = if d=0 then dummyVar |
|
670 else Term.$ (showTerm d f, showTerm (d-1) u); |
|
671 |
|
672 |
|
673 (*Print tracing information at each iteration of prover*) |
|
674 fun tracing sign brs = |
|
675 let fun pr t = prs (Sign.string_of_term sign (showTerm 8 t)) |
|
676 fun printPairs (((G,_)::_,_)::_) = pr G |
|
677 | printPairs (([],(H,_)::_)::_) = (pr H; prs"\t (Unsafe)") |
|
678 | printPairs _ = () |
|
679 fun printBrs (brs0 as (pairs, lits, _, lim) :: brs) = |
|
680 (fullTrace := brs0 :: !fullTrace; |
|
681 seq (fn _ => prs "+") brs; |
|
682 prs (" [" ^ Int.toString lim ^ "] "); |
|
683 printPairs pairs; |
|
684 writeln"") |
|
685 in if !trace then printBrs (map normBr brs) else () |
|
686 end; |
|
687 |
|
688 fun traceNew prems = |
|
689 if !trace then |
|
690 case length prems of |
|
691 0 => writeln"branch closed by rule" |
|
692 | 1 => writeln"branch extended (1 new subgoal)" |
|
693 | n => writeln("branch split: "^ Int.toString n ^ |
|
694 " new subgoals") |
|
695 else (); |
|
696 |
|
697 |
|
698 |
711 |
699 exception PROVE; |
712 exception PROVE; |
700 |
713 |
701 val eq_contr_tac = eresolve_tac [Data.notE] THEN' eq_assume_tac; |
714 val eq_contr_tac = eresolve_tac [Data.notE] THEN' eq_assume_tac; |
702 |
715 |
871 val vars' = foldr add_terms_vars (prems, vars) |
884 val vars' = foldr add_terms_vars (prems, vars) |
872 val choices' = (ntrl, nbrs, PRV) :: choices |
885 val choices' = (ntrl, nbrs, PRV) :: choices |
873 val tacs' = (DETERM o (tac false)) :: tacs |
886 val tacs' = (DETERM o (tac false)) :: tacs |
874 (*no duplication*) |
887 (*no duplication*) |
875 in |
888 in |
876 traceNew prems; |
889 traceNew prems; traceVars ntrl; |
877 (if null prems then (*closed the branch: prune!*) |
890 (if null prems then (*closed the branch: prune!*) |
878 prv(tacs', brs0::trs, |
891 prv(tacs', brs0::trs, |
879 prune (nbrs, nxtVars, choices'), |
892 prune (nbrs, nxtVars, choices'), |
880 brs) |
893 brs) |
881 else |
894 else |
917 handle CLOSEF => closeF (map fst haz) |
931 handle CLOSEF => closeF (map fst haz) |
918 handle CLOSEF => closeFl pairs |
932 handle CLOSEF => closeFl pairs |
919 in tracing sign brs0; |
933 in tracing sign brs0; |
920 if lim<0 then backtrack choices |
934 if lim<0 then backtrack choices |
921 else |
935 else |
922 prv (Data.vars_gen_hyp_subst_tac false :: tacs, |
936 prv ((TRY o Data.vars_gen_hyp_subst_tac false) :: tacs, |
|
937 (*The TRY above allows the substitution to fail, e.g. if |
|
938 the real version is z = f(?x z). Rest of proof might |
|
939 still succeed!*) |
923 brs0::trs, choices, |
940 brs0::trs, choices, |
924 equalSubst (G, (br,haz)::pairs, lits, vars, lim) :: brs) |
941 equalSubst sign (G, (br,haz)::pairs, lits, vars, lim) :: brs) |
925 handle DEST_EQ => closeF lits |
942 handle DEST_EQ => closeF lits |
926 handle CLOSEF => closeFl ((br,haz)::pairs) |
943 handle CLOSEF => closeFl ((br,haz)::pairs) |
927 handle CLOSEF => |
944 handle CLOSEF => |
928 deeper rules |
945 deeper rules |
929 handle NEWBRANCHES => |
946 handle NEWBRANCHES => |