我正在与Boogie合作,我遇到了一些我不理解的行为。
我一直在使用assert(false)
来检查以前的assume
语句是否荒谬。
例如,在下列情况下,程序验证没有错误......
type T;
const t1, t2: T;
procedure test()
{
assume (t1 == t2);
assume (t1 != t2);
assert(false);
}
......因为t1 == t2 && t1 != t2
是一个荒谬的陈述。
另一方面,如果我有类似
的话type T;
var map: [T]bool;
const t1, t2: T;
procedure test()
{
assume(forall a1: T, a2: T :: !map[a1] && map[a2]);
//assert(!map[t1]);
assert(false);
}
assert(false)
仅在取消注释注释行时失败。为什么注释断言会改变assert(false)
?
答案 0 :(得分:3)
要点:如果您未在程序中提及map[...]
的地面实例,则Boogie基础的SMT求解器将不会实例化量词。
原因如下:SMT求解器(使用电子匹配)通常使用句法启发式来决定何时实例化量词。考虑以下量词:
forall i: Int :: f(i)
此量词允许无限多个实例化(因为i
范围超过无界域),尝试所有实例将因此导致非终止。相反,SMT求解器期望语法提示指示它应该实例化i
量词。这些提示称为模式或触发器。在Boogie中,它们可以写成如下:
forall i: Int :: {f(i)} f(i)
此触发器指示SMT解算器为程序中提到i
的每个f(i)
实例化量词(或者更确切地说,当前证明搜索)。例如,如果您假设f(5)
,则量化器将被实例化,5
替换为i
。
在您的示例中,您没有明确提供模式,因此SMT求解程序可能会通过检查量词体来为您选择一个模式。它很可能会选择{map[a1], map[a2]}
(允许多个函数应用程序,模式必须涵盖所有量化变量)。如果取消注释假设,则基础术语map[t1]
变为可用,并且SMT解算器可以将a1, a2
映射到t1, t1
的量词实例化。因此,获得了矛盾。
有关模式的更多详细信息,请参阅Z3 guide。可以找到更多涉及模式的文本,例如,在 this paper,in this paper或在 this paper