Dafny: property '2*x*y <= x^2+y^2' holds with primitive operations (like 'x*x'), but not when I define operations in my own (like 'power(x,2)') - z3

I am trying to prove a property in Dafny, which makes use of powers.
Concretely, this one: forall x,y in Reals : 2xy <= x^2+y^2. I implemented this idea in the following lemma:
lemma product2_lessEqual_powProduct (x:real, y:real)
requires 0.0<x<=1.0 && 0.0<y<=1.0
ensures 2.0*x*y <= (x*x)+(y*y)
{}
Which is verified with no problem (I guess some automatic induction is performed below).
However, I would like to use an own power function in order to make power(x,2) instead of x*x. Thus, I took a power function from https://github.com/bor0/dafny-tutorial/blob/master/pow.dfy, which is as follows:
function method power(A:int, N:nat):int
{
if (N==0) then 1 else A * power(A,N-1)
}
method pow(A:int, N:int) returns (x:int)
requires N >= 0
ensures x == power(A, N)
{
x := 1;
var i := N;
while i != 0
invariant x == power(A, (N-i))
{
x := x * A;
i := i - 1;
}
}
However, since I am using real values for the basis of the exponential, I modified it a bit so that it works for exponentials:
function method power(A:real, N:nat):real
{
if (N==0) then 1.0 else A * power(A,N-1)
}
method pow(A:real, N:int) returns (x:real)
requires N >= 0
ensures x == power(A, N)
{
x := 1.0;
var i := N;
while i != 0
invariant x == power(A, (N-i))
{
x := x * A;
i := i - 1;
}
}
Thus, I wanted to test it with the previous lemma:
lemma product2_lessEqual_powProduct (x:real, y:real)
requires 0.0<x<=1.0 && 0.0<y<=1.0
ensures 2.0*x*y <= power(x,2)+power(y,2)
{}
Surprisingly, it tells me the typical A postcondition might not hold on this return path.Verifier.
Can anyone explain why this happens? Why is it verifying with primitive operations of Dafny, but not when I define them functions? And how could I prove this lemma now?

Even though second parameter of power is concrete and small, Dafny is not doing enough unrolling to prove desired fact. Adding {:fuel 2} to power makes proof go through. You can read more about fuel here https://dafny.org/dafny/DafnyRef/DafnyRef.html#sec-fuel
function method {:fuel 2} power(A:real, N:nat):real
{
if (N==0) then 1.0 else A * power(A,N-1)
}
method pow(A:real, N:int) returns (x:real)
requires N >= 0
ensures x == power(A, N)
{
x := 1.0;
var i := N;
while i != 0
invariant x == power(A, (N-i))
{
x := x * A;
i := i - 1;
}
}
lemma product2_lessEqual_powProduct (x:real, y:real)
requires 0.0<x<=1.0 && 0.0<y<=1.0
ensures 2.0*x*y <= power(x,2)+power(y,2)
{}

It's surprising until you realize that there is a mathematical theory for A*A, but power(A, 2) requires two unfolding of power to have a meaning.
If you want your function to work seamlessly with the theory and prove your last lemma, you can give it precise postconditions:
function method power(A:real, N:nat): (result: real)
ensures N == 1 ==> result == A
ensures N == 2 ==> result == A*A
{
if (N==0) then 1.0 else A * power(A,N-1)
}
I tested it, your second lemma verifies.

Related

Unsure why this Dafny verification fails

function method abs(m: int): nat
{ if m>0 then m else -m }
method CalcTerm(m: int, n: nat) returns (res: int)
ensures res == 5*m-3*n;
{
var m1: nat := abs(m);
var n1: nat := n;
res := 0;
while (m1!=0)
invariant m1>=0
invariant 0<=res
invariant res <=5*abs(m)
decreases m1
{
res := res+5;
m1 := m1-1;
}
if (m<0) { res := -res; }
while (n1!=0)
invariant n1>=0
decreases n1
{
res := res-3;
n1 := n1-1;
}
}
I have tried to increase the invariance in the loops. To the first loop, I added the condition, res<=5*abs(m) but Dafny complains that "This loop invariant might not be maintained by the loop." I don't understand how it is not.
What could I be doing wrong?
If you make your loop invariant stronger by stating exactly what res is equal to after each iteration, Dafny will be able to verify it.
So in the first while loop, instead of invariant res <= 5*abs(m), use invariant res == 5*abs(m) - 5*m1. When the loop terminates, m1 is equal to zero, so res will be 5*abs(m).
Similarly, for the second while loop, define the invariant res == 5*m - 3*n + 3*n1. Now when this loop terminates, n1 is equal to zero, so res will be 5*m - 3*n and Dafny will be able to prove that the post-condition of the method holds.
P.S. I usually use > 0 instead of != 0 as a loop condition.
After making these changes, you would have:
function method abs(m: int): nat
{
if m > 0 then m else -m
}
method CalcTerm(m: int, n: nat) returns (res: int)
ensures res == 5*m - 3*n;
{
var m1: nat := abs(m);
var n1: nat := n;
res := 0;
while (m1 > 0)
invariant m1 >= 0;
invariant 0 <= res;
invariant res == 5*abs(m) - 5*m1;
decreases m1;
{
res := res + 5;
m1 := m1 - 1;
}
if (m < 0)
{
res := -res;
}
while (n1 > 0)
invariant n1 >= 0;
invariant res == 5*m - 3*n + 3*n1;
decreases n1;
{
res := res - 3;
n1 := n1 - 1;
}
}
which verifies in Dafny.

Dafny, Dutch Flag, loop invariant might not be maintained by the loop

in the program below I am creating something like Dutch national flag problem and following the same logic which is also provided here
the program sorts array of 0s,1s and 2s in the manner all 1s in the beginning 0s in the middle and 2s at the end. [1,1,1,0,0,2,2,2].
but at the loop invariants, I get the error This loop invariant might not be maintained by the loop.
initially, i and j are at index 0, and k at last index. the logic is that j moves up if it sees 2, swap with k and k reduces if sees 0 just j moves up, and if sees 1 swap with i and both i and j increase.
the code is also here in rise4fun
method sort(input: array?<int>)
modifies input
requires input !=null;
requires input.Length>0;
requires forall x::0<=x<input.Length ==> input[x]==0||input[x]==1||input[x]==2;
ensures sorted(input);
{
var k: int := input.Length;
var i, j: int := 0 , 0;
while(j != k )
invariant 0<=i<=j<=k<=input.Length;
/* the following invariants might not be maintained by the loop.*/
invariant forall x:: 0<=x<i ==> input[x]==1;
invariant forall x:: i<=x<j ==> input[x]==0;
invariant forall x:: k<=x<input.Length ==> input[x]==2;
invariant forall x:: j<=x<k ==> input[x]==0||input[x]==1||input[x]==2;
decreases if j <= k then k - j else j - k
{
if(input[j] == 2){
swap(input, j, k-1);
k := k - 1;
} else if(input[j] == 0){
j := j + 1;
} else {
swap(input, i, j);
i:= i + 1;
j := j + 1;
}
}
}
and here are swap method and sorted predicate
predicate sorted(input:array?<int>)
requires input!=null;
requires input.Length>0;
reads input;
{
forall i,j::0<=i<j<input.Length ==> input[i]==1 || input[i]==input[j] || input[j]==2
}
method swap(input: array?<int>, n:int, m:int)
modifies input;
requires input!=null;
requires input.Length>0;
requires 0<=n<input.Length && 0<=m<input.Length
{
var tmp : int := input[n];
input[n] := input[m];
input[m] := tmp;
}
The problem is that swap has no postcondition. The default postcondition is true, so the specification of swap says that it changes the array in any arbitrary way.
When the verifier sees a call to swap in the body of method sort, it only pays attention to swap's specification --- not it's body. Thus, after the call to swap, the array could have any values in it at all, at least as far as the verifier can tell. So it is hardly surpising that any invariant relating to the contents of the array can not be proved.
The following specification for swap should work:
method swap(input: array?<int>, n:int, m:int)
modifies input;
requires input!=null;
requires input.Length>0;
requires 0<=n<input.Length && 0<=m<input.Length
ensures n < m ==> input[..] == old( input[0..n] + [input[m]] + input[n+1..m] + [input[n]] + input[m+1..] ) ;
ensures n==m ==> input[..] == old(input[..])
ensures n > m ==> input[..] == old( input[0..m] + [input[n]] + input[m+1..n] + [input[m]] + input[n+1..] ) ;
So should this
method swap(input: array?<int>, n:int, m:int)
modifies input;
requires input!=null;
requires input.Length>0;
requires 0<=n<input.Length && 0<=m<input.Length
ensures input[n] == old( input[m] ) ;
ensures input[m] == old( input[n] ) ;
ensures forall i | 0 <= i < input.Length && i != n && i != m :: input[i] == old(input[i])

Dafny linear search

When working on a basic linear search I encountered an error with my Valid() predicate. It seems to only work when I uncomment the additional ensures statements on the constructor and the data method. That is, when I am very explicit about the contents.
I'm also having trouble with the postcondition of my search when the item isn't found.
Any suggestions on how to resolve these?
class Search{
ghost var Contents: set<int>;
var a : array<int>;
predicate Valid()
reads this, a;
{
a != null &&
a.Length > 0 &&
Contents == set x | 0 <= x < a.Length :: a[x]
}
constructor ()
ensures a != null;
ensures a.Length == 4;
//ensures a[0] == 0;
ensures Valid();
{
a := new int[4](_ => 0);
Contents := {0};
new;
}
method data()
modifies this, a;
requires Valid();
requires a != null;
requires a.Length == 4;
ensures a != null;
ensures a.Length == 4;
// ensures a[0] == 0;
// ensures a[1] == 1;
// ensures a[2] == 2;
// ensures a[3] == 3;
ensures Valid();
{
a[0] := 0;
a[1] := 1;
a[2] := 2;
a[3] := 3;
Contents := {0, 1, 2, 3};
}
method search(e: int) returns (r: bool)
modifies this, a;
requires Valid();
ensures Valid();
ensures r == (e in Contents)
ensures r == exists i: int :: 0 <= i < a.Length && a[i] == e
{
var length := a.Length - 1;
while (length >= 0)
decreases length;
{
var removed := a[length];
if (e == removed)
{
return true;
}
length := length - 1;
}
return false;
}
}
method Main()
{
var s := new Search();
s.data();
}
There are several orthogonal issues going on here.
First, you have noticed that Dafny is reluctant to reason about the part of Valid that describes Contents. This is a common problem when reasoning about sets in Dafny. Essentially, the only way Dafny will ever "notice" that something is a member of the set set x | 0 <= x < a.Length :: a[x] is if it already has the expression a[x] lying around somewhere. Your solution of including extra postconditions works because it mentions a lot of expressions of the form a[x]. Another solution is to include those facts as assertions instead of postconditions:
// in data()
assert a[0] == 0;
assert a[1] == 1;
assert a[2] == 2;
assert a[3] == 3;
Second, Dafny cannot show your search procedure satisfies its postcondition. You need a loop invariant to keep track of the progress of the search. See the guide for more information about how to design loop invariants.
Third, Dafny reports a problem with your Main about modifies clauses. You can fix this by adding a postcondition fresh(a) to the constructor. The problem here is that the data method claims to modify a, but Dafny can't tell if a is visible from the caller.

Dafny generic type array error

In trying to verify a generic FIFO queue backed by an array I ran into a confusing error. The queue was found in this paper, authored by the creator of Dafny.
The error in question is:
unless an initializer is provided for the array elements, a new array of 'Data' must have empty size
which relates to both lines allocating an array via new Data[whatever] in the constructor and the enqueue method.
Dafny version: Dafny 2.0.0.00922 technical preview 0
Full code for reference.
class {:autocontracts} SimpleQueue<Data>
{
ghost var Contents: seq<Data>;
var a: array<Data>;
var m: int, n: int;
predicate Valid() {
a != null && a.Length != 0 && 0 <= m <= n <= a.Length && Contents == a[m..n]
}
constructor ()
ensures Contents == [];
{
a := new Data[10];
m := 0;
n := 0;
Contents := [];
}
method Enqueue(d: Data)
ensures Contents == old(Contents) + [d];
{
if n == a.Length {
var b := a;
if m == 0 {
b := new Data[2 * a.Length];
}
forall (i | 0 <= i < n - m) {
b[i] := a[m + i];
}
a, m, n := b, 0, n - m;
}
a[n], n, Contents := d, n + 1, Contents + [d];
}
method Dequeue() returns (d: Data)
requires Contents != [];
ensures d == old(Contents)[0] && Contents == old(Contents)[1..];
{
assert a[m] == a[m..n][0];
d, m, Contents := a[m], m + 1, Contents[1..];
}
}
method Main()
{
var q := new SimpleQueue();
q.Enqueue(5); q.Enqueue(12);
var x := q.Dequeue();
assert x == 5;
}
Since the time of writing that paper, Dafny's type system has been generalized to support types that are not "default initializable". This has led to some backwards incompatibilities.
The easiest fix is to change
class SimpleQueue<Data>
to
class SimpleQueue<Data(0)>
which means that the type variable Data can only be instantiated with default-initializable types.
Another fix is to change the constructor to accept a default value for type Data as an argument. Then you can allocate an array using an initializer function, as in
new Data[10] (_ => d)

How can I do mod without a mod operator?

This scripting language doesn't have a % or Mod(). I do have a Fix() that chops off the decimal part of a number. I only need positive results, so don't get too robust.
Will
// mod = a % b
c = Fix(a / b)
mod = a - b * c
do? I'm assuming you can at least divide here. All bets are off on negative numbers.
a mod n = a - (n * Fix(a/n))
For posterity, BrightScript now has a modulo operator, it looks like this:
c = a mod b
If someone arrives later, here are some more actual algorithms (with errors...read carefully)
https://eprint.iacr.org/2014/755.pdf
There are actually two main kind of reduction formulae: Barett and Montgomery. The paper from eprint repeat both in different versions (algorithms 1-3) and give an "improved" version in algorithm 4.
Overview
I give now an overview of the 4. algorithm:
1.) Compute "A*B" and Store the whole product in "C" that C and the modulus $p$ is the input for that algorithm.
2.) Compute the bit-length of $p$, say: the function "Width(p)" returns exactly that value.
3.) Split the input $C$ into N "blocks" of size "Width(p)" and store each in G. Start in G[0] = lsb(p) and end in G[N-1] = msb(p). (The description is really faulty of the paper)
4.) Start the while loop:
Set N=N-1 (to reach the last element)
precompute $b:=2^{Width(p)} \bmod p$
while N>0 do:
T = G[N]
for(i=0; i<Width(p); i++) do: //Note: that counter doesn't matter, it limits the loop)
T = T << 1 //leftshift by 1 bit
while is_set( bit( T, Width(p) ) ) do // (N+1)-th bit of T is 1
unset( bit( T, Width(p) ) ) // unset the (N+1)-th bit of T (==0)
T += b
endwhile
endfor
G[N-1] += T
while is_set( bit( G[N-1], Width(p) ) ) do
unset( bit( G[N-1], Width(p) ) )
G[N-1] += b
endwhile
N -= 1
endwhile
That does alot. Not we only need to recursivly reduce G[0]:
while G[0] > p do
G[0] -= p
endwhile
return G[0]// = C mod p
The other three algorithms are well defined, but this lacks some information or present it really wrong. But it works for any size ;)
What language is it?
A basic algorithm might be:
hold the modulo in a variable (modulo);
hold the target number in a variable (target);
initialize modulus variable;
while (target > 0) {
if (target > modulo) {
target -= modulo;
}
else if(target < modulo) {
modulus = target;
break;
}
}
This may not work for you performance-wise, but:
while (num >= mod_limit)
num = num - mod_limit
In javascript:
function modulo(num1, num2) {
if (num2 === 0 || isNaN(num1) || isNaN(num2)) {
return NaN;
}
if (num1 === 0) {
return 0;
}
var remainderIsPositive = num1 >= 0;
num1 = Math.abs(num1);
num2 = Math.abs(num2);
while (num1 >= num2) {
num1 -= num2
}
return remainderIsPositive ? num1 : 0 - num1;
}

Resources