不满意模型的性能问题

时间:2011-10-27 09:18:44

标签: z3 smt

我正在使用Z3来构建有界模型检查器。在尝试实现完整性测试时,我遇到了一个奇怪的性能问题。完整性测试必须确保每个路径最多包含一次状态的所有状态。如果仍然存在满足此属性的路径,则Z3快速得到答案,但是在考虑了所有路径的情况下,Z3似乎呈指数级缓慢。

我已将测试用例减少到以下内容:

; Set the problem size (length of path)
(define-fun sz () Int 5)

; Used to define valid states
(define-fun limit ((s Int)) Bool
  (and (>= s 0)
       (<= s sz)))

; Constructs a path of a given length
(define-fun path-of-len ((path (Array Int Int)) (len Int)) Bool
  (forall ((i Int))
          (=> (and (>= i 0)
                   (< i len))
          (limit (select path i)))))

; Asserts that a given path only contains unique states
(define-fun loop-free ((path (Array Int Int)) (len Int)) Bool
  (forall ((i Int) (j Int))
          (=> (and (>= i 0)
                   (>= j 0)
                   (< i len)
                   (< j len)
                   (not (= i j)))
              (not (= (select path i) (select path j))))))

; Construct a unique path of a given length
(define-fun path ((path (Array Int Int)) (len Int)) Bool
  (and (path-of-len path len)
       (loop-free path len)))

; Declare a concrete path
(declare-const tpath (Array Int Int))

; Assert that the path is loop free
(assert (path tpath (+ sz 2)))

(check-sat)

在我的计算机上,这会导致以下运行时间(取决于路径长度):

  • 3:0.057s
  • 4:0.561s
  • 5:42.602s
  • 6:> 15m(已中止)

如果我从Int切换到64位的位向量,性能会好一点,但仍然看似指数:

  • 3:0.035s
  • 4:0.053s
  • 5:0.061s
  • 6:0.106s
  • 7:0.467s
  • 8:1.809s
  • 9:2m49.074s

奇怪的是,长度为10只需要2m34.197s。 如果我切换到较小尺寸的位向量,性能会好一点,但仍然呈指数级。

所以我的问题是:这是预期的吗?是否有更好的方法来制定这种“无循环”约束?

2 个答案:

答案 0 :(得分:1)

你的公式基本上编码了“鸽子洞”问题。 您有sz+1个洞(值0,1,...,sz)和sz+2鸽子(阵列单元格(select tpath 0),...,(select tpath (+ sz 1)))。 你首先量词是说每只鸽子应该放在其中一个洞里。 第二个是说两只不同的鸽子不应该在同一个洞里。

“鸽子洞”问题没有多项式大小分辨率证明。 因此,预计运行时间将呈指数增长。 请注意,基于分辨率,DPLL或CDCL的任何SAT求解器都会对鸽笼问题表现不佳。

使用位向量时,您可以获得更好的性能,因为Z3将它们缩减为命题逻辑,并且案例分析在该级别上更有效。

顺便说一句,您使用量词来编码参数问题。 这是一个优雅的解决方案,但它不是Z3最有效的方法。 对于Z3,一般来说,断言“扩展”量词免费问题更好。 但是,对于你问题中描述的问题,它不会产生很大的不同,因为你仍然会经历指数增长。

答案 1 :(得分:0)

就像莱昂纳多所说的那样,由于鸽笼问题本质上是指数级的,所以表现最终会变坏。你可能做的唯一事情是推迟表现糟糕的时间。既然你已经尝试了位向量,我的建议是尝试将问题转换为莱昂纳多建议的无量词问题,因为问题大小是预先定义的,并尝试使用一些策略。