Z3返回的模型不可用

Z3返回的模型不可用,z3,Z3,如果可能的话,我想对我的代码发表第二个意见 这一问题的制约因素有: a、b、c、d、e、f是非零整数 s1=[a,b,c]和s2=[d,e,f]是集合 i,j=0..2的和s1_i+s2_j必须是一个完美的平方 我不明白为什么,但我的代码返回的模型不可用。此外,在注释以下行时: (assert (and (> sqrtx4 1) (= x4 (* sqrtx4 sqrtx4)))) (assert (and (> sqrtx5 1) (= x5 (* sqrtx5 sqrtx5)

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

这一问题的制约因素有:

  • a、b、c、d、e、f
    是非零整数
  • s1=[a,b,c]
    s2=[d,e,f]
    是集合
  • i,j=0..2
    的和
    s1_i+s2_j
    必须是一个完美的平方
我不明白为什么,但我的代码返回的模型不可用。此外,在注释以下行时:

(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(=a3))
(assert(=b168))
将导致解算器找到正确的值。这让我更加困惑

完整代码:

(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告诉您的,当它说“未知”作为您查询的答案时

当然,这并不意味着个别案件无法得到答复。Z3在解决这些公式时采用了某些策略,但它在处理问题方面存在固有的局限性。您的问题属于这一类:Z3无法解决的问题

Z3有一个专门的NRA(非线性实数算术)策略,您可以利用它。它本质上将所有变量视为实数,解决问题(非线性实数算法是可判定的,z3可以找到所有代数实数解),然后检查结果是否为整数。如果没有,它会在reals上尝试另一种解决方案。有时,如果您碰巧找到了正确的解决方案,这种策略可以处理非线性整数问题。您可以使用以下方法触发它:

(check-sat-using qfnra)
不幸的是,在我允许它运行的时间内,它并没有解决您的特定问题。(超过10分钟)不太可能找到正确的解决方案

你真的没有很多选择。SMT解算器并不适合处理非线性整数问题。事实上,正如我上面提到的,由于不可判定性,没有任何工具可以处理任意非线性整数问题;但一些工具的表现要好于其他工具,这取决于它们使用的算法

当你告诉z3什么是
a
b
时,你基本上消除了很多非线性,其余的变得容易处理。你可以找到一系列的战术来解决你原来的问题,但是这些技巧在实践中非常脆弱,不容易被发现;因为您基本上是在搜索中引入启发式,而您无法控制其行为

旁注:您的脚本可以稍微改进。要表示一组数字都是不同的,请使用distinct谓词:

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

这是一个很好的答案,非常感谢。这(可悲的)完全有道理,这是我一直担心的。我实际上已经尝试过qnfra选项,但在1小时后没有任何效果。。。我会尝试另一种方法,线性银似乎不是正确的方法。我想你会在你的答案中建议一些向量编码(:Patrick:我很确定他们在寻找整数算法。模块化算法肯定会找到与实际解决方案空间无关的解决方案。我想,设置+约束上的位对于虚假解决方案来说是一个足够好的对策。可能需要再考虑一下。比你更重要;)帕特里克:也许可以使用Z3的“溢出/下溢”谓词(作为SMTLib扩展)通过位向量来陈述和获得结果。但是,根据我的经验,除非你已经对解决方案的位置有了很好的了解,否则它很快就会变成一个永无止境的附加约束来取缔错误的模型。我想知道是否有一个普遍适用的技巧,尽管我怀疑它是否存在。