Z3:用量词建模

Z3: Modeling with Quantifiers

我想用z3证明(∀i(0≤i<k→a[i]>0)∧a[k]>0)→∀i(0≤i≤k→a[i]>0)。它的否定是:∀i(0≤i<k→a[i]>0)∧a[k]>0∧∃i(0≤i≤k∧¬(a[i]>0))。首先,我将 k 的值设置为 5 并忽略 a[k]>0 部分,然后尝试:

from z3 import *
i = Int('i')`
a = Array('a',IntSort(),IntSort())
solver = Solver()
solver.add(ForAll(i, Implies(And(i >= 0,i < 5),a[i] > 0)))
solver.add(Exists(i, And(i >= 0,i <= 5, Not(a[i] > 0))))
print solver.check()
print solver.model()

输出为:

sat
[i!0 = 5,
a = [else -> k!8!10(k!9(Var(0)))],
k!8 = [else -> k!8!10(k!9(Var(0)))],
k!9 = [else -> If(Var(0) >= 4, If(Var(0) >= 5, 5, 4), 0)],
k!8!10 = [0 -> 7720, 4 -> 1, else -> -38]]

我不知道输出的意思,我想它的模型应该是i = 5。然后,我加上a[5] > 0,我想应该是不满足吧。代码如下:

from z3 import *
i = Int('i')
a = Array('a',IntSort(),IntSort())
solver = Solver()
solver.add(ForAll(i, Implies(And(i >= 0,i < 5),a[i] > 0)))
solver.add(Exists(i, And(i >= 0,i <= 5, Not(a[i] > 0))))
solver.add(a[5] > 0)
print solver.check()
print solver.model()

输出为:

unsat

那么,我如何通过z3py证明(∀i(0≤i<k→a[i]>0)∧a[k]>0)→∀i(0≤i≤k→a[i]>0),输出的含义是什么?

我有点不清楚你想用你的查询做什么。你为什么"set"k的值?根据问题的开头,这似乎与您要证明的一般情况不符,但也许您现在只对特殊情况感兴趣。

您已正确地将有效性问题转变为可满足性问题:公式的否定是可满足的,前提是原始公式有效。

在Z3的第一个回复中,确实得到了模型;这表示您试图证明的(较弱的)第一个蕴涵的反例。如果你想想这个反例的演示需要什么,你不得不选择将(绑定的)存在变量实例化为5。这就是模型中i!0的意义;它是一个新的(免费的)名称,代表存在绑定变量被分配到的模型元素。

从另一个角度来看(更准确地说,关于工具的作用),存在量词在 Z3 之前 "skolemised" 已经消失(存在绑定变量被新常量替换)有趣的工作,所以它实际上是在处理一个等同于查询公式可满足性的查询:

∀i(0≤i<k→a[i]>0)∧a[k]>0∧(0≤ i!0 ≤k∧¬(a[ i!0 ]>0))

当您将查询加强到原始蕴涵的否定时,您会从 Z3 中得到不满意。这意味着这个否定的公式是不可满足的,所以你感兴趣的蕴涵是有效的;你已经证明 ∀i(0≤i<5→a[i]>0)∧a[5]>0)→∀i(0≤i≤5→a[i]>0)

如果您在问题中跳过将 k 设置为 5,您应该会得到相同的结果。

关于 Z3 的第一个响应中的其他信息,模型不仅必须包含 (skolemised) i 的值,还必须包含问题中数组 a 的值。数组被表示为函数,可以在这样的模型中由案例定义; "else" 案例是包罗万象的,也是此处使用的每个函数中唯一的案例。 Var(0) 是函数的(第一个也是唯一的)参数的语法。在这个模型中,数组是通过其他两个函数的组合间接定义的,k!9(它似乎用于标识与模型相关的部分索引集;在本例中为 0,4 和 5),以及k!8!10(它定义了这些索引到值的映射)。特别是,在这个模型中,数组在索引 0 处存储 7720,在索引 4 处存储 1,在索引 5 处存储 -38(k!9 定义的情况下不会产生其他索引;从概念上讲,我会理解这意味着此模型中的数组在其他索引处未定义)。