Dafny, post condition does not hold after loop - verification

In the following method, Dafny reports that the postcondition might not hold, even though I am quite sure that it does.
method toArrayConvert(s:seq<int>) returns (a:array<int>)
requires |s| > 0
ensures |s| == a.Length
ensures forall i :: 0 <= i < a.Length ==> s[i] == a[i] // This is the postcondition that might not hold.
{
a := new int[|s|];
var i:int := 0;
while i < |s|
decreases |s| - i
invariant 0 <= i <= |s|
{
a[i] := s[i];
i := i + 1;
}
return a; // A postcondition might not hold on this return path.
}

Indeed, the postcondition does always hold, but Dafny cannot tell!
That's because you're missing a loop invariant annotation such as
invariant forall j :: 0 <= j < i ==> s[j] == a[j]
After adding that line to the loop, the method verifies.
For more explanation about why Dafny sometimes reports errors on correct programs, see the (brand new) FAQ. For more about loop invariants, see the corresponding section in the rise4fun guide.

Related

The same return but one function can not assert values properly, but other don't in Dafny

I have 2 functions, all is for checking how many values that are the same values and same index in 2 sequences, example:
requires there's no duplicates in the sequence
s:= [1,3,2,5,6]
u:= [2,3,4,5,1]
==> bullspec(s,u) = 2
So both my 2 functions return the right value but the assertion of one is true, other is false
Here are my 2 functions:
function bullspec(s:seq<nat>, u:seq<nat>): nat
requires 0 < |s| <= 10
requires 0 < |u| <= 10
requires |s| <= |u|
// Remove duplicates
requires forall i, j | 0 <= i < |s| && 0 <= j < |s| && i != j :: s[i] != s[j] && s[i] <= 10
requires forall i, j | 0 <= i < |u| && 0 <= j < |u| && i != j :: u[i] != u[j] && u[i] <= 10
{
if |s| == 1 then (
if s[0] in u && s[0] == u[0]
then 1 else 0
) else (
if s[|s|-1] in u && s[|s|-1]==u[|s|-1]
then (1 + bullspec(s[..|s|-1], u))
else bullspec(s[..|s|-1],u)
)
}
and
function bullspec2(s:seq<nat>, u:seq<nat>): nat
requires 0 < |s| <= 10
requires 0 < |u| <= 10
requires |s| <= |u|
// Remove duplicates
requires forall i, j | 0 <= i < |s| && 0 <= j < |s| && i != j :: s[i] != s[j] && s[i] <= 10
requires forall i, j | 0 <= i < |u| && 0 <= j < |u| && i != j :: u[i] != u[j] && u[i] <= 10
{
if |s| == 1 then (
if s[0] in u && s[0] == u[0]
then 1 else 0
) else (
if s[0] in u && s[0] == u[0]
then (1 + bullspec2(s[1..], u))
else bullspec2(s[1..], u)
)
}
I have a method Main below:
method Main()
{
var sys:seq<nat> := [4,2,9,3,1];
var usr:seq<nat> := [1,2,3,4,5];
assert bullspec(sys, usr) == 1; //Assertion might not hold
assert bullspec2(sys, usr) == 1; //This is good
}
The difference between 2 functions is the loop recusive, one start from the beginning, other start from the end, and somehow the backward make assertion works well
I try to write some ensures statements but there's no working.
First, please be aware that you are using a static analyzer, not a run-time tester. So the assertion might hold at run-time, but the static analyzer can't prove it.
The fact that the static analyzer can prove the second one is pretty astounding already. But I would always advise you switch the order of assertions, because an assertion after a first unproven one is always proved with the condition that the unproven one is true. In your case, it's still bullspec that can't be resolved, no matter what.
The reason why it currently fail to verify is that the axiom that indirectly serves at evaluating a sequence's length in the presence of a sequence literal without consuming fuel is not implemented yet. See this similar issue. That means that, for your second example, "evaluating" the function using axioms does not consume "fuel" (I'll go back to that later), but for the first failing example, it cannot unroll the function enough to do the computation.
What you can do for now is:
Create a lemma and prove it (hard)
lemma bullspec2equalsBullspec(s:seq<nat>, u:seq<nat>): nat
ensures bullspec2(sys, usr) == bullspec(sys, usr)
{
// TODO
}
and then write:
assert bullspec2(sys, usr) == 1;
assert bullspec(sys, usr) == 1 by {
bullspec2equalsBullspec(sys, usr);
}
Pass the sequence's length as a ghost parameter in bullspec
function bullspec(s:seq<nat>, u:seq<nat>, length: nat): nat
requires |s| == length
requires 0 < |s| <= 10
requires 0 < |u| <= 10
requires |s| <= |u|
// Remove duplicates
requires forall i, j | 0 <= i < |s| && 0 <= j < |s| && i != j :: s[i] != s[j] && s[i] <= 10
requires forall i, j | 0 <= i < |u| && 0 <= j < |u| && i != j :: u[i] != u[j] && u[i] <= 10
{
if length == 1 then (
if s[0] in u && s[0] == u[0]
then 1 else 0
) else (
if s[length-1] in u && s[length-1]==u[length-1]
then (1 + bullspec(s[..length-1], u,length-1))
else bullspec(s[..length-1],u,length-1)
)
}
/// ...
method Main()
{
var sys:seq<nat> := [4,2,9,3,1];
var usr:seq<nat> := [1,2,3,4,5];
assert bullspec2(sys, usr) == 1; //This is good
assert bullspec(sys, usr, 5) == 1; //This is good
}
verifies because now it can unroll the function applied to literals without fuel.
Unroll bullspec by verification debugging to see where it blocks.
If this assertion should hold, what should hold before? You can unroll the function's definition and assert intermediate results. If you assert something non-trivial that Dafny can finally prove, all the rest will be proven. I unrolled the function for 3 steps only.
method Main()
{
var sys:seq<nat> := [4,2,9,3,1];
var usr:seq<nat> := [1,2,3,4,5];
assert bullspec2(sys, usr) == 1; //This is good
var sys1 := sys[..|sys|-1];
var sys2 := sys1[..|sys1|-1];
var sys3 := sys2[..|sys2|-1];
var sys4 := sys3[..|sys3|-1];
var sys5 := sys4[..|sys4|-1];
assert bullspec(sys3, usr) == 1;
assert bullspec(sys2, usr) == 1;
assert bullspec(sys1, usr) == 1;
assert bullspec(sys, usr) == 1; //Assertion might not hold
}
Give more fuel to your function (best in your case)
By just changing the definition of your function, you can give it more fuel for the verifier to instantiate it. For your case, a fuel of 3 is sufficient.
function {:fuel 10} bullspec(s:seq<nat>, u:seq<nat>): nat

How to prove time complexity of bubble sort using dafny?

Is there a way in dafny to create an invariant specific to a single loop iteration? Below I'm trying to create a dafny program to upper bound the number of swaps of bubble sort. That value is stored in variable n. So I'd like to upper bound n by (a.Length * (a.Length - 1))/2. The reason being is that the maximum number of swaps that can occur is if the array is in the opposite order so then there must be n swaps on the first iteration of the inside loop and then n-1 swaps of the second iteration of the inside loop, etc. until the array is sorted. This is equivalent to 1+2+3+...+n-1+n = n(n-1)/2, which is precisely what I'm trying to show. I'm wondering if there's a method in dafny to upper bound the value of i-j or n in the code below based on the iteration of the inner loop. Is there such a way?
If not is there another method to upper bound this n value given the explanation provided above? Perhaps additional invariants I'm not thinking of?
method BubbleSort(a: array<int>) returns (n: nat)
modifies a
requires a != null
ensures n <= (a.Length * (a.Length - 1))/2
{
var i := a.Length - 1;
n := 0;
while (i > 0)
invariant 0 < a.Length ==> 0 <= i < a.Length;
decreases i;
{
var j := 0;
while (j < i)
invariant i - j <= old(i) - old(j);
invariant i < 0 && j < 0 ==> 0 <= n <= a.Length;
decreases i - j;
{
if(a[j] > a[j+1])
{
a[j], a[j+1] := a[j+1], a[j];
n := n + 1;
}
j := j + 1;
}
i := i -1;
}
}
I don't think you need to "create an invariant specific to a single loop iteration", but instead to rephrase your loop invariants in a way that they apply to all iterations.
Your English argument for why the complexity is bounded is a good one.
the maximum number of swaps that can occur is if [there are] n swaps on the first iteration of the inside loop and then n-1 swaps of the second iteration of the inside loop, etc. until the array is sorted. This is equivalent to 1+2+3+...+n-1+n = n(n-1)/2
All you need to do is to formalize this argument into Dafny. I suggest introducing a function for "the sum of all integers between a and b" and then using that function to phrase your loop invariants.

dafny initial assert in loop not verifying yet same final assert verifies

Hi I have simplified the problem to a method that simply copies the elements of one array to another array. My problem is that the final assert verifies yet the initial assert fails to verify even though I have a guard to ensure that initial assert only applies after the first time the loop is entered. Hence I think the final assert should imply the initial assert.
Any help much appreciated.
method simpImp(a:array<int>) returns (r:array<int>)
{
print "a ",a[..],"\n";
r := new int[a.Length];
var i:nat := 0;
while (i< a.Length)
decreases a.Length - i
invariant a.Length >= i
{
if (i> 0) { print " bool ",r[i-1] == a[i-1],"\n";}
else {print "*i ",i,"\n";}
//if (i> 0) { assert r[i-1] == a[i-1]; } //Fail
//assert (i>0) ==> r[i-1] == a[i-1]; //Fail
r[i] := a[i];
i:= i +1;
assert r[i-1] == a[i-1];
}
}
method Main() {
var a:array<int> := new int[5];
a[0],a[1],a[2],a[3],a[4] := 10,2,30,4,3;
var iny:= simpImp(a);
print "r ",iny[..],"\n";
}
The issue is that you need to add something to your loop invariant to "remember" any facts you need to carry between iterations. Dafny analyzes the loop body in isolation, assuming only the loop invariants at the beginning of the body. So unless you add the fact to the loop invariant, it will be "forgotten" by Dafny.
In your simplified example, adding
invariant i > 0 ==> r[i-1] == a[i-1]
to the loop causes the program to verify.
You can read more about loop invariants in the second half of this answer. Note that that discussion is phrased in terms of establishing that loop invariants are preserved, but the reasoning is mostly identical to trying to establish that an assertion inside the loop body is valid. Please feel free to ask further questions!

dafny non aliased memory weird behavior

I have a dafny defined graph ADT (from this SO question) brought here again for completeness:
class Graph
{
var adjList : seq<seq<int>>;
constructor (adjListInput : seq<seq<int>>)
ensures adjList == adjListInput
{
adjList := adjListInput;
}
}
function ValidGraph(G : Graph) : bool
reads G
{
(forall u :: 0 <= u < |G.adjList| ==> forall v :: 0 <= v < |G.adjList[u]| ==> 0 <= G.adjList[u][v] < |G.adjList|) &&
(forall u :: 0 <= u < |G.adjList| ==> forall v,w :: 0 <= v < w < |G.adjList[u]| ==> G.adjList[u][v] != G.adjList[u][w])
}
method main()
{
var G : Graph := new Graph([[1,2],[0,2],[0,1]]);
var nonRelatedArray := new int[8];
var i := 0; while (i < 14)
{
// nonRelatedArray[3] := 55;
i := i + 1;
}
assert (ValidGraph(G));
}
If I remove the write comment to nonRelatedArray at index 3, I get an assertion violation, which is a bit weird because it seems reasonable that the memory model would be able to determine that nonRelatedArray is (well) non related to G.
You can fix this by adding modifies nonRelatedArray to the loop. The key to this modifies clause is that it does not mention G. So then Dafny knows that G will not be modified by the loop, so it will still be a valid graph.
It is a little confusing what happens if you leave off a modifies clause from a loop. If you don't do any writes to the heap (like when you comment out the write above), then Dafny (actually, Boogie) is able to automatically see that nothing is changed at all. But if you do any writes into the heap, Dafny's default modifies clause all of a sudden becomes "anything the surrounding scope is allowed to modify". If you want something other than these two defaults, you need to ask for it explicitly by giving a modifies clause.

Loop Invariant for linear array search

int i = 0
boolean answer = false
while (i < a.length) {
if a[i] == 0
answer = true
i = i + 1
where 'a' is an array of integers.
I'm doing a question paper where it has asked me what the loop invariant of this is, I have already established that the code works out whether the array contains a 0. But so far I can only think of the invariant as being
i <= a.length
and the question states to include variables i, a and answer in the invariant so I know this can't be right. I have not come across loop invariants involving booleans before and am confused, could anyone help explaining?
Here is an implementation of your loop in Microsoft Dafny with appropriate loop invariants specified:
method Main(a:array<int>) returns (answer:bool)
requires a != null
ensures answer <==> (exists i :: 0 <= i < a.Length && a[i] == 0)
{
var i:int := 0;
answer := false;
while (i < a.Length)
invariant 0 <= i <= a.Length;
invariant !answer ==> !(exists j :: 0 <= j < i && a[j] == 0)
invariant answer ==> (exists j :: 0 <= j < i && a[j] == 0)
{
if a[i] == 0 {
answer := true;
}
i := i + 1;
}
}
You can verify its correctness automatically in the online version of Dafny