我正在尝试练习,如以下视频中稍后所述:https://www.youtube.com/watch?v=-_tx3lk7yn4
该方法应实现BinarySearch,当未找到键时,该方法应返回索引,如果将其插入到搜索数组中,键将以该键结束。我相信该练习的正确附加规范如下:
ensures 0 <= r <= a.Length
ensures forall i :: 0 <= i < r ==> a[i] < key
ensures forall i :: r < i < a.Length ==> a[i] >= key
我的实现:
method BinarySearch(a: array<int>, key: int) returns (r: int)
requires forall i,j :: 0 <= i < j < a.Length ==> a[i] <= a[j] // a is a sorted array
// old specification
//ensures 0 <= r ==> r < a.Length && a[r] == key // when found a[r] is key
//ensures r < 0 ==> forall i :: 0 <= i < a.Length ==> a[i] != key // when no key found return negative value
// restrictions for simpler debugging
requires a.Length == 2
requires forall i :: 0 <= i < a.Length ==> 0 <= a[i] < 5
// new specification
ensures 0 <= r <= a.Length // "it will always return some indication between 0 and the length of the array inclusive"
ensures forall i :: 0 <= i < r ==> a[i] < key // "all values to the left of the value R that you're returning are strictly smaller than the key"
ensures forall i :: r < i < a.Length ==> a[i] >= key // "from all values to the right of R is either the key or larger"
{
// simple/common cases first
// if array is empty
if a.Length == 0
{
return 0;
}
// if key larger than largest
else if key > a[a.Length - 1]
{
return a.Length;
}
// if key equal or smaller than smallest
else if key <= a[0]
{
return 0;
}
// key is in array range
var lo, hi := 0, a.Length;
while lo < hi
decreases hi - lo
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
{
var mid := (lo + hi) / 2;
if key < a[mid]
{
hi := mid;
}
else if a[mid] < key
{
lo := mid + 1;
}
else
{
// key found, decrease while preceding value is equal
while mid != 0 && a[mid-1] == a[mid]
decreases mid
invariant 0 <= mid < a.Length
invariant lo < hi
invariant forall i :: 0 <= i < lo ==> a[i] != key
invariant forall i :: hi <= i < a.Length ==> a[i] != key
{
mid := mid - 1;
}
return mid;
}
}
return lo;
}
我的问题是验证者说规范不成立,然后给了我一个反例,而这种反例最初不会发生:
我怀疑while循环本身缺少规范,但是我不知道要填补什么空白。
使用最新的Visual Code和Dafny插件。