我已经在下面编写了程序,以验证数组是否“干净”了任何特定元素。我在断言该方法的结果时遇到麻烦。尝试声明该方法的结果时,我不断收到声明冲突。
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
答案 0 :(得分:0)
您需要在ensures
上使用isClean
子句。 Dafny验证程序时,一次只查看一个method
。因此,当Dafny验证Main
时,它根本不会查看isClean
的定义。相反,它仅查看requires
和ensures
子句。
您已经在循环不变式中完成了困难的证明。基本上,您只需要修改该不变量的副本,以使其在调用方的上下文中有意义,就像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