-
Notifications
You must be signed in to change notification settings - Fork 200
/
TLCMC.tla
278 lines (248 loc) · 12.3 KB
/
TLCMC.tla
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
------------------------------- MODULE TLCMC -------------------------------
EXTENDS Integers, Sequences, FiniteSets, TLC
(***************************************************************************)
(* Convertes the given Sequence seq into a Set of all the *)
(* Sequence's elements. In other words, the image of the function *)
(* that seq is. *)
(***************************************************************************)
SeqToSet(seq) == {seq[i] : i \in 1..Len(seq)}
(***************************************************************************)
(* Returns a Set of those permutations created out of the elements of Set *)
(* set which satisfy Filter. *)
(***************************************************************************)
SetToSeqs(set, Filter(_)) == UNION {{perm \in [1..Cardinality(set) -> set]:
\* A filter applied on each permutation
\* generated by [S -> T]
Filter(perm)}}
(***************************************************************************)
(* Returns a Set of all possible permutations with distinct elements *)
(* created out of the elements of Set set. All elements of set occur in *)
(* in the sequence. *)
(***************************************************************************)
SetToDistSeqs(set) == SetToSeqs(set,
LAMBDA p: Cardinality(SeqToSet(p)) = Cardinality(set))
(***************************************************************************)
(* A (state) graph G is a directed cyclic graph. *)
(* *)
(* A graph G is represented by a record with 'states' and 'actions' *)
(* components, where G.states is the set of states and G.actions[s] is the *)
(* set of transitions of s -- that is, all states t such that there is an *)
(* action (arc) from s to t. *)
(***************************************************************************)
IsGraph(G) == /\ {"states", "initials", "actions"} = DOMAIN G
/\ G.actions \in [G.states -> SUBSET G.states]
/\ G.initials \subseteq G.states
(***************************************************************************)
(* A set of all permutations of the initial states of G. *)
(***************************************************************************)
SetOfAllPermutationsOfInitials(G) == SetToDistSeqs(G.initials)
(***************************************************************************)
(* A Set of successor states state. *)
(***************************************************************************)
SuccessorsOf(state, SG) == {successor \in SG.actions[state]:
successor \notin {state}}
(***************************************************************************)
(* The predecessor of v in a forest t is the first element of the pair *)
(* <<predecessor, successor>> nested in a sequence of pairs. In an actual *)
(* implementation such as TLC, pair[1] is rather an index into t than *)
(* an id of an actual state. *)
(***************************************************************************)
Predecessor(t, v) == SelectSeq(t, LAMBDA pair: pair[2] = v)[1][1]
CONSTANT StateGraph, ViolationStates, null
ASSUME \* The given StateGraph is actually a graph
\/ IsGraph(StateGraph)
\* The violating states are vertices in the state graph.
\/ ViolationStates \subseteq StateGraph.states
(***************************************************************************
The PlusCal code of the model checker algorithm
--fair algorithm ModelChecker {
variables
\* A FIFO containing all unexplored states. A simple
\* set provides no order, but TLC should explore the
\* StateGraph in either BFS (or DFS => LIFO).
\* Note that S is initialized with each
\* possible permutation of the initial states
\* here because there is no defined order
\* of initial states.
S \in SetOfAllPermutationsOfInitials(StateGraph),
\* A set of already explored states.
C = {},
\* The state currently being explored in scsr
state = null,
\* The set of state's successor states
successors = {},
\* Counter
i = 1,
\* A path from some initial state ending in a
\* state in violation.
counterexample = <<>>,
\* A sequence of pairs such that a pair is a
\* sequence <<predecessor, successors>>.
T = <<>>;
{
(* Check initial states for violations. We could
be clever and check the initial states as part
of the second while loop. However, we then
either check all states twice or add unchecked
states to S. *)
init: while (i \leq Len(S)) {
\* Bug in thesis:
\*state := Head(S);
state := S[i];
\* state is now fully explored,
\* thus exclude it from any
\* further exploration if graph
\* exploration visits it again
\* due to a cycle.
C := C \cup {state};
i := i + 1;
if (state \in ViolationStates) {
counterexample := <<state>>;
\* Terminate model checking
goto trc;
};
};
\* Assert that all initial states have been explored.
initPost: assert C = SeqToSet(S);
(* Explores all successor states
until no new successors are found
or a violation has been detected. *)
scsr: while (Len(S) # 0) {
\* Assign the first element of
\* S to state. state is
\* what is currently being checked.
state := Head(S);
\* Remove state from S.
S := Tail(S);
\* For each unexplored successor 'succ' do:
successors := SuccessorsOf(state, StateGraph) \ C;
if (SuccessorsOf(state, StateGraph) = {}) {
\* Iff there exists no successor besides
\* the self-loop, the system has reached
\* a deadlock state.
counterexample := <<state>>;
goto trc;
};
each: while (successors # {}) {
with (succ \in successors) {
\* Exclude succ in this while loop.
successors := successors \ {succ};
\* Mark successor globally visited.
C := C \cup {succ}; S := S \o <<succ>>;
\* Append succ to T and add it
\* to the list of unexplored states.
T := T \o << <<state,succ>> >>;
\* Check state for violation of a
\* safety property (simplified
\* to a check of set membership.
if (succ \in ViolationStates) {
counterexample := <<succ>>;
\* Terminate model checking
goto trc;
};
};
};
};
(* Model Checking terminated without finding
a violation. *)
\* No states left unexplored and no ViolationState given.
assert S = <<>> /\ ViolationStates = {};
goto Done;
(* Create a counterexample, that is a path
from some initial state to a state in
ViolationStates. In the Java implementation
of TLC, the path is a path of fingerprints.
Thus, a second, guided state exploration
resolves fingerprints to actual states. *)
trc : while (TRUE) {
if (Head(counterexample) \notin StateGraph.initials) {
counterexample := <<Predecessor(T, Head(counterexample))>> \o counterexample;
} else {
assert counterexample # <<>>;
goto Done;
};
};
}
}
***************************************************************************)
\* BEGIN TRANSLATION
VARIABLES S, C, state, successors, i, counterexample, T, pc
vars == << S, C, state, successors, i, counterexample, T, pc >>
Init == (* Global variables *)
/\ S \in SetOfAllPermutationsOfInitials(StateGraph)
/\ C = {}
/\ state = null
/\ successors = {}
/\ i = 1
/\ counterexample = <<>>
/\ T = <<>>
/\ pc = "init"
init == /\ pc = "init"
/\ IF i \leq Len(S)
THEN /\ state' = S[i]
/\ C' = (C \cup {state'})
/\ i' = i + 1
/\ IF state' \in ViolationStates
THEN /\ counterexample' = <<state'>>
/\ pc' = "trc"
ELSE /\ pc' = "init"
/\ UNCHANGED counterexample
ELSE /\ pc' = "initPost"
/\ UNCHANGED << C, state, i, counterexample >>
/\ UNCHANGED << S, successors, T >>
initPost == /\ pc = "initPost"
/\ Assert(C = SeqToSet(S),
"Failure of assertion at line 116, column 18.")
/\ pc' = "scsr"
/\ UNCHANGED << S, C, state, successors, i, counterexample, T >>
scsr == /\ pc = "scsr"
/\ IF Len(S) # 0
THEN /\ state' = Head(S)
/\ S' = Tail(S)
/\ successors' = SuccessorsOf(state', StateGraph) \ C
/\ IF SuccessorsOf(state', StateGraph) = {}
THEN /\ counterexample' = <<state'>>
/\ pc' = "trc"
ELSE /\ pc' = "each"
/\ UNCHANGED counterexample
ELSE /\ Assert(S = <<>> /\ ViolationStates = {},
"Failure of assertion at line 164, column 8.")
/\ pc' = "Done"
/\ UNCHANGED << S, state, successors, counterexample >>
/\ UNCHANGED << C, i, T >>
each == /\ pc = "each"
/\ IF successors # {}
THEN /\ \E succ \in successors:
/\ successors' = successors \ {succ}
/\ C' = (C \cup {succ})
/\ S' = S \o <<succ>>
/\ T' = T \o << <<state,succ>> >>
/\ IF succ \in ViolationStates
THEN /\ counterexample' = <<succ>>
/\ pc' = "trc"
ELSE /\ pc' = "each"
/\ UNCHANGED counterexample
ELSE /\ pc' = "scsr"
/\ UNCHANGED << S, C, successors, counterexample, T >>
/\ UNCHANGED << state, i >>
trc == /\ pc = "trc"
/\ IF Head(counterexample) \notin StateGraph.initials
THEN /\ counterexample' = <<Predecessor(T, Head(counterexample))>> \o counterexample
/\ pc' = "trc"
ELSE /\ Assert(counterexample # <<>>,
"Failure of assertion at line 177, column 20.")
/\ pc' = "Done"
/\ UNCHANGED counterexample
/\ UNCHANGED << S, C, state, successors, i, T >>
(* Allow infinite stuttering to prevent deadlock on termination. *)
Terminating == pc = "Done" /\ UNCHANGED vars
Next == init \/ initPost \/ scsr \/ each \/ trc
\/ Terminating
Spec == /\ Init /\ [][Next]_vars
/\ WF_vars(Next)
Termination == <>(pc = "Done")
\* END TRANSLATION
Live == ViolationStates # {} => <>[](/\ Len(counterexample) > 0
/\ counterexample[Len(counterexample)] \in ViolationStates
/\ counterexample[1] \in StateGraph.initials)
=============================================================================