-
Notifications
You must be signed in to change notification settings - Fork 1
/
OneHundredPrisonersAndALightbulb.dfy
59 lines (52 loc) · 1.08 KB
/
OneHundredPrisonersAndALightbulb.dfy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// RUN: /compile:0 /nologo
method CardinalitySubsetLt<T>(A: set<T>, B: set<T>)
requires A < B
ensures |A| < |B|
decreases B
{
var b :| b in B && b !in A;
var B' := B - {b};
assert |B| == |B'| + 1;
if A < B' {
CardinalitySubsetLt(A, B');
} else {
assert A == B';
}
}
method strategy<T>(P: set<T>, Special: T) returns (count: int)
requires |P| > 1 && Special in P
ensures count == |P| - 1
decreases *
{
count := 0;
var I := {};
var S := {};
var switch := false;
while count < |P| - 1
invariant count <= |P| - 1
invariant count > 0 ==> Special in I
invariant Special !in S && S < P && S <= I <= P
invariant if switch then |S| == count + 1 else |S| == count
decreases *
{
var p :| p in P;
I := I + {p};
if p == Special {
if switch {
switch := false;
count := count + 1;
}
} else {
if p !in S && !switch {
S := S + {p};
switch := true;
}
}
}
CardinalitySubsetLt(S, I);
if I < P {
CardinalitySubsetLt(I, P);
}
assert P <= I;
assert I == P;
}