dafny non aliased memory weird behavior - alias

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.

Related

Invariant for Hoare-Logic on RandomSearch

I'm trying to proof the following RandomSeach-Algorithm and to figure out the invariant for the loop.
Since the function randomIndex(..) creates a random number I cannot use an invariant like
𝑠 ≥ 0 ∧ 𝑠 < 𝑖 − 1 ⇒ 𝑓[𝑠] ≠ 𝑣𝑎𝑙𝑢e
. That means, all elements between 0 and i-1, with i is the index of the current checked element, is not the searched element.
So I thought I define a hypothetical sequence r, that contains all elements that have already been compared to the searched value or are going to be compared to the searched value. Thats why it is just a hypothetical sequence, because I actually do not know the elements that are going to be compared to the searched value until they have been realy compared.
That means it applies r.lenght() ≤ runs and in the case the searched element was found
(r[r.lenght()-1] = value) ↔ (r[currentRun] = value).
Then I can define a invariant like:
𝑠 ≥ 0 ∧ 𝑠 < currentRun ⇒ r[𝑠] ≠ 𝑣𝑎𝑙𝑢e
Can I do this, because the sequence r is not real? It does not feel right. Does anyone have a diffrent idea for an invariant?
The program:
public boolean RandomSearch (int value, int[] f, int runs) {
int currentRun = 0;
boolean found = false;
while (currentRun < runs || !found) {
int x = randomIndex(0, n-1)
if (value == f[x]) {
found = true;
}
currentRun = currentRun + 1;
}//end while
return found;
}//end RandomSearch
Ok,
I use following invariant
currentRun <= runs & f.length > 0
Than I can proof the algorithm :)

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!

an obvious invariant fails in Dafny

datatype CACHE_STATE = I| S| E
datatype MSG_CMD = Empty| ReqS| ReqE| Inv| InvAck| GntS| GntE
type NODE=nat
type DATA=nat
type boolean=bool
class class_0 {
var
Data : DATA,
Cmd : MSG_CMD
}
class class_1 {
var
Data : DATA,
State : CACHE_STATE
}
method n_RecvGntSinv__1_2(
Chan2 : array<class_0 > ,
Cache : array<class_1 > ,i:nat, N1:nat ,p__Inv0:nat,p__Inv2:nat)
modifies Chan2[i]
modifies Cache[i]
requires 0<= i<N1
requires Cache.Length ==N1
requires N1>0
requires Chan2.Length ==N1
requires p__Inv0!=p__Inv2&&p__Inv2<N1&& p__Inv0<N1
requires Chan2[i] != null
requires Cache[i] !=null
requires i!=p__Inv0&&i!=p__Inv2
requires (!((Cache[p__Inv2].State == E) && (!(Cache[p__Inv0].State == I))))
requires (Chan2[i].Cmd == GntS)
ensures Cache==old(Cache)
ensures Chan2==old(Chan2)
ensures (!((Cache[p__Inv2].State == E) && (!(Cache[p__Inv0].State == I))))
{
Cache[i].State := S;
Cache[i].Data := Chan2[i].Data;
Chan2[i].Cmd := Empty;
}
I have placed the requirement i is different from p__Inv2 and p_Inv0, thus the assignments should not disturb the evaluation of the invariant.
It is obvious that the invariant (!((Cache[p__Inv2].State == E) && (!(Cache[p__Inv0].State == I)))) should hold if it holds before execution.
Dafny shows my assertions fail and gives a counterexample I cann't understand.
Your precondition allows the possibility that Cache[i] references the same object as Cache[p__Inv0] or Cache[p__Inv2]. If that's what you intended, then the method body is indeed incorrect, as reported by the verifier. If that's not what you intended, then a precondition like
requires forall j,k :: 0 <= j < k < Cache.Length ==> Cache[j] != Cache[k]
will make your method verify.

Verifying sum of sequence under a condition in dafny

I am having a problem with getting an invariant to be be maintained in dafny. The invariant is trying to maintain that a total is equal to the a recursive sum of elements in a sequence that match a given condition. What do i need to add/change to get this to verify. Here is my attempt:
datatype MovieTitle = A | B | C
class Movie {
var title: MovieTitle;
var run_time: int;
predicate Valid()
reads this
{
run_time >= 0
}
constructor(mt: MovieTitle, rt: int)
requires rt >= 0;
ensures Valid();
modifies this;
{
title := mt;
run_time := rt;
}
}
function movieSum(s: seq<Movie>, mt: MovieTitle, i: int): int
requires 0 <= i <= |s|;
decreases s, i;
reads s;
reads set x | x in s[..];
{
if |s| == 0 || i == 0 then 0
else if s[0].title == mt then s[0].run_time + movieSum(s[1..], mt, i - 1)
else movieSum(s[1..], mt, i - 1)
}
lemma {:induction s, mt, i} movieSumLemma(s: seq<Movie>, mt: MovieTitle, i: int)
requires 0 <= i < |s|;
ensures s[i].title == mt ==> (movieSum(s, mt, i) + s[i].run_time == movieSum(s, mt, i + 1)) &&
s[i].title != mt ==> (movieSum(s, mt, i) == movieSum(s, mt, i + 1));
decreases s;
{
}
method SumRuntimes(s: seq<Movie>)
{
var total := 0;
var i := 0;
while i < |s|
invariant 0 <= i <= |s|;
invariant total == movieSum(s, A, i);
decreases |s| - i;
{
if s[i].title == A {
total := total + s[i].run_time;
movieSumLemma(s, A, i);
}
i := i + 1;
}
}
Here invariant total == movieSum(s, A, i); won't hold. Any help in getting this to verify is appreciated. Thank you!
The problem is in function movieSum. You're both chopping off the initial element of s in the recursive call and decrementing i. That will not produce the sum of all the mt-movie elements.
You don't need the lemma. But its postcondition doesn't say what you may think it says. It currently has the form
ensures A ==> B && !A ==> C
The 2-character-wide && has higher binding power than the 3-character-wide ==>. So, your postcondition is saying
ensures A ==> ((B && !A) ==> C)
which simplifies to true. Instead, you want
ensures (A ==> B) && (!A ==> C)
which you can also write on two lines (for better readability):
ensures A ==> B
ensures !A ==> C
Your program also has a number of redundant decreases clauses and :induction attributes. I'm guessing you have added these from the blue information squiggles in the IDE. The blue squiggles are just FYI--Dafny is just trying to tell you what its default settings are.
It seems you may be using a very version of Dafny, or I expected you should have got a warning about the deprecated modifies this on the constructor.

How to reason about array access in VST?

I have a trouble proving a trivial array access function (file arr.c):
int get(int* arr, int key)
{
return arr[key];
}
which is translated by clightgen arr.c to (file arr.v):
...
Definition f_get := {|
fn_return := tint;
fn_callconv := cc_default;
fn_params := ((_arr, (tptr tint)) :: (_key, tint) :: nil);
fn_vars := nil;
fn_temps := nil;
fn_body :=
(Sreturn (Some (Ederef
(Ebinop Oadd (Etempvar _arr (tptr tint))
(Etempvar _key tint) (tptr tint)) tint)))
|}.
...
Here is the proof start (verif_arr.v):
Require Import floyd.proofauto.
Require Import arr.
Local Open Scope logic.
Local Open Scope Z.
Definition get_spec :=
DECLARE _get
WITH sh : share, k : Z, arr : Z->val, vk : val, varr : val
PRE [_key OF tint, _arr OF (tptr tint)]
PROP (0 <= k < 100; forall i, 0 <= i < 100 -> is_int (arr i))
LOCAL (`(eq vk) (eval_id _key);
`(eq varr) (eval_id _arr);
`isptr (eval_id _arr))
SEP (`(array_at tint sh arr
0 100) (eval_id _arr))
POST [tint] `(array_at tint sh arr
0 100 varr) &&
local(`(eq (arr k)) retval).
Definition Vprog : varspecs := nil.
Definition Gprog : funspecs := get_spec :: nil.
Lemma body_get: semax_body Vprog Gprog f_get get_spec.
Proof.
start_function.
name karg _key.
name arrarg _arr.
forward.
After performing the forward (the last line in verif_arr.v) I've got the following goal:
array_at tint sh arr 0 100 arrarg
|-- !!(False /\ False /\ arr k = Vundef) &&
array_at tint sh arr 0 100 arrarg
Which implies False, so I can not prove it. However, the c-implementation is trivial, and the proof just started.
Now to the Question:
What is wrong with the spec, why it got to an unprovable goal?
VST version:
Definition svn_rev := "6834P".
Definition release := "1.5".
Definition date := "2014-10-02".
CompCert version: 2.4
Coq version:
The Coq Proof Assistant, version 8.4pl3 (January 2014)
compiled on Jan 19 2014 23:14:16 with OCaml 4.01.0
In "standard" Verifiable-C, memory references cannot occur in expressions except at top level within a load statement:
x = a[e]; or x = *(e.field); (same as x = e->field;)
where e is any expression that does not access memory.
Or, a store statement,
a[e1] = e2; or e1->field = e2;
where e1 and e2 do not access memory.
A memory reference must not occur within a return statement. You'll have to factor your program as follows:
int x;
x = arr[key];
return x;
and then go ahead with the proof.
We are considering extensions, i.e. "nonstandard" Verifiable C, in which memory references can be nested inside expressions in other contexts; but it is not at all clear that this is a good way to reason about programs. It will be worth the experiment.
The reason you're getting "False" in your precondition is that the expression arr[key] does not type-check as a valid expression, since it contains a memory reference. We need to work on better error-message feedback in such situations.