summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar kyessenov <unknown>2010-08-23 18:04:31 +0000
committerGravatar kyessenov <unknown>2010-08-23 18:04:31 +0000
commit30be884942230517f855b8a6a2d20ac9bc31f809 (patch)
tree11152ffdf209adfec383fa86d8ca00fad2bc01a7
parentb70795fd8b275d77ca5ee9056233c0742bd50c35 (diff)
Chalice:
* added celebrity example (theory of sequences is still weak to prove basic things...) * bug in Chalice: old in while loops is ignored, needs to be fixed if ever want to complete DSW example * evil input from Z3 makes subsequent refinement proofs unsound; need to debug before building upon DSW.chalice; the error is triggered when adding parent field to Node
-rw-r--r--Chalice/refinements/Celebrity.chalice48
-rw-r--r--Chalice/refinements/DSW.chalice64
-rw-r--r--Chalice/refinements/original/Celebrity.chalice63
3 files changed, 63 insertions, 112 deletions
diff --git a/Chalice/refinements/Celebrity.chalice b/Chalice/refinements/Celebrity.chalice
new file mode 100644
index 00000000..b0d398e0
--- /dev/null
+++ b/Chalice/refinements/Celebrity.chalice
@@ -0,0 +1,48 @@
+// Celebrity example, inspired by the Rodin tutorial
+class Person {
+ function knows(other: Person): bool
+ requires this != other;
+}
+
+class Celebrity0 {
+ function IsCelebrity(c: Person, people: seq<Person>): bool
+ requires null !in people;
+ {
+ c in people && forall p in people :: p != c ==> (p.knows(c)) && (! c.knows(p))
+ }
+
+ method Find(people: seq<Person>, /*ghost*/ c: Person) returns (r: Person)
+ requires null !in people && IsCelebrity(c, people);
+ {
+ var r [r == c];
+ }
+}
+
+/** Without theory of sets, hard to describe: "remove an element from a sequence" */
+class Celebrity1 refines Celebrity0 {
+ refines Find(people: seq<Person>, c: Person) returns (r: Person)
+ {
+ var q:seq<Person> := people;
+
+ // pick and remove a
+ var a:Person := q[0]; q := q[1..]; assert people == [a] ++ q;
+
+ while (|q| > 0)
+ invariant forall p in q :: p in people;
+ invariant a in people;
+ invariant IsCelebrity(c,[a] ++ q);
+ {
+ // pick and remove b
+ var oldq:seq<Person> := q;
+ var b:Person := q[0]; q := q[1..];
+ assert oldq == [b] ++ q;
+
+ if (a != b && a.knows(b)) {
+ a := b;
+ }
+ }
+
+ r := a;
+ }
+}
+
diff --git a/Chalice/refinements/DSW.chalice b/Chalice/refinements/DSW.chalice
index 78a84354..5be52f96 100644
--- a/Chalice/refinements/DSW.chalice
+++ b/Chalice/refinements/DSW.chalice
@@ -5,8 +5,6 @@ class Node {
var children: seq<Node>;
var marked: bool;
ghost var path: seq<Node>;
-
- var parent: Node;
}
class DSW0 {
@@ -58,13 +56,7 @@ class DSW0 {
// termination
invariant stop ==> |stack| == 0 && (forall ch in t.children :: ch.marked);
{
- var n: Node;
-
- // stupid syntactic trick to make transformers go around call
- if (true) {
- call n := PickUnmarked(t.children);
- }
-
+ call n := PickUnmarked(t.children);
if (n != null) {
// push
stack := [t] ++ stack;
@@ -95,43 +87,17 @@ class DSW0 {
}
}
-class DSW1 refines DSW0 {
- transforms IterativeMark(root: Node, S: seq<Node>)
- {
- assume forall n in S :: n.parent == null;
- _
- while
- invariant forall n in S :: n !in stack ==> n.parent == null;
- invariant forall i in [1..|stack|] :: stack[i-1].parent == stack[i];
- {
- _
- if {*}
- if {
- // push
- if (|stack| > 0) {
- t.parent := stack[0];
- }
- *
- } else {
- // pop
- if {*} else {
- _
- t.parent := null;
- }
- }
- }
- }
-
- transforms PickUnmarked(p: seq<Node>) returns (x: Node)
- {
- replaces x by {
- if (|p| == 0) {
- x := null;
- } else if (! p[0].marked) {
- x := p[0];
- } else {
- call x := PickUnmarked(p[1..]);
- }
- }
- }
-} \ No newline at end of file
+class DSW1 refines DSW0 {
+ transforms PickUnmarked(p: seq<Node>) returns (x: Node)
+ {
+ replaces x by {
+ if (|p| == 0) {
+ x := null;
+ } else if (! p[0].marked) {
+ x := p[0];
+ } else {
+ call x := PickUnmarked(p[1..]);
+ }
+ }
+ }
+}
diff --git a/Chalice/refinements/original/Celebrity.chalice b/Chalice/refinements/original/Celebrity.chalice
deleted file mode 100644
index 266ebb1b..00000000
--- a/Chalice/refinements/original/Celebrity.chalice
+++ /dev/null
@@ -1,63 +0,0 @@
-// Celebrity example, inspired by the Rodin tutorial
-class Person {
- var knows: seq<Person>;
-}
-
-class Celebrity {
- function IsCelebrity(c: Person, people: seq<Person>): bool
- requires forall p in people :: p != null;
- requires c in people && rd(people[*].knows);
- {
- forall p in people :: p != c ==> (c in p.knows) && (p !in c.knows)
- }
-
- method FindCelebrity0(people: seq<Person>) returns (r: Person)
- requires null !in people && rd(people[*].knows);
- requires exists c in people :: IsCelebrity(c, people);
- ensures rd(people[*].knows);
- ensures r in people && IsCelebrity(r, people);
- {
- var cc:Person;
- assume cc in people && IsCelebrity(cc, people);
- r := cc;
- }
-
- method FindCelebrity1(people: seq<Person>) returns (r: Person)
- requires null !in people && rd(people[*].knows);
- requires exists c in people :: IsCelebrity(c, people);
- ensures rd(people[*].knows);
- ensures r in people && IsCelebrity(r, people);
- {
- call r := Eliminate0(people, people);
- }
-
- method Eliminate0(Q: seq<Person>, people: seq<Person>) returns (r: Person)
- requires null !in people && rd(people[*].knows);
- requires forall c in Q :: c != null && c in people;
- requires exists c in Q :: IsCelebrity(c, people);
- ensures rd(people[*].knows);
- ensures r in people && IsCelebrity(r, people);
- {
- if (|Q| == 1) {
- r := Q[0];
- } else {
- var x:Person := Q[0];
- var y:Person := Q[1];
- var W:seq<Person>;
- assume x != y;
- if (y in x.knows) {
- W := Q[1..];
- assert !IsCelebrity(x, people);
- assert Q == [x] ++ W;
- } else {
- W := [x] ++ Q[2..];
- assert !IsCelebrity(y, people);
- assert W[0] == x;
- assert W[1..] == Q[2..];
-
- assert exists c in W :: IsCelebrity(c, people);
- }
- call r := Eliminate0(W, people);
- }
- }
-}