How to write a specification of a method that char array convert to an integer in dafny? - specifications

method atoi(a:array<char>) returns(r:int)
requires a.Length>0
requires forall k :: 0<= k <a.Length ==> (a[k] as int) - ('0' as int) <= 9
ensures ??
{
var j:int := 0;
while j < a.Length
invariant ??
{
r := r*10 + (a[j] as int) - ('0' as int);
j := j + 1;
}
}
How to write "ensures" for the atoi method and "invariant" for the while loops in dafny?
I express the idea "each bit of the return value corresponds to each bit of the character array" as following:
// Ten to the NTH power
// e.g.: ten_pos_pow(2) == 10*10 == 100
function ten_pos_pow(p:int):int
requires p>=0
ensures ten_pos_pow(p) >= 1
{
if p==0 then 1 else
10*ten_pos_pow(p-1)
}
// Count from right to left, the ith digit of integer v (i starts from zero)
// e.g.: num_in_int(123,0) == 3 num_in_int(123,1) == 2 num_in_int(123,2) == 1
function num_in_int(v:int,i:int) : int
requires i>=0
{
(v % ten_pos_pow(i+1))/ten_pos_pow(i)
}
method atoi(a:array<char>) returns(r:int)
requires a.Length>0
requires forall k :: 0<= k <a.Length ==> (a[k] as int) - ('0' as int) <= 9
ensures forall k :: 0<= k < a.Length ==> ((a[k] as int) - ('0' as int)) == num_in_int(r,a.Length-k-1)
{
var i:int := 0;
r := 0;
while i < a.Length
invariant 0<= i <= a.Length
invariant forall k :: 0<= k < i ==> ((a[k] as int) - ('0' as int)) == num_in_int(r,i-k-1) // loop invariant violation
{
r := r*10 + (a[i] as int) - ('0' as int);
i := i + 1;
}
}
But the loops invariant violation. How to write a correct and provable specification?

Related

Trigger Dafny with multisets

This lemma verifies, but it raises the warning Not triggers found:
lemma multisetPreservesGreater (a:seq<int>, b:seq<int>, c:int, f:int, x:int)
requires |a|==|b| && 0 <= c <= f + 1 <= |b|
requires (forall j :: c <= j <= f ==> a[j] >= x)
requires multiset(a[c..f+1]) == multiset(b[c..f+1])
ensures (forall j :: c <= j <= f ==> b[j] >= x)
{
assert (forall j :: j in multiset(a[c..f+1]) ==> j in multiset(b[c..f+1]));
}
I do not know how to instantiate this trigger (cannot instantiate it as a function, or can I?). Any help?
Edit: Maybe I can instantiate a method f such that takes an array and inserts it in a multiset, and therefore I can trigger f(a), but that does not mention i. I will try.
Here's one way to transform the program so that there are no trigger warnings.
function SeqRangeToMultiSet(a: seq<int>, c: int, f: int): multiset<int>
requires 0 <= c <= f + 1 <= |a|
{
multiset(a[c..f+1])
}
lemma multisetPreservesGreater (a:seq<int>, b:seq<int>, c:int, f:int, x:int)
requires |a|==|b| && 0 <= c <= f + 1 <= |b|
requires (forall j :: c <= j <= f ==> a[j] >= x)
requires multiset(a[c..f+1]) == multiset(b[c..f+1])
ensures (forall j :: c <= j <= f ==> b[j] >= x)
{
assert forall j :: j in SeqRangeToMultiSet(a, c, f) ==> j in SeqRangeToMultiSet(b, c, f);
forall j | c <= j <= f
ensures b[j] >= x
{
assert b[j] in SeqRangeToMultiSet(b, c, f);
}
}
The point is that we introduce the function SeqRangeToMultiSet to stand for a subexpression that is not a valid trigger (because it contains arithmetic). Then SeqRangeToMultiSet itself can be the trigger.
The downside of this approach is that it decreases automation. You can see that we had to add a forall statement to prove the postcondition. The reason is that we need to mention the trigger, which does not appear in the post condition.

Facing Issues in Recursion of Perfect Number Problem

I've been working on the scala recursion problem. I used to develop the program using loops and then use the concept of recursion to convert the existing loop problem in a recursive solution.
So I have written the following code to find the perfect number using loops.
def isPerfect(n: Int): Boolean = {
var sum = 1
// Find all divisors and add them
var i = 2
while ( {
i * i <= n
}) {
if (n % i == 0) if (i * i != n) sum = sum + i + n / i
else sum = sum + i
i += 1
}
// If sum of divisors is equal to
// n, then n is a perfect number
if (sum == n && n != 1) return true
false
}
Here is my attempt to convert it into a recursive solution. But I'm getting the incorrect result.
def isPerfect(n: Int): Boolean = {
var sum = 1
// Find all divisors and add them
var i = 2
def loop(i:Int, n:Int): Any ={
if(n%i == 0) if (i * i != n) return sum + i + n / i
else
return loop(i+1, sum+i)
}
val sum_ = loop(2, n)
// If sum of divisors is equal to
// n, then n is a perfect number
if (sum_ == n && n != 1) return true
false
}
Thank you in advance.
Here is a tail-recursive solution
def isPerfectNumber(n: Int): Boolean = {
#tailrec def loop(d: Int, acc: List[Int]): List[Int] = {
if (d == 1) 1 :: acc
else if (n % d == 0) loop(d - 1, d :: acc)
else loop(d - 1, acc)
}
loop(n-1, Nil).sum == n
}
As a side-note, functions that have side-effects such as state mutation scoped locally are still considered pure functions as long as the mutation is not visible externally, hence having while loops in such functions might be acceptable.

Dafny fails to prove max element in integer array

I'm trying to prove a simple program in Dafny that finds the maximum element of an integer array. Dafny succeeds in a few seconds proving the program below. When I remove the comments from the last two ensures specifications, Dafny fires error messages saying that
a postcondition might not hold on this return path
This is probably caused by the fact that index is guaranteed to be <= a.Length. However, max_index < a.Length is correct, and I'm having a hard time proving it. I tried writing a nested invariant in the if statement, but Dafny rejected that syntax. Any possible solution?
Here is my code:
method FindMax(a: array<int>) returns (max: int, max_index : int)
requires a.Length > 0
ensures forall k :: 0 <= k < a.Length ==> a[k] <= max
ensures 0 <= max_index
// ensures max_index < a.Length
// ensures a[max_index] == max
{
max := 0;
var index := 0;
max_index := 0;
while index < a.Length
invariant 0 <= index <= a.Length
invariant forall k :: 0 <= k < index ==> a[k] <= max
{
if (max < a[index])
// invariant 0 <= index < a.Length
{
max := a[index];
max_index := index;
}
index := index + 1;
}
}
It turns out my loop invariants needed more careful planning. Here is the correct version:
method FindMax(a: array<int>) returns (max: int, max_index : int)
requires a.Length > 0
ensures forall k :: 0 <= k < a.Length ==> a[k] <= max
ensures 0 <= max_index
ensures max_index < a.Length
ensures a[max_index] == max
{
var index := 0;
max_index := 0;
max := a[max_index];
while index < a.Length
invariant max_index < a.Length
invariant 0 <= index <= a.Length
invariant forall k :: 0 <= k < index ==> a[k] <= max
invariant a[max_index] == max
{
if (max < a[index])
{
max := a[index];
max_index := index;
}
index := index + 1;
}
}
And it takes Dafny a little over than 10 seconds to prove.

coq Basics: bin_to_nat function

I am passing Logical Foundations course and became stuck upon the last excersize of Basics:
Having binary number write a converter to it's unary representation:
Inductive bin : Type :=
| Z
| A (n : bin)
| B (n : bin).
Fixpoint bin_to_nat (m:bin) : nat :=
(* What to do here? *)
I solved the problem with a recursive function in C. The only thing, I used "0" istead of "A" and "1" instead of "B".
#include <stdio.h>
unsigned int pow2(unsigned int power)
{
if(power != 0)
return 2 << (power - 1);
else
return 1;
}
void rec_converter(char str[], size_t i)
{
if(str[i] == 'Z')
printf("%c", 'Z');
else if(str[i] == '0')
rec_converter(str, ++i);
else if(str[i] == '1')
{
unsigned int n = pow2(i);
for (size_t j = 0; j < n; j++)
{
printf("%c", 'S');
}
rec_converter(str, ++i);
}
}
int main(void)
{
char str[] = "11Z";
rec_converter(str, 0);
printf("\n");
return 0;
}
My problem now is how to write this code in coq:
unsigned int n = pow2(i);
for (size_t j = 0; j < n; j++)
{
printf("%c", 'S');
}
rec_converter(str, ++i);
The main difference between your code and the Coq code is that the Coq code ought to return the natural number, rather than printing it. That means we'll need to keep track of everything that your solution printed and return the result all at once.
Since printing an S means that the answer is the successor of whatever else is printed, we'll need a function that can take the 2^(n)th successor of a natural number. There are various ways to do this, but I'd suggest recursion on n and noting that the 2^(n + 1)th successor of x is the 2^(n)th successor of the 2^(n)th successor of x.
That should be enough to get what you want.
unsigned int n = pow2(i);
for (size_t j = 0; j < n; j++)
{
printf("%c", 'S');
}
rec_converter(str, ++i);
can be written (in pseudo-Coq) as
pow2_succ i (rec_converter str (S i)).
However, one other thing to note: you may not be able to directly access the ith "character" of the input, but this shouldn't be a problem. When you write your function as a Fixpoint
Fixpoint rec_converter (n: bin) (i: nat): nat :=
match n with
| Z => 0
| A m => ...
| B m => ...
end.
the first "character" of m will be the second "character" of the original input. So you'll just need to access the first "character", which is exactly what a Fixpoint does.
For the question on computing powers of 2, you should look at the following file, provided in the Coq libraries (at least up to version 8.9):
https://coq.inria.fr/distrib/current/stdlib/Coq.Init.Nat.html
This file contains a host of functions around the natural numbers, they could all be used as illustrations about how to program with Coq and this datatype.
Fixpoint bin_to_nat (m:bin) : nat :=
match m with
| Z => O
| A n =>2 * (bin_to_nat n)
| B n =>2 * (bin_to_nat n) + 1
end.
see: coq art's 2004. P167-P168. ( How to understand 'positive' type in Coq)

Tail Recursive function for the sum of fractions

I am trying to convert this recursive function into a tail recursive function
def sumOfFractions(n: Int): Double = {
require(n > 0, "Parameter n has to be greater than 0");
if (n==1)
1.0
else
1.0 / n + sumOfFractions(n - 1)
}
I thought that this solution would work but when it runs it just returns 1.0
def sumOfFractions(n:Int):Double = {
def inner(acc:Int, n:Int): Double={
if(n <= 1)1.0
else
{
inner(acc+(1/n),n-1)
}
}
inner(0,n)
}
I think this is because the accumulator is not being updated correctly but I don't understand why. The code is in Scala but an example in any language would be helpful.
You need the base case (n <= 1) to return the accumulator, not 1.0. You'll also run into problems because the accumulator is an Int instead of a Double, which means that + (1 / n) is just adding 0 (the result of dividing 1: Int by any n: Int greater than one).
You can fix this by changing acc's type and making the numerator of the reciprocal a literal double:
def sumOfFractions(n: Int):Double = {
def inner(acc: Double, n: Int): Double =
if (n <= 1) acc else inner(acc + (1.0 / n), n - 1)
inner(0, n)
}
This should work.
Correct your code
1) Return acc (accumulator) when n <= 1
2) Your acc should be Double type
3) Division should be floating point division
def sumOfFractions(n: Int): Double = {
def inner(acc: Double, n:Int): Double = if(n <= 1) acc
else inner(acc + (1.0 / n), n - 1)
inner(0,n)
}
Using foldLeft
def sumOfFractions(n: Int): Double =
(1 to n).foldLeft(0.0)((r, c) => r + (1.0 / c))