Z3返回模型不可用

时间:2019-01-23 11:22:23

标签: z3

如果可能的话,我想对我的代码发表第二意见。

问题的制约因素是:

  • a,b,c,d,e,f是非零整数
  • s1 = [a,b,c]s2 = [d,e,f]已设置
  • s1_i + s2_j的总和i,j = 0..2必须是一个完美的平方

我不明白为什么,但是我的代码返回的模型不可用。此外,注释掉以下几行时:

(assert (and (> sqrtx4 1) (= x4 (* sqrtx4 sqrtx4))))
(assert (and (> sqrtx5 1) (= x5 (* sqrtx5 sqrtx5))))
(assert (and (> sqrtx6 1) (= x6 (* sqrtx6 sqrtx6))))

(assert (and (> sqrtx7 1) (= x7 (* sqrtx7 sqrtx7))))
(assert (and (> sqrtx8 1) (= x8 (* sqrtx8 sqrtx8))))
(assert (and (> sqrtx9 1) (= x9 (* sqrtx9 sqrtx9))))

d,e,f的值为负。没有任何约束要求他们这样做。我想知道是否可能有一些隐藏的约束潜入并弄乱了模型。

有效的预期解决方案是:

a = 3
b = 168
c = 483
d = 1
e = 193
f = 673

编辑:插入(assert (= a 3))(assert (= b 168))会导致求解器找到正确的值。这只会进一步困扰我。

完整代码:

(declare-fun sqrtx1 () Int)
(declare-fun sqrtx2 () Int)
(declare-fun sqrtx3 () Int)
(declare-fun sqrtx4 () Int)
(declare-fun sqrtx5 () Int)
(declare-fun sqrtx6 () Int)
(declare-fun sqrtx7 () Int)
(declare-fun sqrtx8 () Int)
(declare-fun sqrtx9 () Int)

(declare-fun a     () Int)
(declare-fun b     () Int)
(declare-fun c     () Int)
(declare-fun d     () Int)
(declare-fun e     () Int)
(declare-fun f     () Int)

(declare-fun x1     () Int)
(declare-fun x2     () Int)
(declare-fun x3     () Int)
(declare-fun x4     () Int)
(declare-fun x5     () Int)
(declare-fun x6     () Int)
(declare-fun x7     () Int)
(declare-fun x8     () Int)
(declare-fun x9     () Int)


;all numbers are non-zero integers
(assert (not (= a 0)))
(assert (not (= b 0)))
(assert (not (= c 0)))
(assert (not (= d 0)))
(assert (not (= e 0)))
(assert (not (= f 0)))

;both arrays need to be sets
(assert (not (= a b)))
(assert (not (= a c)))
(assert (not (= b c)))

(assert (not (= d e)))
(assert (not (= d f)))
(assert (not (= e f)))



(assert (and (> sqrtx1 1) (= x1 (* sqrtx1 sqrtx1))))
(assert (and (> sqrtx2 1) (= x2 (* sqrtx2 sqrtx2))))
(assert (and (> sqrtx3 1) (= x3 (* sqrtx3 sqrtx3))))


(assert (and (> sqrtx4 1) (= x4 (* sqrtx4 sqrtx4))))
(assert (and (> sqrtx5 1) (= x5 (* sqrtx5 sqrtx5))))
(assert (and (> sqrtx6 1) (= x6 (* sqrtx6 sqrtx6))))

(assert (and (> sqrtx7 1) (= x7 (* sqrtx7 sqrtx7))))
(assert (and (> sqrtx8 1) (= x8 (* sqrtx8 sqrtx8))))
(assert (and (> sqrtx9 1) (= x9 (* sqrtx9 sqrtx9))))

;all combinations of sums need to be squared
(assert (= (+ a d) x1))
(assert (= (+ a e) x2))
(assert (= (+ a f) x3)) 

(assert (= (+ b d) x4))
(assert (= (+ b e) x5))
(assert (= (+ b f) x6))

(assert (= (+ c d) x7))
(assert (= (+ c e) x8))
(assert (= (+ c f) x9))


(check-sat-using (then simplify solve-eqs smt))
(get-model)
(get-value (a))
(get-value (b))
(get-value (c))
(get-value (d))
(get-value (e))
(get-value (f))

1 个答案:

答案 0 :(得分:3)

非线性整数算法是不确定的。这意味着没有决策程序可以将任意非线性整数约束确定为可满足的。这就是z3告诉您的查询答案时,它告诉您的信息。

这当然并不意味着不能回答个别案件。 Z3具有适用于求解此类公式的某些策略,但是它固有的局限性在于它可以处理的内容。您的问题属于这一类:Z3不能解决的问题。

Z3具有您可以利用的专用NRA(非线性实数)策略。它本质上将所有变量视为实数,解决了问题(非线性实数是可判定的,并且z3可以找到所有代数实数解),然后检查结果是否实际上是整数。如果没有,它将尝试其他的解决方案。如果您碰巧找到了正确的解决方案,则有时这种策略可以处理非线性整数问题。您可以使用以下方式触发它:

(check-sat-using qfnra)

不幸的是,在我允许它运行时,它不能解决您的特定问题。 (超过10分钟。)不太可能找到正确的解决方案。

您这里确实没有太多选择。 SMT求解器不适用于非线性整数问题。实际上,如上所述,由于不确定性,没有工具可以处理任意非线性整数问题。但是某些工具的效果要好于其他工具,具体取决于它们使用的算法。

当您告诉z3 ab是什么时,您实际上就消除了大部分非线性,其余的则变得易于处理。您可能会找到可以解决原始问题的一系列应用策略,但是这些技巧在实践中非常脆弱,不容易发现;因为您实质上是在搜索中引入启发式方法,但对其行为没有太多控制权。

侧面说明:您的脚本可以稍作改进。要表达一堆数字都是不同的,请使用不同的谓词:

(assert (distinct (a b c)))
(assert (distinct (d e f)))