Я пытаюсь формализовать свойство достижимости, чтобы я мог найти удовлетворительное решение, если оно существует, путь длиной 4 (что означает, что есть 3 промежуточных узла, через которые соединяются 2 желаемых узла). Примечание. Я ограничиваю поиск пути длиной 4. Я сделал следующее:
from z3 import*
# link between two nodes
L= Function('L', IntSort(), IntSort(),BoolSort())
# path between two nodes
p=Function('p', IntSort(), IntSort(), BoolSort())
u=Int('u')
x=Int('x')
y=Int('y')
z=Int('z')
i=Int('i')
j=Int('j')
s=Solver()
s.add(x>=0, x<=5, y>=0,y<=5, u>=0,u<=5,i>=0,i<=5, j>=0,j<=5,z>=0,z<=5)
# no self link or path
si1= ForAll(i, And (L(i,i)==False,p(i,i)==False))
si2=ForAll([x,y], p(x,y)==p(y,x))
# To fix source and destination
si3= ForAll([u,x,y], And(L(u,x)==False, L(y,u)==False) )
# To fix the length of path
si4=ForAll([x,y], Exists([i,j,z] , And( L(x,i)==True, L(i,j)==True,L(j,z)==True,L(z,y)==True) ) )
si5=ForAll([x,y,z], Implies (And (p(x,y)==True, L(x,z)==False,L(y,z)==False), L(x,y)==True))
#s.add(L(1,2)==True,L(2,3)==True, L(3,4)==True,L(4,5)==True)
s.add( Implies (p(x,y)==True, Exists([x,y], And(si1==True,si2==True,si3==True,si4==True,si5==True))) )
#s.add(p(x,y)==True)
result=s.check()
model = s.model()
print result, model ,model[p].else_value()
Он возвращает мне SAT, но теперь проблема в том, что, если я не комментирую / добавляю s.add (p (x, y) == True), он возвращает мне unsat, скорее он должен вернуть мне результат SAT. Потому что существует путь между x и y. Даже если я упоминаю вручную (что наивно)
s.add(L(1,2)==True,L(2,3)==True, L(3,4)==True,L(4,5)==True)
он по-прежнему возвращает мне x = 0 и y = 3, где, поскольку это неудовлетворительное решение, первое удовлетворительное решение должно быть x = 0 и y = 4 согласно
si4=ForAll([x,y], Exists([i,j,z] , And( L(x,i)==True, L(i,j)==True,L(j,z)==True,L(z,y)==True) ) )
Где я не прав?