我想检查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()
关于我可以做什么的任何建议?
答案 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()
在变量列表较长或变量已在列表中的情况下,具有可读性。