-
Notifications
You must be signed in to change notification settings - Fork 159
Expand file tree
/
Copy pathdeque_array_based.lean
More file actions
144 lines (126 loc) · 2.93 KB
/
Copy pathdeque_array_based.lean
File metadata and controls
144 lines (126 loc) · 2.93 KB
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import Strata.MetaVerifier
------------------------------------------------------------
namespace Strata
-- Array-backed double-ended queue.
--
-- A deque supports insertion and removal at both ends. This example uses a
-- bounded, non-circular array model: live elements occupy indices
-- `front .. back - 1`, with `front == back` meaning empty. The front can move
-- left and the back can move right, so `PushFront` requires spare space before
-- `front` and `PushBack` requires spare space after `back`.
--
-- The circular-buffer queue example covers wraparound behavior separately.
-- Keeping this deque non-circular makes the specifications direct and lets the
-- example focus on four endpoint operations, `old(...)`, and frame properties.
private def dequeArrayPgm :=
#strata
program Boole;
type Array := Map int int;
var D : Array;
var n : int;
var front : int;
var back : int;
// Initialize an empty deque. Starting both endpoints at `start` leaves room
// to grow in either direction if `0 < start < cap`.
procedure DequeInit(cap : int, start : int) returns ()
spec
{
requires cap > 0;
requires 0 <= start && start <= cap;
modifies n;
modifies front;
modifies back;
ensures n == cap;
ensures front == start;
ensures back == start;
}
{
n := cap;
front := start;
back := start;
};
// Return whether the deque has no live elements.
procedure DequeEmpty() returns (b : bool)
spec
{
ensures (b ==> front == back);
ensures (front == back ==> b);
}
{
if (front == back) {
b := true;
} else {
b := false;
}
};
// Add `x` to the back of the deque.
procedure PushBack(x : int) returns ()
spec
{
requires 0 <= front && front <= back;
requires back < n;
modifies D;
modifies back;
ensures back == old(back) + 1;
ensures D[old(back)] == x;
ensures (
∀ i:int .
old(front) <= i && i < old(back) ==> D[i] == old(D[i])
);
}
{
D := D[back := x];
back := back + 1;
};
// Remove and return the last element of the deque.
procedure PopBack() returns (x : int)
spec
{
requires front < back;
modifies back;
ensures back == old(back) - 1;
ensures x == old(D[old(back) - 1]);
ensures front <= back;
}
{
back := back - 1;
x := D[back];
};
// Add `x` to the front of the deque.
procedure PushFront(x : int) returns ()
spec
{
requires 0 < front && front <= back;
requires back <= n;
modifies D;
modifies front;
ensures front == old(front) - 1;
ensures D[front] == x;
ensures (
∀ i:int .
old(front) <= i && i < old(back) ==> D[i] == old(D[i])
);
}
{
front := front - 1;
D := D[front := x];
};
// Remove and return the first element of the deque.
procedure PopFront() returns (x : int)
spec
{
requires front < back;
modifies front;
ensures front == old(front) + 1;
ensures x == old(D[old(front)]);
ensures front <= back;
}
{
x := D[front];
front := front + 1;
};
#end
example : Strata.smtVCsCorrect dequeArrayPgm := by
gen_smt_vcs
all_goals grind
end Strata