Skip to content

Commit 873057e

Browse files
committed
boolsimp
1 parent efc1f54 commit 873057e

File tree

1 file changed

+51
-16
lines changed

1 file changed

+51
-16
lines changed

src/kdrag/tactics.py

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)