我想找到一个最大间隔,其中对于所有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立即输出吗?
答案 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>