为什么Z3在没有看似微不足道的修改的情况下无法解决这个问题呢?

时间:2015-10-18 08:47:52

标签: z3 smt

最初的问题是:

(declare-const a Real)
(declare-const b Bool)
(declare-const c Int)

(assert (distinct a 0.))

(assert (= b (distinct (* a a) 0.)))

(assert (= c (ite b 1 0)))

(assert (not (distinct c 0)))

(check-sat)

结果未知。

但最后两个约束合在一起,等同于(assert (= b false)),并且在手动执行此重写之后

(declare-const a Real)
(declare-const b Bool)
(declare-const c Int)

(assert (distinct a 0.))

(assert (= b (distinct (* a a) 0.)))

(assert (= b false))

;(assert (= c (ite b 1 0)))

;(assert (not (distinct c 0)))

(check-sat)

Z3现在能够解决这个问题(不太好)。

为什么Z3可以解决第二个实例而不是第一个实例,即使第一个实例可以简化为第二个实例?

修改

在找到问题时,我发现了一些非常奇怪的事情。

Z3解决了以下实例并返回"不良":

(declare-fun a() Real)
(declare-fun b() Bool)
(declare-fun c() Int)

(assert (distinct a 0.0))

(assert (= b (distinct (* a a) 0.0)))

(assert (= b false))

;(assert (= c 0))

(check-sat)

但如果我取消注释(assert (= c 0)),求解器将返回" unknown",即使c=0与上述断言无关。

1 个答案:

答案 0 :(得分:0)

这里的问题是像(* a a)这样的表达式是非线性的,Z3的非线性问题的默认求解器会放弃,因为它认为它太难了。 Z3确实有另一个解算器,但是它的理论组合非常有限,即你不能将它用于混合布尔,位向量,数组等问题,但仅用于算术问题。通过使用(check-sat)替换(check-sat-using qfnra-nlsat)命令,可以轻松进行测试。