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.
Related
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 :)
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.
The following self contained code highlights a problem in OCaml, possibly with the code generation.
Array x has connectivity information for nodes in [0..9]. Function init_graph originally constructed explicit arrays of incoming nodes for every node. The reduced version shown below just prints the two connected nodes.
Function init_graph2 is identical to init_graph except for a "useless" else branch. But outputs produced by these two functions are quite different. You can run it and see that init_graph skips over the second if-then-else in some cases!
We have run this program on version 3.12.1 (with make_matrix substituted appropriately), 4.03.0 and 4.03.0+flambda. All of them have the same problem.
I have been dealing with this and related problems where OCaml mysteriously skips branches or in some cases takes both branches. Thanks to a collaborator we were able to pare down the real code to a small self contained example.
Any ideas on what's going on here? And is there a way to avoid this and related problems?
let x =
let arr = Array.make_matrix 10 10 false in
begin
arr.( 6).( 4) <- true;
arr.( 2).( 9) <- true;
end;
arr
let init_graph () =
for i = 0 to 9 do
for j = 0 to (i-1) do
begin
if x.(i).(j) then
let (i_inarr, _) = ([||],[||]) in
begin
Format.printf "updateA: %d %d \n" i j;
end
(* else () *)
;
if x.(j).(i) then
let (j_inarr, _) = ([||],[||]) in
begin
Format.printf "updateB: %d %d \n" i j;
end
end
done
done;
Format.printf "init_graph: num nodes is %i\n" 10
let init_graph2 () =
for i = 0 to 9 do
for j = 0 to (i-1) do
begin
if x.(i).(j) then
let (i_inarr, _) = ([||],[||]) in
begin
Format.printf "updateA: %d %d \n" i j;
end
else ()
;
if x.(j).(i) then
let (j_inarr, _) = ([||],[||]) in
begin
Format.printf "updateB: %d %d \n" i j;
end
end
done
done;
Format.printf "init_graph: num nodes is %i\n" 10
let test1 = init_graph ()
let test2 = init_graph2 ()
Update: Ocamllint flags the else branch in init_graph2 as "useless" which is clearly wrong.
Second, the indentation method suggested by camlspotter can be misleading in precisely this scenario. We follow Ocamllint advice and comment out the else branch. Emacs with taureg-mode doesn't re-indent this code unless explicitly asked leading us to believe everything is fine.
What is needed is a lint like tool that raises warning in these situations. I am waiting for good suggestions for this one.
Thanks.
Your problem appears to be with the handling of let ... in. This construct introduces a series of semicolon-separated expressions, not a single expression. So this code:
if x.(i).(j) then
let (i_inarr, _) = ([||],[||]) in
begin
Format.printf "updateA: %d %d \n" i j;
end
(* else () *)
;
if x.(j).(i) then
let (j_inarr, _) = ([||],[||]) in
begin
Format.printf "updateB: %d %d \n" i j;
end
Actually parses like this:
if x.(i).(j) then
let (i_inarr, _) = ([||],[||]) in
begin
Format.printf "updateA: %d %d \n" i j;
end
(* else () *)
;
if x.(j).(i) then
let (j_inarr, _) = ([||],[||]) in
begin
Format.printf "updateB: %d %d \n" i j;
end
In other words, both the first begin/end and the second if/then are controlled by the first if/then.
Another way to say that is that ; has higher precedence than let ... in. So let x = y in a ; b is parsed as let x = y in (a; b), not as (let x = y in a); b.
When you included the "useless" else, things parse like you think they should.
It's true, you have to be pretty careful when mixing if/then with let in OCaml. I have had problems like this. The general intuition that if/then and else control a single expression, while true, is easy to get wrong when one of the expressions is a let.
As Jeffrey has answered, your intention which is readable from your code indentations is very different from how the code is actually parsed.
You can avoid this kind of mistakes by using proper auto-indentation tools, such as caml-mode, tuareg-mode, ocp-indent and vim plugins for OCaml.
By auto-indenting the second if of init_graph, you can immediately find it is under the first if's then clasuse.
I am a newbie to golang and want to find a way to define a single byte variable.
It's a demo program in Effective Go reference.
package main
import (
"fmt"
)
func unhex(c byte) byte{
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
case 'A' <= c && c <= 'F':
return c - 'A' + 10
}
return 0
}
func main(){
// It works fine here, as I wrap things with array.
c := []byte{'A'}
fmt.Println(unhex(c[0]))
//c := byte{'A'} **Error** invalid type for composite literal: byte
//fmt.Println(unhex(c))
}
As you see I can wrap a byte with array, things goes fine, but How can I define a single byte without using array? thanks.
In your example, this would work, using the conversion syntax T(x):
c := byte('A')
Conversions are expressions of the form T(x) where T is a type and x is an expression that can be converted to type T.
See this playground example.
cb := byte('A')
fmt.Println(unhex(cb))
Output:
10
If you don't want to use the := syntax, you can still use a var statement, which lets you explicitly specify the type. e.g:
var c byte = 'A'
I am really new to SML and I can't figure out how to get answer for the same;
It goes something like: 3^4 < 32 but 3^5 > 32 so my answer is 4 (power of 3), similarly if I have numbers 4 and 63 then 4^2<63 but 4^3>63 so my answer is 2(power of 4).
I have come up with the following code
val log (b, n) =
let
val counter = ref b
val value = 0
in
while !counter > n do
( counter := !counter*b
value := !value + 1)
end;
So here value is what I need as my answer but I get a lot of errors. I know I am wrong at many places. Any help would be appreciated.
I can perhaps do this the normal ML way but I want to learnt impure ML also...
fun loghelper(x,n,b) = if x>n then 0 else (1+loghelper((x*b),n,b));
fun log(b,n) = loghelper(b,n,b);
ok so finally here is the correct code for the while loop and it works as well;
fun log (b, n) =
let
val counter = ref b
val value = ref 0
in
while (!counter <= n) do
(counter := !counter*b;
value := !value + 1);
!value
end;
You have several problems in your code:
Errors:
Instead of val log (b, n) = it should be fun log (b, n) =. fun is a convenience syntax that lets you define functions easily. If you wanted to write this with val you would write: val log = fn (b, n) => (it gets more complicated in the cases of recursive functions or functions with multiple curried arguments)
You need a semicolon to separate two imperative statements: ( counter := !counter*b;
value := !value + 1)
value needs to be a ref: val value = ref 0
Logic:
Your function doesn't return anything. A while loop has the unit type, so your function returns () (unit). You probably want to return !value. To do this, you need to add a semicolon after the whole while loop thing, and then write !value
Your while loop condition doesn't really make sense. It seems reversed. You probably want while !counter <= n do
Your base case is not right. Either value should start at 1 (since counter starts at b, and b is b to the first power); or counter should start at 1 (since b to the zeroth power is 1). The same issue exists with your functional version.