I am trying to verify a code that uses simple modulo operation in a while loop to insert the digits of a number into an array.
I recieve a number,
an array with defined size,
and start - an index in the array from which I fit the most significant digit.
i.e if n=123, a = [w,x,y,z], start=0 then I need to create an array [1,2,3] and then fit it into a: [1,2,3,z]
I start by enforcing that the count of number digits (3 in our example) + the starting index do not exceed the bounds of the target array a.
If it doesn't exceed the bounds, I start slicing the number into digits:
var i:nat := (start + nLength - 1);
var n':=n;
while (i>=start && i>0)
decreases i
****invariant *********
{
a[i] := (n' % 10);
i := i - 1;
n' := n' / 10;
}
I am unable to find the right invariant to enfroce the correctness of the loop I made to iterate over the number and split it into digits.
Any suggestions?
Let me help you with a possible invariant. It looks like this invariant holds, but I was not able to prove it. Probably it requires more engineering.
function computeNumber(a: seq<int>, startIncluded: int, endExcluded: int, multiplier: int): int
decreases endExcluded - startIncluded
requires 0 <= startIncluded <= endExcluded <= |a|
requires startIncluded >= endExcluded
{
if startIncluded >= endExcluded then 0
else a[startIncluded]*multiplier + computeNumber(a, startIncluded+1, endExcluded, multiplier/10)
}
...
var endExcluded := start + nLength;
var i:int := endExcluded;
var n':=n;
ghost var tenPower := 1;
ghost var remainder := 0;
while n' > 0 && i > 0
decreases i
invariant n == n' * tenPower + remainder
invariant computeNumber(a[..], i, endExcluded, tenPower) == remainder
{
i := i - 1;
var digit := n' % 10;
a[i] := digit;
n' := n' / 10;
remainder := digit * tenPower + remainder;
tenPower := tenPower * 10;
}
if n' == 0 && i >= 0 {
assert n == remainder;
assert computeNumber(a[..], i, endExcluded, tenPower) == n;
}
Related
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..])
}
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
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.
I really need some help at this problem:
Given a positive integer N, we define xsum(N) as sum's sum of all positive integer divisors' numbers less or equal to N.
For example: xsum(6) = 1 + (1 + 2) + (1 + 3) + (1 + 2 + 4) + (1 + 5) + (1 + 2 + 3 + 6) = 33.
(xsum - sum of divizors of 1 + sum of divizors of 2 + ... + sum of div of 6)
Given a positive integer K, you are asked to find the lowest N that satisfies the condition: xsum(N) >= K
K is a nonzero natural number that has at most 14 digits
time limit : 0.2 sec
Obviously, the brute force will fall for most cases with Time Limit Exceeded. I haven't find something better than it yet, so that's the code:
fscanf(fi,"%lld",&k);
i=2;
sum=1;
while(sum<k) {
sum=sum+i+1;
d=2;
while(d*d<=i) {
if(i%d==0 && d*d!=i)
sum=sum+d+i/d;
else
if(d*d==i)
sum+=d;
d++;
}
i++;
}
Any better ideas?
For each number n in range [1 , N] the following applies: n is divisor of exactly roundDown(N / n) numbers in range [1 , N]. Thus for each n we add a total of n * roundDown(N / n) to the result.
int xsum(int N){
int result = 0;
for(int i = 1 ; i <= N ; i++)
result += (N / i) * i;//due to the int-division the two i don't cancel out
return result;
}
The idea behind this algorithm can aswell be used to solve the main-problem (smallest N such that xsum(N) >= K) in faster time than brute-force search.
The complete search can be further optimized using some rules we can derive from the above code: K = minN * minN (minN would be the correct result if K = 2 * 3 * ...). Using this information we have a lower-bound for starting the search.
Next step would be to search for the upper bound. Since the growth of xsum(N) is (approximately) quadratic we can use this to approximate N. This optimized guessing allows to find the searched value pretty fast.
int N(int K){
//start with the minimum-bound of N
int upperN = (int) sqrt(K);
int lowerN = upperN;
int tmpSum;
//search until xsum(upperN) reaches K
while((tmpSum = xsum(upperN)) < K){
int r = K - tmpSum;
lowerN = upperN;
upperN += (int) sqrt(r / 3) + 1;
}
//Now the we have an upper and a lower bound for searching N
//the rest of the search can be done using binary-search (i won't
//implement it here)
int N;//search for the value
return N;
}
I am writing program to count Bell numbers,
it is my first big program in OCaml.
I want to use loop While in the loop While, but there is syntax error.
Please correct it. Thanks.
I'm using site http://try.ocamlpro.com/
let rec factorial n =
if n < 2
then 1
else
n * factorial(n-1)
let rec newton n k =
factorial n / (factorial k * factorial (n-k))
let bell = [|1;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0|]
let i = ref 2
let k = ref 0
let x = ref 0
let z = ref 0
let s = ref 0
here you need to choose number u want to calc e.g. 4
let n = ref 4
if !n != 0 || !n != 1 then
while !i <= !n do
while !k <= (!i-1) do
x := newton (!i-1) !k;
s := !s + (!x * bell.(!k));
k := !k + 1 ;
z := !k + 1
done
s:=0;
i:= !i + 1;
done
else
bell.(!n)<-1
should use Num to calc Bell numbers, but I first I I would like to make the program work on int
You can try to add ; after 1st done.