(Dafny) Adding elements of an array into another - loop invariant - arrays

I have a function sum that takes two arrays a and b as inputs and modifies b such that b[i] = a[0] + a[1] + ... + a[i]. I wrote this function and want to verify it with Dafny. However, Dafny tells me that my loop invariant might not be maintainted by the loop. Here is the code :
function sumTo(a:array<int>, n:int) : int
requires a != null;
requires 0 <= n < a.Length;
decreases n;
reads a;
{
if (n == 0) then a[0] else sumTo(a, n-1) + a[n]
}
method sum(a:array<int>, b:array<int>)
requires a != null && b != null
requires a.Length >= 1
requires a.Length == b.Length
modifies b
ensures forall x | 0 <= x < b.Length :: b[x] == sumTo(a,x)
{
b[0] := a[0];
var i := 1;
while i < b.Length
invariant b[0] == sumTo(a,0)
invariant 1 <= i <= b.Length
//ERROR : invariant might not be maintained by the loop.
invariant forall x | 1 <= x < i :: b[x] == sumTo(a,x)
decreases b.Length - i
{
b[i] := a[i] + b[i-1];
i := i + 1;
}
}
How can I fix this error?

Your program would not be correct if a and b reference the same array. You need the precondition a != b. (If you add it, Dafny will verify your program.)
Rustan

Related

(Dafny) Postcondition might not hold when filtering vowels

I'm studying for my Dafny exam and I don't know what's wrong with my code.
I think it has something to do with my "index out of range" error but I don't know how to solve that.
Any hints would be greatly appreciated.
The problem:
Given an array of characters, it filters all the vowels.
My approach:
method filterTheVowels(a: array<char>) returns (vowels: array<char>)
requires a.Length > 0
ensures forall i, j | 0 <= i < a.Length && 0 <= j < vowels.Length :: a[i] in ['a','e','i','o','u'] ==> vowels[j] in ['a','e','i','o','u']
// ^^^ THE POSTCONDITION THAT MIGHT NOT HOLD ^^^
{
var count := countTheVowels(a);
vowels := new char[count];
var i := 0;
var j := 0;
while i < a.Length
invariant 0 <= i <= a.Length
invariant 0 <= j <= count
invariant forall k, l | 0 <= k < a.Length && 0 <= l < j :: a[k] in ['a','e','i','o','u'] ==> vowels[l] in ['a','e','i','o','u']
{
if a[i] in ['a','e','i','o','u'] {
vowels[j] := a[i]; // INDEX OUT OF RANGE
j := j + 1;
}
i := i + 1;
}
}
The auxiliary methods:
method countTheVowels(a: array<char>) returns (count: int)
requires a.Length > 0
ensures count >= 0
{
count := 0;
var i := 0;
while i < a.Length
invariant 0 <= i <= a.Length
{
if a[i] in ['a','e','i','o','u'] {
count := count + 1;
}
i := i + 1;
}
}
method Main()
{
var a := new char[6];
a[0],a[1],a[2],a[3],a[4],a[5] := 'c','h','e','e','s','e';
var e := countTheVowels(a);
print e;
}
The errors produced:
/home/dafny/exam/fclex.dfy(9,1): Error: A postcondition might not hold on this return path.
/home/dafny/exam/fclex.dfy(3,8): Related location: This is the postcondition that might not hold.
/home/dafny/exam/fclex.dfy(3,113): Related location
Execution trace:
(0,0): anon0
/home/dafny/exam/fclex.dfy(9,2): anon24_LoopHead
(0,0): anon24_LoopBody
/home/dafny/exam/fclex.dfy(9,2): anon25_Else
(0,0): anon35_Then
/home/dafny/exam/fclex.dfy(15,9): Error: index out of range
Execution trace:
(0,0): anon0
/home/dafny/exam/fclex.dfy(9,2): anon24_LoopHead
(0,0): anon24_LoopBody
/home/dafny/exam/fclex.dfy(9,2): anon25_Else
/home/dafny/exam/fclex.dfy(9,2): anon35_Else
(0,0): anon36_Then
Dafny program verifier finished with 4 verified, 2 errors
Only information dafny can use for verification in filterTheVowels about countTheVowels return value is it is greater than 0. It does n't connect dot between number of vowels and count as it is not part of post condition. One way to avoid this is to make countTheVowels function method
function method countTheVowels(a: seq<char>) : int
{
if |a| == 0 then 0
else if a[0] in ['a','e','i','o','u'] then 1 + countTheVowels(a[1..])
else countTheVowels(a[1..])
}

Identity loop - This loop invariant might not be maintained by the loop

please checkout my code below. The idea is just to add a constant (for example +1) to each array position. But dafny returns BP5005: This loop invariant might not be maintained by the loop. for the forall condition.
It does not make much sense to me, because the loop body literally does exactly what we have defined in the invariant.
It is crucial that the asserts are valid in the Main method.
method doNothing(arr: array<int>)
modifies arr;
ensures arr.Length == old(arr.Length);
ensures forall i :: 0 <= i < arr.Length ==> arr[i] == (old(arr[i]) + 1);
{
var idx: int := 0;
while(idx < arr.Length)
decreases arr.Length - idx;
invariant 0 <= idx <= arr.Length;
// # ERROR: BP5005: This loop invariant might not be maintained by the loop.Dafny VSCode
invariant forall i :: 0 <= i < idx ==> arr[i] == (old(arr[i]) + 1);
{
arr[idx] := arr[idx] + 1;
idx := idx + 1;
}
}
method Main()
{
var arr := new int[3];
arr[0] := 1;
arr[1] := 2;
arr[2] := 3;
doNothing(arr);
assert(arr[0] == 2);
assert(arr[1] == 3);
assert(arr[2] == 4);
}
Does dafny somehow change the reference by assigning the same value???
Can somebody support me?
Thanks in advise.
Your loop invariant speaks about the relation between arr[i] and old(arr[i]) for indices in the range 0..idx. But it doesn't say anything about that relation for indices in the range idx..a.Length. Therefore, there is no information about the value of arr[idx] + 1 that the loop body assigns to arr[idx].
Ok after getting out of my rapid hole, please see the working solution:
thx to #Rustan
The crucial thing to notice is, that we do not need to explicit create an invarient for arr[idx], because this index is coveted by the invariant 0 <= j < idx if we evaluate at the body end.
method doNothing(arr: array<int>)
modifies arr;
ensures arr.Length == old(arr.Length);
ensures forall i :: 0 <= i < arr.Length ==> arr[i] == old(arr[i]) + 1;
{
var idx: int := 0;
while(idx < arr.Length)
decreases arr.Length - idx;
invariant 0 <= idx <= arr.Length;
// #INFO: no need, it's covered by the invariant below, evaluating at the body end.
// invariant arr[idx] == old(arr[idx]) + 1;
invariant forall j : int :: 0 <= j < idx ==> arr[j] == old(arr[j]) + 1;
invariant forall j : int :: idx <= j < arr.Length ==> arr[j] == old(arr[j]);
{
// Evaluate Inv before loop body
arr[idx] := arr[idx] + 1;
idx := idx + 1;
// Evaluate Inv after loop body => uses already updated idx value
}
}
// neglect Main method

I keep getting index out of range error what is wrong with my code?

My code won't run properly I am trying to get it to find peaks including the end and beginning of the array and then compare all the indexes that aren't the beginning or end to the index before and after them does anyone know why I am getting the out of index range error?
package main
import "fmt"
func linearFindPeaks(arg []int) []int {
peaks := []int{}
lenArg := len(arg)
for i := 0; i < lenArg; i++ {
//if its the first element run this
//second if statement for the end of array
// for default statements
if arg[0] > arg[1] {
peaks = append(peaks, arg[0])
} else if arg[lenArg-1] > arg[lenArg-2] {
peaks = append(peaks, arg[lenArg-1])
} else if arg[i] > arg[i+1] && arg[i] > arg[i-1] && arg[i] != arg[0] && arg[i] != arg[lenArg-1] {
peaks = append(peaks, arg[i])
}
}
fmt.Println(peaks)
return peaks
}
func main() {}
Playground: https://play.golang.org/p/2JRgEyRA50
Two possibilities i can see. Firstly, in the first else if:
}else if arg[lenArg - 1] > arg[lenArg -2] {
If lenArg is 1 then lenArg-2will be -1. This means arg[lenArg-2] is arg[-1] which will give you out of bounds.
Secondly, in the second else if:
} else if arg[i] > arg[i+1] ... {
On the last iteration over the loop, i will be lenArg-1, if you add 1 to this you'll get arg[lenArg-1+1] or arg[lenArg] which will out of bounds. (The last available index is at lenArg-1)
The Go Programming Language Specification
Index expressions
A primary expression of the form
a[x]
denotes the element of the slice a indexed by x.
The index x must be of integer type or untyped; it is in range if
0 <= x < len(a)
Otherwise it is out of range.
You need to pay attention to corner cases like lengths 0, 1, and 2 for indices i - 1, i, i + 1 out of range. For example,
package main
// For array a, a[i] is a peak if it is not smaller than its neighbor(s),
// where a[-1] = a[n] = -∞.
func findPeaks(a []int) []int {
var p []int
// special cases
if len(a) == 0 {
return p
}
if len(a) == 1 {
return append(p, a[0])
}
// first
i := 0
if a[i] >= a[i+1] {
p = append(p, a[i])
}
// first < i < last
for i = 1; i < len(a)-1; i++ {
if a[i-1] <= a[i] && a[i] >= a[i+1] {
p = append(p, a[i])
}
}
// last
i = len(a) - 1
if a[i-1] <= a[i] {
p = append(p, a[i])
}
return p
}
func main() {}
Playground: https://play.golang.org/p/9klj1wYnXZ

Array copy wants to modify source

In the following code that copies a slice of an array into another one, the loop invariant that tells that the source array is preserved does not validate.
This is related to this question and this other one, but I have not found anything that works in this case yet.
method copy
(a: array<int>, a0: nat,
b: array<int>, b0: nat,
len: nat)
requires a != null && b != null
requires a0 + len <= a.Length
requires b0 + len <= b.Length
modifies b
{
var i := 0;
while i < len
decreases len - i
invariant i <= len
invariant a[..] == old(a[..])
{
b[b0 + i] := a[a0 + i];
i := i + 1;
}
}
You need to add a precondition that a != b. Otherwise, if a and b are aliased, then the method might indeed modify a.

Find the Ninja Index of an array

It is an interesting puzzle I came across , according to which , given an array , we need to find the ninja index in it.
A Ninja index is defined by these rules :
An index K such that all elements with smaller indexes have values lower or equal to A[K] and all elements with greater indexes have values greater or equal to A[K].
For example , consider :
A[0]=4, A[1]=2, A[2]=2, A[3]=3, A[4]=1, A[5]=4, A[6]=7, A[7]=8, A[8]=6, A[9]=9.
In this case, 5 is a ninja index , since A[r]<=A[5] for r = [0,k] and A[5]<=A[r] r = [k,n].
What algorithm shall we follow to find it in O(n) . I already have a brute force O(n^2) solution.
EDIT : There can be more than 1 ninja index , but we need to find the first one preferably. And in case there is no NI , then we shall return -1.
Precompute minimum values for all the suffixes of the array and maximum values for all prefixes. With this data every element can be checked for Ninja in O(1).
A python solution that will take O(3n) operations
def n_index1(a):
max_i = []
maxx = a[0]
for j in range(len(a)):
i=a[j]
if maxx<=i and j!=0:
maxx=i
max_i.append(1)
else:
max_i.append(-1)
return max_i
def n_index2(a):
max_i = []
maxx = -a[len(a)-1]
for j in range(len(a)-1,-1,-1):
i=-a[j] # mind the minus
if maxx<=i and j!=len(a)-1:
maxx=i
max_i.append(1)
else:
max_i.append(-1)
return max_i
def parse_both(a,b):
for i in range(len(a)):
if a[i]==1 and b[len(b)-1-i]==1:
return i
return -1
def ninja_index(v):
a = n_index1(v)
b = n_index2(v)
return parse_both(a,b)
Another Python solution, following the same general approach. Maybe a bit shorter.
def ninja(lst):
maxs = lst[::]
mins = lst[::]
for i in range(1, len(lst)):
maxs[ i] = max(maxs[ i], maxs[ i-1])
mins[-1-i] = min(mins[-1-i], mins[-i ])
return [i for i in range(len(lst)) if maxs[i] <= lst[i] <= mins[i]]
I guess it could be optimized a bit w.r.t that list-copying-action, but this way it's more concise.
This straight-forward Java code calculates leftmost index that has property "all elements rightwards are not lesser":
private static int fwd(int[] a) {
int i = -1;
for (int j = 0; j < a.length - 1; j++) {
if (a[j + 1] >= a[j] && i == -1) {
i = j + 1;
} else if (i != -1 && a[j + 1] < a[i]) {
i = -1;
}
}
return i;
}
Almost same code calculates leftmost index that has property "all elements leftwards are not greater":
private static int bwd(int[] a) {
int i = -1;
for (int j = 0; j < a.length - 1; j++) {
if (a[j + 1] >= a[j] && i == -1) {
i = j + 1;
} else if (i != -1 && a[j + 1] < a[i]) {
i = -1;
}
}
return i;
}
If results are the same, leftmost Ninja index is found.

Resources