Count dafny中的段计数无效

Count dafny中的段计数无效,count,formal-verification,dafny,Count,Formal Verification,Dafny,我在下面的链接中为代码编写了以下证明。 我想在提供count2方法方面得到一些帮助。我不太清楚交替证明 谢谢 methodmain(){ 变量a:数组:=新整数[4]; a[0]:=7; a[1]:=-2; a[2]:=3; a[3]:=-2; 断言a[…]==[7,-2,3,-2]; 变量c:=SumProdAndCount(a,-2); 断言a[0]==7&&a[1]==2&&a[2]==3&&a[3]==2; 断言c==RecursiveCount(-2,a,0);//==2 打印“\n

我在下面的链接中为代码编写了以下证明。 我想在提供count2方法方面得到一些帮助。我不太清楚交替证明 谢谢

methodmain(){
变量a:数组:=新整数[4];
a[0]:=7;
a[1]:=-2;
a[2]:=3;
a[3]:=-2;
断言a[…]==[7,-2,3,-2];
变量c:=SumProdAndCount(a,-2);
断言a[0]==7&&a[1]==2&&a[2]==3&&a[3]==2;
断言c==RecursiveCount(-2,a,0);//==2
打印“\n在[7,-2,3,-2]中出现-2的次数为”;
打印c;
}
函数RecursiveCount(键:int,a:array,from:nat):int
读到
需要一个无效的
需要(从0开始)

不变量0当向后循环时,必须先减小索引,然后才能使用它访问数组

i, c := i0-1, c0
因为是向后循环,所以在访问数组之前必须减小计数器。通过检查方法的先决条件可以看到这一点。给定

0 < i0 <= a.Length
您还需要增加而不是减少发生次数

c := c + 1;
下面是一个验证

我认为,如果您使用更清晰的编程风格和更少的间接性,您可能会发现验证这些程序更容易(尽管您可能正在做一个关于方法前置和后置条件的练习)。我的经验是,成功验证算法的一部分首先是找到一种好的、清晰的方法来表达算法

methodmain(){
变量a:数组:=新整数[4];
a[0]:=7;
a[1]:=-2;
a[2]:=3;
a[3]:=-2;
断言a[…]==[7,-2,3,-2];
变量c:=SumProdAndCount(a,-2);
断言a[0]==7&&a[1]==2&&a[2]==3&&a[3]==2;
断言c==RecursiveCount(-2,a,0);//==2
打印“\n在[7,-2,3,-2]中出现-2的次数为”;
打印c;
}
函数RecursiveCount(键:int,a:array,from:nat):int
读到
需要一个无效的
要求来自
0 < i0 <= a.Length ==> 0 <= (i0-1) < a.Length
c := c + 1;
method Main() {
    var a: array<int> := new int[4];
    a[0] := 7;
    a[1] := -2;
    a[2] := 3;
    a[3] := -2;
    assert a[..] == [7,-2,3,-2];

    var c := SumProdAndCount(a, -2);
    assert a[0] == 7 && a[1] == -2 && a[2] == 3 && a[3] == -2;
    assert c == RecursiveCount(-2, a, 0); // == 2
    print "\nThe number of occurrences of -2 in [7,-2,3,-2] is ";
    print c;
}

function RecursiveCount(key: int, a: array<int>, from: nat) : int
    reads a
    requires a != null
    requires from <= a.Length
    decreases a.Length-from
{
    if from == a.Length then 0
    else if a[from] == key then 1+RecursiveCount(key, a, from+1)
    else RecursiveCount(key, a, from+1)
}

method SumProdAndCount(a: array<int>, key: int) returns (c: nat)
    requires a != null
    ensures c == RecursiveCount(key, a, 0)
{
  c := 0;
  var i : nat := 0;
  ghost var r := RecursiveCount(key, a, 0);
  while (i < a.Length)
    invariant 0 <= i <= a.Length
    invariant r == c + RecursiveCount(key,a,i);
  {
       i, c := i+1, if a[i]==key then c+1 else c;
  }
}