给出以下输入
(set-option :auto_config false)
(set-option :smt.mbqi false)
(declare-fun len (Int) Int)
(declare-fun idx (Int Int) Int)
(declare-const x Int)
(define-fun FOO () Bool
(forall ((i Int)) (!
(implies
(and (<= 0 i) (< i (len x)))
(exists ((j Int)) (!
(implies
(and (<= 0 j) (< j (len x)))
(> (idx x j) 0))))))))
(assert FOO)
; (push)
(assert (not FOO))
(check-sat)
; (pop)
; (push)
(assert (not FOO))
(check-sat)
; (pop)
Z3 4.3.2 x64报告unsat
表示第一个check-sat
(正如预期的那样),但unknown
表示第二个push
。如果评论的pop
/ check-sat
已取消注释,则unknown
生成check-sat
。
我的猜测是,这是一个错误,或者是Z3在达到第二个check-sat
时切换到增量模式的结果。后者也可以解释为什么unknown
如果使用push
/ pop
会产生push
,因为Z3(据我所知)会在第一个{切换到增量模式{ {1}}。
问题:这是错误还是预期后果?
答案 0 :(得分:2)
很好的例子。
这是Z3如何处理公式的限制: 1.当使用push / pop时,它不会检测断言的公式之间的矛盾,而是将公式转换为否定的正规形式,并将量化的公式简化。 2.当第二次呼叫check-sat时,它不会跟踪状态是否从先前不可满足的状态撤回。
这不是一个不健全的错误,但确定行为不是用户期望的行为。
答案 1 :(得分:2)
除了Nikolaj的回答:是的,这是因为Z3切换到另一个解算器,这将更早放弃。我们可以通过设置(set-option :combined_solver.ignore_solver1 true)
来获得相同的效果。