在Z3,get-value
只允许用户参考“全球性”的声明。 存在变量x
是一个本地声明。因此,无法使用get-value
进行访问。 默认情况下,Z3使用称为“skolemization”的过程消除存在变量。 这个想法是用新的常量和函数符号代替存在变量。 例如,式
exists x. forall y. exists z. P(x, y, z)
被转换成
forall y. P(x!1, y, z!1(y))
注意在于Z变的函数,因为z的选择可取决于年。 Wikipedia上有一个条目skolem normal form
这就是说,我从来没有找到你所描述的问题的令人满意的解决方案。 例如,一个公式可能有许多不同的具有相同名称的存在变量。 因此,不清楚如何以非模棱两可的方式引用get-value
命令中的每个实例。
此限制的一个可能的解决方法是“手动”应用skolemization步骤,或者至少为您想知道值的变量。 例如,
(assert (exists ((x (_ BitVec 16))) (forall ((y (_ BitVec 16))) (bvuge y x))))
被写为:
(declare-const x (_ BitVec 16))
(assert (forall ((y (_ BitVec 16))) (bvuge y x)))
(check-sat)
(get-value x)
如果存在变量嵌套在一个通用的量词如:
(assert (forall ((y (_ BitVec 16))) (exists ((x (_ BitVec 16))) (bvuge y x))))
(check-sat)
(get-model)
一个新鲜斯科伦函数可以用来获得每个y
的值x
。 上面的例子变成:
(declare-fun sx ((_ BitVec 16)) (_ BitVec 16))
(assert (forall ((y (_ BitVec 16))) (bvuge y (sx y))))
(check-sat)
(get-model)
在这个例子中,是sx
新鲜功能。该模型由Z3生产,将指派一名口译sx
。在3.0版中,解释是身份函数。此功能可用于获得x
每个y
的值。
感谢莱昂纳多..这是一个特别漂亮的把戏如果existentials先共性,在这种情况下skolemization是微不足道的。 在嵌套/交替量词一般情况下,一个更好的解决方案可能是用户“标记”他们在某些明确的方式,类似于ACL2提示。我想应该由用户来确保节点是唯一标记的。类似于(伪SMT-Lib2语法): '存在((x(_ BitVec 16):model_name“x”))...' 这可能破坏纯SMT-Lib兼容性,但它可能是一种好无论如何Z3是如何推动边界的妥协。 –
感谢您的建议。我会考虑未来版本的Z3的可能性。然而,用户将不具有在由Z3产生的斯科伦功能符号的签名控制。 Z3在skolemization之前执行许多简化,并且skolemization步骤试图最小化通用变量的依赖性数量。 我用一个关于如何提取嵌套在通用量词中的存在变量的例子更新了我的答案。 –