Array copy wants to modify source - arrays

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.

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

Maximum binary number a binary string will result to if only one operation is allowed i.e. Right-Rotate By K-Bits where K = [0, Length of String]

Suppose you have a binary string S and you are only allowed to do one operation i.e. Right-Rotate by K-bits where K = [0, Length of the string]. Write an algorithm that will print the maximum binary-number you can create by the defined process.
For Example:
S = [00101] then maximum value I can get from the process is 10100 i.e. 20.
S = [011010] then maximum value I can get from the process is 110100 i.e. 52.
S = [1100] then maximum value I can get from the process is 1100 i.e. 12.
The length of the string S has an upper-limit i.e. 5*(10^5).
The idea which I thought of is kind of very naive which is: as we know that when you right-rotate any binary number by 1-bit, you get the same binary number after m rotations where m = number of bits required to represent that number.
So, I right-rotate by 1 until I get to the number with which I started with and during the process, I keep track of the max-value I encountered and in last I print the max-value.
Is there an efficient approach to solve the problem?
UPD1: This the source of the problem One-Zero, it all boils down to the statement I have described above.
UPD2: As the answer can be huge, the program will print the answer modulo 10^9 + 7.
You want to find the largest number expressed in a binary encoded string with wrap around.
Here are steps for a solution:
let len be the length of the string
allocate an array of size 2 * len and duplicate the string to it.
using linear search, find the position pos of the largest substring of length len in this array (lexicographical order can be used for that).
compute res, the converted number modulo 109+7, reading len bits starting at pos.
free the array and return res.
Here is a simple implementation as a function:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long max_bin(const char *S) {
size_t i, pos, len;
char *a;
// long has at least 31 value bits, enough for numbers upto 2 * 1000000007
long res;
if ((len = strlen(S)) == 0)
return 0;
if ((a = malloc(len + len)) == NULL)
return -1;
memcpy(a, S, len);
memcpy(a + len, S, len);
// find the smallest right rotation for the greatest substring
for (pos = i = len; --i > 0;) {
if (memcmp(a + i, a + pos, len) > 0)
pos = i;
}
res = 0;
for (i = 0; i < len; i++) {
res = res + res + a[pos + i] - '0';
if (res >= 1000000007)
res -= 1000000007;
}
free(a);
return res;
}
int main(int argc, char *argv[]) {
for (int i = 1; i < argc; i++) {
printf("[%s] -> %ld\n", argv[i], max_bin(argv[i]));
}
return 0;
}
It is feasible to avoid memory allocation if it is a requirement.
It's me again.
I got to thinking a bit more about your problem in the shower this morning, and it occurred to me that you could do a QuickSelect (if you're familiar with that) over an array of the start indexes of the input string and determine the index of the most "valuable" rotate based on that.
What I show here does not concern itself with presenting the result the way you are required to, only with determining what the best offset for rotation is.
This is not a textbook QuickSelect implementation but rather a simplified method that does the same thing while taking into account that it's a string of zeros and ones that we are dealing with.
Main driver logic:
static void Main(string[] args)
{
Console.WriteLine(FindBestIndex("")); // exp -1
Console.WriteLine(FindBestIndex("1")); // exp 0
Console.WriteLine(FindBestIndex("0")); // exp 0
Console.WriteLine(FindBestIndex("110100")); // exp 0
Console.WriteLine(FindBestIndex("100110")); // exp 3
Console.WriteLine(FindBestIndex("01101110")); // exp 4
Console.WriteLine(FindBestIndex("11001110011")); // exp 9
Console.WriteLine(FindBestIndex("1110100111110000011")); // exp 17
}
Set up the index array that we'll be sorting, then call FindHighest to do the actual work:
static int FindBestIndex(string input)
{
if (string.IsNullOrEmpty(input))
return -1;
int[] indexes = new int[input.Length];
for (int i = 0; i < indexes.Length; i++)
{
indexes[i] = i;
}
return FindHighest(input, indexes, 0, input.Length);
}
Partition the index array into two halves depending on whether each index points to a string that starts with zero or one at this offset within the string.
Once that's done, if we have just one element that started with one, we have the best string, else if we have more, partition those based on the next index. If none started with one, proceed with zero in the same way.
static int FindHighest(string s, int[] p, int index, int len)
{
// allocate two new arrays,
// one for the elements of p that have zero at this index, and
// one for the elements of p that have one at this index
int[] zero = new int[len];
int[] one = new int[len];
int count_zero = 0;
int count_one = 0;
// run through p and distribute its elements to 'zero' and 'one'
for (int i = 0; i < len; i++)
{
int ix = p[i]; // index into string
int pos = (ix + index) % s.Length; // wrap for string length
if (s[pos] == '0')
{
zero[count_zero++] = ix;
}
else
{
one[count_one++] = ix;
}
}
// if we have a one in this position, use that, else proceed with zero (below)
if (count_one > 1)
{
// if we have more than one, sort on the next position (index)
return FindHighest(s, one, index + 1, count_one);
} else if (count_one == 1)
{
// we have exactly one entry left in ones, so that's the best one we have overall
return one[0];
}
if (count_zero > 1)
{
// if we have more than one, sort on the next position (index)
return FindHighest(s, zero, index + 1, count_zero);
}
else if (count_zero == 1)
{
// we have exactly one entry left in zeroes, and we didn't have any in ones,
// so this is the best one we have overall
return zero[0];
}
return -1;
}
Note that this can be optimized further by expanding the logic: If the input string has any ones at all, there's no point in adding indexes where the string starts with zero to the index array in FindBestIndex since those will be inferior. Also, if an index does start with a one but the previous index also did, you can omit the current one as well because the previous index will always be better since that string flows into this character.
If you like, you can also refactor to remove the recursion in favor of a loop.
If I were tackling this I would do so as follows.
I think it's all to do with counting alternating runs of '1' and runs of '0', treating a run of '1's followed by a run of '0's as a pair, then bashing a list of those pairs.
Let us start by scanning to the first '1', and setting start position s. Then count each run of '1's c1 and the following run of '0's c0, creating pairs (c1,c0).
The scan then proceeds forwards to the end, wrapping round as required. If we represent runs of one or more '1' and '0' as single digits, and '|' as the start and end of the string, then we have cases:
|10101010|
^ initial start position s -- the string ends neatly with a run of '0's
|1010101|
^ new start position s -- the string starts and ends in a '1', so the first
run of '1's and run of '0's are rotated (left),
to be appended to the last run of '1's
Note that this changes our start position.
|01010101|
^ initial start position s -- the first run of '0's is rotated (left),
to follow the last run of '1's.
|010101010|
^ initial start position s -- the first run of '0's is rotated (left),
to be appended to the last run of '0's.
NB: if the string both starts and ends with a '1', there are, initially, n runs of '0's and n+1 runs of '1's, but the rotation reduces that to n runs of '1's. And similarly, but conversely, if the string both starts and ends with a '0'.
Let us use A as shorthand for the pair (a1,a0). Suppose we have another pair, X -- (x1,x0) -- then can compare the two pairs, thus:
if a1 > x1 or (a1 = x1 and (a0 < x0) => A > X -- A is better start
if a1 = x1 and a0 = x0 => A = X
if a1 < x1 or (a1 = x1 and (a0 > x0) => A < X -- X is better start
The trick is probably to pack each pair into an integer -- say (x1 * N) - x0, where N is at least the maximum allowed length of the string -- for ease of comparison.
During the scan of the string (described above) let us construct a vector of pairs. During that process, collect the largest pair value A, and a list of the positions, s, of each appearance of A. Each s on the list is a potential best start position. (The recorded s needs to be the index in the vector of pairs and the offset in the original string.)
[If the input string is truly vast, then constructing the entire vector of all pairs will eat memory. In which case the vector would need to be handled as a "virtual" vector, and when an item in that vector is required, it would have to be created by reading the respective portion of the actual string.]
Now:
let us simplify groups of two or more contiguous A. Clearly the second and subsequent A's in such a group cannot be the best start, since there is a better one immediately to the left. So, in the scan we need to record only the s for the first A of such groups.
if the string starts with one or more A's and ends with one or more A's, need to "rotate" to collect those as a single group, and record the s only for the leftmost A in that group (in the usual way).
If there is only one s on the list, our work is done. If the string is end-to-end A, that will be spotted here.
Otherwise, we need to consider the pairs which follow each of the s for our (initial) A's -- where when we say 'follow' we include wrapping round from the end to the start of the string (and, equivalently, the list of pairs).
NB: at this point we know that all the (initial) A's on our list are followed by zero or more A's and then at least one x, where x < A.
So, set i = 1, and consider all the pairs at s+i for our list of s. Keep only the s for the instances of the largest pair found. So for i = 1, in this example we are considering pairs x, y and z:
...Ax....Az...Az..Ax...Ay...
And if x is the largest, this pass discards Ay and both Az. If only one s remains -- in the example, y is the largest -- our work is done. Otherwise, repeat for i = i+1.
There is one last (I think) wrinkle. Suppose after finding z to be the largest of the ith pairs, we have:
...A===zA===z...
where the two runs === are the same as each other. By the same logic that told us to ignore second and subsequent A's in runs of same, we can now discard the second A===z. Indeed we can discard third, fourth, etc. contiguous A===z. Happily that deals with the extreme case of (say):
=zA===zA===zA==
where the string is a sequence of A===z !
I dunno, that all seems more complicated than I expected when I set out with my pencil and paper :-(
I imagine someone much cleverer than I can reduce this to some standard greatest prefix-string problem.
I was bored today, so I knocked out some code (and revised it on 10-Apr-2020).
typedef unsigned int uint ; // assume that's uint32_t or similar
enum { max_string_len = 5 * 100000 } ; // 5 * 10^5
typedef uint64_t pair_t ;
static uint
one_zero(const char* str, uint N)
{
enum { debug = false } ;
void* mem ;
size_t nmx ;
uint s1, s0 ; // initial run of '1'/'0's to be rotated
uint s ;
pair_t* pv ; // pair vector
uint* psi ; // pair string index
uint* spv ; // starts vector -- pair indexes
uint pn ; // count of pairs
uint sn ; // count of starts
pair_t bp ; // current best start pair value
uint bpi ; // current best start pair index
uint bsc ; // count of further best starts
char ch ;
if (N > max_string_len)
{
printf("*** N = %u > max_string_len (%u)\n", N, max_string_len) ;
return UINT_MAX ;
} ;
if (N < 1)
{
printf("*** N = 0 !!\n") ;
return UINT_MAX ;
} ;
// Decide on initial start position.
s = s1 = s0 = 0 ;
if (str[0] == '0')
{
// Start at first '1' after initial run of '0's
do
{
s += 1 ;
if (s == N)
return 0 ; // String is all '0's !!
}
while (str[s] == '0') ;
s0 = s ; // rotate initial run of '0's
}
else
{
// First digit is '1', but if last digit is also '1', need to rotate.
if (str[N-1] == '1')
{
// Step past the leading run of '1's and set length s1.
// This run will be appended to the last run of '1's in the string
do
{
s += 1 ;
if (s == N)
return 0 ; // String is all '1's !!
}
while (str[s] == '1') ;
s1 = s ; // rotate initial run of '1's
// Step past the (now) leading run of '0's and set length s0.
// This run will be appended to the last run of '1's in the string
//
// NB: we know there is at least one '0' and at least one '1' before
// the end of the string
do { s += 1 ; } while (str[s] == '0') ;
s0 = s - s1 ;
} ;
} ;
// Scan the string to construct the vector of pairs and the list of potential
// starts.
nmx = (((N / 2) + 64) / 64) * 64 ;
mem = malloc(nmx * (sizeof(pair_t) + sizeof(uint) + sizeof(uint))) ;
pv = (pair_t*)mem ;
spv = (uint*)(pv + nmx) ;
psi = (uint*)(spv + nmx) ;
pn = 0 ;
bp = 0 ; // no pair is 0 !
bpi = 0 ;
bsc = 0 ; // no best yet
do
{
uint x1, x0 ;
pair_t xp ;
psi[pn] = s ;
x1 = x0 = 0 ;
do
{
x1 += 1 ;
s += 1 ;
ch = (s < N) ? str[s] : '\0' ;
}
while (ch == '1') ;
if (ch == '\0')
{
x1 += s1 ;
x0 = s0 ;
}
else
{
do
{
x0 += 1 ;
s += 1 ;
ch = (s < N) ? str[s] : '\0' ;
}
while (str[s] == '0') ;
if (ch == '\0')
x0 += s0 ;
} ;
// Register pair (x1,x0)
reg:
pv[pn] = xp = ((uint64_t)x1 << 32) - x0 ;
if (debug && (N == 264))
printf("si=%u, sn=%u, pn=%u, xp=%lx bp=%lx\n", psi[sn], sn, pn, xp, bp) ;
if (xp > bp)
{
// New best start.
bpi = pn ;
bsc = 0 ;
bp = xp ;
}
else
bsc += (xp == bp) ;
pn += 1 ;
}
while (ch != '\0') ;
// If there are 2 or more best starts, need to find them all, but discard
// second and subsequent contiguous ones.
spv[0] = bpi ;
sn = 1 ;
if (bsc != 0)
{
uint pi ;
bool rp ;
pi = bpi ;
rp = true ;
do
{
pi += 1 ;
if (pv[pi] != bp)
rp = false ;
else
{
bsc -= 1 ;
if (!rp)
{
spv[sn++] = pi ;
rp = true ;
} ;
} ;
}
while (bsc != 0) ;
} ;
// We have: pn pairs in pv[]
// sn start positions in sv[]
for (uint i = 1 ; sn > 1 ; ++i)
{
uint sc ;
uint pi ;
pair_t bp ;
if (debug && (N == 264))
{
printf("i=%u, sn=%u, pv:", i, sn) ;
for (uint s = 0 ; s < sn ; ++s)
printf(" %u", psi[spv[s]]) ;
printf("\n") ;
} ;
pi = spv[0] + i ; // index of first s+i pair
if (pi >= pn) { pi -= pn ; } ;
bp = pv[pi] ; // best value, so far.
sc = 1 ; // new count of best starts
for (uint sj = 1 ; sj < sn ; ++sj)
{
// Consider the ith pair ahead of sj -- compare with best so far.
uint pb, pj ;
pair_t xp ;
pb = spv[sj] ;
pj = pb + i ; // index of next s+i pair
if (pj >= pn) { pj -= pn ; } ;
xp = pv[pj] ;
if (xp == bp)
{
// sj is equal to the best so far
//
// So we keep both, unless we have the 'A==zA==z' case,
// where 'z == xp == sp', the current 'ith' position.
uint pa ;
pa = pi + 1 ;
if (pa == pn) { pa = 0 ; } ; // position after first 'z'
// If this is not an A==zA==z case, keep sj
// Otherwise, drop sj (by not putting it back into the list),
// but update pi so can spot A==zA==zA===z etc. cases.
if (pa != pb)
spv[sc++] = spv[sj] ; // keep sj
else
pi = pj ; // for further repeats
}
else if (xp < bp)
{
// sj is less than best -- do not put it back into the list
}
else
{
// sj is better than best -- discard everything so far, and
// set new best.
sc = 1 ; // back to one start
spv[0] = spv[sj] ; // new best
pi = pj ; // new index of ith pair
bp = xp ; // new best pair
} ;
} ;
sn = sc ;
} ;
s = psi[spv[0]] ;
free(mem) ;
return s ;
}
I have tested this against the brute force method given elsewhere, and as far as I can see this is (now, on 10-Apr-2020) working code.
When I timed this on my machine, for 100,000 random strings of 400,000..500,000 characters (at random) I got:
Brute Force: 281.8 secs CPU
My method: 130.3 secs CPU
and that's excluding the 8.3 secs to construct the random string and run an empty test. (That may sound a lot, but for 100,000 strings of 450,000 characters, on average, that's a touch less than 1 CPU cycle per character.)
So for random strings, my complicated method is a little over twice as fast as brute-force. But it uses ~N*16 bytes of memory, where the brute-force method uses N*2 bytes. Given the effort involved, the result is not hugely gratifying.
However, I also tried two pathological cases, (1) repeated "10" and (2) repeated "10100010" and for just 1000 (not 100000) strings of 400,000..500,000 characters (at random) I got:
Brute Force: (1) 1730.9 (2) 319.0 secs CPU
My method: 0.7 0.7 secs CPU
That O(n^2) will kill you every time !
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
int convt(int N,string S)
{
int sum=0;
for(int i=0; i<N; i++)
{
int num=S[i];
sum += pow(2,N-1-i)*(num-48);
}
return sum;
}
string rot(int N, string S)
{
int temp;
temp = S[0];
for( int i=0; i<N;i++)
S[i]=S[i+1];
S[N-1]=temp;
return S;
}
int main() {
int t;
cin>>t;
while(t--)
{
int N,K;
cin>>N;
cin>>K;
char S[N];
for(int i=0; i<N; i++)
cin>>S[i];
string SS= S;
int mx_val=INT_MIN;
for(int i=0;i<N;i++)
{
string S1=rot(N,SS);
SS= S1;
int k_val=convt(N,SS);
if (k_val>mx_val)
mx_val=k_val;
}
int ki=0;
int j=0;
string S2=S;
while(ki!=K)
{
S2=rot(N,S2);
if (convt(N,S2)==mx_val)
ki++;
j++;
}
cout<<j<<endl;
}
}

What's an inductive invariant for this piece of code?

For this piece of code:
// n is a user input that can be any integer
s = 0
i = 0
while i < n:
s = s + 1
i = i + 1
return s
I would like to prove that the post condition is if n > 0 then s = sum(0, n) else s = 0 where sum(s,e) just adds 1 from s to e exclusive, starting from initial value of 0.
I thought an invariant is
if n > 0 and i < n then s = sum(0, i) else s = 0 but I can't get it to be proven in Coq or z3. Any hints?
You seem to imply that this algorithm computes the sum but it doesn't actually do that. Instead, it'll count up to n. Perhaps what you intended is:
i = 0
s = 0
while i < n:
i = i+1
s = s+i
Note that we increment s by i, not by 1 as in your program.
Assuming this is the intended program, then a good invariant would be:
s is the sum of all numbers upto and including i
i is at most n
In more programmatic notation:
s == i*(i+1)/2 && i <= n
To see why, remember that the invariant has to hold before and after each loop iteration; and when the loop condition is false, it needs to imply your post-condition. That's why you need the conjunct i <= n, so that when you exit the loop, s will contain the sum indeed.
How about this solution:
// Function left unimplemented, for simplicity
function sum(s: Int, e: Int): Int
ensures result == e - s
method foo(n: Int) returns (s: Int)
requires 0 <= n
{
var i: Int := 0
s := 0
while (i < n)
invariant s == n - sum(i, n)
{
s := s + 1
i := i + 1
}
}
Language and tool are called Viper. You can try your example online (the web interface is somewhat slow and unstable), or use the VSCode plugin.

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

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

Resources