找到可能的值

时间:2018-05-17 10:33:24

标签: formula z3 smt z3py

我想验证表单的公式:

Exists p . ForAll x != 0 . f(x, p) > 0 and g(x, p) < 0

所有变量都是实数。

根据建议here,我将此列表添加到求解器:

[ForAll([x0, x1],
    Implies(Or(x0 != 0, x1 != 0),
        And(P0*x0*x0 + P1*x0*x1 + P2*x0*x1 + P3*x1*x1 > 0,
            -2*P0*x0*x1 + P1*x0*x0 - P1*x0*x1 - P1*x1*x1 + P2*x0*x0 - P2*x0*x1 - P2*x1*x1 + 2*P3*x0*x1 - 2*P3*x1*x1 < 0
            )
        )
    )
]

具有上述公式的求解器返回unsat。一个可能的解决方案是P[[1.5, -0.5], [-0.5, 1]],事实上,通过替换这些值,公式得到满足:

And(3/2*x0*x0 - 1*x0*x1 + x1*x1 > 0,
    -1*x0*x0 - 1*x1*x1 < 0)

有没有办法真正计算出这样的p?如果z3很难,那么这个问题还有其他选择吗?

1 个答案:

答案 0 :(得分:0)

如果您说'存在'后跟'Forall',那么您说每个x0x1的公式都应该为真。并且Z3告诉你事实并非如此。

如果您有兴趣找到一个这样的P和相应的x值,只需删除量化并使所有内容成为顶级变量:

from z3 import *

def f(x0, x1, P0, P1, P2, P3):
    return P0*x0*x0 + P1*x0*x1 + P2*x0*x1 + P3*x1*x1

def g(x0, x1, P0, P1, P2, P3):
    return -2*P0*x0*x1 + P1*x0*x0 - P1*x0*x1 - P1*x1*x1 + P2*x0*x0 - P2*x0*x1 - P2*x1*x1 + 2*P3*x0*x1 - 2*P3*x1*x1

p0, p1, p2, p3  = Reals('p0 p1 p2 p3')

x0, x1 = Reals('x0 x1')
fmls = [Implies(Or(x0 != 0, x1 != 0), And(f(x0, x1, p0, p1, p2, p3) > 0, g(x0, x1, p0, p1, p2, p3) < 0))]

while True:
    s = Solver()
    s.add(fmls)
    res = s.check()
    print res
    if res == sat:
        m = s.model()
        print m
        fmls += [Or(p0 != m[p0], p1 != m[p1])]
    else:
       print "giving up"
       break

当我跑步时,我得到:

sat
[x0 = 1/8, p0 = -1/2, p1 = -1/2, x1 = 1/2, p2 = 1, p3 = 1]

和其他许多人;我相信你所追求的是什么。

请注意,您还可以根据自己的位置进行一些编程以消除存在量化;即,从量化版本开始,如果得到unsat,则切换到新的求解器并使用未量化的版本自动执行此过程。当然,这只是编程,并且在这一点上与z3没有任何关系。