为什么我的 Dafny 断言在 x == y 和 x != y 上都失败了?
Why is my Dafny assertion failing on both x == y and x != y?
我正在学习教程 here,代码似乎是正确的,但是当我使用断言进行测试时,出现错误!
运行 程序打印出正确答案,但断言似乎自相矛盾。当显示反例时,似乎 -1
被考虑,即使它不应该被考虑。
method binarySearch(a:array<int>, key:int) returns (r:int)
requires forall i,j :: 0 <= i <= j < a.Length ==> a[i] <= a[j]
ensures 0 <= r ==> r < a.Length && a[r] == key
ensures r < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != key
{
var lo, hi := 0, a.Length;
while (lo < hi)
invariant 0 <= lo <= hi <= a.Length
invariant forall i :: 0 <= i < lo ==> a[i] < key
invariant forall i :: hi <= i < a.Length ==> a[i] > key
decreases hi - lo;
{
var mid := (lo + hi) / 2;
if key < a[mid]
{
hi := mid;
}
else if key > a[mid]
{
lo := mid + 1;
}
else
{
return mid;
}
}
return -1;
}
// tests
method Main()
{
var a := new int[6][1,2,3,4,5,6];
var r := binarySearch(a, 5);
assert r == 4; // fails
assert r != 4; // also fails
}
这是一个错误还是我遗漏了什么?
Dafny 使用 post-condition 方法来推理方法调用的结果。
这里post-condition是
- 如果 r 在 0 到数组长度之间,则 r 处的元素等于键
- 如果r小于0,则不在数组中。
Dafny 不知道其中哪些是空洞的,但你可以暗示一下。
用 if r >= 0 && r < a.Length
保护 assert r == 4
将使其验证。
或者在assert r == 4
之前添加assert a[4] == 5
之后,验证将通过。
出现奇怪错误的原因是在调用二进制搜索之后,这些是 dafny 已知的事实
assert (r < 0) || (0 <= r < 6)
assert (r < 0) ==> forall i :: 0 <= i < a.Length ==> a[i] != 5
assert (0 <= r < 6) ==> a[r] == 5
用这些既不能证明r == 4
也不能证明r != 4
。默认情况下,Dafny 似乎不会向证明者传播 assert a[0] == 1
等信息,您必须明确要求它。
我正在学习教程 here,代码似乎是正确的,但是当我使用断言进行测试时,出现错误!
运行 程序打印出正确答案,但断言似乎自相矛盾。当显示反例时,似乎 -1
被考虑,即使它不应该被考虑。
method binarySearch(a:array<int>, key:int) returns (r:int)
requires forall i,j :: 0 <= i <= j < a.Length ==> a[i] <= a[j]
ensures 0 <= r ==> r < a.Length && a[r] == key
ensures r < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != key
{
var lo, hi := 0, a.Length;
while (lo < hi)
invariant 0 <= lo <= hi <= a.Length
invariant forall i :: 0 <= i < lo ==> a[i] < key
invariant forall i :: hi <= i < a.Length ==> a[i] > key
decreases hi - lo;
{
var mid := (lo + hi) / 2;
if key < a[mid]
{
hi := mid;
}
else if key > a[mid]
{
lo := mid + 1;
}
else
{
return mid;
}
}
return -1;
}
// tests
method Main()
{
var a := new int[6][1,2,3,4,5,6];
var r := binarySearch(a, 5);
assert r == 4; // fails
assert r != 4; // also fails
}
这是一个错误还是我遗漏了什么?
Dafny 使用 post-condition 方法来推理方法调用的结果。
这里post-condition是
- 如果 r 在 0 到数组长度之间,则 r 处的元素等于键
- 如果r小于0,则不在数组中。
Dafny 不知道其中哪些是空洞的,但你可以暗示一下。
用 if r >= 0 && r < a.Length
保护 assert r == 4
将使其验证。
或者在assert r == 4
之前添加assert a[4] == 5
之后,验证将通过。
出现奇怪错误的原因是在调用二进制搜索之后,这些是 dafny 已知的事实
assert (r < 0) || (0 <= r < 6)
assert (r < 0) ==> forall i :: 0 <= i < a.Length ==> a[i] != 5
assert (0 <= r < 6) ==> a[r] == 5
用这些既不能证明r == 4
也不能证明r != 4
。默认情况下,Dafny 似乎不会向证明者传播 assert a[0] == 1
等信息,您必须明确要求它。