I have the following method for performing selection sort in descending order. However, the very first invariant in the while loop is said to be not maintained by the loop, why is that the case?
method sortDesc (a : array<int>)
modifies a;
requires a != null;
ensures forall m,n :: 0 <= m < n < a.Length ==> a[m] >= a[n];
requires a.Length > 1;
ensures multiset(a[..]) == multiset(old(a[..]));
{
var index := a.Length - 1;
while(index > -1)
invariant forall m,n :: 0 <= m <= index && index < n < a.Length ==> a[m] >= a[n]; // all elements that we have not sorted are bigger than any element we have sorted !!!!!!!!!!!!
invariant a.Length > index > -1;
invariant forall k,l :: index < k < l < a.Length ==> a[k] >= a[l]; //the part we have gone through is already sorted!!
invariant multiset(a[..]) == multiset(old(a[..])); // USED TO MAKE SURE ALL THE STARTING ELEMENTS ARE STILL THERE!!!!!
decreases index;
{
var minIndex := findMinBetween(a, index, a.Length);
if (a[index] < a[minIndex])
{
a[index], a[minIndex] := a[minIndex],a[index]; //SWAP ELEMENTS!!!
}
if (index == 0)
{
return;
}
index := index - 1;
}
}
Perhaps the comparison a[index] < a[minIndex] is the wrong way around. You are trying to move the small stuff to the right, so if a[minindex] is smaller than a[index] you need to move it (a[minindex]) to the right.
Related
So I've tried implementing a program for a simplified Dutch flag problem in Dafny where all indices 0 <= n < k are red and all indices k <= n < arr.Length are blue, except it keeps saying that k might go out of bounds even though it should be at most arr.Length based on how I coded it. What am I doing wrong here?
method dutch(arr: array?<char>) returns (k: int)
requires arr != null && forall x :: 0 <= x < arr.Length ==> arr[x] == 'r' || arr[x] == 'b'
ensures k <= arr.Length //postcondition might not hold
ensures forall n :: 0 <= n < k ==> arr[n] == 'r' //out of range
ensures forall n :: k <= n < arr.Length ==> arr[n] == 'b' //out of range
modifies arr
{
var x := 0;
k := 0;
while(x < arr.Length)
invariant k <= x
invariant forall n :: 0 <= n < k ==> arr[n] == 'r' //out of range
invariant forall n :: k <= n < x ==> arr[n] == 'b' //invariant might not be maintained by loop
{
if(arr[x] == 'r')
{
arr[x] := arr[k];
arr[k] := 'r';
k := k + 1;
}
x := x + 1;
}
}
After the loop, all that is known is the invariant and the negation of the loop guard. So, arr.Length <= x holds and so does k <= x. So, according to your loop specification, x might be arr.Length + 10 and k might be arr.Length + 2.
To verify the program, you need to turn your belief that k "should be at most arr.Length based on how I coded it" into a loop specification. So, add
invariant k <= arr.Length
Check whether exists index 0 <= k < n - 2 such that elements of array A[] moved clockwise by k indexes make a reverse bitonic array.
My approach to do it in O(n) time complexity:
bool is_antibitonicable(int A[], int n) {
// returns if there is such index k that
// after moving clockwise k elements of array
// A[], that array is reverse bitonic
// - strictly decreasing then strictly
// increasing
if (n < 3)
return false;
// if is_increasing[i] == 1 means this part of A[] is increasing,
// == 0 means that part of A[] is decreasing, == -1 default
int is_increasing[3] = { -1, -1, -1 };
for (int i = 0, j; i < n - 1;) {
if (A[i] < A[i + 1]) { // if A[] is increasing
j = 0;
while (j < 3 && is_increasing[j] != -1)
j++;
if (j == 3)
return false;
is_increasing[j] = 1;
while (i < n - 1 && A[i] < A[i + 1])
i++;
}
else if (A[i] > A[i + 1]) { // check if decreasing
j = 0;
while (j < 3 && is_increasing[j] != -1)
j++;
if (j == 3)
return false;
is_increasing[j] = 0;
while (i < n - 1 && A[i] > A[i + 1])
i++;
}
else // sequence of A[] is neither increasing nor decreasing
return false;
}
// if A[] is only increasing/decreasing
if (is_increasing[1] == is_increasing[2])
return false;
// if A[] is increasing->decreasing->increasing check if increasing
// parts can be merged into one increasing sequence
if (is_increasing[0] == 1 && is_increasing[1] == 0 && is_increasing[2] == 1)
return (A[0] > A[n - 1]);
// decreasing->increasing->decreasing
if (is_increasing[0] == 0 && is_increasing[1] == 1 && is_increasing[2] == 0)
return (A[0] < A[n - 1]);
return true; // increasing -> decreasing or opposite
}
I'd be very glad if someone could look at my solution and comment whether it seems correct or how to do it better, any feedback will be appreciated.
Your solution doesn't look bad, but it does incorrectly return false // if A[] is only increasing/decreasing. Such a sequence can always be turned into a first decreasing and then increasing one by rotating by one in the right (appropriate) direction.
I saw an example program which sets every value in an array to 0:
int a[n]; int i = 0;
while(i < n) {
a[i] = 0;
i++;
}
It said that part of the loop invariant was 0<=i<n. However, after the loop is finished terminating, i will equal n. Am i correct in saying that this is then not part of the loop invariant? If so, what should it be replaced with?
The full invariant was For All j (0<= j < i --> a[i] = 0) & 0 <= i < n)
The loop invariant must hold on loop entry and be preserved by every iteration, including the last iteration.
Therefore the loop invariant should be 0 <= i <= n
To support my claim, I offer as evidence your program translated into the automatically verified language Microsoft Dafny:
method Main(a:array<int>)
requires a != null
modifies a
ensures forall j :: 0 <= j < a.Length ==> a[j] == 0
{
var i:int := 0;
while(i < a.Length)
invariant 0 <= i <= a.Length
invariant forall j :: (0 <= j < i ==> a[j] == 0)
{
a[i] := 0;
i := i+1;
}
}
You can check that this program does indeed verify by running it in the online version of Dafny.
I'm trying to prove this program in dafny but I still get an error with the last invariant and I can't see why it's not working.
The program consists on a method which inserts an int into a sorted array. The int will be inserted in the correct position ie: inserting 5 into 1,2,3,4,5,6,7 will return: 1,2,3,4,5,5,6,7
function sorted (a: array<int>): bool
requires a != null ;
reads a;
{
forall i :: 0 <= i < (a.Length - 1) ==> a[i] <= a[ i+1]
}
method InsertSorted(a: array<int>, key: int ) returns (b: array<int>)
requires a != null && sorted(a);
ensures b != null ;
ensures sorted(b);
{
var i:= 0;
b:= new int[a.Length + 1];
if(a.Length > 0){
while (i < a.Length)
invariant 0<= i;
invariant i <= a.Length;
invariant b.Length == a.Length + 1;
invariant sorted(a);
invariant forall j :: 0 <= j < i ==> b[j] <= b[j+1];
{
if(a[i]<=key)
{
b[i]:= a[i];
b [i+1] := key;
assert b[i] <= b[i+1];
}
else if (key > a[i])
{
if(i==0)
{
b[i] := key;
}
b [i+1] := a[i];
assert key > a[i];
assert b[i]<= b[i+1];
}
else{
b[i]:= a[i];
b [i+1] := a[i];
assert sorted(a);
assert b[i] <= b[i+1];
}
assert b[i]<= b[i+1];
i := i+1;
}
}
else{
b[0] := key;
}
}
Thanks
I think that perhaps you algorithm is not correct. In any case, I find the conditionals hard to understand, if the first branch is not taken then we know that !(a[i] <= key) or more simply a[i] > key which implies that the second branch guarded by key > a[i] is unreachable.
!(a[i]<=key) && a[i] < key ==> false
In any case, I suspect the loop invariant isn't strong enough to prove even a correct version since you are not keeping track of the state of b in sufficient detail.
Below is a proof of an algorithm that is similar to yours, showing a stronger loop invariant. I keep track of where in the array key is inserted using a ghost variable (a variable that is just used for verification and will not appear in the compiler output).
http://rise4fun.com/Dafny/RqGi
predicate sorted (a: seq<int>)
{
forall i,j :: 0 <= i < j < |a| ==> a[i] <= a[j]
}
predicate lessThan(a:seq<int>, key:int) {
forall i :: 0 <= i < |a| ==> a[i] < key
}
predicate greaterEqualThan(a:seq<int>, key:int) {
forall i :: 0 <= i < |a| ==> a[i] >= key
}
method InsertSorted(a: array<int>, key: int ) returns (b: array<int>)
requires a != null && sorted(a[..])
ensures b != null && sorted(b[..]);
{
b:= new int[a.Length + 1];
ghost var k := 0;
b[0] := key;
ghost var a' := a[..];
var i:= 0;
while (i < a.Length)
modifies b;
invariant 0 <= k <= i <= a.Length
invariant b.Length == a.Length + 1
invariant a[..] == a'
invariant lessThan(a[..i], key) ==> i == k;
invariant lessThan(a[..k], key)
invariant b[..k] == a[..k]
invariant b[k] == key
invariant k < i ==> b[k+1..i+1] == a[k..i]
invariant k < i ==> greaterEqualThan(b[k+1..i+1], key)
invariant 0 <= k < b.Length && b[k] == key
{
if(a[i]<key)
{
b[i]:= a[i];
b[i+1] := key;
k := i+1;
}
else if (a[i] >= key)
{
b[i+1] := a[i];
}
i := i+1;
}
assert b[..] == a[..k] + [key] + a[k..];
}
I am working on a verified implementation of gaussian elimination and I am having problems verifying this super simple method that adds the contents of the array b to the contents of the array a. Here is the code.
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;
}
}
(I deleted my first answer since it didn't work).
It seems that the problem is that Dafny detects potential aliasing problems. As an experiment, I first modified your code to get an even easier function which does verify:
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;
}
}
The only difference is that I am using a literal real (1.0) rather than a real drawn from b. Why should that make a difference?
Well suppose that you invoke your method with a call which looks like
addAssign(a,a)
then in the body of the function b and a both refer to the same array. Suppose, for example, that a[0] is 1.0. Then in the first pass through the loop you execute a[0] := a[0] + b[0].
This sets a[0] to 2.0. But -- it also sets b[0] to 2.0.
But in this situation assert a[0] == old(a[0]) + b[0] is equivalent to
assert 2.0 == 1.0 + 2.0 -- which should fail.
By the way -- the following does verify:
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;
}
}