使用方法结果时违反dafny断言

时间:2020-09-09 01:25:27

标签: dafny

我已经在下面编写了程序,以验证数组是否“干净”了任何特定元素。我在断言该方法的结果时遇到麻烦。尝试声明该方法的结果时,我不断收到声明冲突。

method Main (){
 
  
  var a:= new int[3];
  
  a[0], a[1], a[2] := 1,2,3;
  var v := isClean (a, 1);
  assert v == false;

}



method isClean (a : array <int>, key : int) returns (clean : bool)
  
  requires a.Length > 0


{
  
  var i := 0;
  
  while (i < a.Length)
  
  invariant 0 <= i <= a.Length
  invariant forall k :: 0 <= k < i ==> a[k] != key
  
  {
    
    if (a[i] == key) {
      
      clean := false;
      return;
    }
    
    i := i + 1;
    
  }
  
  clean := true;
  
}

Dafny 2.3.0.10506
stdin.dfy(8,11): Error: assertion violation

Dafny program verifier finished with 2 verified, 1 error

1 个答案:

答案 0 :(得分:0)

您需要在ensures上使用isClean子句。 Dafny验证程序时,一次只查看一个method。因此,当Dafny验证Main时,它根本不会查看isClean的定义。相反,它仅查看requiresensures子句。

您已经在循环不变式中完成了困难的证明。基本上,您只需要修改该不变量的副本,以使其在调用方的上下文中有意义,就像ensures子句一样,

ensures clean <==> (forall k :: 0 <= k < a.Length ==> a[k] != key)

(在requires的{​​{1}}子句下面添加该字符。)在此isClean子句中,ensures指的是clean的命名返回值。方法。如果添加此子句,Dafny仍会抱怨,因为您正在要求它证明isClean量词是forall。这等效于试图证明false量词exists,并且需要一个明确的“见证”,它是true的值,使得公式的主体变成{{1 }} / k

在这种情况下,true返回false的直观原因是因为isClean的值为1,所以false不是 “清除”。我们可以通过添加断言来向达夫尼展示这种“见证”

a[0]

在调用a之后立即访问assert a[0] == 1; 的正文。


为清楚起见,这是验证程序的完整版本:

Main