@@ -777,6 +777,54 @@ def simp(self, at=None, unfold=False, path=None) -> "ProofState":
777777 )
778778 return self
779779
780+ def boolsimp (self ) -> "ProofState" :
781+ """
782+ Simplify boolean expressions to true or false is possible. More for exploration that for leaving in a finished proof.
783+
784+ >>> p,q,r = smt.Bools("p q r")
785+ >>> l = Lemma(smt.Implies(smt.And(p, smt.Not(q)), smt.And(q, p, r)))
786+ >>> l.intros()
787+ And(p, Not(q))
788+ >>> l.boolsimp()
789+ [And(p, Not(q)), p == True, And(q, p, r) == False, q == False] ?|= False
790+ >>> l = Lemma(smt.Implies(p, smt.If(smt.Not(p), p, q) == r))
791+ >>> l.intros()
792+ p
793+ >>> l.boolsimp()
794+ [p, p == True, Not(p) == False] ?|= If(False, True, q) == r
795+ """
796+ goalctx = self .top_goal ()
797+ bools = [
798+ e for e in kd .utils .subterms (goalctx .goal ) if isinstance (e , smt .BoolRef )
799+ ]
800+ trues = []
801+ falses = []
802+ ctx = smt .And (goalctx .ctx )
803+ for b in bools :
804+ try :
805+ kd .prove (smt .Implies (ctx , b ), timeout = 50 )
806+ trues .append (b )
807+ except kd .kernel .LemmaError :
808+ try :
809+ kd .prove (smt .Implies (ctx , smt .Not (b )))
810+ falses .append (b )
811+ except kd .kernel .LemmaError :
812+ pass
813+ if len (trues ) == 0 and len (falses ) == 0 :
814+ raise ValueError ("No boolean simplifications found" )
815+ newctx = (
816+ goalctx .ctx
817+ + [b == smt .BoolVal (True ) for b in trues ]
818+ + [b == smt .BoolVal (False ) for b in falses ]
819+ )
820+ newgoal = smt .substitute (
821+ goalctx .goal ,
822+ * zip (trues , [smt .BoolVal (True )] * len (trues )),
823+ * zip (falses , [smt .BoolVal (False )] * len (falses )),
824+ )
825+ self .goals [- 1 ] = goalctx ._replace (ctx = newctx , goal = newgoal )
826+ return self
827+
780828 def emt (self ):
781829 """
782830 Use egraph based equality modulo theories to simplify the goal.
@@ -862,30 +910,17 @@ def auto(self, **kwargs) -> "ProofState":
862910 self .top_goal () # TODO: This is clearing lemmacallbacks but why do I need to?
863911 return self
864912
865- def vampire (self , by = [], admit = False ) :
913+ def vampire (self , ** kwargs ) -> "ProofState" :
866914 """
867915 Call vampire to see if the current goal is solvable.
868916 Currently a sanity check only.
869917
870918 >>> p,q = smt.Bools("p q")
871919 >>> l = Lemma(smt.Implies(p, p))
872920 >>> l.vampire()
873- ...
874- Vampire proved the goal
875- [] ?|= Implies(p, p)
921+ Nothing to do. Hooray!
876922 """
877- solver = solvers .VampireSolver ()
878- solver .add (by )
879- solver .add (smt .Not (self .top_goal ().to_expr ()))
880- res = solver .check ()
881- if res == smt .sat :
882- raise ValueError ("Vampire failed to prove the goal" , self .top_goal ())
883- elif res == smt .unsat :
884- print ("Vampire proved the goal" )
885- if admit :
886- self .pop_goal ()
887- self .add_lemma (kd .kernel .prove (self .top_goal ().to_expr (), admit = True ))
888- return self
923+ return self .auto (solver = solvers .VampireSolver , ** kwargs )
889924
890925 def cvc5 (self , by = [], admit = False ):
891926 """
0 commit comments