Z3 returns 型号不可用
Z3 returns model not available
如果可能的话,我希望对我的代码提出第二意见。
问题的约束条件是:
a,b,c,d,e,f
是非零整数
s1 = [a,b,c]
和s2 = [d,e,f]
是集合
i,j = 0..2
的总和 s1_i + s2_j
必须是正方形
我不明白为什么我的代码 returns 模型不可用。此外,在注释掉以下行时:
(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
Edit:插入 (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))
非线性整数运算是不可判定的。这意味着没有决策过程可以决定任意非线性整数约束是否可满足。这就是 z3 在回答您的查询时说 "unknown" 时告诉您的内容。
当然,这并不意味着个别情况无法回答。 Z3 有一些适用于解决此类公式的策略,但它在处理能力方面存在固有的局限性。您的问题属于这一类:Z3 无法解决的问题。
Z3 有一个你可以使用的专用 NRA(非线性实数算术)策略。它实质上将所有变量都视为实数,解决问题(非线性实数算术是可判定的,z3 可以找到所有代数实数解),然后检查结果是否实际上是整数。如果不是,它会尝试另一种解决方案。有时,如果您碰巧找到了正确的解决方案,这种策略可以处理非线性整数问题。您可以使用以下方式触发它:
(check-sat-using qfnra)
不幸的是,在我允许 运行 的时候,它并没有解决您的特定问题。 (超过 10 分钟。)它不太可能找到正确的解决方案。
你真的没有太多选择。 SMT 求解器并不适合非线性整数问题。事实上,正如我上面提到的,由于不可判定性,没有工具可以处理任意非线性整数问题;但有些工具比其他工具效果更好,具体取决于它们使用的算法。
当您告诉 z3 a
和 b
是什么时,您实际上是在消除大部分非线性,其余部分变得容易处理。您可能会找到一系列策略来解决您的原始问题,但这些技巧在实践中非常脆弱,不容易被发现;因为您实质上是在搜索中引入了启发式方法,而您对其行为方式没有太多控制权。
旁注:您的脚本可以稍作改进。要表示一堆数字都是不同的,请使用 distinct 谓词:
(assert (distinct (a b c)))
(assert (distinct (d e f)))
如果可能的话,我希望对我的代码提出第二意见。
问题的约束条件是:
a,b,c,d,e,f
是非零整数s1 = [a,b,c]
和s2 = [d,e,f]
是集合i,j = 0..2
的总和s1_i + s2_j
必须是正方形
我不明白为什么我的代码 returns 模型不可用。此外,在注释掉以下行时:
(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
Edit:插入 (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))
非线性整数运算是不可判定的。这意味着没有决策过程可以决定任意非线性整数约束是否可满足。这就是 z3 在回答您的查询时说 "unknown" 时告诉您的内容。
当然,这并不意味着个别情况无法回答。 Z3 有一些适用于解决此类公式的策略,但它在处理能力方面存在固有的局限性。您的问题属于这一类:Z3 无法解决的问题。
Z3 有一个你可以使用的专用 NRA(非线性实数算术)策略。它实质上将所有变量都视为实数,解决问题(非线性实数算术是可判定的,z3 可以找到所有代数实数解),然后检查结果是否实际上是整数。如果不是,它会尝试另一种解决方案。有时,如果您碰巧找到了正确的解决方案,这种策略可以处理非线性整数问题。您可以使用以下方式触发它:
(check-sat-using qfnra)
不幸的是,在我允许 运行 的时候,它并没有解决您的特定问题。 (超过 10 分钟。)它不太可能找到正确的解决方案。
你真的没有太多选择。 SMT 求解器并不适合非线性整数问题。事实上,正如我上面提到的,由于不可判定性,没有工具可以处理任意非线性整数问题;但有些工具比其他工具效果更好,具体取决于它们使用的算法。
当您告诉 z3 a
和 b
是什么时,您实际上是在消除大部分非线性,其余部分变得容易处理。您可能会找到一系列策略来解决您的原始问题,但这些技巧在实践中非常脆弱,不容易被发现;因为您实质上是在搜索中引入了启发式方法,而您对其行为方式没有太多控制权。
旁注:您的脚本可以稍作改进。要表示一堆数字都是不同的,请使用 distinct 谓词:
(assert (distinct (a b c)))
(assert (distinct (d e f)))