Z3 量词与非量词

Z3 量词与非量词,z3,Z3,我有一个关于量词的问题 假设我有一个数组,我想计算这个数组的数组索引0、1和2- (declare-const cpuA (Array Int Int)) (assert (or (= (select cpuA 0) 0) (= (select cpuA 0) 1))) (assert (or (= (select cpuA 1) 0) (= (select cpuA 1) 1))) (assert (or (= (select cpuA 2) 0) (= (select cpuA 2) 1

我有一个关于量词的问题

假设我有一个数组,我想计算这个数组的数组索引0、1和2-

(declare-const cpuA (Array Int Int))
(assert (or (= (select cpuA 0) 0) (= (select cpuA 0) 1))) 
(assert (or (= (select cpuA 1) 0) (= (select cpuA 1) 1))) 
(assert (or (= (select cpuA 2) 0) (= (select cpuA 2) 1)))
或者,我可以使用forall构造指定相同的-

(assert (forall ((x Int)) (=> (and (>= x 0) (<= x 2)) (or (= (select cpuA x) 0) (= (select cpuA x) 1)))))

(assert(forall((x Int))(=>(and(>=x 0)(量词推理通常非常昂贵。在您的示例中,量化公式相当于您提供的三个断言。
然而,这不是Z3决定/求解公式的方式。Z3使用一种称为基于模型的量词实例化(MBQI)的技术来求解公式。
此技术可以决定许多片段(请参阅)。它主要对本指南中描述的片段有效。
它支持未解释的函数、算术和位向量理论,对数组和数据类型的支持也有限。
这足以解决您的示例。Z3生成的模型似乎更复杂,因为使用同一个引擎来确定更复杂的片段。
该模型应被视为一个小型功能程序。您可以在以下文章中找到有关该方法工作原理的更多信息:

请注意,数组理论主要用于表示/建模无界数组或大数组。也就是说,数组的实际大小未知或太大。所谓大,我指的是公式中的数组访问数(即,
选择
)远小于数组的实际大小。我们应该问问自己:“我们真的需要数组来建模/解决问题X吗?”。
  • (未解释)函数而不是数组。您的示例也可以编码为:

    (声明有趣的cpuA(Int)Int)

    (断言(或(=(cpuA 0)0)(=(cpuA 0)1))
    (断言(或(=(cpuA 1)0)(=(cpuA 1)1))
    (断言(或(=(cpuA 2)0)(=(cpuA 2)1)))

  • 编程API。我们已经看到了许多使用数组(和函数)提供紧凑编码的示例。紧凑而优雅的编码不一定更容易解决。实际上,通常情况正好相反。您可以实现两个方面的最佳效果(性能和紧凑性)使用Z3的编程API。在下面的链接中,我为“数组”的每个位置使用一个“变量”对示例进行编码。宏/函数用于编码约束,例如:表达式是
    0
    1


亲爱的莱昂纳多,我又回到了同一个问题。我正在尝试优化sat解算器的代码。你能告诉我什么时候可以使用常量,什么时候可以使用未解释的函数。例如,我的代码中有大约30-40个未解释的函数。例如,当我将一些函数替换为多个常量时mple(xa0)由xA0等替代,我在运行时得到了减少,但对于其他人,我没有得到。在它们之间选择的关键规则是什么?这取决于您在代码中使用它们的程度吗?性能波动是非常常见的。即使我们做了一些小的修改,例如重新排序断言,我们也会观察到波动。任何小的修改y改变Z3遍历搜索空间的顺序。根据经验,我们应该尽可能避免使用量词。如果我们可以使用单一理论对问题进行编码,我们通常会获得更好的性能。当然,我们总是有例外。你观察到了什么样的性能波动?它的数量级是2x、10x、100x?