以下代码
(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)
返回"未知"。换句话说,涉及乘法的实数组元素上的任何非线性代数表达都是不可解的:'(
答案 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年的相关讨论。
即使你摆脱了未解释的功能,只要你混合unknown
和Int
类型和非线性术语,你仍然会在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))")
因此,混合类型和非线性术语会出现问题。