z3py:如何在z3py中表示整数或字符数组

时间:2015-02-20 20:57:49

标签: arrays z3 smt z3py

我是z3py和SMT的新手,我还没有找到关于z3py的好教程。

以下是我的问题设置:

给定输入整数数组I = [1,2,3,4,5],输出整数数组O = [1,2,4,5]。

我想推断运算符Delete的k,它删除数组中位置k的元素,其中

Delete(I,O) =  (ForAll 0<=x<k, O[x] = I[x] ) and (ForAll k<=x<length(I)-1, O[x] = I[x+1]) is true

我应该使用Array或IntVector或其他任何东西来表示输入/输出数组吗?

修改

我的代码如下:

from z3 import *

k=Int('k')
s=Solver()

x = Int('x')
y = Int('y')

s.add(k >= 0)
s.add(k < 4)    
s.add(x >= 0)
s.add(x < k)
s.add(y >= k)
s.add(y < 4)

I = Array('I',IntSort(),IntSort())
O = Array('O',IntSort(),IntSort())
Store(I, 0, 1)
Store(I, 1, 2)
Store(I, 2, 3)
Store(I, 3, 4)
Store(I, 4, 5)

Store(O, 0, 1)
Store(O, 1, 2)
Store(O, 2, 4)
Store(O, 3, 5)

s.add(And(ForAll(x,Select(O,x) == Select(I,x)),ForAll(y,Select(O,y) == Select(I,y+1))))
print s.check()
print s.model()

返回

sat
[I = [2 -> 2, else -> 2],
 O = [2 -> 2, else -> 2],
 y = 1,
 k = 1,
 x = 0,
 elem!0 = 2,
 elem!1 = 2,
 k!4 = [2 -> 2, else -> 2]]

我不明白我,O,elem!0,elem!1和k!4是什么意思,这显然不是我的预期。

2 个答案:

答案 0 :(得分:3)

免责声明:我之前几乎没有使用过Z3py,但我已经使用过Z3了。

我觉得你对编码逻辑问题有些新意 - 可能是吗?你的问题中有几件(奇怪的)事情发生了。

  1. 您在xy上设置了约束,但实际上您从未使用它们 - 而是绑定不同的 x和{{1在量化的断言中。后两者可能具有相同的名称,但它们与您约束的yx完全无关(因为每个forall绑定其自己的变量,您也可以在两者中使用y )。因此,您量化的xx范围超过了所有y,而您可能希望将它们限制在Int区间。在forall中使用暗示。

  2. 根据文档,[0..4) 返回Store(a, i, v)相同的新数组a'a除外。也就是说,您需要调用x[i] == v等,以便最终获得存储所需值的数组I = Store(I, 0, 1)

  3. 由于您不这样做,Z3可以自由选择满足您约束条件的模型。正如您从输出中看到的那样,I的模型为I,其中[2 -> 2, else -> 2]I[2] == 2代表任何I[i] == 2。我不知道为什么Z3选择了那个特定的模型,但它(与i != 2的模型一起)满足了你的需要。

  4. 您可以忽略Oelem!0elem!1,它们是内部生成的符号。

  5. 以下是无法验证的示例的简化版

    k!4

    它不可满足的原因是x = Int('x')   I = Array('O',IntSort(),IntSort()) O = Array('O',IntSort(),IntSort()) I = Store(I, 0, 1) I = Store(I, 1, 2) s.add( And( ForAll(x, Select(O,x) == Select(I,x)), ForAll(x, Select(O,x) == Select(I,x+1)))) print s.check() # UNSAT ,这与你的矛盾相矛盾。如果您使用I[0] == 1 && I[1] == 2实例化量化x,则得到0 - 无法满足的约束,即O[0] == I[0] && O[0] == I[1]没有满足它的模型。


  6. 修改(以发表评论):

    如果你感到困惑,给出一个像

    这样的片段
    O

    Z3报告I = Array('O',IntSort(),IntSort()) I = Store(I, 0, 1) I = Store(I, 1, 2) # print(I) s.check() s.model() 并返回sat的模型,然后回想起每个I = []返回一个代表商店操作的新Z3表达式,每个表达式又返回一个新数组(等于初始值,以更新为模)。正如Store(...)所示,print的最终值是表达式I。因此,让Store(Store(I, 0, 1), 1, 2)本身成为空数组就足够了,即I - 更新(I s)将各自产生一个新数组(想象Store和{{ 1}}在这种情况下),但由于它们是无名的,它们不会(或至少不必)显示在模型中。

    如果要在模型中显式查看数组的“最终”值,可以通过为最后I1创建的数组指定名称来实现此目的,例如

    I2

答案 1 :(得分:1)

这是我的问题的正确答案:

from z3 import *

x = Int('x')  
y = Int('y')
k = Int('k')

s = Solver()

I = Array('I',IntSort(),IntSort())
O = Array('O',IntSort(),IntSort())
I = Store(I, 0, 1)
I = Store(I, 1, 2)
I = Store(I, 2, 3)
I = Store(I, 3, 4)
I = Store(I, 4, 5)

O = Store(O, 0, 1)
O = Store(O, 1, 2)
O = Store(O, 2, 4)
O = Store(O, 3, 5)

s.add(k >= 0)
s.add(k < 4)
s.add(And(ForAll([x],Implies(And(x>=0,x<k),Select(O,x) == Select(I,x))),ForAll([y],Implies(And(y>=k,y<4),Select(O,y) == Select(I,y+1)))))
print s.check()
if s.check() == z3.sat:
    print s.model()

答案是

sat
[I = [2 -> 2, else -> 2],
 k = 2,
 O = [2 -> 2, else -> 2],
 k!17 = [2 -> 2, else -> 2]]