为什么涉及数组的Dafny断言失败了?

时间:2015-07-25 18:21:09

标签: arrays verification dafny

我正在研究经过验证的高斯消除实现,我在验证这个超级简单方法时遇到了问题,该方法将数组b的内容添加到数组a的内容中。这是代码。

method addAssign(a: array<real>, b: array<real>)
   requires a != null && b != null && a.Length == b.Length;
   modifies a
   ensures forall k:: 0 <= k < a.Length ==> a[k] == old(a[k]) + b[k];
{
   var i := 0;
   assert a == old(a);
   while(i < a.Length)
      invariant 0 <= i <= a.Length
      invariant forall k:: i <= k < a.Length ==> a[k] == old(a[k])
      invariant forall k:: 0 <= k < i ==> a[k] == old(a[k]) + b[k];
   {
      assert a[i] == old(a[i]); // dafny verifies this
      a[i] := a[i] + b[i];
      assert a[i] == old(a[i]) + b[i]; // dafny says this is an assertion violation
      i := i + 1;
   }
}

1 个答案:

答案 0 :(得分:0)

(我删除了我的第一个答案,因为它没有工作)。

似乎问题是Dafny检测到潜在的混叠问题。作为一项实验,我首先修改了您的代码以获得更简单的功能,该功能可以验证:

method addOne(a: array<real>)
   requires a != null;
   modifies a;
   ensures forall k:: 0 <= k < a.Length ==> a[k] == old(a[k]) + 1.0;
{
   var i := 0;
   assert a == old(a);
   while(i < a.Length)
      invariant 0 <= i <= a.Length
      invariant forall k:: i <= k < a.Length ==> a[k] == old(a[k])
      invariant forall k:: 0 <= k < i ==> a[k] == old(a[k]) + 1.0;
   {
      assert a[i] == old(a[i]); // dafny verifies this
      a[i] := a[i] + 1.0;
      assert a[i] == old(a[i]) + 1.0; // dafny *doesn't* say this is an assertion violation
      i := i + 1;
   }
}

唯一的区别是我使用的是真实的(1.0),而不是b的实际绘制。为什么 会有所作为?

假设您使用类似

的调用调用方法
addAssign(a,a)

然后在函数ba的主体中都引用相同的数组。例如,假设a[0]为1.0。然后在第一次循环中执行a[0] := a[0] + b[0]

这会将a[0]设置为2.0。但是 - 它b[0]设置为2.0。

但在这种情况下assert a[0] == old(a[0]) + b[0]相当于

assert 2.0 == 1.0 + 2.0 - 应该失败。

顺便说一下 - 以下 验证:

method addAssign(a: array<real>, b: array<real>)
   requires a != null && b != null && a.Length == b.Length;
   modifies a;
   ensures forall k:: 0 <= k < a.Length ==> a[k] == old(a[k]) + old(b[k]);
{
   var i := 0;
   assert a == old(a);
   while(i < a.Length)
      invariant 0 <= i <= a.Length
      invariant forall k:: i <= k < a.Length ==> a[k] == old(a[k])
      invariant forall k:: 0 <= k < i ==> a[k] == old(a[k]) + old(b[k]);
   {
      assert a[i] == old(a[i]); // dafny verifies this
      a[i] := a[i] + b[i];
      assert a[i] == old(a[i]) + old(b[i]); // and also this!
      i := i + 1;
   }
}