Boogie奇怪的断言(假)行为

时间:2017-03-23 20:07:53

标签: z3 dafny

我正在与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)

的结果

1 个答案:

答案 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