我有一个程序在非线性实数算术中生成一组约束。考虑以下两个约束:
(<( - ( - ( - (+(*( - v0_x v3_x)) ( - v1_y v3_y) (+(*( - v2_x v3_x)( - v2_x v3_x)) (*( - v2_y v3_y)( - v2_y v3_y)))) (*( - v0_y v3_y) ( - v2_x v3_x) (+(*( - v1_x v3_x)( - v1_x v3_x)) (*( - v1_y v3_y)( - v1_y v3_y)))) (*( - v1_x v3_x) ( - v2_y v3_y) (+(*( - v0_x v3_x)( - v0_x v3_x)) (*( - v0_y v3_y)( - v0_y v3_y))))) (*( - v1_y v3_y) ( - v2_x v3_x) (+(*( - v0_x v3_x)( - v0_x v3_x)) (*( - v0_y v3_y)( - v0_y v3_y))))) (*( - v0_y v3_y) ( - v1_x v3_x) (+(*( - v2_x v3_x)( - v2_x v3_x))(*( - v2_y v3_y)( - v2_y v3_y)))))) (*( - v0_x v3_x) ( - v2_y v3_y) (+(*( - v1_x v3_x)( - v1_x v3_x))(*( - v1_y v3_y)( - v1_y v3_y))))) 0)
(>( - ( - ( - (+(*( - v0_x v2_x)) ( - v1_y v2_y) (+(*( - v3_x v2_x)( - v3_x v2_x)) (*( - v3_y v2_y)( - v3_y v2_y)))) (*( - v0_y v2_y) ( - v3_x v2_x) (+(*( - v1_x v2_x)( - v1_x v2_x)) (*( - v1_y v2_y)( - v1_y v2_y)))) (*( - v1_x v2_x) ( - v3_y v2_y) (+(*( - v0_x v2_x)( - v0_x v2_x)) (*( - v0_y v2_y)( - v0_y v2_y))))) (*( - v1_y v2_y) ( - v3_x v2_x) (+(*( - v0_x v2_x)( - v0_x v2_x)) (*( - v0_y v2_y)( - v0_y v2_y))))) (*( - v0_y v2_y) ( - v1_x v2_x) (+(*( - v3_x v2_x)( - v3_x v2_x))(*( - v3_y v2_y)( - v3_y v2_y)))))) (*( - v0_x v2_x) ( - v3_y v2_y) (+(*( - v1_x v2_x)( - v1_x v2_x))(*( - v1_y v2_y)( - v1_y v2_y)))))) 0)
当我将它们断言为Z3时,它表示它是可以满足的,但是只要我将第二个约束改为(< ... 0)而不是(> ... 0),现在应该是不可满足的,z3永远运行。我想知道z3在处理非线性实数算术时的局限性。 Z3是否有可能处理上述限制(例如改变它们的制定方式或任何其他方式)?
答案 0 :(得分:4)
是的,当我们将(< ... 0)
更改为(> ... 0)
时,问题就变得不可理解了,并且有一个简单的证明,因为它变为p < 0 and p > 0
。简化后,帖子中的两个多项式是相同的。然而,Z3错过了这个简单的证明。这将在下一版本中修复。与此同时,我们可以通过使用自定义策略来捕获具有此类简单证据的示例。
(check-sat-using (then (! simplify :som true) (! simplify :sort-sums true) smt))
此策略执行多项式规范化并调用检测p < 0
和p > 0
中的不一致性的引擎。整个示例可在线获取:http://rise4fun.com/Z3/JP4。我还在信息的最后粘贴了它。
Z3一直在运行,因为它错过了简短的证据,并试图使用更昂贵和完整的方法找到证据。 Z3使用的算法描述为here。该算法使用基于subresultants的投影算子。此操作非常昂贵,并为您的示例生成非常大的多项式。这个过程适用于包含小多项式的问题,每个小多项式都有一小组变量。在未来,我们计划将完整和不完整的技术结合起来,并改善Z3在合理的时间内可以解决的问题集。
(declare-const v0_x Real)
(declare-const v1_x Real)
(declare-const v2_x Real)
(declare-const v3_x Real)
(declare-const v4_x Real)
(declare-const v0_y Real)
(declare-const v1_y Real)
(declare-const v2_y Real)
(declare-const v3_y Real)
(declare-const v4_y Real)
(assert
(< (- (- (- (+ (* (- v0_x v3_x) (- v1_y v3_y) (+ (* (- v2_x v3_x) (- v2_x v3_x)) (* (- v2_y v3_y) (- v2_y v3_y)))) (* (- v0_y v3_y) (- v2_x v3_x) (+ (* (- v1_x v3_x) (- v1_x v3_x)) (* (- v1_y v3_y) (- v1_y v3_y)))) (* (- v1_x v3_x) (- v2_y v3_y) (+ (* (- v0_x v3_x) (- v0_x v3_x)) (* (- v0_y v3_y) (- v0_y v3_y))))) (* (- v1_y v3_y) (- v2_x v3_x) (+ (* (- v0_x v3_x) (- v0_x v3_x)) (* (- v0_y v3_y) (- v0_y v3_y))))) (* (- v0_y v3_y) (- v1_x v3_x) (+ (* (- v2_x v3_x) (- v2_x v3_x)) (* (- v2_y v3_y) (- v2_y v3_y))))) (* (- v0_x v3_x) (- v2_y v3_y) (+ (* (- v1_x v3_x) (- v1_x v3_x)) (* (- v1_y v3_y) (- v1_y v3_y))))) 0.0))
(assert
(< (- (- (- (+ (* (- v0_x v2_x) (- v1_y v2_y) (+ (* (- v3_x v2_x) (- v3_x v2_x)) (* (- v3_y v2_y) (- v3_y v2_y)))) (* (- v0_y v2_y) (- v3_x v2_x) (+ (* (- v1_x v2_x) (- v1_x v2_x)) (* (- v1_y v2_y) (- v1_y v2_y)))) (* (- v1_x v2_x) (- v3_y v2_y) (+ (* (- v0_x v2_x) (- v0_x v2_x)) (* (- v0_y v2_y) (- v0_y v2_y))))) (* (- v1_y v2_y) (- v3_x v2_x) (+ (* (- v0_x v2_x) (- v0_x v2_x)) (* (- v0_y v2_y) (- v0_y v2_y))))) (* (- v0_y v2_y) (- v1_x v2_x) (+ (* (- v3_x v2_x) (- v3_x v2_x)) (* (- v3_y v2_y) (- v3_y v2_y))))) (* (- v0_x v2_x) (- v3_y v2_y) (+ (* (- v1_x v2_x) (- v1_x v2_x)) (* (- v1_y v2_y) (- v1_y v2_y))))) 0.0))
(check-sat-using (then (! simplify :som true) (! simplify :sort-sums true) smt))