具有未解释函数的乘积的方程在Z3中是不可解的

时间:2017-03-31 18:59:57

标签: z3

以下代码

(declare-fun f (Int) Real)
(declare-fun g (Int) Real)
(declare-const x Int)
(declare-const y Int)
(assert (= (* (f x) (g y)) 1.0))
(check-sat)
(get-model)

返回"未知",即使有明显的解决方案。消除f和g的参数(有效地使它们成为常数?)导致" sat"预期的任务。我想,我的问题是:有关未解释函数的算术有什么特别之处?

顺便说一下,用+替换*也会导致" sat",所以问题不在于未解释的函数本身,而在于它们如何组合。

其他想法

使域(非常)有限无济于事,例如,

(declare-fun f (Bool) Real)
(declare-fun g (Bool) Real)
(declare-const x Bool)
(declare-const y Bool)
(assert (= (* (f x) (g y)) 1.0))
(check-sat)
(get-model)

返回"未知"。这是奇怪的,因为f:Bool-> Real基本上只是两个变量f(False)和f(True)(当然,解算器必须认识到这一点)。

无法处理实值未解释函数的非线性算法是一个非常严重的限制,因为数组是作为未解释的函数实现的。所以,例如,

(declare-const a (Array Int Real))
(assert (= (* (select a 1) (select a 1)) 1))
(check-sat)
(get-model)

返回"未知"。换句话说,涉及乘法的实数组元素上的任何非线性代数表达都是不可解的:'(

1 个答案:

答案 0 :(得分:2)

乘法引入的非线性使问题难以解决,而不是未解释的函数。实际上,您可以使用get-info命令询问解算器的原因:

(set-logic QF_UFNIRA)
(declare-fun f (Int) Real)
(declare-fun g (Int) Real)
(declare-const x Int)
(declare-const y Int)
(assert (= (* (f x) (g y)) 1.0))
(check-sat)
(get-info :reason-unknown)

以下是我从各种解决方案中得到的一些回复:

Z3:

(:reason-unknown smt tactic failed to show goal to be sat/unsat (incomplete (theory arithmetic)))

CVC4:

(:reason-unknown incomplete)

MathSAT:

(error "sat, but with non-linear terms")

因此,当求解器本身改进并开始处理更多的非线性算法时,最终可能得到模型。但是,一般而言,非线性问题总是存在问题,因为当涉及整数时它们是不可判定的。 (因为你可以使用非线性项来编码丢番图方程。)

另请参阅How does Z3 handle non-linear integer arithmetic?,了解2012年的相关讨论。

删除未解释的函数

即使你摆脱了未解释的功能,只要你混合unknownInt类型和非线性术语,你仍然会在Real的土地上:

(set-logic QF_NIRA)
(declare-const f Real)
(declare-const g Real)
(declare-const x Int)
(declare-const y Int)
(assert (= (+ (* f g) (to_real (+ x y))) 1.0))
(check-sat)
(get-info :reason-unknown)

Z3说:

(:reason-unknown "smt tactic failed to show goal to be sat/unsat (incomplete (theory arithmetic))")

因此,混合类型和非线性术语会出现问题。