不确定为什么此Dafny验证失败

时间:2020-03-26 02:14:28

标签: dafny

function method abs(m: int): nat
{ if m>0 then m else -m }

method CalcTerm(m: int, n: nat) returns (res: int)
  ensures res == 5*m-3*n;
{
  var m1: nat := abs(m);
  var n1: nat := n;
  res := 0;

  while (m1!=0)
    invariant m1>=0
    invariant 0<=res
    invariant res <=5*abs(m)
    decreases m1
  {
    res := res+5;
    m1 := m1-1;
  }
  if (m<0) { res := -res; }

  while (n1!=0)
    invariant n1>=0 
    decreases n1
  {
    res := res-3;
    n1 := n1-1;
  }
}

我试图增加循环的不变性。在第一个循环中,我添加了条件res <= 5 * abs(m),但Dafny抱怨说“该循环不变性可能不会被该循环保持”。我不明白怎么回事。

我做错了什么?

1 个答案:

答案 0 :(得分:0)

如果通过在每次迭代后确切说明res等于invariant res <= 5*abs(m)来使循环不变性更强,Dafny将能够对其进行验证。

因此,在第一个while循环中,请使用invariant res == 5*abs(m) - 5*m1而不是m1。当循环终止时,res等于零,因此5*abs(m)将为invariant res == 5*m - 3*n + 3*n1

类似地,对于第二个while循环,定义n1。现在,当该循环终止时,res等于零,因此5*m - 3*n将是> 0,Dafny将能够证明该方法的后置条件成立。

P.S。我通常使用!= 0而不是function method abs(m: int): nat { if m > 0 then m else -m } method CalcTerm(m: int, n: nat) returns (res: int) ensures res == 5*m - 3*n; { var m1: nat := abs(m); var n1: nat := n; res := 0; while (m1 > 0) invariant m1 >= 0; invariant 0 <= res; invariant res == 5*abs(m) - 5*m1; decreases m1; { res := res + 5; m1 := m1 - 1; } if (m < 0) { res := -res; } while (n1 > 0) invariant n1 >= 0; invariant res == 5*m - 3*n + 3*n1; decreases n1; { res := res - 3; n1 := n1 - 1; } } 作为循环条件。

进行这些更改后,您将:

{{1}}

在Dafny中验证。