Я пытаюсь выполнить упражнение, как описано позже в следующем видео: 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;
}
Моя проблема в том, что верификатор говорит, что спецификации не выполняются, а затем дает мне встречный пример, который не может произойти в первую очередь:
![bad counter example](https://i.stack.imgur.com/p278l.png)
Я подозреваю, что в то время как у-l oop (s) отсутствуют спецификации, но я Понятия не имею, какие пробелы даже заполнить.
Использование самых последних визуальных кодов и плагинов Dafny.