z3py中可达性的形式化

z3py中可达性的形式化,z3,smt,z3py,Z3,Smt,Z3py,我试图将可达性属性形式化,这样,如果存在长度为4的路径,我可以找到一个可满足的解决方案,这意味着如果有3个中间节点,通过这3个中间节点,两个期望的节点是连接的。 注意:我将其限制为仅查找长度为4的路径。以下是我所做的: from z3 import* # link between two nodes L= Function('L', IntSort(), IntSort(),BoolSort()) # path between two nodes p=Function('p', IntSort

我试图将可达性属性形式化,这样,如果存在长度为4的路径,我可以找到一个可满足的解决方案,这意味着如果有3个中间节点,通过这3个中间节点,两个期望的节点是连接的。 注意:我将其限制为仅查找长度为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()
它仍然返回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) )   )

我错在哪里?

我将尝试解释为什么从sat转换到unsat,但忽略如何编码可达性。简单地说,问题是si3和si5意味着px,y对于所有x和y都是假的。当您取消注释/断言px时,y==True,这将断言si3和si5,并导致矛盾

更详细地说,让我们断言px,y==True。s1至s5必须在以下情况下保持:

s.add( Implies (p(x,y)==True, Exists([x,y], And(si1==True,si2==True,si3==True,si4==True,si5==True))) )
; |- Exists([x,y], And(si1==True,si2==True,si3==True,si4==True,si5==True))
; |- And(si1==True,si2==True,si3==True,si4==True,si5==True) as the existential bindings for x and y are not instantiated in any subformula.
我们可以分解si3,推断它等于所有的Lx,y都是假的

si3= ForAll([u,x,y], And(L(u,x)==False, L(y,u)==False) ) 
; moving the forall across the and we get
And (ForAll([u,x,y], L(u,x)==False), ForAll([u,x,y], L(y,u)==False) ) 
; dropping unused variables
And(ForAll([u,x], L(u,x)==False), ForAll([u,y], L(y,u)==False) ) 
; which are the same statement up to variable renaming. So
ForAll([x,y], L(x,y)==False)
使用s3,我们可以替换s5中L-,-的所有实例,以获得:

s5=ForAll([x,y,z], Implies (And (p(x,y)==True, L(x,z)==False,L(y,z)==False), L(x,y)==True))
; replacing L(-,-) with False and reducing False==False and False==True gives:
ForAll([x,y,z], Implies (And (p(x,y)==True, True, True), False))
; which is equivalent to
ForAll([x,y], p(x,y)==False)
这与px相矛盾,y==True。注意,这与量词中的x和y绑定不同

一个令人满意的模型是u=x=y=z=i=j=0和p0,0=False。一旦px,y为假,则可以忽略s1到s5以满足公式要求。我在这里说model有点松散,但希望直觉是清楚的

作为一般建议,我建议重命名由量词绑定的变量以消除歧义。下一行中有3个不同的x和y副本

s.add( Implies (p(x,y)==True, Exists([x,y], And(si1==True,si2==True,si3==True,si4==True,si5==True))) )

px,y中有顶级未绑定的x和y,由Exists[x,y]绑定的版本,。。。没有任何实例,版本绑定在si1到si5中。也许您可以跟踪这一点,但我发现这很难。

我能够更新我的形式化,如下所示,现在我得到了一个满意的解决方案,但仍然无法找到中间节点的不同值:I,j,z

from z3 import*

L= Function('L', IntSort(), IntSort(),BoolSort())
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(And(x>=0, x<=5, y>=0,y<=5, u>=0,u<=5,i>=0,i<=5, j>=0,j<=5,z>=0,z<=5))

#si_1
s.add(ForAll(x,  And( L(x,x)==False,p(x,x)==False )))

#si_2
s.add(ForAll([x,y], And(L(x,y)==L(y,x), p(x,y)==p(y,x))))


#si_3
s.add(ForAll([x,y], Implies(p(x,y)==True,  Exists([i,j,z], And( L(x,i)==True, L(i,j)==True,L(j,z)==True,L(z,y)==True)))))


#si_4
s.add(ForAll([x,y,z], Implies (And (p(x,y)==True, L(x,z)==False,L(y,z)==False), L(x,y)==True) ))


s.add(p(x,y)==True)




result=s.check()
model = s.model()

print result, model
我应该得到I、j和z的不同值,因为si_1确保Lx、x为假:

s.add(ForAll(x,  And( L(x,x)==False,p(x,x)==False )))

我应该改变什么,以便我可以得到不同的I、j、z值,并且它们不应该是相同的…

感谢您的回复Tim,我已经更新了下面的形式化,但我仍然面临一个问题…将问题的更新发布为答案被认为是不好的做法-改为编辑您的原始问题。
    s.add(ForAll([x,y], Implies(p(x,y)==True,  Exists([i,j,z], And( L(x,i)==True, L(i,j)==True,L(j,z)==True,L(z,y)==True)))))
s.add(ForAll(x,  And( L(x,x)==False,p(x,x)==False )))