在z3中迭代添加

时间:2019-10-30 17:19:33

标签: z3 z3py

我想检查a,b,c的值,如果值“ a”等于1,则将“ x”加1。我们继续执行值“ b”和“ c”的过程。 因此,如果a = 1,b = 1,c = 1,则x的结果应为3。 如果a = 1,b = 1,c = 0,则x的结果应为2。 在z3中要实现什么方法? 源代码如下:

from z3 import *

a, b, c = Ints('a b c')
x, y = Ints('x y')
s = Solver()
s.add(If(a==1, x=x + 1, y = y-1))
s.add(If(b==1, x=x + 1, y = y-1))
s.add(If(c==1, x=x + 1, y = y-1))
s.check()
print s.model()

关于我可以做什么的任何建议?

2 个答案:

答案 0 :(得分:1)

通常通过展开分配并创建所谓的SSA表单来对这种“迭代”处理进行建模。 (静态单次分配。)在这种格式下,每个变量只分配一次,但是可以多次使用。通常这是由一些基础工具完成的,因为它相当繁琐,但是您也可以手动完成。应用于您的问题,它看起来像:

from z3 import *

s = Solver()

a, b, c = Ints('a b c')

x0, x1, x2, x3 = Ints('x0 x1 x2 x3')

s.add(x0 == 0)
s.add(x1 == If(a == 1, x0+1, x0))
s.add(x2 == If(b == 1, x1+1, x1))
s.add(x3 == If(c == 1, x2+1, x2))

# Following asserts are not part of your problem, but
# they make the output interesting
s.add(b == 1)
s.add(c == 0)

# Find the model
if s.check() == sat:
   m = s.model()
   print("a=%d, b=%d, c=%d, x=%d" % (m[a].as_long(), m[b].as_long(), m[c].as_long(), m[x3].as_long()))

else:
    print "no solution"

SSA转换应用于变量x,并创建为分配分配建模所需的尽可能多的实例。运行时,该程序将产生:

a=0, b=1, c=0, x=1

希望有帮助!

答案 1 :(得分:0)

请注意,z3具有许多功能。您可以在这里使用的是Sum()作为列表的总和。在列表内,您可以放置​​简单变量,也可以放置表达式。这是一个简单和更复杂的总和的示例:

from z3 import *

a, b, c = Ints('a b c')
x, y = Ints('x y')
s = Solver()
s.add(a==1, b==0, c==1)
s.add(x==Sum([a,b,c]))
s.add(y==Sum([If(a==1,-1,0),If(b==1,-1,0),If(c==1,-1,0)]))
if s.check() == sat:
    print ("solution:", s.model())
else:
    print ("no solution possible")

结果:     solution: [y = 2, x = 2, c = 1, b = 0, a = 1]

如果您的问题更复杂,则使用BitVecs代替Ints可以使其运行更快。

edit:除了Sum()之外,您还可以像

那样简单地使用加法

s.add(x == a + b + c)   s.add(y == If(a == 1,-1,0)+ If(b == 1,-1,0)+ If(c == 1,-1,0))

Sum()在变量列表较长或变量已在列表中的情况下,具有可读性。