Z3Py

时间:2018-06-20 11:44:50

标签: z3 z3py

我想找到一个最大间隔,其中对于所有x,表达式e为真。编写此类公式的方法应为:Exists d : ForAll x in (-d,d) . e and ForAll x not in (-d,d) . !e

要获得这样的d,Z3中的公式f(看上面的一个)可以是:

from __future__ import division
from z3 import *

x = Real('x')
delta = Real('d')
s = Solver()

e = And(1/10000*x**2 > 0, 1/5000*x**3 + -1/5000*x**2 < 0)

f = ForAll(x,
And(Implies(And(delta > 0,
                -delta < x, x < delta, 
                x != 0),
            e),
    Implies(And(delta > 0,
                Or(x > delta, x < -delta),
                x != 0),
            Not(e))
    )
)

s.add(Not(f))
s.check()
print s.model()

哪个输出[d = 1/4]

要进行检查,我设置了delta = RealVal('1/4'),从ForAll删除了f量词,然后得到了x = 1/2。我用delta替换了1/2,得到了3/4,然后是7/8,依此类推。边界应为1。我可以让Z3立即输出吗?

1 个答案:

答案 0 :(得分:1)

如果您自己进行数学运算,则可以看到解决方案是x != 0, x < 1。或者,您可以简单地要求Wolfram Alpha为您完成此操作。因此,没有这样的delta

您遇到的问题是您要断言:

s.add(Not(f))

这将x上的通用量化转换为存在的量化;要求z3找到一个delta,例如有一些x 符合要求。 (也就是说,您要否定整个公式。)相反,您应该这样做:

s.add(delta > 0, f)

这还可以确保delta为正。有了这一更改,z3将正确响应:

unsat

(然后,对s.model()的调用会出错,如果先前对s.model()的调用返回了s.check(),则仅应调用sat。)< / p>