简体   繁体   English

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

[英]Unsure why this Dafny verification fails

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;
  }
}

I have tried to increase the invariance in the loops.我试图增加循环中的不变性。 To the first loop, I added the condition, res<=5*abs(m) but Dafny complains that "This loop invariant might not be maintained by the loop."在第一个循环中,我添加了条件 res<=5*abs(m) 但 Dafny 抱怨“这个循环不变量可能不会由循环维护”。 I don't understand how it is not.我不明白怎么不是。

What could I be doing wrong?我可能做错了什么?

If you make your loop invariant stronger by stating exactly what res is equal to after each iteration, Dafny will be able to verify it.如果通过在每次迭代后准确说明res等于什么来使循环不变性更强,Dafny 将能够验证它。

So in the first while loop, instead of invariant res <= 5*abs(m) , use invariant res == 5*abs(m) - 5*m1 .因此,在第一个 while 循环中,使用invariant res == 5*abs(m) - 5*m1而不是invariant res <= 5*abs(m) When the loop terminates, m1 is equal to zero, so res will be 5*abs(m) .当循环终止时, m1等于 0,因此res将为5*abs(m)

Similarly, for the second while loop, define the invariant res == 5*m - 3*n + 3*n1 .类似地,对于第二个 while 循环,定义invariant res == 5*m - 3*n + 3*n1 Now when this loop terminates, n1 is equal to zero, so res will be 5*m - 3*n and Dafny will be able to prove that the post-condition of the method holds.现在当这个循环终止时, n1等于 0,所以res将是5*m - 3*n并且 Dafny 将能够证明该方法的后置条件成立。

PS I usually use > 0 instead of != 0 as a loop condition. PS 我通常使用> 0而不是!= 0作为循环条件。

After making these changes, you would have:进行这些更改后,您将拥有:

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;
    }
}

which verifies in Dafny.在 Dafny 中进行验证。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM