我正在玩Z3的QBVF求解器,并想知道是否有可能从存在主义断言中提取值。也就是说,让我说我有以下内容:
(assert (exists ((x (_ BitVec 16))) (forall ((y (_ BitVec 16))) (bvuge y x))))
这基本上表示存在“最小”16位无符号值。然后,我可以说:
(check-sat)
(get-model)
Z3-3.0愉快地回应:
sat
(model (define-fun x!0 () (_ BitVec 16)
#x0000)
)
这真的很酷。但我想做的是能够通过get-value提取该模型的各个部分。不出所料,以下似乎都不起作用
(get-value (x))
(get-value (x!0))
在每种情况下,Z3都正确地抱怨没有这样的常数。显然,Z3具有该信息,如对(check-sat)
电话的响应所证明的那样。有没有办法通过get-value
或其他一些机制自动访问存在价值?
谢谢..
答案 0 :(得分:3)
在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的选择可能取决于y。 维基百科在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)
可以使用新的skolem函数来获取每个x
的{{1}}值。
上面的例子变成:
y
在此示例中,(declare-fun sx ((_ BitVec 16)) (_ BitVec 16))
(assert (forall ((y (_ BitVec 16))) (bvuge y (sx y))))
(check-sat)
(get-model)
是新功能。由Z3制作的模型将为sx
指定解释。在3.0版中,解释是身份功能。此函数可用于获取每个sx
的{{1}}值。