arrays - 为什么这个涉及数组的 Dafny 断言会失败?

标签 arrays verification dafny

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

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

最佳答案

(我删除了我的第一个答案,因为它不起作用)。

问题似乎在于 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] 相当于

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

关于arrays - 为什么这个涉及数组的 Dafny 断言会失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31629705/

相关文章:

Dafny 无法证明简单的存在量词

java - 为什么即使对于不相等的字符串,equalsignorecase 也会返回 true

algorithm - 通过NuSMV验证Dekker的互斥算法

mercurial - 在推/拉之前自动触发 Hg 存储库验证,无需编程

C - 循环中的输入验证行为很奇怪

dafny - 精益、f* 和 dafny 有什么区别?

ios - 在 UITableView 中显示 2D 数组

c++ - 初始化多维数组中的所有位置?

java - 在Java中将字符串插入字节数组中的某个索引处

arrays - Dafny:验证最简单的数组求和是行不通的。有人可以向我解释为什么吗?