Ненулевой вектор в квантификаторе
Я хочу проверить формулу формы:
Exists p . ForAll x != 0 . f(x, p) > 0
Реализация (которая не работает) заключается в следующем:
def f0(x0, x1, x, y):
return x1 ** 2 * y + x0 ** 2 * x
s = Solver()
x0, x1 = Reals('x0 x1')
p0, p1 = Reals('p0 p1')
s.add(Exists([p0, p1],
ForAll([x0, x1],
f0(x0, x1, p0, p1) > 0
)
))
#s.add(Or(x0 != 0, x1 != 0))
while s.check() == sat:
m = s.model()
m.evaluate(x0, model_completion=True)
m.evaluate(x1, model_completion=True)
m.evaluate(p0, model_completion=True)
m.evaluate(p1, model_completion=True)
print m
s.add(Or(x0 != m[x0], x1 != m[x1]))
Формула не выполняется.
С f0() >= 0
, единственный выход (0, 0)
,
я хочу иметь f0() > 0
и сдерживать (x0, x1) != (0, 0)
,
Что-то, что я ожидал бы, является: p0, p1 = 1, 1
или же 2, 2
например, но я не знаю, как удалить 0, 0
из возможных значений для x0, x1
,
2 ответа
В продолжение ответа Левента. Во время первой проверки Z3 использует пользовательскую процедуру принятия решения, которая работает с квантификаторами. В инкрементном режиме все сводится к тому, что не является процедурой принятия решения. Для принудительного решения проблемы с одним выстрелом попробуйте следующее:
from z3 import *
def f0(x0, x1, x, y):
return x1 * x1 * y + x0 * x0 * x
p0, p1 = Reals('p0 p1')
x0, x1 = Reals('x0 x1')
fmls = [ForAll([x0, x1], Implies(Or(x0 != 0, x1 != 0), f0(x0, x1, p0, p1) > 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
Вы просто напишите это как следствие внутри количественного определения. Я думаю, что вы также перепутали некоторые переменные там. Следующее, кажется, отражает ваши намерения:
from z3 import *
def f0(x0, x1, x, y):
return x1 * x1 * y + x0 * x0 * x
s = Solver()
p0, p1 = Reals('p0 p1')
x0, x1 = Reals('x0 x1')
s.add(ForAll([x0, x1], Implies(Or(x0 != 0, x1 != 0), f0(x0, x1, p0, p1) > 0)))
while True:
res = s.check()
print res
if res == sat:
m = s.model()
print m
s.add(Or(p0 != m[p0], p1 != m[p1]))
else:
print "giving up"
break
Конечно, z3 не гарантирует вам каких-либо решений; хотя, кажется, справиться с одним:
$ python a.py
sat
[p1 = 1, p0 = 1]
unknown
giving up
Как только вы используете квантификаторы, все ставки отключаются, так как логика становится полуразрешимой. Z3 делает хорошую работу здесь и возвращает одно решение, а затем сдается. Я не думаю, что вы можете ожидать чего-то лучшего, если вы не используете некоторые собственные процедуры принятия решений.