Verification of Shell Sorting algorithm loop invariants? - sorting

Good day to all! I wrote the Shell sort verification code, but I can’t build the correct loop invariants.It is not possible to correctly compose invariants and prove the correctness of the program... Please help me!
/*# predicate Sorted{L}(int* a, integer m, integer n) =
# \forall integer i, j; m <= i <= j < n ==> a[i] <= a[j];
*/
/*# predicate GapSorted(int* a, integer m, integer n, integer gap) =
# \forall integer i, j; (m <= i <= j < n && j % gap == i % gap) ==> a[i] <=a[j];
*/
/*#
# requires \valid(arr + (0..n-1));
# requires n > 1;
# ensures GapSorted(arr, 0, n, 1);
*/
void shell_lr(int *arr, int n) {
int i, j, tmp, gap;
/*# ghost int gap1 = n
# loop invariant 0 <= gap1 <= n/2;
# loop invariant gap1 < n/2 ==> GapSorted(arr, 0, n, gap+1);
# //loop invariant \forall integer k; gap < k <= n/2 ==> GapSorted(arr, 0, n, k);
# loop variant gap1;
*/
for (gap = n / 2; gap > 0; gap--) {
/*# loop invariant 0 <= i <= n;
# //loop invariant \forall integer m; gap < m <= n/2 ==> GapSorted(arr, 0, i, m);
# loop invariant GapSorted(arr, 0, i, gap);
# loop variant n - i; */
for (i = gap; i < n; i++) {
tmp = arr[i];
/*#
# loop invariant 0 <= j <= i;
# //loop invariant arr[j] >= tmp;
# loop invariant \forall integer k; (j < k <= i) ==> GapSorted(arr, 0, i, k);
#// loop invariant \forall integer k; j <= k <= gap ==> GapSorted(arr, k, i, gap);
# loop variant j;
#*/
for (j = i; j >= gap && arr[j - gap] > tmp; j -= gap) {
arr[j] = arr[j - gap];
//# assert arr[j] >= arr[j - gap];
//# assert tmp < arr[j - gap];
}
//# assert j>=0;
arr[j] = tmp;
}
//# assert i == n;
//# assert GapSorted(arr, 0, i, gap);
//# assert gap > 0;
// assert GapSorted(arr, 0, n, gap);
}

First, the code you provided is not syntactically correct:
a brace closing the function's body is missing
the ghost declaration of gap1 cannot be mixed with the loop annotations. This should be two distinct annotations. Anyway, I don't see the use of gap1 (especially as it is not updated inside the loop), everything can be expressed with gap. If what you were trying to achieve was to have a local variable for the whole loop annotation, this is not possible in ACSL: you have the \let gap1 = ...; ... construction, but its scope is only a single term/predicate: you can't share it with across two loop invariants (or loop invariants and loop variant)
Now, your most pressing issue here is the lack of loop assigns in your loop annotations. You must provide such clauses for all your loops, or WP will not be able to assume much about the state of the program after the loops (see for instance this answer for more detail). You might also want to strengthen a bit your invariant on i in the middle loop as gap <= i <= n, but this is a detail.
With the following loop assigns, most of your annotations gets proved (Frama-C 20.0 Calcium with -wp -wp-rte).
/*# predicate Sorted{L}(int* a, integer m, integer n) =
# \forall integer i, j; m <= i <= j < n ==> a[i] <= a[j];
*/
/*# predicate GapSorted(int* a, integer m, integer n, integer gap) =
# \forall integer i, j; (m <= i <= j < n && j % gap == i % gap) ==> a[i] <=a[j];
*/
/*#
# requires \valid(arr + (0..n-1));
# requires n > 1;
# ensures GapSorted(arr, 0, n, 1);
*/
void shell_lr(int *arr, int n) {
int i, j, tmp, gap;
/*#
# loop invariant 0 <= gap <= n/2;
# loop invariant gap < n/2 ==> GapSorted(arr, 0, n, gap+1);
# loop assigns gap, i, j, tmp, arr[0 .. n - 1];
# //loop invariant \forall integer k; gap < k <= n/2 ==> GapSorted(arr, 0, n, k);
# loop variant gap;
*/
for (gap = n / 2; gap > 0; gap--) {
/*# loop invariant gap <= i <= n;
# //loop invariant \forall integer m; gap < m <= n/2 ==> GapSorted(arr, 0, i, m);
# loop invariant GapSorted(arr, 0, i, gap);
loop assigns i,j,tmp,arr[0..n-1];
# loop variant n - i; */
for (i = gap; i < n; i++) {
tmp = arr[i];
/*#
# loop invariant 0 <= j <= i;
# //loop invariant arr[j] >= tmp;
# loop invariant \forall integer k; (j < k <= i) ==> GapSorted(arr, 0, i, k);
#// loop invariant \forall integer k; j <= k <= gap ==> GapSorted(arr, k, i, gap);
loop assigns j, arr[gap .. i];
# loop variant j;
#*/
for (j = i; j >= gap && arr[j - gap] > tmp; j -= gap) {
arr[j] = arr[j - gap];
//# assert arr[j] >= arr[j - gap];
//# assert tmp < arr[j - gap];
}
//# assert j>=0;
arr[j] = tmp;
}
//# assert i == n;
//# assert GapSorted(arr, 0, i, gap);
//# assert gap > 0;
// assert GapSorted(arr, 0, n, gap);
}
}
What remains to be proved are the GapSorted invariants for the two inner loops, which probably require more work and an answer much longer than what is fit for this format.

Related

What is the use of condition (i< n-1) instead of (i<n) in outerloop of bubble sort?

for (int i = 0; i < (n - 1); i++)
{
for (int j = 0; j < (n - i - 1); j++)
{
if (array[j] > array[j + 1])
{
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
I have replaced (i < n-1) with (i<n) and it works fine for all the test cases.
If 'n' is number of variables in array (i<n) doesn't any segmentation error as it access only last element for maximum value of i.
(if n =10, for a condition (i<n), maximum value of i could be 9 and it access last element i.e a[9].So there would be no segmentation error).
Then what is the purpose if i<n-1 in the outer loop of bubble sort?

Longest sequence that holds a property in Dafny

In Dafny I am trying to make a Max polymorphic and high-order function that, given a sequence and a predicate, returns the longest subsequence that holds it. For instance, the longest increasing subsequence, or the longest subsequence in which all the elements are zero.
To do so, I designed a slow algorithm (given the P predicate and a S sequence):
1. Start an i pivot in the left and a j pivot in the same place.
2. Start the max_sequence = [] and the max_sequence_length = 0.
3. While i<S.length:
counter = 0
j = i
While max_sequence[i..j] satisfies P and j<S.length:
If counter > max_sequence_length:
max_sequence_length = counter
max_sequence = max_sequence[i..j]
Increment j
Increment i
4. Return max_sequence
You can see it implemented:
method maxPropertySequence<T>(P: seq<T> -> bool, sequ: seq<T>) returns (max_seq: seq<T>)
{
var i := 0;
var j := 0;
var longest := 0;
var the_sgmt := sequ;
var fresh_segmnt := sequ;
var counter := longest;
while i<(|sequ|)
decreases |sequ|-i
{
j := i;
counter := 0;
fresh_segmnt := [sequ[i]];
if P(fresh_segmnt)
{
j := j+1;
counter:=counter+1;
if counter>longest {
longest:=counter;
the_sgmt := fresh_segmnt;
}
while P(fresh_segmnt) && j<|sequ|
decreases |sequ|-j
{
fresh_segmnt := fresh_segmnt + [sequ[j]];
j := j+1;
counter:=counter+1;
if counter>longest {
longest:=counter;
the_sgmt := fresh_segmnt;
}
}
}
i := i+1;
}
return the_sgmt;
}
My question is: how can I verify that the Max function behaves as I expect? More concretely: which are the ensures I have to add?
I have thought something like: forall the subsequences of the original sequence, there is no subsequence that holds P and is longer than the_sgmt. But I do not know how to express it efficiently.
Thanks!
I wrote code for finding the (leftmost) longest subsequence of zeros from a given integer array. Since you can map sequ using the predicate, these two are almost identical problems.
// For a given integer array, let's find the longest subesquence of 0s.
// sz: size, pos: position. a[pos..(pos+sz)] will be all zeros
method longestZero(a: array<int>) returns (sz:int, pos:int)
requires 1 <= a.Length
ensures 0 <= sz <= a.Length
ensures 0 <= pos < a.Length
ensures pos + sz <= a.Length
ensures forall i:int :: pos <= i < pos + sz ==> a[i] == 0
ensures forall i,j :: (0 <= i < j < a.Length && getSize(i, j) > sz) ==> exists k :: i <= k <= j && a[k] != 0
{
var b := new int[a.Length]; // if b[i] == n, then a[i], a[i-1], ... a[i-n+1] will be all zeros and (i-n ==0 or a[i-n] !=0)
if a[0] == 0
{b[0] := 1;}
else
{b[0] := 0;}
var idx:int := 0;
while idx < a.Length - 1 // idx <- 0 to a.Length - 2
invariant 0 <= idx <= a.Length - 1
invariant forall i:int :: 0 <= i <= idx ==> 0 <= b[i] <= a.Length
invariant forall i:int :: 0 <= i <= idx ==> -1 <= i - b[i]
invariant forall i:int :: 0 <= i <= idx ==> (forall j:int :: i-b[i] < j <= i ==> a[j] == 0)
invariant forall i:int :: 0 <= i <= idx ==> ( 0 <= i - b[i] ==> a[i - b[i]] != 0 )
{
if a[idx + 1] == 0
{ b[idx + 1] := b[idx] + 1; }
else
{ b[idx + 1] := 0;}
idx := idx + 1;
}
idx := 1;
sz := b[0];
pos := 0;
// Let's find maximum of array b. That is the desired sz.
while idx < a.Length
invariant 1 <= idx <= b.Length
invariant 0 <= sz <= a.Length
invariant 0 <= pos < a.Length
invariant pos + sz <= a.Length
invariant forall i:int :: 0 <= i < idx ==> b[i] <= sz
invariant forall i:int :: pos <= i < pos + sz ==> a[i] == 0
invariant forall i, j:int :: (0 <= i < j < idx && getSize(i,j) > sz) ==> a[j-b[j]] != 0
{
// find max
if b[idx] > sz
{
sz := b[idx];
pos := idx - b[idx] + 1;
}
idx := idx + 1;
}
}
function getSize(i: int, j:int) : int
{
j - i + 1
}
Since I am new to dafny, any comments on style or anything are appreciated.

How to find loop invariant of Sieve of Eratosthenes Algorithm?

Can anyone help me to make loop invarients of Eratosthenes Algorithm please?
Here is the peace of code:
algorithm Sieve of Eratosthenes is
input: an integer n > 1.
output: all prime numbers from 2 through n.
let A be an array of Boolean values, indexed by integers 2 to n,
initially all set to true.
for i = 2, 3, 4, ..., not exceeding √n do
if A[i] is true
for j = i2, i2+i, i2+2i, i2+3i, ..., not exceeding n do
A[j] := false
return all i such that A[i] is true.
After the ith iteration, A[x] = false for all x <= n where x is a multiple of any integer j such that 2 <= j <= i.
You can do as
vector<int> getPrimes(int n) {
vector<bool> A(n + 1, true);
for (int i = 2; i * i <= n; i++) {
for (int j = i * i; j <= n; j += i) {
A[j] = false;
}
}
vector<int> primes;
for (int i = 2; i <= n; i++) {
if (A[i]) {
primes.push_back(i);
}
}
return primes;
}

Find the coefficients of the polynomial given its roots

I am trying to write an algorithm which will find a(0),..., a(n-1), given the values of n, x_1, ..., x_n, a(n), such that:
a(n)*p^n + a(n-1)*p^(n-1) + ... + a(1)*p + a(0) = a(n)(p-x_1)(p-x_2)...(p-x_n)
for all real p.
After multiplying a(n)(p-x_1)(p-x_2) I've thought of using Viete's formulas to find the coefficients.
But it turns out writing the code down isn't as obvious as I expected.
I want to use only the basics in my code - that is loops, if-s addition and multiplication - no ready/ complex functions.
Here are the formulas:
First, I would like to emphasise that I only need a pseudocode, and I do not care about defining arrays for the root and coefficients. That's why I will just write a(n), xn. Oh, and I hope it won't bother you very much if I start indexing from i=1 not i=0 in order to be in synch with the mathematical notation. In order to start with i=0 I would have to renumerate the roots and introduce more brackets.
And this is what I've come up with so far:
a(n-1)=0;
for(i=1; i <= n; i++){
a(n-1) = a(n-1) + x_i;
}
a(n-1) = -a(n)*a(n-1);
a(n-2)=0;
for(i=1; i <= n; i++){
for(j=i; j <= n; j++){
a(n-2) = a(n-2)+ x_i * x_j;
}
}
a(n-2) = -a(n)*a(n-2);
a(n-3)=0;
for(i=1; i <= n; i++){
for(j=i; j <= n; j++){
for(k=j; k <= n; k++){
a(n-3) = a(n-3)+ x_i * x_j * x_k;
}
}
}
a(n-3) = a(n)*a(n-3);
...
a(0)=1;
for(i=1; i<=n; i++){
a(0) = a(0) * x_i;
}
if(n%2 == 0) a(0) = a(n) * a(0);
else a(0) = -a(n) * a(0);
As you can see, it doesn't look good.
I would like to link all those loops into one loop, because without I cannot write the full code, I cannot fill the gap between a(0) and a(n-j) for a fixed j.
Could you help me out?
This is what I have, based on Nico Schertler's answer:
for(i=1; i<=n; i++)
{a(i)=1;
for(j=1; j <= n; j++)
{b(i)= clone( a(i) );
a(i) = a(i-1);
b(i) = x_j * b(i);
c(i) = a(i) - b(i);
}
}
Would it be the same if instead we wrote
for(i=1; i<=n; i++)
{a(i)=1; b(i)=1;
for(j=1; j <= n; j++)
{t = a(i) ;
a(i) = a(i-1);
b(i) = x_j * t;
c(i) = a(i) - b(i);
}
}
(this is how we for example swap two elements of an array, by keeping the value of a[i] in some variable t).
You can create the polynomial incrementally.
Start with p = 1. I.e. a(0) = 1.
In order to add a root, you have to multiply the current polynomial by x - x_i. This is:
p * (x - x_i) = p * x - p * x_i
So you need to support three operations:
1. Multiplication by x
This is quite simple. Just shift all coefficients by one to the left. I.e.
a(i ) := a(i - 1)
a(i - 1) := a(i - 2)
...
a(1 ) := a(0)
a(0 ) := 0
2. Multiplication by a scalar
This is equally simple. Multiply each coefficient:
a(i ) *= s
a(i - 1) *= s
...
3. Subtraction
Just subtract the respective coefficients:
c(i ) = a(i ) - b(i )
c(i - 1) = a(i - 1) - b(i - 1)
...
Altogether
Add root by root. First, clone your current polynomial. Then, do the operations as described above:
p := 1
for each root r
p' = clone(p)
multiply p with x
multiply p' with r
p := p - p'
next
A static function in c# for this purpose.
The roots of x^4-11x^3+44x^2-76x+48 are {2,2,3,4} and given the argument
roots = new Complex[4] {2, 2, 3, 4}
this function returns [48,-76,44,-11,1]
public static double[] FromRoots(Complex[] roots)
{
int N = roots.Length;
Complex[] coefs = new Complex[N + 1];
coefs[0] = -roots[0];
coefs[1] = 1.0;
for (int k = 2; k <= N; k++)
{
coefs[k] = 1.0;
for (int i = k - 2; i >= 0; i--)
{
coefs[i + 1] = coefs[i] - roots[k - 1] * coefs[i + 1];
}
coefs[0] *= -roots[k - 1];
if (Math.IEEERemainder(k, 2) == 1)
coefs[k] = -coefs[k];
}
double[] realCoefs = new double[N + 1];
for (int i = 0; i < N + 1; i++)
realCoefs[i] = coefs[i].Real; // Not sure about this part!
return realCoefs;
}

dafny implementation of insertionsort

i am new in Dafny and i have problems verifying my insertionSort-implementation.
Dafny tells me the the multiset invariants are not holding, anything else is working fine. After Hours of searching the mistake i could need some help :)
Would be nice if somebody could tell me the trick!
My Code:
predicate sorted(a:array<int>, min:int, max:int)
requires a != null;
requires 0<= min <= max <= a.Length;
reads a;
{
forall j, k :: min <= j < k < max ==> a[j] <= a[k]
}
/*
*
*/
method insertionSort(a: array<int>)
requires a != null;
requires a.Length > 0;
ensures sorted(a, 0, a.Length);
ensures multiset(a[..]) == multiset(old(a[..]));
modifies a;
{
var i := 1;
while(i < a.Length)
invariant 1 <= i <= a.Length;
invariant sorted(a, 0, i);
invariant a != null;
invariant multiset(old(a[..])) == multiset(a[..]);
decreases a.Length-i;
{
var j := i - 1;
var key := a[i];
while(j >= 0 && key < a[j])
invariant -1 <= j <= i - 1 <= a.Length;
invariant (j == i-1 && sorted(a, 0, i)) || (sorted(a, 0, i+1));
invariant forall k :: j < k < i ==> a[k] >= key;
invariant -1 < j == i - 1 ==> multiset(old(a[..])) == multiset(a[..]);
invariant |multiset(old(a[..]))| == |multiset(a[..])|;
invariant -1 < j < i - 1 && key < a[j] ==> multiset(old(a[..])) == multiset(a[..]) - multiset({a[j+1]}) + multiset({key});
invariant -1 == j ==> multiset(old(a[..])) == multiset(a[..]) + multiset({key}) - multiset({a[j+1]});
decreases j;
{
a[j + 1] := a[j];
j := j - 1;
}
a[j + 1] := key;
i := i + 1;
}
}
It produces
1 This loop invariant might not be maintained by the loop. 29,38
2 This loop invariant might not be maintained by the loop. 42,73
3 This loop invariant might not be maintained by the loop. 43,52
Link: http://rise4fun.com/Dafny/3R5
Here is a slightly modified algorithm that does verify. It shifts the elements up by doing a swap. I think with a bit more work it could be adapted to your algorithm. It just needs a slightly more complex multiset invariant (which would require a lemma about adding and removing things from multisets).
predicate sorted(a:array<int>, min:int, max:int)
requires a != null;
requires 0<= min <= max <= a.Length;
reads a;
{
forall j, k :: min <= j < k < max ==> a[j] <= a[k]
}
predicate sortedSeq(a:seq<int>)
{
forall j, k :: 0 <= j < k < |a| ==> a[j] <= a[k]
}
lemma sortedSeqSubsequenceSorted(a:seq<int>, min:int, max:int)
requires 0<= min <= max <= |a|
requires sortedSeq(a)
ensures sortedSeq(a[min .. max])
{ }
method swap(a: array<int>, i:int, j:int)
modifies a;
requires a != null && 0 <= i < j < a.Length
requires i + 1 == j
ensures a[..i] == old(a[..i])
ensures a[j+1..] == old(a[j+1..])
ensures a[j] == old(a[i])
ensures a[i] == old(a[j])
ensures multiset(a[..]) == multiset(old(a[..]))
{
var tmp := a[i];
a[i] := a[j];
a[j] := tmp;
}
method insertionSort(a: array<int>)
modifies a;
requires a != null;
requires a.Length > 0;
ensures sorted(a, 0, a.Length);
ensures multiset(a[..]) == multiset(old(a[..]));
{
var i := 0;
while(i < a.Length)
invariant 0 <= i <= a.Length
invariant sorted(a, 0, i)
invariant multiset(old(a[..])) == multiset(a[..]);
{
var key := a[i];
var j := i - 1;
ghost var a' := a[..];
assert sortedSeq(a'[0..i]);
while(j >= 0 && key < a[j])
invariant -1 <= j <= i - 1
invariant a[0 .. j+1] == a'[0 .. j+1]
invariant sorted(a, 0, j+1);
invariant a[j+1] == key == a'[i];
invariant a[j+2 .. i+1] == a'[j+1 .. i]
invariant sorted(a, j+2, i+1);
invariant multiset(old(a[..])) == multiset(a[..])
invariant forall k :: j+1 < k <= i ==> key < a[k]
{
ghost var a'' := a[..];
swap(a, j, j+1);
assert a[0..j] == a''[0..j];
assert a[0..j] == a'[0..j];
assert a[j] == a''[j+1] == a'[i] == key;
assert a[j+2..] == a''[j+2..];
assert a[j+2..i+1] == a''[j+2..i+1] == a'[j+1..i];
j := j - 1;
sortedSeqSubsequenceSorted(a'[0..i], j+1, i);
assert sortedSeq(a'[j+1..i]);
assert a[j+2 .. i+1] == a'[j+1 .. i];
assert sortedSeq(a[j+2..i+1]);
}
i := i + 1;
}
}
http://rise4fun.com/Dafny/Gplux

Resources