在Z3中,在阵列理论中描述这个的最有效方法是什么?

时间:2013-01-14 11:12:04

标签: arrays z3

我想用Z3描述以下问题。

int []array1=new int[100];
int []array2=new int[100];
array1[0~99]={i0, i1, ..., i99}; (i0...i99 > 0)
array2[0~99]={j0, j1, ..., j99}; (j0...j99 < 0)
int i, j; (0<=i<=99, 0<=j<=99)
does array1[i]==array2[j]?

这是不可接受的。

我使用Z3来描述这个问题如下:

(declare-const a1 (Array Int Int))
(declare-const a2 (Array Int Int))
(declare-const a1f (Array Int Int))
(declare-const a2f (Array Int Int))
(declare-const x0 Int)
....    
(declare-const x99 Int)
(assert (> x0 0))
....
(assert (> x99 0))
(declare-const y0 Int)
....    
(declare-const y99 Int)
(assert (< y0 0))
....
(assert (< y99 0))
(declare-const i1 Int)
(declare-const c1 Int)
(assert (<= i1 99))
(assert (>= i1 0))

(declare-const i2 Int)
(declare-const c2 Int)
(assert (<= i2 99))
(assert (>= i2 0))
(assert (= a1f (store (store (store (store (store (store (store (store ........ 95 x95) 96 x96) 97 x97) 98 x98) 99 x99)))
(assert (= a2f (store (store (store (store (store (store (store (store ........ 95 y95) 96 y96) 97 y97) 98 y98) 99 y99)))

(assert (= c1 (select a1f i1)))
(assert (= c2 (select a2f i2)))
(assert (= c1 c2))
(check-sat)

是不是? 是否有其他更有效的方法来描述这个使用数组理论? 我的意思是,更有效的方式需要更少的Z3解决时间。 感谢。

1 个答案:

答案 0 :(得分:3)

为了解决这个问题,Z3将使用暴力方法,它将基本上尝试所有可能的组合。它无法找到我们(作为人类)立即看到的“智能”证据。 在我的机器上,解决大小为100的阵列需要大约17秒,对于大小为50的阵列大约需要2.5秒,对于大小为10的阵列需要0.1秒。

但是,如果我们使用量词编码问题,它可以即时证明任何数组大小,我们甚至不需要指定固定的数组大小。 在此编码中,我们对i[0, N)a1[i] > 0中的所有a2[i] < 0说明。然后,我们说我们想在j1 s.t中找到j2[0, N)a1[j1] = a2[j2]。 Z3将立即返回unsat。以下是使用Z3 Python API编码的问题。 It is also available online at rise4fun

a1 = Array('a1', IntSort(), IntSort())
a2 = Array('a2', IntSort(), IntSort())
N  = Int('N')
i  = Int('i')
j1  = Int('j1')
j2  = Int('j2')
s = Solver()
s.add(ForAll(i, Implies(And(0 <= i, i < N), a1[i] > 0)))
s.add(ForAll(i, Implies(And(0 <= i, i < N), a2[i] < 0)))
s.add(0 <= j1, j1 < N)
s.add(0 <= j2, j2 < N)
s.add(a1[j1] == a2[j2])
print s
print s.check()

在上面的编码中,我们使用量词来总结Z3在编码中无法自行解决的信息。事实上,[0, N)一个数组中的索引只有正值,另一个只有负值。