forked from qingkaishi/z3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
efsmt.py
47 lines (43 loc) · 1.41 KB
/
efsmt.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from z3 import *
from z3.z3util import get_vars
'''
Modified from the example in pysmt
https://github.com/pysmt/pysmt/blob/97088bf3b0d64137c3099ef79a4e153b10ccfda7/examples/efsmt.py
'''
def efsmt(y, phi, maxloops=None):
"""Solving exists x. forall y. phi(x, y)"""
vars = get_vars(phi)
x = [item for item in vars if item not in y]
esolver = Solver()
fsolver = Solver()
esolver.add(BoolVal(True))
loops = 0
while maxloops is None or loops <= maxloops:
loops += 1
eres = esolver.check()
if eres == unsat:
return unsat
else:
emodel = esolver.model()
tau = [emodel.eval(var, True) for var in x]
sub_phi = phi
for i in range(len(x)):
sub_phi = simplify(substitute(sub_phi, (x[i], tau[i])))
fsolver.add(Not(sub_phi))
if fsolver.check() == sat:
fmodel = fsolver.model()
sigma = [fmodel.eval(v, True) for v in y]
sub_phi = phi
for j in range(len(y)):
sub_phi = simplify(substitute(sub_phi, (y[j], sigma[j])))
esolver.add(sub_phi)
else:
return sat
return unknown
def test():
x, y, z = Reals("x y z")
fmla = Implies(And(y > 0, y < 10), y - 2 * x < 7)
fmlb = And(y > 3, x == 1)
print(efsmt([y], fmla))
print(efsmt([y], fmlb))
test()