├── LICENSE ├── README.md ├── edac ├── edac.tla ├── edac_abstract.tla └── edac_abstract_m1.tla ├── fair_cons ├── fair_cons.tla ├── fair_cons_abstract.tla └── fair_cons_abstract_m1.tla ├── floodmin_k1 ├── floodmin_k1.tla ├── floodmin_k1_abstract.tla └── floodmin_k1_abstract_m1.tla ├── floodmin_k2 ├── floodmin_k2.tla ├── floodmin_k2_abstract.tla ├── floodmin_k2_abstract_m1.tla └── floodmin_k2_abstract_m2.tla ├── floodset ├── floodset.tla ├── floodset_abstract.tla └── floodset_abstract_m1.tla ├── nbac ├── nbac.tla ├── nbac_abstract.tla └── nbac_abstract_m1.tla └── pdif ├── pdif.tla ├── pdif_abstract.tla └── pdif_abstract_m1.tla /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Ilina Stoilkovska 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # synchronous-tla-benchmarks 2 | Several synchronous fault-tolerant distributed algorithms encoded in [TLA+](https://lamport.azurewebsites.net/tla/tla.html). 3 | These benchmarks were checked using the model checker [TLC](https://lamport.azurewebsites.net/tla/tools.html) in the following [paper](https://link.springer.com/chapter/10.1007%2F978-3-319-73721-8_1): 4 | 5 | Benjamin Aminof, Sasha Rubin, Ilina Stoilkovska, Josef Widder, Florian Zuleger. 6 | Parameterized Model Checking of Synchronous Distributed Algorithms by Abstraction. 7 | VMCAI 2018 8 | 9 | This repository contains the following benchmarks: 10 | 11 | Name | Problem | Reference 12 | :-----|:--------|:--------- 13 | [edac](edac) | early deciding consensus | [Charron-Bost, Schiper](https://www.sciencedirect.com/science/article/pii/S0196677403001652) 14 | [fair_cons](fair_cons) | consensus | [Raynal](https://www.morganclaypool.com/doi/abs/10.2200/S00294ED1V01Y201009DCT003), p.17 15 | [floodmin_k1](floodmin_k1) | k-set agreement, for k=1| [Lynch](http://groups.csail.mit.edu/tds/distalgs.html), p.136 16 | [floodmin_k2](floodmin_k2) | k-set agreement, for k=2| [Lynch](http://groups.csail.mit.edu/tds/distalgs.html), p.136 17 | [floodset](floodset) | consensus | [Lynch](http://groups.csail.mit.edu/tds/distalgs.html), p.103 18 | [nbac](nbac) | non-blocking atomic commit | [Raynal](https://www.morganclaypool.com/doi/abs/10.2200/S00294ED1V01Y201009DCT003), p.82 19 | [pdif](pdif) | early stopping consensus | [Raynal](https://www.morganclaypool.com/doi/abs/10.2200/S00294ED1V01Y201009DCT003), p.38 20 | 21 | All of the benchmarks assume the crash fault model, where at most T of the total N processes in the system can fail by crashing, with T < N. Once a process crashes, it stops executing the algorithm and it cannot restart. 22 | 23 | For each benchmark `name`, the directory `name` contains the following TLA+ files: 24 | - `name.tla` - this is a concrete encoding of the algorithm, that can be used to check the safety and liveness properties of the algorithm for small system instances, e.g., up to N = 5 processes. When checking, one needs to assign concrete values to the parameters N, T, F. 25 | - `name_abstract.tla` - this is an abstract encoding of the algorithm, that can be used to check the safety and liveness properties in the parameterized case, that is, for all values of the parameters N, T, F. In this encoding, the behavior of a small number M of processes (usually 2 or 3) is kept as in the concrete system, while the behavior of the remaining N - M processes is abstracted. The M processes are assumed to be correct, which implies that T <= N - M. 26 | - `name_abstract_m'.tla` - this is an abstract encoding that captures the corner cases where M' < M processes are fixed and assumed correct, that is, when N - M < T < N. 27 | 28 | For more details, and for our experimental results, please check the [VMCAI 2018 paper](https://link.springer.com/chapter/10.1007%2F978-3-319-73721-8_1). 29 | -------------------------------------------------------------------------------- /edac/edac.tla: -------------------------------------------------------------------------------- 1 | -------------------------------- MODULE edac -------------------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | CONSTANTS N, T, F 6 | 7 | VARIABLES state, msgs, previous, round, phase, 8 | crash, failed, receivers 9 | 10 | vars == <> 11 | 12 | P == 1 .. N \* set of processes 13 | unknown == 2 14 | V == {0, 1} 15 | M == {"W", "D"} \* message type 16 | Messages == {"W"} \X (SUBSET(V) \ {{}}) \cup {"D"} \X V \cup {<<>>} 17 | 18 | C == [ W : {{0}, {1}, {0, 1}}, halt : {FALSE}, decision : {0, 1, unknown}] 19 | InitC == [ W : {{0}, {1}}, halt : {FALSE}, decision : {unknown}] 20 | 21 | InitEnvironment == 22 | /\ phase = "msgs" 23 | /\ round = 0 24 | /\ crash \in SUBSET(P) 25 | /\ failed = {} 26 | /\ Cardinality(failed \cup crash) <= F 27 | /\ receivers \in [crash -> SUBSET(P)] 28 | 29 | InitAlgorithm == 30 | /\ state \in [P -> InitC] 31 | /\ msgs = [p \in P |-> [q \in P |-> <<>>]] \* two-dimensional messages array 32 | /\ previous = [p \in P |-> P] 33 | 34 | NRcv(p) == {q \in P : msgs[q][p] = <<>>} 35 | 36 | Msgs(p) == IF p \in failed 37 | THEN {} 38 | ELSE UNION {U \in SUBSET(V): \E q \in P : msgs[q][p] = <<"W", U>> } 39 | 40 | SendMessage(p, q) == 41 | IF state[p].decision # unknown 42 | THEN <<"D", state[p].decision>> 43 | ELSE <<"W", state[p].W>> 44 | 45 | EnvSemMsg(m, p, q) == 46 | IF \/ p \in failed 47 | \/ state[p].halt 48 | \/ (p \in crash /\ q \notin receivers[p]) 49 | THEN <<>> 50 | ELSE m 51 | 52 | EnvSemState(p, s1, s2) == 53 | IF p \in failed \/ p \in crash \/ s2.halt 54 | THEN s2 55 | ELSE s1 56 | 57 | Update(p, X) == 58 | LET arrived == {x \in V : \E q \in P: msgs[q][p] = <<"D", x>>} IN 59 | LET w == state[p].W \cup Msgs(p) IN 60 | LET dec == IF arrived = {0} 61 | THEN 0 62 | ELSE IF arrived = {1} 63 | THEN 1 64 | ELSE IF previous[p] = NRcv(p) 65 | THEN IF 0 \in w 66 | THEN 0 67 | ELSE 1 68 | ELSE state[p].decision IN 69 | LET h == state[p].decision # unknown IN 70 | [W |-> w, halt |-> h, decision |-> dec] 71 | 72 | MsgsEnvironment == 73 | IF \A p \in P \ failed : state[p].halt 74 | THEN UNCHANGED vars 75 | ELSE 76 | /\ phase' = "trans" 77 | /\ round' = round+1 78 | /\ UNCHANGED <> 79 | 80 | TransEnvironment == 81 | /\ phase' = "msgs" 82 | /\ failed' = failed \cup crash 83 | /\ crash' \in SUBSET(P \ failed') 84 | /\ Cardinality(failed' \cup crash') <= F 85 | /\ receivers' \in [crash' -> SUBSET(P)] 86 | /\ UNCHANGED round 87 | 88 | MsgsAlgorithm == 89 | IF \A p \in P \ failed : state[p].halt 90 | THEN UNCHANGED vars 91 | ELSE 92 | /\ msgs' = [p \in P |-> [q \in P |-> EnvSemMsg(SendMessage(p, q), p, q)]] 93 | /\ UNCHANGED <> 94 | 95 | TransAlgorithm == 96 | /\ state' = [p \in P |-> EnvSemState(p, Update(p, Msgs(p)), state[p])] 97 | /\ previous' = [p \in P |-> IF ~state[p].halt THEN NRcv(p) ELSE previous[p]] 98 | /\ msgs' = [p \in P |-> [q \in P |-> <<>>]] 99 | 100 | 101 | \* next state action predicates 102 | NextEnvironment == 103 | \/ phase = "msgs" /\ MsgsEnvironment 104 | \/ phase = "trans" /\ TransEnvironment 105 | 106 | NextAlgorithm == 107 | \/ phase = "msgs" /\ MsgsAlgorithm 108 | \/ phase = "trans" /\ TransAlgorithm 109 | 110 | Init == InitAlgorithm /\ InitEnvironment 111 | Next == NextAlgorithm /\ NextEnvironment 112 | 113 | \* fairness constraint 114 | Fairness == WF_vars(Next) 115 | 116 | \* specification 117 | Spec == Init /\ [][Next]_vars /\ Fairness 118 | 119 | \* safety properties 120 | Validity == \A v \in V : (\A p \in P : state[p].W = {v}) => [](\A q \in P : (q \notin failed /\ state[q].decision # unknown) => state[q].decision = v) 121 | Agreement == [](\A p \in P : \A q \in P : (p \notin failed /\ state[p].decision # unknown /\ q \notin failed /\ state[q].decision # unknown => 122 | state[p].decision = state[q].decision)) 123 | 124 | \* liveness property 125 | Termination == <>(\A p \in P : p \in failed \/ state[p].decision # unknown) 126 | 127 | 128 | 129 | ============================================================================= 130 | \* Modification History 131 | \* Last modified Thu Sep 28 18:50:35 CEST 2017 by stoilkov 132 | \* Created Thu Sep 28 18:35:23 CEST 2017 by stoilkov 133 | -------------------------------------------------------------------------------- /edac/edac_abstract.tla: -------------------------------------------------------------------------------- 1 | ----------------------- MODULE edac_abstract ----------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, loc2, locOther, msgs, previous, phase, crash, decisionRound, receivers, someP 6 | 7 | vars == <> 8 | 9 | v0 == 0 \* default decision value 10 | V == {0, 1} \* set of values 11 | I == 1 .. 12 \* indices corresponding process locations 12 | U == 1 .. 14 \* array indices (process locations + 2 concrete processes) 13 | u1 == 13 \* index for process 1 14 | u2 == 14 \* index for process 2 15 | Loc == [ W : {{0}, {1}, {0, 1}}, halt : BOOLEAN, decide : BOOLEAN] \* possible process locations 16 | AM == {W \in SUBSET(SUBSET(V)) : W = {} \/ Cardinality(W) = 1 \/ (Cardinality(W) = 2 /\ {} \in W)} \* abstract message alphabet 17 | 18 | \* translate index i \in I to location l \in Loc 19 | location(i) == 20 | LET x == i - 1 IN 21 | LET w == IF x \div 4 = 0 THEN {0} ELSE IF x \div 4 = 1 THEN {1} ELSE {0, 1} IN 22 | LET y == x % 4 IN 23 | LET h == IF y \div 2 = 0 THEN FALSE ELSE TRUE IN 24 | LET d == IF y % 2 = 0 THEN FALSE ELSE TRUE IN 25 | [W |-> w, halt |-> h, decide |-> d] 26 | 27 | \* translate location l \in Loc to index i \in I 28 | index(l) == 29 | LET d == IF l.decide = FALSE THEN 0 ELSE 1 IN 30 | LET h == IF l.halt = FALSE THEN 0 ELSE 1 IN 31 | LET w == IF l.W = {0} THEN 0 ELSE IF l.W = {1} THEN 1 ELSE 2 IN 32 | 4 * w + 2 * h + d + 1 33 | 34 | \* get value set, given index u \in U 35 | valueSet(u) == 36 | IF u = u1 37 | THEN loc1.W 38 | ELSE IF u = u2 39 | THEN loc2.W 40 | ELSE location(u).W 41 | \* get decided flag, given index u \in U 42 | decided(u) == 43 | IF u = u1 44 | THEN loc1.decide 45 | ELSE IF u = u2 46 | THEN loc2.decide 47 | ELSE location(u).decide 48 | \* get halted flag, given index u \in U 49 | halted(u) == 50 | IF u = u1 51 | THEN loc1.halt 52 | ELSE IF u = u2 53 | THEN loc2.halt 54 | ELSE location(u).halt 55 | 56 | \* Set of locations of active processes 57 | Active == {loc1, loc2} \cup locOther 58 | \* Set of indices of active processes 59 | IndexActive == {u1, u2} \cup {index(l) : l \in locOther} 60 | \* Set of indices witnessing non-halted processes 61 | IndexNonHalted == {u \in IndexActive : ~halted(u)} 62 | \* Set of indices witnessing undecided processes 63 | IndexUndecided == {u \in IndexActive : ~halted(u) /\ ~decided(u)} 64 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 65 | Correct == {u \in IndexActive : ~halted(u) /\ ~decided(u) /\ (u \in {u1, u2} \/ crash[location(u)] # {TRUE})} 66 | 67 | \* set failure flag of l to TRUE 68 | failedLocation(l) == 69 | [W |-> l.W, halt |-> TRUE, decide |-> l.decide] 70 | 71 | \* a process in a decided location stops participating in the algorithm 72 | decidedLocation(l) == 73 | [W |-> l.W, halt |-> TRUE, decide |-> TRUE] 74 | 75 | \* Set of initial locations 76 | InitActive == {[W |-> {0}, halt |-> FALSE, decide |-> FALSE], 77 | [W |-> {1}, halt |-> FALSE, decide |-> FALSE]} 78 | 79 | \* type invariant 80 | TypeOK == 81 | /\ loc1 \in Loc 82 | /\ loc2 \in Loc 83 | /\ locOther \in SUBSET(Loc) 84 | /\ msgs \in [IndexNonHalted -> [IndexNonHalted -> AM]] 85 | /\ phase \in {"msgs", "trans"} 86 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 87 | /\ decisionRound \in [Correct -> BOOLEAN] 88 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : Cardinality(valueSet(u)) = 1} -> SUBSET(BOOLEAN)] 89 | /\ someP \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 90 | 91 | \* initial predicate of the environment 92 | InitEnvironment == 93 | /\ phase = "msgs" \* current phase of the algorithm 94 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] \* crash array 95 | /\ decisionRound = [u \in Correct |-> FALSE] \* early decision predicates for the correct processes 96 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X Correct -> ((SUBSET(BOOLEAN)) \ {{}})] \* receivers array 97 | /\ someP = [l \in {k \in locOther : crash[k] # {TRUE}} |-> FALSE] 98 | 99 | InitAlgorithm == 100 | /\ loc1 \in InitActive \* first fixed process 101 | /\ loc2 \in InitActive \* second fixed process 102 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of locations witnessing the other N - 2 processes 103 | /\ msgs = [u \in IndexNonHalted |-> [v \in IndexNonHalted |-> {<<>>}]] \* two-dimensional messages array 104 | /\ previous = [u \in IndexNonHalted |-> [v \in IndexUndecided |-> {<<>>}]] \* {} ]] \* two-dimensional array storing messages from the previous round 105 | 106 | \* equality of messages between the previous and current round 107 | equal(u, v) == 108 | IF <<>> \in msgs[u][v]' 109 | THEN previous[u][v] = msgs[u][v]' 110 | ELSE previous[u][v] # {<<>>} /\ msgs[u][v]' \subseteq previous[u][v] 111 | 112 | \* check for equality of messages received in the previous and the current round 113 | \* by processes witnessed by v 114 | isDecisionRound(v) == 115 | IF Cardinality(valueSet(v)) = 1 116 | THEN /\ \A u \in DOMAIN crash : TRUE \notin crash[u] \/ FALSE \notin receivers[u, v] 117 | /\ \A u \in IndexNonHalted : equal(u, v) 118 | ELSE \A u \in DOMAIN crash : TRUE \notin crash[u] 119 | 120 | \* environment transition in the message exchage phase 121 | MsgsEnvironment == 122 | /\ phase' = "trans" 123 | /\ decisionRound' = [v \in Correct |-> isDecisionRound(v)] 124 | /\ someP' \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 125 | /\ UNCHANGED <> 126 | 127 | \* environment transition in the state update phase 128 | TransEnvironment == 129 | /\ phase' = "msgs" 130 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 131 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} 132 | \times {u \in Correct' : Cardinality(valueSet(u)') = 1} 133 | -> (SUBSET(BOOLEAN) \ {{}})] 134 | /\ someP' = [l \in {k \in locOther : ~k.halt /\ Cardinality(k.W) = 1 /\ crash[k] # {TRUE}}' |-> FALSE] 135 | /\ UNCHANGED <> 136 | 137 | \* message generation function of a correct process 138 | SendMessage(u, v) == 139 | <> 140 | 141 | \* update function of a correct process 142 | \* (that received the same messages as the abstract location that witnesses it) 143 | Update(l, u) == 144 | LET arrived == {m \in V : \E v \in IndexNonHalted : <<{m}, TRUE>> \in msgs[v][u]} IN 145 | LET x == IF \/ /\ l.W = {0} 146 | /\ \E m \in {{1}, {0, 1}} : \E v \in IndexNonHalted : <> \in msgs[v][u] 147 | \/ /\ l.W = {1} 148 | /\ \E m \in {{0}, {0, 1}} : \E v \in IndexNonHalted : <> \in msgs[v][u] 149 | THEN {0, 1} 150 | ELSE l.W IN 151 | LET w == IF arrived # {} 152 | THEN arrived 153 | ELSE IF decisionRound[u] 154 | THEN IF x = {0} 155 | THEN {0} 156 | ELSE IF x = {1} 157 | THEN {1} 158 | ELSE {v0} 159 | ELSE x IN 160 | LET h == IF l.decide 161 | THEN TRUE 162 | ELSE FALSE IN 163 | LET d == IF arrived # {} \/ decisionRound[u] 164 | THEN TRUE 165 | ELSE FALSE IN 166 | [W |-> w, halt |-> h, decide |-> d] 167 | 168 | \* update function of a correct process 169 | \* (that received messages different from the ones received by abstract location that witnesses it) 170 | UpdateOther(l, u, M) == 171 | LET arrived == {m \in V : \E v \in IndexNonHalted : <<{m}, TRUE>> \in msgs[v][u]} IN 172 | LET w == IF arrived # {} 173 | THEN arrived 174 | ELSE IF decisionRound[u] 175 | THEN IF l.W \cup M = {0} 176 | THEN {0} 177 | ELSE IF l.W \cup M = {1} 178 | THEN {1} 179 | ELSE {v0} 180 | ELSE l.W \cup M IN 181 | LET h == IF l.decide 182 | THEN TRUE 183 | ELSE FALSE IN 184 | LET d == IF arrived # {} \/ decisionRound[u] 185 | THEN TRUE 186 | ELSE FALSE IN 187 | [W |-> w, halt |-> h, decide |-> d] 188 | 189 | \* update of a process location witnessing correct processes 190 | UpdateCorrect(l, u) == 191 | IF \A m \in V : \A v \in IndexNonHalted : <<{m}, TRUE>> \notin msgs[v][u] 192 | THEN IF Cardinality(l.W) = 1 /\ loc1.W = l.W /\ loc2.W = l.W 193 | THEN IF \A v \in IndexNonHalted : v \notin {u1, u2} /\ location(v).W # l.W => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 194 | THEN {UpdateOther(l, u, l.W)} 195 | ELSE IF someP[l] 196 | THEN {Update(l, u), UpdateOther(l, u, l.W)} 197 | ELSE {Update(l, u)} 198 | ELSE {Update(l, u)} 199 | ELSE {Update(l, u)} 200 | 201 | \* delivery of messages by the environment 202 | EnvSemMsg(m, u, v) == 203 | IF u \in {u1, u2} 204 | THEN {m} 205 | ELSE LET l == location(u) IN 206 | IF crash[l] = {TRUE, FALSE} 207 | THEN IF ~decided(v) /\ Cardinality(valueSet(v)) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 208 | THEN IF receivers[l,v] = {TRUE} 209 | THEN {m} 210 | ELSE {<<>>, m} 211 | ELSE {<<>>} 212 | ELSE IF crash[l] = {TRUE} 213 | THEN IF ~decided(v) /\ Cardinality(valueSet(v)) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 214 | THEN IF receivers[l,v] = {TRUE} 215 | THEN {m} 216 | ELSE IF receivers[l,v] = {FALSE} 217 | THEN {<<>>} 218 | ELSE {<<>>, m} 219 | ELSE {<<>>} 220 | ELSE IF ~decided(v) /\ Cardinality(valueSet(v)) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 221 | THEN {m} 222 | ELSE {<<>>} 223 | 224 | \* state update of the fixed processes w.r.t. the environment 225 | EnvSemState(l, u) == 226 | IF l.halt 227 | THEN l 228 | ELSE IF l.decide 229 | THEN decidedLocation(l) 230 | ELSE Update(l, u) 231 | 232 | \* state update of the other processes w.r.t. the environment 233 | EnvSemStateOther(l) == 234 | IF l.halt 235 | THEN {l} \* halted processes do not update their location 236 | ELSE IF l.decide \* if processes have decided, there is no need in processing received messages 237 | THEN {decidedLocation(l)} \* processes that decided in the previous round halt in this round 238 | ELSE IF crash[l] = {TRUE} \* all processes in l have crashed in this round 239 | THEN {failedLocation(l)} \* they are flagged as failed in the next rounds 240 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes in l crashed, and some did not 241 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} \* partially correct, partially failed 242 | ELSE UpdateCorrect(l, index(l)) \* no failed (fully correct) 243 | 244 | \* update of messages 245 | UpdatePrevious(u, v) == 246 | LET E == IF u \in {u1, u2} 247 | THEN {u} 248 | ELSE {index(k) : k \in {l \in locOther : location(u) \in EnvSemStateOther(l)}} IN 249 | LET F == IF v \in {u1, u2} 250 | THEN {v} 251 | ELSE {index(k) : k \in {l \in locOther : location(v) \in EnvSemStateOther(l)}} IN 252 | UNION({msgs[e][f] : e \in E, f \in F}) 253 | 254 | \* algorithm transition in the message exchange phase 255 | MsgsAlgorithm == 256 | /\ msgs' = [u \in IndexNonHalted |-> [v \in IndexNonHalted |-> EnvSemMsg(SendMessage(u, v), u, v)]] 257 | /\ UNCHANGED <> 258 | 259 | \* local state transition phase of the algorithm module 260 | TransAlgorithm == 261 | /\ loc1' = EnvSemState(loc1, u1) 262 | /\ loc2' = EnvSemState(loc2, u2) 263 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 264 | /\ previous' = [u \in IndexNonHalted' |-> [v \in IndexUndecided' |-> UpdatePrevious(u, v)]] 265 | /\ msgs' = [u \in IndexNonHalted' |-> [v \in IndexNonHalted' |-> {<<>>}]] 266 | 267 | 268 | NextEnvironment == 269 | \/ phase = "msgs" /\ MsgsEnvironment 270 | \/ phase = "trans" /\ TransEnvironment 271 | 272 | NextAlgorithm == 273 | \/ phase = "msgs" /\ MsgsAlgorithm 274 | \/ phase = "trans" /\ TransAlgorithm 275 | 276 | Init == InitAlgorithm /\ InitEnvironment 277 | 278 | Next == NextAlgorithm /\ NextEnvironment 279 | 280 | \* constraints 281 | Fairness == 282 | /\ WF_vars(Next) 283 | /\ <>[](\A c \in DOMAIN crash : TRUE \notin crash[c]) 284 | 285 | \* specification 286 | Spec == Init /\ [][Next]_vars /\ Fairness 287 | 288 | \* safety properties 289 | Validity0 == ((\A l \in Active : l.W = {0}) => 290 | [](/\ loc1.halt => loc1.W = {0} 291 | /\ loc2.halt => loc2.W = {0})) 292 | Validity1 == ((\A l \in Active : l.W = {1}) => 293 | [](/\ loc1.halt => loc1.W = {1} 294 | /\ loc2.halt => loc2.W = {1})) 295 | \* Validity: if all processes start with the same value, then this is the only 296 | \* possible decision value 297 | Validity == Validity0 /\ Validity1 298 | 299 | \* Agreement: no two correct processes decide on a different value 300 | Agreement == [](loc1.halt /\ loc2.halt => loc1.W = loc2.W) 301 | 302 | \* liveness property 303 | \* Termination: all correct processes eventually decide 304 | Termination == <>(loc1.halt /\ loc2.halt) 305 | 306 | 307 | ============================================================================= 308 | \* Modification History 309 | \* Last modified Wed Nov 22 20:31:58 CET 2017 by ilina 310 | \* Last modified Tue Nov 14 17:43:13 CET 2017 by stoilkov 311 | \* Created Mon Aug 15 13:59:16 CEST 2017 by stoilkov 312 | -------------------------------------------------------------------------------- /edac/edac_abstract_m1.tla: -------------------------------------------------------------------------------- 1 | ----------------------- MODULE edac_abstract_m1 ----------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, locOther, msgs, previous, phase, crash, decisionRound, receivers, someP 6 | 7 | vars == <> 8 | 9 | v0 == 0 \* default decision value 10 | V == {0, 1} \* set of values 11 | I == 1 .. 12 \* indices corresponding process locations 12 | U == 1 .. 13 \* array indices (process locations + 1 fixed process) 13 | u1 == 13 \* index for process 1 14 | Loc == [ W : {{0}, {1}, {0, 1}}, halt : BOOLEAN, decide : BOOLEAN] \* possible process locations 15 | AM == {W \in SUBSET(SUBSET(V)) : W = {} \/ Cardinality(W) = 1 \/ (Cardinality(W) = 2 /\ {} \in W)} \* abstract message alphabet 16 | 17 | \* translate index i \in I to location l \in Loc 18 | location(i) == 19 | LET x == i - 1 IN 20 | LET w == IF x \div 4 = 0 THEN {0} ELSE IF x \div 4 = 1 THEN {1} ELSE {0, 1} IN 21 | LET y == x % 4 IN 22 | LET h == IF y \div 2 = 0 THEN FALSE ELSE TRUE IN 23 | LET d == IF y % 2 = 0 THEN FALSE ELSE TRUE IN 24 | [W |-> w, halt |-> h, decide |-> d] 25 | 26 | \* translate location l \in Loc to index i \in I 27 | index(l) == 28 | LET d == IF l.decide = FALSE THEN 0 ELSE 1 IN 29 | LET h == IF l.halt = FALSE THEN 0 ELSE 1 IN 30 | LET w == IF l.W = {0} THEN 0 ELSE IF l.W = {1} THEN 1 ELSE 2 IN 31 | 4 * w + 2 * h + d + 1 32 | 33 | \* get value set, given index u \in U 34 | valueSet(u) == 35 | IF u = u1 36 | THEN loc1.W 37 | ELSE location(u).W 38 | \* get decided flag, given index u \in U 39 | decided(u) == 40 | IF u = u1 41 | THEN loc1.decide 42 | ELSE location(u).decide 43 | \* get halted flag, given index u \in U 44 | halted(u) == 45 | IF u = u1 46 | THEN loc1.halt 47 | ELSE location(u).halt 48 | 49 | \* Set of locations of active processes 50 | Active == {loc1} \cup locOther 51 | \* Set of indices of active processes 52 | IndexActive == {u1} \cup {index(l) : l \in locOther} 53 | \* Set of indices witnessing non-halted processes 54 | IndexNonHalted == {u \in IndexActive : ~halted(u)} 55 | \* Set of indices witnessing undecided processes 56 | IndexUndecided == {u \in IndexActive : ~halted(u) /\ ~decided(u)} 57 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 58 | Correct == {u \in IndexActive : ~halted(u) /\ ~decided(u) /\ (u \in {u1} \/ crash[location(u)] # {TRUE})} 59 | 60 | \* set failure flag of l to TRUE 61 | failedLocation(l) == 62 | [W |-> l.W, halt |-> TRUE, decide |-> l.decide] 63 | 64 | \* a process in a decided location stops participating in the algorithm 65 | decidedLocation(l) == 66 | [W |-> l.W, halt |-> TRUE, decide |-> TRUE] 67 | 68 | \* Set of initial locations 69 | InitActive == {[W |-> {0}, halt |-> FALSE, decide |-> FALSE], 70 | [W |-> {1}, halt |-> FALSE, decide |-> FALSE]} 71 | 72 | \* type invariant 73 | TypeOK == 74 | /\ loc1 \in Loc 75 | /\ locOther \in SUBSET(Loc) 76 | /\ msgs \in [IndexNonHalted -> [IndexNonHalted -> AM]] 77 | /\ phase \in {"msgs", "trans"} 78 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 79 | /\ decisionRound \in [Correct -> BOOLEAN] 80 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : Cardinality(valueSet(u)) = 1} -> SUBSET(BOOLEAN)] 81 | /\ someP \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 82 | 83 | \* initial predicate of the environment 84 | InitEnvironment == 85 | /\ phase = "msgs" \* current phase of the algorithm 86 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] \* crash array 87 | /\ decisionRound = [u \in Correct |-> FALSE] \* early decision predicates for the correct processes 88 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X Correct -> ((SUBSET(BOOLEAN)) \ {{}})] \* receivers array 89 | /\ someP = [l \in {k \in locOther : crash[k] # {TRUE}} |-> FALSE] 90 | 91 | InitAlgorithm == 92 | /\ loc1 \in InitActive \* first fixed process 93 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of locations witnessing the other N - 2 processes 94 | /\ msgs = [u \in IndexNonHalted |-> [v \in IndexNonHalted |-> {<<>>}]] \* two-dimensional messages array 95 | /\ previous = [u \in IndexNonHalted |-> [v \in IndexUndecided |-> {}]] \* {} ]] \* two-dimensional array storing messages from the previous round 96 | 97 | \* equality of messages between the previous and current round 98 | equal(u, v) == 99 | IF <<>> \in msgs[u][v]' 100 | THEN previous[u][v] = msgs[u][v]' 101 | ELSE previous[u][v] # {<<>>} /\ msgs[u][v]' \subseteq previous[u][v] 102 | 103 | \* check for equality of messages received in the previous and the current round 104 | \* by processes witnessed by v 105 | isDecisionRound(v) == 106 | \A u \in IndexNonHalted : equal(u, v) 107 | 108 | \* environment transition in the message exchage phase 109 | MsgsEnvironment == 110 | /\ phase' = "trans" 111 | /\ decisionRound' = [v \in Correct |-> isDecisionRound(v)] 112 | /\ someP' \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 113 | /\ UNCHANGED <> 114 | 115 | \* environment transition in the state update phase 116 | TransEnvironment == 117 | /\ phase' = "msgs" 118 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 119 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} 120 | \times {u \in Correct' : Cardinality(valueSet(u)') = 1} 121 | -> (SUBSET(BOOLEAN) \ {{}})] 122 | /\ someP' = [l \in {k \in locOther : ~k.halt /\ Cardinality(k.W) = 1 /\ crash[k] # {TRUE}}' |-> FALSE] 123 | /\ UNCHANGED <> 124 | 125 | \* message generation function of a correct process 126 | SendMessage(u, v) == 127 | <> 128 | 129 | \* update function of a correct process 130 | \* (that received the same messages as the abstract location that witnesses it) 131 | Update(l, u) == 132 | LET arrived == {m \in V : \E v \in IndexNonHalted : <<{m}, TRUE>> \in msgs[v][u]} IN 133 | LET x == IF \/ /\ l.W = {0} 134 | /\ \E m \in {{1}, {0, 1}} : \E v \in IndexNonHalted : <> \in msgs[v][u] 135 | \/ /\ l.W = {1} 136 | /\ \E m \in {{0}, {0, 1}} : \E v \in IndexNonHalted : <> \in msgs[v][u] 137 | THEN {0, 1} 138 | ELSE l.W IN 139 | LET w == IF arrived # {} 140 | THEN arrived 141 | ELSE IF decisionRound[u] 142 | THEN IF x = {0} 143 | THEN {0} 144 | ELSE IF x = {1} 145 | THEN {1} 146 | ELSE {v0} 147 | ELSE x IN 148 | LET h == IF l.decide 149 | THEN TRUE 150 | ELSE FALSE IN 151 | LET d == IF arrived # {} \/ decisionRound[u] 152 | THEN TRUE 153 | ELSE FALSE IN 154 | [W |-> w, halt |-> h, decide |-> d] 155 | 156 | \* update function of a correct process 157 | \* (that received messages different from the ones received by abstract location that witnesses it) 158 | UpdateOther(l, u, M) == 159 | LET arrived == {m \in V : \E v \in IndexNonHalted : <<{m}, TRUE>> \in msgs[v][u]} IN 160 | LET w == IF arrived # {} 161 | THEN arrived 162 | ELSE IF decisionRound[u] 163 | THEN IF l.W \cup M = {0} 164 | THEN {0} 165 | ELSE IF l.W \cup M = {1} 166 | THEN {1} 167 | ELSE {v0} 168 | ELSE l.W \cup M IN 169 | LET h == IF l.decide 170 | THEN TRUE 171 | ELSE FALSE IN 172 | LET d == IF arrived # {} \/ decisionRound[u] 173 | THEN TRUE 174 | ELSE FALSE IN 175 | [W |-> w, halt |-> h, decide |-> d] 176 | 177 | \* update of a process location witnessing correct processes 178 | UpdateCorrect(l, u) == 179 | IF \A m \in V : \A v \in IndexNonHalted : <<{m}, TRUE>> \notin msgs[v][u] 180 | THEN IF Cardinality(l.W) = 1 /\ loc1.W = l.W 181 | THEN IF \A v \in IndexNonHalted : v \notin {u1} /\ location(v).W # l.W => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 182 | THEN {UpdateOther(l, u, l.W)} 183 | ELSE IF someP[l] 184 | THEN {Update(l, u), UpdateOther(l, u, l.W)} 185 | ELSE {Update(l, u)} 186 | ELSE {Update(l, u)} 187 | ELSE {Update(l, u)} 188 | 189 | \* delivery of messages by the environment 190 | EnvSemMsg(m, u, v) == 191 | IF u \in {u1} 192 | THEN {m} 193 | ELSE LET l == location(u) IN 194 | IF crash[l] = {TRUE, FALSE} 195 | THEN IF ~decided(v) /\ Cardinality(valueSet(v)) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 196 | THEN IF receivers[l,v] = {TRUE} 197 | THEN {m} 198 | ELSE {<<>>, m} 199 | ELSE {<<>>} 200 | ELSE IF crash[l] = {TRUE} 201 | THEN IF ~decided(v) /\ Cardinality(valueSet(v)) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 202 | THEN IF receivers[l,v] = {TRUE} 203 | THEN {m} 204 | ELSE IF receivers[l,v] = {FALSE} 205 | THEN {<<>>} 206 | ELSE {<<>>, m} 207 | ELSE {<<>>} 208 | ELSE IF ~decided(v) /\ Cardinality(valueSet(v)) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 209 | THEN {m} 210 | ELSE {<<>>} 211 | 212 | \* state update of the fixed processes w.r.t. the environment 213 | EnvSemState(l, u) == 214 | IF l.halt 215 | THEN l 216 | ELSE IF l.decide 217 | THEN decidedLocation(l) 218 | ELSE Update(l, u) 219 | 220 | \* state update of the other processes w.r.t. the environment 221 | EnvSemStateOther(l) == 222 | IF l.halt 223 | THEN {l} \* halted processes do not update their location 224 | ELSE IF l.decide \* if processes have decided, there is no need in processing received messages 225 | THEN {decidedLocation(l)} \* processes that decided in the previous round halt in this round 226 | ELSE IF crash[l] = {TRUE} \* all processes in l have crashed in this round 227 | THEN {failedLocation(l)} \* they are flagged as failed in the next rounds 228 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes in l crashed, and some did not 229 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} \* partially correct, partially failed 230 | ELSE UpdateCorrect(l, index(l)) \* no failed (fully correct) 231 | 232 | \* update of messages 233 | UpdatePrevious(u, v) == 234 | LET E == IF u \in {u1} 235 | THEN {u} 236 | ELSE {index(k) : k \in {l \in locOther : location(u) \in EnvSemStateOther(l)}} IN 237 | LET F == IF v \in {u1} 238 | THEN {v} 239 | ELSE {index(k) : k \in {l \in locOther : location(v) \in EnvSemStateOther(l)}} IN 240 | UNION({msgs[e][f] : e \in E, f \in F}) 241 | 242 | \* algorithm transition in the message exchange phase 243 | MsgsAlgorithm == 244 | /\ msgs' = [u \in IndexNonHalted |-> [v \in IndexNonHalted |-> EnvSemMsg(SendMessage(u, v), u, v)]] 245 | /\ UNCHANGED <> 246 | 247 | \* local state transition phase of the algorithm module 248 | TransAlgorithm == 249 | /\ loc1' = EnvSemState(loc1, u1) 250 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 251 | /\ previous' = [u \in IndexNonHalted' |-> [v \in IndexUndecided' |-> UpdatePrevious(u, v)]] 252 | /\ msgs' = [u \in IndexNonHalted' |-> [v \in IndexNonHalted' |-> {<<>>}]] 253 | 254 | 255 | NextEnvironment == 256 | \/ phase = "msgs" /\ MsgsEnvironment 257 | \/ phase = "trans" /\ TransEnvironment 258 | 259 | NextAlgorithm == 260 | \/ phase = "msgs" /\ MsgsAlgorithm 261 | \/ phase = "trans" /\ TransAlgorithm 262 | 263 | Init == InitAlgorithm /\ InitEnvironment 264 | 265 | Next == NextAlgorithm /\ NextEnvironment 266 | 267 | \* constraints 268 | Fairness == 269 | /\ WF_vars(Next) 270 | /\ <>[](\A c \in DOMAIN crash : TRUE \notin crash[c]) 271 | 272 | \* specification 273 | Spec == Init /\ [][Next]_vars /\ Fairness 274 | 275 | \* safety properties 276 | Validity0 == ((\A l \in Active : l.W = {0}) => 277 | [](loc1.halt => loc1.W = {0})) 278 | Validity1 == ((\A l \in Active : l.W = {1}) => 279 | [](loc1.halt => loc1.W = {1})) 280 | \* Validity: if all processes start with the same value, then this is the only 281 | \* possible decision value 282 | Validity == Validity0 /\ Validity1 283 | 284 | \* liveness property 285 | \* Termination: all correct processes eventually decide 286 | Termination == <>(loc1.halt) 287 | 288 | ============================================================================= 289 | \* Modification History 290 | \* Last modified Tue Oct 17 11:50:19 CEST 2017 by stoilkov 291 | \* Created Thu Sep 28 17:11:33 CEST 2017 by stoilkov 292 | -------------------------------------------------------------------------------- /fair_cons/fair_cons.tla: -------------------------------------------------------------------------------- 1 | ----------------------------- MODULE fair_cons ----------------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | CONSTANTS N, T, F 6 | 7 | VARIABLES state, msgs, round, phase, 8 | crash, failed, receivers 9 | 10 | vars == <> 11 | 12 | P == 1 .. N 13 | unknown == 2 14 | V == {0, 1} 15 | v0 == 0 16 | 17 | C == [ est : V, prev_est : V \cup {unknown}, decided : BOOLEAN] 18 | InitC == [ est : V, prev_est : {unknown}, decided : {FALSE}] 19 | 20 | 21 | InitEnvironment == 22 | /\ phase = "msgs" 23 | /\ round = 0 24 | /\ crash \in SUBSET(P) 25 | /\ failed = {} 26 | /\ Cardinality(failed \cup crash) <= F 27 | /\ receivers \in [crash -> SUBSET(P)] 28 | 29 | InitAlgorithm == 30 | /\ state \in [P -> InitC] 31 | /\ msgs = [p \in P |-> [q \in P |-> unknown]] \* two-dimensional messages array 32 | 33 | Msgs(p) == IF p \in failed 34 | THEN {} 35 | ELSE {m \in V : \E q \in P : msgs[q][p] = m} 36 | 37 | Min(S) == IF 0 \in S THEN 0 ELSE 1 38 | 39 | SendMessage(p, q) == 40 | IF state[p].est # state[p].prev_est 41 | THEN state[p].est 42 | ELSE unknown 43 | 44 | EnvSemMsg(m, p, q) == 45 | IF \/ p \in failed 46 | \/ p \in crash /\ q \notin receivers[p] 47 | THEN unknown 48 | ELSE m 49 | 50 | EnvSemState(p, s1, s2) == 51 | IF p \in failed \/ p \in crash 52 | THEN s2 53 | ELSE s1 54 | 55 | Update(s, X) == 56 | LET e == Min({s.est} \cup X) IN 57 | LET d == IF round >= T + 1 58 | THEN TRUE 59 | ELSE FALSE IN 60 | [est |-> e, prev_est |-> s.est, decided |-> d] 61 | 62 | 63 | MsgsEnvironment == 64 | IF round <= T 65 | THEN 66 | /\ phase' = "trans" 67 | /\ round' = round+1 68 | /\ UNCHANGED <> 69 | ELSE UNCHANGED vars 70 | 71 | TransEnvironment == 72 | /\ phase' = "msgs" 73 | /\ failed' = failed \cup crash 74 | /\ crash' \in SUBSET(P \ failed') 75 | /\ Cardinality(failed' \cup crash') <= F 76 | /\ receivers' \in [crash' -> SUBSET(P)] 77 | /\ UNCHANGED round 78 | 79 | MsgsAlgorithm == 80 | IF round <= T 81 | THEN 82 | /\ msgs' = [p \in P |-> [q \in P |-> EnvSemMsg(SendMessage(p, q), p, q)]] 83 | /\ UNCHANGED state 84 | ELSE UNCHANGED vars 85 | 86 | TransAlgorithm == 87 | /\ state' = [p \in P |-> EnvSemState(p, Update(state[p], Msgs(p)), state[p])] 88 | /\ msgs' = [p \in P |-> [q \in P |-> unknown]] 89 | 90 | 91 | \* next state action predicates 92 | 93 | NextEnvironment == 94 | \/ phase = "msgs" /\ MsgsEnvironment 95 | \/ phase = "trans" /\ TransEnvironment 96 | 97 | NextAlgorithm == 98 | \/ phase = "msgs" /\ MsgsAlgorithm 99 | \/ phase = "trans" /\ TransAlgorithm 100 | 101 | Init == InitAlgorithm /\ InitEnvironment 102 | Next == NextAlgorithm /\ NextEnvironment 103 | 104 | \* fairness constraint 105 | Fairness == WF_vars(Next) 106 | 107 | \* specification 108 | Spec == Init /\ [][Next]_vars /\ Fairness 109 | 110 | \* safety properties 111 | Validity == \A v \in V : (\A p \in P : state[p].est = v) => [](\A q \in P : (q \notin failed /\ state[q].decided) => state[q].est = v) 112 | 113 | Agreement == [](\A p \in P : \A q \in P : (state[p].decided /\ state[q].decided => state[p].est = state[q].est)) 114 | 115 | \* liveness property 116 | Termination == <>(\A p \in P : p \in failed \/ state[p].decided) 117 | ============================================================================= 118 | \* Modification History 119 | \* Last modified Fri Sep 29 11:55:55 CEST 2017 by stoilkov 120 | \* Created Thu Sep 28 19:27:32 CEST 2017 by stoilkov 121 | -------------------------------------------------------------------------------- /fair_cons/fair_cons_abstract.tla: -------------------------------------------------------------------------------- 1 | ----------------------- MODULE fair_cons_abstract ----------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, loc2, locOther, msgs, phase, crash, pclean, decisionRound, receivers, someP 6 | 7 | vars == <> 8 | 9 | unknown == 2 10 | v0 == 0 \* default decision value 11 | V == {0, 1} \* set of values 12 | I == 1 .. 12 \* indices corresponding process locations 13 | U == 1 .. 14 \* message array indices (process locations + 2 concrete processes) 14 | u1 == 13 \* index for process 1 15 | u2 == 14 \* index for process 2 16 | Loc == [est : V, prev_est : V \cup {unknown}, halt : BOOLEAN] \* possible process locations 17 | AM == {{0}, {1}, {unknown}, {0, unknown}, {1, unknown}} \* abstract message alphabets 18 | 19 | \* translate index i \in I to location l \in Loc 20 | location(i) == 21 | LET x == i - 1 IN 22 | LET p == IF x \div 4 = 0 THEN 0 ELSE IF x \div 4 = 1 THEN 1 ELSE unknown IN 23 | LET y == x % 4 IN 24 | LET e == IF y \div 2 = 0 THEN 0 ELSE 1 IN 25 | LET h == IF y % 2 = 0 THEN FALSE ELSE TRUE IN 26 | [est |-> e, prev_est |-> p, halt |-> h] 27 | 28 | \* translate location l \in Loc to index i \in I 29 | index(l) == 30 | LET h == IF l.halt = FALSE THEN 0 ELSE 1 IN 31 | LET e == IF l.est = 0 THEN 0 ELSE 1 IN 32 | LET p == IF l.prev_est = 0 THEN 0 ELSE IF l.prev_est = 1 THEN 1 ELSE 2 IN 33 | 2 * e + 4 * p + h + 1 34 | 35 | \* get value, given index u \in U 36 | estValue(u) == 37 | IF u = u1 38 | THEN loc1.est 39 | ELSE IF u = u2 40 | THEN loc2.est 41 | ELSE location(u).est 42 | 43 | \* get previous value, given index u \in U 44 | prevEstValue(u) == 45 | IF u = u1 46 | THEN loc1.prev_est 47 | ELSE IF u = u2 48 | THEN loc2.prev_est 49 | ELSE location(u).prev_est 50 | 51 | \* Set of indices witnessing non-failed processes 52 | IndexNonFailed == {u1, u2} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt}} 53 | \* Set of locations of active processes 54 | Active == {loc1, loc2} \cup locOther 55 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 56 | Correct == {u1, u2} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt /\ crash[l1] # {TRUE}}} 57 | 58 | \* set failure flag of l to TRUE 59 | failedLocation(l) == 60 | [est |-> l.est, prev_est |-> l.prev_est, halt |-> TRUE] 61 | 62 | \* Set of initial locations 63 | InitActive == {[est |-> 0, prev_est |-> unknown, halt |-> FALSE], 64 | [est |-> 1, prev_est |-> unknown, halt |-> FALSE]} 65 | 66 | \* type invariant 67 | TypeOK == 68 | /\ loc1 \in Loc 69 | /\ loc2 \in Loc 70 | /\ locOther \in SUBSET(Loc) 71 | /\ msgs \in [IndexNonFailed -> [IndexNonFailed -> AM]] 72 | /\ phase \in {"msgs", "trans"} 73 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 74 | /\ pclean \in BOOLEAN 75 | /\ decisionRound \in BOOLEAN 76 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : estValue(u) = 1} -> SUBSET(BOOLEAN)] 77 | /\ someP \in [{l \in locOther : ~l.halt /\ l.est = 1} -> BOOLEAN] 78 | 79 | \* initial predicate of the environment 80 | InitEnvironment == 81 | /\ phase = "msgs" \* current phase of the algorithm 82 | /\ decisionRound = FALSE \* termination round predicate 83 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] \* crash array 84 | /\ pclean = FALSE \* clean round predicate 85 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X Correct -> ((SUBSET(BOOLEAN)) \ {{}})] \* receivers array 86 | /\ someP = [l \in locOther |-> FALSE] 87 | 88 | \* initial predicate of the algorithm 89 | InitAlgorithm == 90 | /\ loc1 \in InitActive \* first process kept explicitly 91 | /\ loc2 \in InitActive \* second process kept explicitly 92 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of witnesses for the other N - 2 processes 93 | /\ msgs = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> {unknown}]] \* two-dimensional messages array 94 | 95 | \* environment transition in the message exchage phase 96 | MsgsEnvironment == 97 | /\ phase' = "trans" 98 | /\ pclean' = IF \A l \in DOMAIN crash : TRUE \notin crash[l] THEN TRUE ELSE pclean 99 | /\ decisionRound' \in IF pclean' THEN {TRUE, FALSE} ELSE {FALSE} 100 | /\ someP' \in [{l \in locOther : ~l.halt /\ l.est = 1} -> BOOLEAN] 101 | /\ UNCHANGED <> 102 | 103 | \* environment transition in the state update phase 104 | TransEnvironment == 105 | /\ phase' = "msgs" 106 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 107 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} 108 | \X {u \in Correct' : estValue(u)' = 1} 109 | -> (SUBSET(BOOLEAN) \ {{}})] 110 | /\ someP' = [l \in {l \in locOther : ~l.halt /\ l.est = 1 /\ crash[l] # {TRUE}}' |-> FALSE] 111 | /\ UNCHANGED <> 112 | 113 | \* message generation function of a correct process 114 | SendMessage(u, v) == 115 | IF estValue(u) # prevEstValue(u) 116 | THEN estValue(u) 117 | ELSE unknown 118 | 119 | \* update function of a correct process 120 | \* (that received the same messages as the abstract location that witnesses it) 121 | Update(l, u) == 122 | LET e == IF l.est = 1 /\ \E v \in IndexNonFailed : 0 \in msgs[v][u] 123 | THEN 0 124 | ELSE l.est IN 125 | LET h == IF decisionRound 126 | THEN TRUE 127 | ELSE FALSE IN 128 | [est |-> e, prev_est |-> l.est, halt |-> h] 129 | 130 | \* update function of a correct process 131 | \* (that received messages different from the ones received by abstract location that witnesses it) 132 | UpdateOther(l, e) == 133 | LET h == IF decisionRound 134 | THEN TRUE 135 | ELSE FALSE IN 136 | [est |-> e, prev_est |-> l.est, halt |-> h] 137 | 138 | \* update of a process location witnessing correct processes 139 | UpdateCorrect(l, u) == 140 | IF l.est = 1 /\ loc1.est = l.est /\ loc2.est = l.est 141 | THEN IF \A v \in IndexNonFailed : v \notin {u1, u2} /\ location(v).est # l.est => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 142 | THEN {UpdateOther(l, l.est)} 143 | ELSE IF someP[l] 144 | THEN {Update(l, u), UpdateOther(l, l.est)} 145 | ELSE {Update(l, u)} 146 | ELSE {Update(l, u)} 147 | 148 | \* delivery of messages by the environment 149 | EnvSemMsg(m, u, v) == 150 | IF u \in {u1, u2} 151 | THEN {m} 152 | ELSE LET l == location(u) IN 153 | IF crash[l] = {TRUE, FALSE} 154 | THEN IF estValue(v) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 155 | THEN IF receivers[l,v] = {TRUE} 156 | THEN {m} 157 | ELSE {unknown, m} 158 | ELSE {unknown} 159 | ELSE IF crash[l] = {TRUE} 160 | THEN IF estValue(v) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 161 | THEN IF receivers[l,v] = {TRUE} 162 | THEN {m} 163 | ELSE IF receivers[l,v] = {FALSE} 164 | THEN {unknown} 165 | ELSE {unknown, m} 166 | ELSE {unknown} 167 | ELSE IF estValue(v) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 168 | THEN {m} 169 | ELSE {unknown} 170 | 171 | \* state update of the fixed processes w.r.t. the environment 172 | EnvSemState(l, u) == 173 | IF l.halt 174 | THEN l 175 | ELSE Update(l, u) 176 | 177 | \* state update of the other processes w.r.t. the environment 178 | EnvSemStateOther(l) == 179 | IF l.halt 180 | THEN {l} 181 | ELSE IF crash[l] = {TRUE} 182 | THEN {failedLocation(l)} \* all processes witnessed by l crashed 183 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes witnessed by l crashed, and some not 184 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} 185 | ELSE UpdateCorrect(l, index(l)) \* no processes witnessed by l crashed 186 | 187 | \* algorithm transition in the message exchange phase 188 | MsgsAlgorithm == 189 | /\ msgs' = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> EnvSemMsg(SendMessage(u, v), u, v)]] 190 | /\ UNCHANGED <> 191 | 192 | \* algorithm transition in the state update phase 193 | TransAlgorithm == 194 | /\ loc1' = EnvSemState(loc1, u1) 195 | /\ loc2' = EnvSemState(loc2, u2) 196 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 197 | /\ msgs' = [u \in IndexNonFailed' |-> [v \in IndexNonFailed' |-> {unknown}]] 198 | 199 | NextEnvironment == 200 | \/ phase = "msgs" /\ MsgsEnvironment 201 | \/ phase = "trans" /\ TransEnvironment 202 | 203 | NextAlgorithm == 204 | \/ phase = "msgs" /\ MsgsAlgorithm 205 | \/ phase = "trans" /\ TransAlgorithm 206 | 207 | Init == InitAlgorithm /\ InitEnvironment 208 | 209 | Next == NextAlgorithm /\ NextEnvironment 210 | 211 | \* constraints 212 | Fairness == 213 | /\ WF_vars(Next) 214 | /\ <>[](\A l \in DOMAIN crash : TRUE \notin crash[l]) 215 | /\ <>decisionRound 216 | 217 | \* specification 218 | Spec == Init /\ [][Next]_vars /\ Fairness 219 | 220 | \* safety properties 221 | Validity0 == ((\A l \in Active : l.est = 0) => 222 | [](/\ loc1.halt => loc1.est = 0 223 | /\ loc2.halt => loc2.est = 0)) 224 | Validity1 == ((\A l \in Active : l.est = 1) => 225 | [](/\ loc1.halt => loc1.est = 1 226 | /\ loc2.halt => loc2.est = 1)) 227 | \* Validity: if all processes start with the same value, then this is the only 228 | \* possible decision value 229 | Validity == Validity0 /\ Validity1 230 | 231 | \* Agreement: no two correct processes decide on a different value 232 | Agreement == [](loc1.halt /\ loc2.halt => loc1.est = loc2.est) 233 | 234 | \* liveness property 235 | \* Termination: all correct processes eventually decide 236 | Termination == <>(loc1.halt /\ loc2.halt) 237 | 238 | ============================================================================= 239 | \* Modification History 240 | \* Last modified Tue Oct 17 15:07:25 CEST 2017 by stoilkov 241 | \* Created Mon Sep 25 15:12:35 CEST 2017 by stoilkov 242 | -------------------------------------------------------------------------------- /fair_cons/fair_cons_abstract_m1.tla: -------------------------------------------------------------------------------- 1 | --------------------- MODULE fair_cons_abstract_m1 --------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, locOther, msgs, phase, crash, pclean, decisionRound, receivers, someP 6 | 7 | vars == <> 8 | 9 | unknown == 2 10 | v0 == 0 \* default decision value 11 | V == {0, 1} \* set of values 12 | I == 1 .. 12 \* indices corresponding process locations 13 | U == 1 .. 13 \* message array indices (process locations + 1 concrete process) 14 | u1 == 13 \* index for process 1 15 | Loc == [est : V, prev_est : V \cup {unknown}, halt : BOOLEAN] \* possible process locations 16 | AM == {{0}, {1}, {unknown}, {0, unknown}, {1, unknown}} \* abstract message alphabets 17 | 18 | \* translate index i \in I to location l \in Loc 19 | location(i) == 20 | LET x == i - 1 IN 21 | LET p == IF x \div 4 = 0 THEN 0 ELSE IF x \div 4 = 1 THEN 1 ELSE unknown IN 22 | LET y == x % 4 IN 23 | LET e == IF y \div 2 = 0 THEN 0 ELSE 1 IN 24 | LET h == IF y % 2 = 0 THEN FALSE ELSE TRUE IN 25 | [est |-> e, prev_est |-> p, halt |-> h] 26 | 27 | \* translate location l \in Loc to index i \in I 28 | index(l) == 29 | LET h == IF l.halt = FALSE THEN 0 ELSE 1 IN 30 | LET e == IF l.est = 0 THEN 0 ELSE 1 IN 31 | LET p == IF l.prev_est = 0 THEN 0 ELSE IF l.prev_est = 1 THEN 1 ELSE 2 IN 32 | 2 * e + 4 * p + h + 1 33 | 34 | \* get value, given index u \in U 35 | estValue(u) == 36 | IF u = u1 37 | THEN loc1.est 38 | ELSE location(u).est 39 | 40 | \* get previous value, given index u \in U 41 | prevEstValue(u) == 42 | IF u = u1 43 | THEN loc1.prev_est 44 | ELSE location(u).prev_est 45 | 46 | \* Set of indices witnessing non-failed processes 47 | IndexNonFailed == {u1} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt}} 48 | \* Set of locations of active processes 49 | Active == {loc1} \cup locOther 50 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 51 | Correct == {u1} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt /\ crash[l1] # {TRUE}}} 52 | 53 | \* set failure flag of l to TRUE 54 | failedLocation(l) == 55 | [est |-> l.est, prev_est |-> l.prev_est, halt |-> TRUE] 56 | 57 | \* Set of initial locations 58 | InitActive == {[est |-> 0, prev_est |-> unknown, halt |-> FALSE], 59 | [est |-> 1, prev_est |-> unknown, halt |-> FALSE]} 60 | 61 | \* type invariant 62 | TypeOK == 63 | /\ loc1 \in Loc 64 | /\ locOther \in SUBSET(Loc) 65 | /\ msgs \in [IndexNonFailed -> [IndexNonFailed -> AM]] 66 | /\ phase \in {"msgs", "trans"} 67 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 68 | /\ pclean \in BOOLEAN 69 | /\ decisionRound \in BOOLEAN 70 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : estValue(u) = 1} -> SUBSET(BOOLEAN)] 71 | /\ someP \in [{l \in locOther : ~l.halt /\ l.est = 1} -> BOOLEAN] 72 | 73 | \* initial predicate of the environment 74 | InitEnvironment == 75 | /\ phase = "msgs" \* current phase of the algorithm 76 | /\ decisionRound = FALSE \* termination round predicate 77 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] \* crash array 78 | /\ pclean = FALSE \* clean round predicate 79 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X Correct -> ((SUBSET(BOOLEAN)) \ {{}})] \* receivers array 80 | /\ someP = [l \in locOther |-> FALSE] 81 | 82 | \* initial predicate of the algorithm 83 | InitAlgorithm == 84 | /\ loc1 \in InitActive \* first process kept explicitly 85 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of witnesses for the other N - 2 processes 86 | /\ msgs = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> {unknown}]] \* two-dimensional messages array 87 | 88 | \* environment transition in the message exchage phase 89 | MsgsEnvironment == 90 | /\ phase' = "trans" 91 | /\ pclean' = IF \A l \in DOMAIN crash : TRUE \notin crash[l] THEN TRUE ELSE pclean 92 | /\ decisionRound' \in IF pclean' THEN {TRUE, FALSE} ELSE {FALSE} 93 | /\ someP' \in [{l \in locOther : ~l.halt /\ l.est = 1} -> BOOLEAN] 94 | /\ UNCHANGED <> 95 | 96 | \* environment transition in the state update phase 97 | TransEnvironment == 98 | /\ phase' = "msgs" 99 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 100 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} 101 | \X {u \in Correct' : estValue(u)' = 1} 102 | -> (SUBSET(BOOLEAN) \ {{}})] 103 | /\ someP' = [l \in {l \in locOther : ~l.halt /\ l.est = 1 /\ crash[l] # {TRUE}}' |-> FALSE] 104 | /\ UNCHANGED <> 105 | 106 | \* message generation function of a correct process 107 | SendMessage(u, v) == 108 | IF estValue(u) # prevEstValue(u) 109 | THEN estValue(u) 110 | ELSE unknown 111 | 112 | \* update function of a correct process 113 | \* (that received the same messages as the abstract location that witnesses it) 114 | Update(l, u) == 115 | LET e == IF l.est = 1 /\ \E v \in IndexNonFailed : 0 \in msgs[v][u] 116 | THEN 0 117 | ELSE l.est IN 118 | LET h == IF decisionRound 119 | THEN TRUE 120 | ELSE FALSE IN 121 | [est |-> e, prev_est |-> l.est, halt |-> h] 122 | 123 | \* update function of a correct process 124 | \* (that received messages different from the ones received by abstract location that witnesses it) 125 | UpdateOther(l, e) == 126 | LET h == IF decisionRound 127 | THEN TRUE 128 | ELSE FALSE IN 129 | [est |-> e, prev_est |-> l.est, halt |-> h] 130 | 131 | \* update of a process location witnessing correct processes 132 | UpdateCorrect(l, u) == 133 | IF l.est = 1 /\ loc1.est = l.est 134 | THEN IF \A v \in IndexNonFailed : v \notin {u1} /\ location(v).est # l.est => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 135 | THEN {UpdateOther(l, l.est)} 136 | ELSE IF someP[l] 137 | THEN {Update(l, u), UpdateOther(l, l.est)} 138 | ELSE {Update(l, u)} 139 | ELSE {Update(l, u)} 140 | 141 | \* delivery of messages by the environment 142 | EnvSemMsg(m, u, v) == 143 | IF u \in {u1} 144 | THEN {m} 145 | ELSE LET l == location(u) IN 146 | IF crash[l] = {TRUE, FALSE} 147 | THEN IF estValue(v) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 148 | THEN IF receivers[l,v] = {TRUE} 149 | THEN {m} 150 | ELSE {unknown, m} 151 | ELSE {unknown} 152 | ELSE IF crash[l] = {TRUE} 153 | THEN IF estValue(v) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 154 | THEN IF receivers[l,v] = {TRUE} 155 | THEN {m} 156 | ELSE IF receivers[l,v] = {FALSE} 157 | THEN {unknown} 158 | ELSE {unknown, m} 159 | ELSE {unknown} 160 | ELSE IF estValue(v) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 161 | THEN {m} 162 | ELSE {unknown} 163 | 164 | \* state update of the fixed processes w.r.t. the environment 165 | EnvSemState(l, u) == 166 | IF l.halt 167 | THEN l 168 | ELSE Update(l, u) 169 | 170 | \* state update of the other processes w.r.t. the environment 171 | EnvSemStateOther(l) == 172 | IF l.halt 173 | THEN {l} 174 | ELSE IF crash[l] = {TRUE} 175 | THEN {failedLocation(l)} \* all processes witnessed by l crashed 176 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes witnessed by l crashed, and some not 177 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} 178 | ELSE UpdateCorrect(l, index(l)) \* no processes witnessed by l crashed 179 | 180 | \* algorithm transition in the message exchange phase 181 | MsgsAlgorithm == 182 | /\ msgs' = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> EnvSemMsg(SendMessage(u, v), u, v)]] 183 | /\ UNCHANGED <> 184 | 185 | \* algorithm transition in the state update phase 186 | TransAlgorithm == 187 | /\ loc1' = EnvSemState(loc1, u1) 188 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 189 | /\ msgs' = [u \in IndexNonFailed' |-> [v \in IndexNonFailed' |-> {unknown}]] 190 | 191 | NextEnvironment == 192 | \/ phase = "msgs" /\ MsgsEnvironment 193 | \/ phase = "trans" /\ TransEnvironment 194 | 195 | NextAlgorithm == 196 | \/ phase = "msgs" /\ MsgsAlgorithm 197 | \/ phase = "trans" /\ TransAlgorithm 198 | 199 | Init == InitAlgorithm /\ InitEnvironment 200 | 201 | Next == NextAlgorithm /\ NextEnvironment 202 | 203 | \* constraints 204 | Fairness == 205 | /\ WF_vars(Next) 206 | /\ <>[](\A l \in DOMAIN crash : TRUE \notin crash[l]) 207 | /\ <>decisionRound 208 | 209 | \* specification 210 | Spec == Init /\ [][Next]_vars /\ Fairness 211 | 212 | \* safety properties 213 | Validity0 == ((\A l \in Active : l.est = 0) => 214 | [](loc1.halt => loc1.est = 0)) 215 | Validity1 == ((\A l \in Active : l.est = 1) => 216 | [](loc1.halt => loc1.est = 1)) 217 | \* Validity: if all processes start with the same value, then this is the only 218 | \* possible decision value 219 | Validity == Validity0 /\ Validity1 220 | 221 | \* liveness property 222 | \* Termination: all correct processes eventually decide 223 | Termination == <>(loc1.halt) 224 | 225 | ============================================================================= 226 | \* Modification History 227 | \* Last modified Tue Oct 17 15:10:05 CEST 2017 by stoilkov 228 | \* Created Thu Sep 28 17:29:23 CEST 2017 by stoilkov 229 | -------------------------------------------------------------------------------- /floodmin_k1/floodmin_k1.tla: -------------------------------------------------------------------------------- 1 | ------------------------------ MODULE floodmin ------------------------------ 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | CONSTANTS N, T, F 6 | 7 | VARIABLES state, msgs, round, phase, 8 | crash, failed, receivers 9 | 10 | vars == <> 11 | 12 | P == 1 .. N 13 | unknown == 2 14 | V == {0, 1} 15 | K == 1 16 | 17 | C == [ min : V, decision : {0, 1, unknown}] 18 | InitC == [ min : V, decision : {unknown}] 19 | 20 | 21 | InitEnvironment == 22 | /\ phase = "msgs" 23 | /\ round = 0 24 | /\ crash \in SUBSET(P) 25 | /\ failed = {} 26 | /\ Cardinality(failed \cup crash) <= F 27 | /\ receivers \in [crash -> SUBSET(P)] 28 | 29 | InitAlgorithm == 30 | /\ state \in [P -> InitC] 31 | /\ msgs = [p \in P |-> [q \in P |-> unknown]] \* two-dimensional messages array 32 | 33 | Min(S) == IF 0 \in S THEN 0 ELSE 1 34 | 35 | Msgs(p) == IF p \in failed 36 | THEN {} 37 | ELSE {v \in V : \E q \in P : msgs[q][p] # unknown /\ msgs[q][p] = v} 38 | 39 | 40 | SendMessage(p, q) == 41 | state[p].min 42 | 43 | EnvSemMsg(m, p, q) == 44 | IF \/ p \in failed 45 | \/ p \in crash /\ q \notin receivers[p] 46 | THEN unknown 47 | ELSE m 48 | 49 | EnvSemState(p, s1, s2) == 50 | IF p \in failed \/ p \in crash \/ s2.decision # unknown 51 | THEN s2 52 | ELSE s1 53 | 54 | Update(s, X) == 55 | LET m == Min(X) IN 56 | LET d == IF round >= (T \div K) + 1 57 | THEN m 58 | ELSE unknown IN 59 | [min |-> m, decision |-> d] 60 | 61 | MsgsEnvironment == 62 | IF round <= T \div K 63 | THEN 64 | /\ phase' = "trans" 65 | /\ round' = round+1 66 | /\ UNCHANGED <> 67 | ELSE UNCHANGED vars 68 | 69 | TransEnvironment == 70 | /\ phase' = "msgs" 71 | /\ failed' = failed \cup crash 72 | /\ crash' \in SUBSET(P \ failed') 73 | /\ Cardinality(failed' \cup crash') <= F 74 | /\ receivers' \in [crash' -> SUBSET(P)] 75 | /\ UNCHANGED round 76 | 77 | MsgsAlgorithm == 78 | IF round <= T \div K 79 | THEN 80 | /\ msgs' = [p \in P |-> [q \in P |-> EnvSemMsg(SendMessage(p, q), p, q)]] 81 | /\ UNCHANGED state 82 | ELSE UNCHANGED vars 83 | 84 | TransAlgorithm == 85 | /\ state' = [p \in P |-> EnvSemState(p, Update(state[p], Msgs(p)), state[p])] 86 | /\ msgs' = [p \in P |-> [q \in P |-> unknown]] 87 | 88 | 89 | \* next state action predicates 90 | 91 | NextEnvironment == 92 | \/ phase = "msgs" /\ MsgsEnvironment 93 | \/ phase = "trans" /\ TransEnvironment 94 | 95 | NextAlgorithm == 96 | \/ phase = "msgs" /\ MsgsAlgorithm 97 | \/ phase = "trans" /\ TransAlgorithm 98 | 99 | Init == InitAlgorithm /\ InitEnvironment 100 | Next == NextAlgorithm /\ NextEnvironment 101 | 102 | \* fairness constraint 103 | Fairness == WF_vars(Next) 104 | 105 | \* specification 106 | Spec == Init /\ [][Next]_vars /\ Fairness 107 | 108 | \* safety properties 109 | Agreement == \E W \in SUBSET(V) : Cardinality(W) = K /\ [](\A q \in P : (q \notin failed /\ state[q].decision # unknown) => state[q].decision \in W) 110 | Validity == \A I \in SUBSET(V) : I = {state[p].min : p \in P} => [](\A p \in P : (state[p].decision # unknown => state[p].decision \in I)) 111 | 112 | \* liveness property 113 | Termination == <>(\A p \in P : p \in failed \/ state[p].decision # unknown) 114 | 115 | 116 | 117 | ============================================================================= 118 | \* Modification History 119 | \* Last modified Thu Sep 28 18:11:32 CEST 2017 by stoilkov 120 | \* Created Thu Sep 28 18:06:12 CEST 2017 by stoilkov -------------------------------------------------------------------------------- /floodmin_k1/floodmin_k1_abstract.tla: -------------------------------------------------------------------------------- 1 | ------------------------- MODULE floodmin_k1_abstract ------------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, loc2, locOther, msgs, phase, crash, pclean, decisionRound, receivers, someP 6 | 7 | vars == <> 8 | 9 | unknown == 2 \* unknown decision value 10 | V == {0, 1} \* set of values 11 | K == 1 \* cardinality of set of decision values 12 | I == 1 .. 4 \* indices corresponding to process locations 13 | U == 1 .. 6 \* array indices (process locations + 2 fixed processes) 14 | u1 == 5 \* index for process 1 15 | u2 == 6 \* index for process 2 16 | Loc == [min : V, halt : BOOLEAN] 17 | AM == {W \in SUBSET(V \cup {unknown}) : W = {} \/ Cardinality(W) = 1 \/ (Cardinality(W) = 2 /\ unknown \in W)} \* abstract message alphabet 18 | 19 | \* translate index i \in I to location l \in Loc 20 | location(i) == 21 | LET x == i - 1 IN 22 | LET m == IF x \div 2 = 0 THEN 0 ELSE 1 IN 23 | LET h == IF x % 2 = 0 THEN FALSE ELSE TRUE IN 24 | [min |-> m, halt |-> h] 25 | 26 | \* translate location l \in Loc to index i \in I 27 | index(l) == 28 | LET h == IF l.halt = FALSE THEN 0 ELSE 1 IN 29 | LET m == IF l.min = 0 THEN 0 ELSE 1 IN 30 | 2 * m + h + 1 31 | 32 | \* get minimum value, given index u \in U 33 | min(u) == 34 | IF u = u1 35 | THEN loc1.min 36 | ELSE IF u = u2 37 | THEN loc2.min 38 | ELSE location(u).min 39 | 40 | 41 | \* Set of indices witnessing non-failed processes 42 | IndexNonFailed == {u1, u2} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt}} 43 | \* Set of locations of active processes 44 | Active == {loc1, loc2} \cup locOther 45 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 46 | Correct == {u1, u2} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt /\ crash[l1] # {TRUE}}} 47 | 48 | \* set failure flag of l to TRUE 49 | failedLocation(l) == 50 | [min |-> l.min, halt |-> TRUE] 51 | 52 | \* Set of initial locations 53 | InitActive == {[min |-> 0, halt |-> FALSE], 54 | [min |-> 1, halt |-> FALSE]} 55 | 56 | \* type invariant 57 | TypeOK == 58 | /\ loc1 \in Loc 59 | /\ loc2 \in Loc 60 | /\ locOther \in SUBSET(Loc) 61 | /\ msgs \in [IndexNonFailed -> [IndexNonFailed -> AM]] 62 | /\ phase \in {"msgs", "trans"} 63 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 64 | /\ pclean \in BOOLEAN 65 | /\ decisionRound \in BOOLEAN 66 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : min(u) = 1} -> SUBSET(BOOLEAN)] 67 | /\ someP \in [{l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 1} -> BOOLEAN] 68 | 69 | \* initial predicate of the environment 70 | InitEnvironment == 71 | /\ phase = "msgs" \* current phase of the algorithm 72 | /\ decisionRound = FALSE \* predicate for the decision round 73 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] \* crash array 74 | /\ pclean = FALSE \* predicate for the clean round 75 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : min(u) = 1} -> ((SUBSET(BOOLEAN)) \ {{}})] \* receivers array 76 | /\ someP = [l \in {k \in locOther : crash[k] # {TRUE} /\ k.min = 1} |-> FALSE] 77 | 78 | \* initial predicate of the algorithm 79 | InitAlgorithm == 80 | /\ loc1 \in InitActive \* first fixed process 81 | /\ loc2 \in InitActive \* second fixed process 82 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of locations witnessing the other N - 2 processes 83 | /\ msgs = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> {unknown}]] \* two-dimensional messages array 84 | 85 | \* environment transition in the message exchage phase 86 | MsgsEnvironment == 87 | /\ phase' = "trans" 88 | /\ pclean' = IF \E l \in DOMAIN crash : (TRUE \in crash[l] /\ \A k \in DOMAIN crash : l # k => TRUE \notin crash[k]) 89 | THEN TRUE 90 | ELSE pclean 91 | /\ decisionRound' \in IF pclean' THEN {TRUE, FALSE} ELSE {FALSE} 92 | /\ someP' \in [{l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 1} -> BOOLEAN] 93 | /\ UNCHANGED <> 94 | 95 | \* environment transition in the state update phase 96 | TransEnvironment == 97 | /\ phase' = "msgs" 98 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 99 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} \X {u \in TLCEval(Correct') : min(u)' = 1} -> ((SUBSET(BOOLEAN)) \ {{}})] \* /\ (l.W # loc1'.W \/ l.W # loc2'.W) \/ \E l1 \in locOther' : l.W # l1.W 100 | /\ someP' = [l \in {l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 1}' |-> FALSE] 101 | /\ UNCHANGED <> 102 | 103 | \* message generation function of a correct process 104 | SendMessage(u, v) == 105 | min(u) 106 | 107 | \* update function of a correct process 108 | \* (that received the same messages as the abstract location that witnesses it) 109 | Update(l, u) == 110 | LET m == IF l.min = 1 /\ \E v \in IndexNonFailed : 0 \in msgs[v][u] 111 | THEN 0 112 | ELSE l.min IN 113 | LET h == IF decisionRound 114 | THEN TRUE 115 | ELSE FALSE IN 116 | [min |-> m, halt |-> h] 117 | 118 | \* update function of a correct process 119 | \* (that received messages different from the ones received by abstract location that witnesses it) 120 | UpdateOther(l, m) == 121 | LET h == IF decisionRound 122 | THEN TRUE 123 | ELSE FALSE IN 124 | [min |-> m, halt |-> h] 125 | 126 | \* update of a process location witnessing correct processes 127 | UpdateCorrect(l, u) == 128 | IF l.min = 1 /\ loc1.min = l.min /\ loc2.min = l.min 129 | THEN IF \A v \in IndexNonFailed : v \notin {u1, u2} /\ min(v) # l.min => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 130 | THEN {UpdateOther(l, l.min)} 131 | ELSE IF someP[l] 132 | THEN {Update(l, u), UpdateOther(l, l.min)} 133 | ELSE {Update(l, u)} 134 | ELSE {Update(l, u)} 135 | 136 | \* delivery of messages by the environment 137 | EnvSemMsg(m, u, v) == 138 | IF u \in {u1, u2} 139 | THEN {m} 140 | ELSE LET l == location(u) IN 141 | IF crash[l] = {TRUE, FALSE} 142 | THEN IF min(v) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 143 | THEN IF receivers[l,v] = {TRUE} 144 | THEN {m} 145 | ELSE {unknown, m} 146 | ELSE {unknown} 147 | ELSE IF crash[l] = {TRUE} 148 | THEN IF min(v) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 149 | THEN IF receivers[l,v] = {TRUE} 150 | THEN {m} 151 | ELSE IF receivers[l,v] = {FALSE} 152 | THEN {unknown} 153 | ELSE {unknown, m} 154 | ELSE {unknown} 155 | ELSE IF min(v) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 156 | THEN {m} 157 | ELSE {unknown} 158 | 159 | \* state update of the fixed processes w.r.t. the environment 160 | EnvSemState(l, u) == 161 | IF l.halt 162 | THEN l 163 | ELSE TLCEval(Update(l, u)) 164 | 165 | \* state update of the other processes w.r.t. the environment 166 | EnvSemStateOther(l) == 167 | IF l.halt 168 | THEN {l} 169 | ELSE IF crash[l] = {TRUE} 170 | THEN {failedLocation(l)} \* all processes witnessed by l crashed 171 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes witnessed by l crashed, and some not 172 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} 173 | ELSE UpdateCorrect(l, index(l)) \* no processes witnessed by l crashed 174 | 175 | \* algorithm transition in the message exchange phase 176 | MsgsAlgorithm == 177 | /\ msgs' = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> EnvSemMsg(SendMessage(u, v), u, v)]] 178 | /\ UNCHANGED <> 179 | 180 | \* algorithm transition in the state update phase 181 | TransAlgorithm == 182 | /\ loc1' = EnvSemState(loc1, u1) 183 | /\ loc2' = EnvSemState(loc2, u2) 184 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 185 | /\ msgs' = [u \in IndexNonFailed' |-> [v \in IndexNonFailed' |-> {unknown}]] 186 | 187 | NextEnvironment == 188 | \/ phase = "msgs" /\ MsgsEnvironment 189 | \/ phase = "trans" /\ TransEnvironment 190 | 191 | NextAlgorithm == 192 | \/ phase = "msgs" /\ MsgsAlgorithm 193 | \/ phase = "trans" /\ TransAlgorithm 194 | 195 | Init == InitAlgorithm /\ InitEnvironment 196 | 197 | Next == NextAlgorithm /\ NextEnvironment 198 | 199 | \* constraints 200 | Fairness == /\ WF_vars(Next) 201 | /\ <>[](\E l \in DOMAIN crash : (TRUE \in crash[l] /\ \A k \in DOMAIN crash : l # k => TRUE \notin crash[k])) 202 | /\ <>decisionRound 203 | 204 | \* specification 205 | Spec == Init /\ [][Next]_vars /\ Fairness 206 | 207 | \* safety properties 208 | \* k-Agreement: There is a subset W of V of cardinality K, such that all decision 209 | \* values are in W 210 | Agreement == \E W \in SUBSET(V) : Cardinality(W) = K /\ 211 | [](loc1.halt /\ loc2.halt => 212 | (loc1.min \in W /\ loc2.min \in W)) 213 | \* k-Validity: Any decision value for any process is the initial value of some process 214 | Validity == \A W \in SUBSET(V) : W = {min(u) : u \in IndexNonFailed} => 215 | [](loc1.halt /\ loc2.halt => 216 | (loc1.min \in W /\ loc2.min \in W)) 217 | \* liveness property 218 | \* k-Termination: All correct processes eventually decide 219 | Termination == <>(loc1.halt /\ loc2.halt) 220 | 221 | ============================================================================= -------------------------------------------------------------------------------- /floodmin_k1/floodmin_k1_abstract_m1.tla: -------------------------------------------------------------------------------- 1 | ---------------------- MODULE floodmin_k1_abstract_m1 ---------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, locOther, msgs, phase, crash, pclean, decisionRound, receivers, someP 6 | 7 | vars == <> 8 | 9 | unknown == 2 \* unknown decision value 10 | V == {0, 1} \* set of values 11 | K == 1 \* cardinality of set of decision values 12 | I == 1 .. 4 \* indices corresponding to process locations 13 | U == 1 .. 5 \* array indices (process locations + 1 fixed process) 14 | u1 == 5 \* index for process 1 15 | Loc == [min : V, halt : BOOLEAN] \* possible process locations 16 | AM == {W \in SUBSET(V \cup {unknown}) : W = {} \/ Cardinality(W) = 1 \/ (Cardinality(W) = 2 /\ unknown \in W)} \* abstract message alphabet 17 | 18 | \* translate index i \in I to location l \in Loc 19 | location(i) == 20 | LET x == i - 1 IN 21 | LET m == IF x \div 2 = 0 THEN 0 ELSE 1 IN 22 | LET h == IF x % 2 = 0 THEN FALSE ELSE TRUE IN 23 | [min |-> m, halt |-> h] 24 | 25 | \* translate location l \in Loc to index i \in I 26 | index(l) == 27 | LET h == IF l.halt = FALSE THEN 0 ELSE 1 IN 28 | LET m == IF l.min = 0 THEN 0 ELSE 1 IN 29 | 2 * m + h + 1 30 | 31 | \* get minimum value, given index u \in U 32 | min(u) == 33 | IF u = u1 34 | THEN loc1.min 35 | ELSE location(u).min 36 | 37 | \* Set of indices witnessing non-failed processes 38 | IndexNonFailed == {u1} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt}} 39 | \* Set of locations of active processes 40 | Active == {loc1} \cup locOther 41 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 42 | Correct == {u1} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt /\ crash[l1] # {TRUE}}} 43 | 44 | \* set failure flag of l to TRUE 45 | failedLocation(l) == 46 | [min |-> l.min, halt |-> TRUE] 47 | 48 | \* Set of initial locations 49 | InitActive == {[min |-> 0, halt |-> FALSE], 50 | [min |-> 1, halt |-> FALSE]} 51 | 52 | \* type invariant 53 | TypeOK == 54 | /\ loc1 \in Loc 55 | /\ locOther \in SUBSET(Loc) 56 | /\ msgs \in [IndexNonFailed -> [IndexNonFailed -> AM]] 57 | /\ phase \in {"msgs", "trans"} 58 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 59 | /\ pclean \in BOOLEAN 60 | /\ decisionRound \in BOOLEAN 61 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : min(u) = 1} -> SUBSET(BOOLEAN)] 62 | /\ someP \in [{l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 1} -> BOOLEAN] 63 | 64 | \* initial predicate of the environment 65 | InitEnvironment == 66 | /\ phase = "msgs" \* current phase of the algorithm 67 | /\ decisionRound = FALSE \* predicate for the decision round 68 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] \* crash array 69 | /\ pclean = FALSE \* predicate for the clean round 70 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : min(u) = 1} -> ((SUBSET(BOOLEAN)) \ {{}})] \* receivers array 71 | /\ someP = [l \in {k \in locOther : crash[k] # {TRUE} /\ k.min = 1} |-> FALSE] 72 | 73 | \* initial predicate of the algorithm 74 | InitAlgorithm == 75 | /\ loc1 \in InitActive \* first fixed process 76 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of locations witnessing the other N - 1 processes 77 | /\ msgs = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> {unknown}]] \* two-dimensional messages array 78 | 79 | \* environment transition in the message exchage phase 80 | MsgsEnvironment == 81 | /\ phase' = "trans" 82 | /\ pclean' = IF \E l \in DOMAIN crash : (TRUE \in crash[l] /\ \A k \in DOMAIN crash : l # k => TRUE \notin crash[k]) 83 | THEN TRUE 84 | ELSE pclean 85 | /\ decisionRound' \in IF pclean' THEN {TRUE, FALSE} ELSE {FALSE} 86 | /\ someP' \in [{l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 1} -> BOOLEAN] 87 | /\ UNCHANGED <> 88 | 89 | \* environment transition in the state update phase 90 | TransEnvironment == 91 | /\ phase' = "msgs" 92 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 93 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} \X {u \in TLCEval(Correct') : min(u)' = 1} -> ((SUBSET(BOOLEAN)) \ {{}})] 94 | /\ someP' = [l \in {l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 1}' |-> FALSE] 95 | /\ UNCHANGED <> 96 | 97 | \* message generation function of a correct process 98 | SendMessage(u, v) == 99 | min(u) 100 | 101 | \* update function of a correct process 102 | \* (that received the same messages as the abstract location that witnesses it) 103 | Update(l, u) == 104 | LET m == IF l.min = 1 /\ \E v \in IndexNonFailed : 0 \in msgs[v][u] 105 | THEN 0 106 | ELSE l.min IN 107 | LET h == IF decisionRound 108 | THEN TRUE 109 | ELSE FALSE IN 110 | [min |-> m, halt |-> h] 111 | 112 | \* update function of a correct process 113 | \* (that received messages different from the ones received by abstract location that witnesses it) 114 | UpdateOther(l, m) == 115 | LET h == IF decisionRound 116 | THEN TRUE 117 | ELSE FALSE IN 118 | [min |-> m, halt |-> h] 119 | 120 | \* update of a process location witnessing correct processes 121 | UpdateCorrect(l, u) == 122 | IF l.min = 1 /\ loc1.min = l.min 123 | THEN IF \A v \in IndexNonFailed : v \notin {u1} /\ min(v) # l.min => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 124 | THEN {UpdateOther(l, l.min)} 125 | ELSE IF someP[l] 126 | THEN {Update(l, u), UpdateOther(l, l.min)} 127 | ELSE {Update(l, u)} 128 | ELSE {Update(l, u)} 129 | 130 | \* delivery of messages by the environment 131 | EnvSemMsg(m, u, v) == 132 | IF u \in {u1} 133 | THEN {m} 134 | ELSE LET l == location(u) IN 135 | IF crash[l] = {TRUE, FALSE} 136 | THEN IF min(v) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 137 | THEN IF receivers[l,v] = {TRUE} 138 | THEN {m} 139 | ELSE {unknown, m} 140 | ELSE {unknown} 141 | ELSE IF crash[l] = {TRUE} 142 | THEN IF min(v) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 143 | THEN IF receivers[l,v] = {TRUE} 144 | THEN {m} 145 | ELSE IF receivers[l,v] = {FALSE} 146 | THEN {unknown} 147 | ELSE {unknown, m} 148 | ELSE {unknown} 149 | ELSE IF min(v) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 150 | THEN {m} 151 | ELSE {unknown} 152 | 153 | \* state update of the fixed processes w.r.t. the environment 154 | EnvSemState(l, u) == 155 | IF l.halt 156 | THEN l 157 | ELSE Update(l, u) 158 | 159 | \* state update of the other processes w.r.t. the environment 160 | EnvSemStateOther(l) == 161 | IF l.halt 162 | THEN {l} 163 | ELSE IF crash[l] = {TRUE} 164 | THEN {failedLocation(l)} \* all processes witnessed by l crashed 165 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes witnessed by l crashed, and some not 166 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} 167 | ELSE UpdateCorrect(l, index(l)) \* no processes witnessed by l crashed 168 | 169 | \* algorithm transition in the message exchange phase 170 | MsgsAlgorithm == 171 | /\ msgs' = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> EnvSemMsg(SendMessage(u, v), u, v)]] 172 | /\ UNCHANGED <> 173 | 174 | \* algorithm transition in the state update phase 175 | TransAlgorithm == 176 | /\ loc1' = EnvSemState(loc1, u1) 177 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 178 | /\ msgs' = [u \in IndexNonFailed' |-> [v \in IndexNonFailed' |-> {unknown}]] 179 | 180 | NextEnvironment == 181 | \/ phase = "msgs" /\ MsgsEnvironment 182 | \/ phase = "trans" /\ TransEnvironment 183 | 184 | NextAlgorithm == 185 | \/ phase = "msgs" /\ MsgsAlgorithm 186 | \/ phase = "trans" /\ TransAlgorithm 187 | 188 | Init == InitAlgorithm /\ InitEnvironment 189 | 190 | Next == NextAlgorithm /\ NextEnvironment 191 | 192 | \* constraints 193 | Fairness == /\ WF_vars(Next) 194 | /\ <>[](\E l \in DOMAIN crash : (TRUE \in crash[l] /\ \A k \in DOMAIN crash : l # k => TRUE \notin crash[k])) 195 | /\ <>decisionRound 196 | 197 | \* specification 198 | Spec == Init /\ [][Next]_vars /\ Fairness 199 | 200 | \* safety properties 201 | \* k-Validity: Any decision value for any process is the initial value of some process 202 | Validity == \A W \in SUBSET(V) : W = {min(u) : u \in IndexNonFailed} => 203 | [](loc1.halt => loc1.min \in W) 204 | \* liveness property 205 | \* k-Termination: All correct processes eventually decide 206 | Termination == <>(loc1.halt) 207 | 208 | ============================================================================= 209 | \* Modification History 210 | \* Last modified Tue May 19 16:42:48 CEST 2020 by ilina 211 | \* Created Tue May 19 16:00:14 CEST 2020 by ilina 212 | -------------------------------------------------------------------------------- /floodmin_k2/floodmin_k2.tla: -------------------------------------------------------------------------------- 1 | ------------------------------ MODULE floodmin_k2 ------------------------------ 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | CONSTANTS N, T, F 6 | 7 | VARIABLES state, msgs, round, phase, 8 | crash, failed, receivers 9 | 10 | vars == <> 11 | 12 | P == 1 .. N 13 | unknown == 3 14 | V == {0, 1, 2} 15 | K == 2 16 | 17 | C == [ min : V, decision : {0, 1, 2, unknown}] 18 | InitC == [ min : V, decision : {unknown}] 19 | 20 | 21 | InitEnvironment == 22 | /\ phase = "msgs" 23 | /\ round = 0 24 | /\ crash \in SUBSET(P) 25 | /\ failed = {} 26 | /\ Cardinality(failed \cup crash) <= F 27 | /\ receivers \in [crash -> SUBSET(P)] 28 | 29 | InitAlgorithm == 30 | /\ state \in [P -> InitC] 31 | /\ msgs = [p \in P |-> [q \in P |-> unknown]] \* two-dimensional messages array 32 | 33 | Min(S) == IF 0 \in S THEN 0 ELSE IF 1 \in S THEN 1 ELSE 2 34 | 35 | Msgs(p) == IF p \in failed 36 | THEN {} 37 | ELSE {v \in V : \E q \in P : msgs[q][p] # unknown /\ msgs[q][p] = v} 38 | 39 | 40 | SendMessage(p, q) == 41 | state[p].min 42 | 43 | EnvSemMsg(m, p, q) == 44 | IF \/ p \in failed 45 | \/ p \in crash /\ q \notin receivers[p] 46 | THEN unknown 47 | ELSE m 48 | 49 | EnvSemState(p, s1, s2) == 50 | IF p \in failed \/ p \in crash \/ s2.decision # unknown 51 | THEN s2 52 | ELSE s1 53 | 54 | Update(s, X) == 55 | LET m == Min(X) IN 56 | LET d == IF round >= (T \div K) + 1 57 | THEN m 58 | ELSE unknown IN 59 | [min |-> m, decision |-> d] 60 | 61 | MsgsEnvironment == 62 | IF round <= T \div K 63 | THEN 64 | /\ phase' = "trans" 65 | /\ round' = round+1 66 | /\ UNCHANGED <> 67 | ELSE UNCHANGED vars 68 | 69 | TransEnvironment == 70 | /\ phase' = "msgs" 71 | /\ failed' = failed \cup crash 72 | /\ crash' \in SUBSET(P \ failed') 73 | /\ Cardinality(failed' \cup crash') <= F 74 | /\ receivers' \in [crash' -> SUBSET(P)] 75 | /\ UNCHANGED round 76 | 77 | MsgsAlgorithm == 78 | IF round <= T \div K 79 | THEN 80 | /\ msgs' = [p \in P |-> [q \in P |-> EnvSemMsg(SendMessage(p, q), p, q)]] 81 | /\ UNCHANGED state 82 | ELSE UNCHANGED vars 83 | 84 | TransAlgorithm == 85 | /\ state' = [p \in P |-> EnvSemState(p, Update(state[p], Msgs(p)), state[p])] 86 | /\ msgs' = [p \in P |-> [q \in P |-> unknown]] 87 | 88 | 89 | \* next state action predicates 90 | 91 | NextEnvironment == 92 | \/ phase = "msgs" /\ MsgsEnvironment 93 | \/ phase = "trans" /\ TransEnvironment 94 | 95 | NextAlgorithm == 96 | \/ phase = "msgs" /\ MsgsAlgorithm 97 | \/ phase = "trans" /\ TransAlgorithm 98 | 99 | Init == InitAlgorithm /\ InitEnvironment 100 | Next == NextAlgorithm /\ NextEnvironment 101 | 102 | \* fairness constraint 103 | Fairness == WF_vars(Next) 104 | 105 | \* specification 106 | Spec == Init /\ [][Next]_vars /\ Fairness 107 | 108 | \* safety properties 109 | Agreement == \E W \in SUBSET(V) : Cardinality(W) = K /\ [](\A q \in P : (q \notin failed /\ state[q].decision # unknown) => state[q].decision \in W) 110 | Validity == \A I \in SUBSET(V) : I = {state[p].min : p \in P} => [](\A p \in P : (state[p].decision # unknown => state[p].decision \in I)) 111 | 112 | \* liveness property 113 | Termination == <>(\A p \in P : p \in failed \/ state[p].decision # unknown) 114 | 115 | 116 | 117 | ============================================================================= 118 | \* Modification History 119 | \* Last modified Tue May 19 16:27:42 CEST 2020 by ilina 120 | \* Last modified Thu Sep 28 18:11:32 CEST 2017 by stoilkov 121 | \* Created Thu Sep 28 18:06:12 CEST 2017 by stoilkov 122 | -------------------------------------------------------------------------------- /floodmin_k2/floodmin_k2_abstract.tla: -------------------------------------------------------------------------------- 1 | ------------------------- MODULE floodmin_k2_abstract ------------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, loc2, loc3, locOther, msgs, phase, crash, pclean, decisionRound, receivers, someP 6 | 7 | vars == <> 8 | 9 | unknown == 3 \* unknown decision value 10 | V == {0, 1, 2} \* set of values 11 | K == 2 \* cardinality of set of decision values 12 | I == 1 .. 6 \* indices corresponding to process locations 13 | U == 1 .. 9 \* array indices (process locations + 3 fixed processes) 14 | u1 == 7 \* index for process 1 15 | u2 == 8 \* index for process 2 16 | u3 == 9 \* index for process 3 17 | Loc == [min : V, halt : BOOLEAN] 18 | AM == {W \in SUBSET(V \cup {unknown}) : W = {} \/ Cardinality(W) = 1 \/ (Cardinality(W) = 2 /\ unknown \in W)} \* abstract message alphabet 19 | 20 | \* translate index i \in I to location l \in Loc 21 | location(i) == 22 | LET x == i - 1 IN 23 | LET m == IF x \div 2 = 0 THEN 0 ELSE IF x \div 2 = 1 THEN 1 ELSE 2 IN 24 | LET h == IF x % 2 = 0 THEN FALSE ELSE TRUE IN 25 | [min |-> m, halt |-> h] 26 | 27 | \* translate location l \in Loc to index i \in I 28 | index(l) == 29 | LET h == IF l.halt = FALSE THEN 0 ELSE 1 IN 30 | LET m == IF l.min = 0 THEN 0 ELSE IF l.min = 1 THEN 1 ELSE 2 IN 31 | 2 * m + h + 1 32 | 33 | \* get minimum value, given index u \in U 34 | min(u) == 35 | IF u = u1 36 | THEN loc1.min 37 | ELSE IF u = u2 38 | THEN loc2.min 39 | ELSE IF u = u3 40 | THEN loc3.min 41 | ELSE location(u).min 42 | 43 | 44 | \* Set of indices witnessing non-failed processes 45 | IndexNonFailed == {u1, u2, u3} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt}} 46 | \* Set of locations of active processes 47 | Active == {loc1, loc2, loc3} \cup locOther 48 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 49 | Correct == {u1, u2, u3} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt /\ crash[l1] # {TRUE}}} 50 | 51 | \* set failure flag of l to TRUE 52 | failedLocation(l) == 53 | [min |-> l.min, halt |-> TRUE] 54 | 55 | \* Set of initial locations 56 | InitActive == {[min |-> 0, halt |-> FALSE], 57 | [min |-> 1, halt |-> FALSE], 58 | [min |-> 2, halt |-> FALSE]} 59 | 60 | \* type invariant 61 | TypeOK == 62 | /\ loc1 \in Loc 63 | /\ loc2 \in Loc 64 | /\ loc3 \in Loc 65 | /\ locOther \in SUBSET(Loc) 66 | /\ msgs \in [IndexNonFailed -> [IndexNonFailed -> AM]] 67 | /\ phase \in {"msgs", "trans"} 68 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 69 | /\ pclean \in BOOLEAN 70 | /\ decisionRound \in BOOLEAN 71 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : min(u) = 2} -> SUBSET(BOOLEAN)] 72 | /\ someP \in [{l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 2} -> BOOLEAN] 73 | 74 | \* initial predicate of the environment 75 | InitEnvironment == 76 | /\ phase = "msgs" \* current phase of the algorithm 77 | /\ decisionRound = FALSE \* predicate for the decision round 78 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] \* crash array 79 | /\ pclean = FALSE \* predicate for the clean round 80 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : min(u) = 2} -> ((SUBSET(BOOLEAN)) \ {{}})] \* receivers array 81 | /\ someP = [l \in {k \in locOther : crash[k] # {TRUE} /\ k.min = 2} |-> FALSE] 82 | 83 | \* initial predicate of the algorithm 84 | InitAlgorithm == 85 | /\ loc1 \in InitActive \* first fixed process 86 | /\ loc2 \in InitActive \* second fixed process 87 | /\ loc3 \in InitActive \* third fixed process 88 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of locations witnessing the other N - 3 processes 89 | /\ msgs = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> {unknown}]] \* two-dimensional messages array 90 | 91 | \* environment transition in the message exchage phase 92 | MsgsEnvironment == 93 | /\ phase' = "trans" 94 | /\ pclean' = IF \E l \in DOMAIN crash : (TRUE \in crash[l] /\ \A k \in DOMAIN crash : l # k => TRUE \notin crash[k]) 95 | THEN TRUE 96 | ELSE pclean 97 | /\ decisionRound' \in IF pclean' THEN {TRUE, FALSE} ELSE {FALSE} 98 | /\ someP' \in [{l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 2} -> BOOLEAN] 99 | /\ UNCHANGED <> 100 | 101 | \* environment transition in the state update phase 102 | TransEnvironment == 103 | /\ phase' = "msgs" 104 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 105 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} \X {u \in TLCEval(Correct') : min(u)' = 2} -> ((SUBSET(BOOLEAN)) \ {{}})] \* /\ (l.W # loc1'.W \/ l.W # loc2'.W) \/ \E l1 \in locOther' : l.W # l1.W 106 | /\ someP' = [l \in {l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 2}' |-> FALSE] 107 | /\ UNCHANGED <> 108 | 109 | \* message generation function of a correct process 110 | SendMessage(u, v) == 111 | min(u) 112 | 113 | \* update function of a correct process 114 | \* (that received the same messages as the abstract location that witnesses it) 115 | Update(l, u) == 116 | LET m == IF l.min = 2 /\ \E v \in IndexNonFailed : 1 \in msgs[v][u] 117 | THEN IF \E v \in IndexNonFailed : 0 \in msgs[v][u] 118 | THEN 0 119 | ELSE 1 120 | ELSE IF l.min = 1 /\ \E v \in IndexNonFailed : 0 \in msgs[v][u] 121 | THEN 0 122 | ELSE l.min IN 123 | LET h == IF decisionRound 124 | THEN TRUE 125 | ELSE FALSE IN 126 | [min |-> m, halt |-> h] 127 | 128 | \* update function of a correct process 129 | \* (that received messages different from the ones received by abstract location that witnesses it) 130 | UpdateOther(l, m) == 131 | LET h == IF decisionRound 132 | THEN TRUE 133 | ELSE FALSE IN 134 | [min |-> m, halt |-> h] 135 | 136 | \* update of a process location witnessing correct processes 137 | UpdateCorrect(l, u) == 138 | IF l.min = 2 /\ loc1.min = l.min /\ loc2.min = l.min /\ loc3.min = l.min 139 | THEN IF \A v \in IndexNonFailed : v \notin {u1, u2, u3} /\ min(v) # l.min => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 140 | THEN {UpdateOther(l, l.min)} 141 | ELSE IF someP[l] 142 | THEN {Update(l, u), UpdateOther(l, l.min)} 143 | ELSE {Update(l, u)} 144 | ELSE {Update(l, u)} 145 | 146 | \* delivery of messages by the environment 147 | EnvSemMsg(m, u, v) == 148 | IF u \in {u1, u2, u3} 149 | THEN {m} 150 | ELSE LET l == location(u) IN 151 | IF crash[l] = {TRUE, FALSE} 152 | THEN IF min(v) = 2 /\ (v \in {u1, u2, u3} \/ crash[location(v)] # {TRUE}) 153 | THEN IF receivers[l,v] = {TRUE} 154 | THEN {m} 155 | ELSE {unknown, m} 156 | ELSE {unknown} 157 | ELSE IF crash[l] = {TRUE} 158 | THEN IF min(v) = 2 /\ (v \in {u1, u2, u3} \/ crash[location(v)] # {TRUE}) 159 | THEN IF receivers[l,v] = {TRUE} 160 | THEN {m} 161 | ELSE IF receivers[l,v] = {FALSE} 162 | THEN {unknown} 163 | ELSE {unknown, m} 164 | ELSE {unknown} 165 | ELSE IF min(v) = 2 /\ (v \in {u1, u2, u3} \/ crash[location(v)] # {TRUE}) 166 | THEN {m} 167 | ELSE {unknown} 168 | 169 | \* state update of the fixed processes w.r.t. the environment 170 | EnvSemState(l, u) == 171 | IF l.halt 172 | THEN l 173 | ELSE TLCEval(Update(l, u)) 174 | 175 | \* state update of the other processes w.r.t. the environment 176 | EnvSemStateOther(l) == 177 | IF l.halt 178 | THEN {l} 179 | ELSE IF crash[l] = {TRUE} 180 | THEN {failedLocation(l)} \* all processes witnessed by l crashed 181 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes witnessed by l crashed, and some not 182 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} 183 | ELSE UpdateCorrect(l, index(l)) \* no processes witnessed by l crashed 184 | 185 | \* algorithm transition in the message exchange phase 186 | MsgsAlgorithm == 187 | /\ msgs' = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> EnvSemMsg(SendMessage(u, v), u, v)]] 188 | /\ UNCHANGED <> 189 | 190 | \* algorithm transition in the state update phase 191 | TransAlgorithm == 192 | /\ loc1' = EnvSemState(loc1, u1) 193 | /\ loc2' = EnvSemState(loc2, u2) 194 | /\ loc3' = EnvSemState(loc2, u3) 195 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 196 | /\ msgs' = [u \in IndexNonFailed' |-> [v \in IndexNonFailed' |-> {unknown}]] 197 | 198 | NextEnvironment == 199 | \/ phase = "msgs" /\ MsgsEnvironment 200 | \/ phase = "trans" /\ TransEnvironment 201 | 202 | NextAlgorithm == 203 | \/ phase = "msgs" /\ MsgsAlgorithm 204 | \/ phase = "trans" /\ TransAlgorithm 205 | 206 | Init == InitAlgorithm /\ InitEnvironment 207 | 208 | Next == NextAlgorithm /\ NextEnvironment 209 | 210 | \* constraints 211 | Fairness == /\ WF_vars(Next) 212 | /\ <>[](\E l \in DOMAIN crash : (TRUE \in crash[l] /\ \A k \in DOMAIN crash : l # k => TRUE \notin crash[k])) 213 | /\ <>decisionRound 214 | 215 | \* specification 216 | Spec == Init /\ [][Next]_vars /\ Fairness 217 | 218 | \* safety properties 219 | \* k-Agreement: There is a subset W of V of cardinality K, such that all decision 220 | \* values are in W 221 | Agreement == \E W \in SUBSET(V) : Cardinality(W) = K /\ 222 | [](loc1.halt /\ loc2.halt /\ loc3.halt => 223 | (loc1.min \in W /\ loc2.min \in W /\ loc3.min \in W)) 224 | \* k-Validity: Any decision value for any process is the initial value of some process 225 | Validity == \A W \in SUBSET(V) : W = {min(u) : u \in IndexNonFailed} => 226 | [](loc1.halt /\ loc2.halt /\ loc3.halt => 227 | (loc1.min \in W /\ loc2.min \in W /\ loc3.min \in W)) 228 | \* liveness property 229 | \* k-Termination: All correct processes eventually decide 230 | Termination == <>(loc1.halt /\ loc2.halt /\ loc3.halt) 231 | 232 | ============================================================================= 233 | -------------------------------------------------------------------------------- /floodmin_k2/floodmin_k2_abstract_m1.tla: -------------------------------------------------------------------------------- 1 | --------------------- MODULE floodmin_k2_abstract_m1 --------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, locOther, msgs, phase, crash, decisionRound, receivers, someP, pclean 6 | 7 | vars == <> 8 | 9 | unknown == 3 \* unknown decision value 10 | V == {0, 1, 2} \* set of values 11 | K == 2 \* cardinality of set of decision values 12 | I == 1 .. 6 \* indices corresponding to process locations 13 | U == 1 .. 7 \* array indices (process locations + 1 fixed process) 14 | u1 == 7 \* index for process 1 15 | Loc == [min : V, halt : BOOLEAN] 16 | AM == {W \in SUBSET(V \cup {unknown}) : W = {} \/ Cardinality(W) = 1 \/ (Cardinality(W) = 2 /\ unknown \in W)} \* abstract message alphabet 17 | 18 | \* translate index i \in I to location l \in Loc 19 | location(i) == 20 | LET x == i - 1 IN 21 | LET m == IF x \div 2 = 0 THEN 0 ELSE IF x \div 2 = 1 THEN 1 ELSE 2 IN 22 | LET h == IF x % 2 = 0 THEN FALSE ELSE TRUE IN 23 | [min |-> m, halt |-> h] 24 | 25 | \* translate location l \in Loc to index i \in I 26 | index(l) == 27 | LET h == IF l.halt = FALSE THEN 0 ELSE 1 IN 28 | LET m == IF l.min = 0 THEN 0 ELSE IF l.min = 1 THEN 1 ELSE 2 IN 29 | 2 * m + h + 1 30 | 31 | \* get minimum value, given index u \in U 32 | min(u) == 33 | IF u = u1 34 | THEN loc1.min 35 | ELSE location(u).min 36 | 37 | \* Set of indices witnessing non-failed processes 38 | IndexNonFailed == {u1} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt}} 39 | \* Set of locations of active processes 40 | Active == {loc1} \cup locOther 41 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 42 | Correct == {u1} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt /\ crash[l1] # {TRUE}}} 43 | 44 | \* set failure flag of l to TRUE 45 | failedLocation(l) == 46 | [min |-> l.min, halt |-> TRUE] 47 | 48 | \* Set of initial locations 49 | InitActive == {[min |-> 0, halt |-> FALSE], 50 | [min |-> 1, halt |-> FALSE], 51 | [min |-> 2, halt |-> FALSE]} 52 | 53 | \* type invariant 54 | TypeOK == 55 | /\ loc1 \in Loc 56 | /\ locOther \in SUBSET(Loc) 57 | /\ msgs \in [IndexNonFailed -> [IndexNonFailed -> AM]] 58 | /\ phase \in {"msgs", "trans"} 59 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 60 | /\ pclean \in BOOLEAN 61 | /\ decisionRound \in BOOLEAN 62 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : min(u) = 2} -> SUBSET(BOOLEAN)] 63 | /\ someP \in [{l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 2} -> BOOLEAN] 64 | 65 | \* initial predicate of the environment 66 | InitEnvironment == 67 | /\ phase = "msgs" \* current phase of the algorithm 68 | /\ decisionRound = FALSE \* predicate for the decision round 69 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] \* crash array 70 | /\ pclean = FALSE \* predicate for the clean round 71 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : min(u) = 2} -> ((SUBSET(BOOLEAN)) \ {{}})] \* receivers array 72 | /\ someP = [l \in {k \in locOther : crash[k] # {TRUE} /\ k.min = 2} |-> FALSE] 73 | 74 | \* initial predicate of the algorithm 75 | InitAlgorithm == 76 | /\ loc1 \in InitActive \* first fixed process 77 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of locations witnessing the other N - 1 processes 78 | /\ msgs = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> {unknown}]] \* two-dimensional messages array 79 | 80 | \* environment transition in the message exchage phase 81 | MsgsEnvironment == 82 | /\ phase' = "trans" 83 | /\ pclean' = IF \E l \in DOMAIN crash : (TRUE \in crash[l] /\ \A k \in DOMAIN crash : l # k => TRUE \notin crash[k]) 84 | THEN TRUE 85 | ELSE pclean 86 | /\ decisionRound' \in IF pclean' THEN {TRUE, FALSE} ELSE {FALSE} 87 | /\ someP' \in [{l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 2} -> BOOLEAN] 88 | /\ UNCHANGED <> 89 | 90 | \* environment transition in the state update phase 91 | TransEnvironment == 92 | /\ phase' = "msgs" 93 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 94 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} \X {u \in TLCEval(Correct') : min(u)' = 2} -> ((SUBSET(BOOLEAN)) \ {{}})] \* /\ (l.W # loc1'.W \/ l.W # loc2'.W) \/ \E l1 \in locOther' : l.W # l1.W 95 | /\ someP' = [l \in {l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 2}' |-> FALSE] 96 | /\ UNCHANGED <> 97 | 98 | \* message generation function of a correct process 99 | SendMessage(u, v) == 100 | min(u) 101 | 102 | \* update function of a correct process 103 | \* (that received the same messages as the abstract location that witnesses it) 104 | Update(l, u) == 105 | LET m == IF l.min = 2 /\ \E v \in IndexNonFailed : 1 \in msgs[v][u] 106 | THEN IF \E v \in IndexNonFailed : 0 \in msgs[v][u] 107 | THEN 0 108 | ELSE 1 109 | ELSE IF l.min = 1 /\ \E v \in IndexNonFailed : 0 \in msgs[v][u] 110 | THEN 0 111 | ELSE l.min IN 112 | LET h == IF decisionRound 113 | THEN TRUE 114 | ELSE FALSE IN 115 | [min |-> m, halt |-> h] 116 | 117 | \* update function of a correct process 118 | \* (that received messages different from the ones received by abstract location that witnesses it) 119 | UpdateOther(l, m) == 120 | LET h == IF decisionRound 121 | THEN TRUE 122 | ELSE FALSE IN 123 | [min |-> m, halt |-> h] 124 | 125 | \* update of a process location witnessing correct processes 126 | UpdateCorrect(l, u) == 127 | IF l.min = 2 /\ loc1.min = l.min 128 | THEN IF \A v \in IndexNonFailed : v \notin {u1} /\ min(v) # l.min => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 129 | THEN {TLCEval(UpdateOther(l, l.min))} 130 | ELSE IF someP[l] 131 | THEN {TLCEval(Update(l, u)), TLCEval(UpdateOther(l, l.min))} 132 | ELSE {TLCEval(Update(l, u))} 133 | ELSE {TLCEval(Update(l, u))} 134 | 135 | \* delivery of messages by the environment 136 | EnvSemMsg(m, u, v) == 137 | IF u \in {u1} 138 | THEN {m} 139 | ELSE LET l == location(u) IN 140 | IF crash[l] = {TRUE, FALSE} 141 | THEN IF min(v) = 2 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 142 | THEN IF receivers[l,v] = {TRUE} 143 | THEN {m} 144 | ELSE {unknown, m} 145 | ELSE {unknown} 146 | ELSE IF crash[l] = {TRUE} 147 | THEN IF min(v) = 2 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 148 | THEN IF receivers[l,v] = {TRUE} 149 | THEN {m} 150 | ELSE IF receivers[l,v] = {FALSE} 151 | THEN {unknown} 152 | ELSE {unknown, m} 153 | ELSE {unknown} 154 | ELSE IF min(v) = 2 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 155 | THEN {m} 156 | ELSE {unknown} 157 | 158 | \* state update of the fixed processes w.r.t. the environment 159 | EnvSemState(l, u) == 160 | IF l.halt 161 | THEN l 162 | ELSE TLCEval(Update(l, u)) 163 | 164 | \* state update of the other processes w.r.t. the environment 165 | EnvSemStateOther(l) == 166 | IF l.halt 167 | THEN {l} 168 | ELSE IF crash[l] = {TRUE} 169 | THEN {failedLocation(l)} \* all processes witnessed by l crashed 170 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes witnessed by l crashed, and some not 171 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} 172 | ELSE UpdateCorrect(l, index(l)) \* no processes witnessed by l crashed 173 | 174 | \* algorithm transition in the message exchange phase 175 | MsgsAlgorithm == 176 | /\ msgs' = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> EnvSemMsg(SendMessage(u, v), u, v)]] 177 | /\ UNCHANGED <> 178 | 179 | \* algorithm transition in the state update phase 180 | TransAlgorithm == 181 | /\ loc1' = EnvSemState(loc1, u1) 182 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 183 | /\ msgs' = [u \in IndexNonFailed' |-> [v \in IndexNonFailed' |-> {unknown}]] 184 | 185 | NextEnvironment == 186 | \/ phase = "msgs" /\ MsgsEnvironment 187 | \/ phase = "trans" /\ TransEnvironment 188 | 189 | NextAlgorithm == 190 | \/ phase = "msgs" /\ MsgsAlgorithm 191 | \/ phase = "trans" /\ TransAlgorithm 192 | 193 | Init == InitAlgorithm /\ InitEnvironment 194 | 195 | Next == NextAlgorithm /\ NextEnvironment 196 | 197 | \* constraints 198 | Fairness == /\ WF_vars(Next) 199 | /\ <>[](\E l \in DOMAIN crash : (TRUE \in crash[l] /\ \A k \in DOMAIN crash : l # k => TRUE \notin crash[k])) 200 | /\ <>decisionRound 201 | 202 | \* specification 203 | Spec == Init /\ [][Next]_vars /\ Fairness 204 | 205 | \* safety properties 206 | \* k-Agreement: There is a subset W of V of cardinality K, such that all decision 207 | \* values are in W 208 | Agreement == \E W \in SUBSET(V) : Cardinality(W) = K /\ 209 | [](loc1.halt => loc1.min \in W) 210 | \* k-Validity: Any decision value for any process is the initial value of some process 211 | Validity == \A W \in SUBSET(V) : W = {min(u) : u \in IndexNonFailed} => 212 | [](loc1.halt => loc1.min \in W) 213 | \* liveness property 214 | \* k-Termination: All correct processes eventually decide 215 | Termination == <>(loc1.halt) 216 | 217 | ============================================================================= 218 | \* Modification History 219 | \* Last modified Tue May 19 16:25:23 CEST 2020 by ilina 220 | \* Last modified Fri Oct 13 18:33:47 CEST 2017 by stoilkov 221 | \* Created Fri Sep 29 11:33:18 CEST 2017 by stoilkov 222 | -------------------------------------------------------------------------------- /floodmin_k2/floodmin_k2_abstract_m2.tla: -------------------------------------------------------------------------------- 1 | --------------------- MODULE floodmin_k2_abstract_m2 --------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, loc2, locOther, msgs, phase, crash, decisionRound, receivers, someP, pclean 6 | 7 | vars == <> 8 | 9 | unknown == 3 \* unknown decision value 10 | V == {0, 1, 2} \* set of values 11 | K == 2 \* cardinality of set of decision values 12 | I == 1 .. 6 \* indices corresponding to process locations 13 | U == 1 .. 8 \* array indices (process locations + 2 fixed processes) 14 | u1 == 7 \* index for process 1 15 | u2 == 8 \* index for process 2 16 | Loc == [min : V, halt : BOOLEAN] 17 | AM == {W \in SUBSET(V \cup {unknown}) : W = {} \/ Cardinality(W) = 1 \/ (Cardinality(W) = 2 /\ unknown \in W)} \* abstract message alphabet 18 | 19 | \* translate index i \in I to location l \in Loc 20 | location(i) == 21 | LET x == i - 1 IN 22 | LET m == IF x \div 2 = 0 THEN 0 ELSE IF x \div 2 = 1 THEN 1 ELSE 2 IN 23 | LET h == IF x % 2 = 0 THEN FALSE ELSE TRUE IN 24 | [min |-> m, halt |-> h] 25 | 26 | \* translate location l \in Loc to index i \in I 27 | index(l) == 28 | LET h == IF l.halt = FALSE THEN 0 ELSE 1 IN 29 | LET m == IF l.min = 0 THEN 0 ELSE IF l.min = 1 THEN 1 ELSE 2 IN 30 | 2 * m + h + 1 31 | 32 | \* get minimum value, given index u \in U 33 | min(u) == 34 | IF u = u1 35 | THEN loc1.min 36 | ELSE IF u = u2 37 | THEN loc2.min 38 | ELSE location(u).min 39 | 40 | \* Set of indices witnessing non-failed processes 41 | IndexNonFailed == {u1, u2} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt}} 42 | \* Set of locations of active processes 43 | Active == {loc1, loc2} \cup locOther 44 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 45 | Correct == {u1, u2} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt /\ crash[l1] # {TRUE}}} 46 | 47 | \* set failure flag of l to TRUE 48 | failedLocation(l) == 49 | [min |-> l.min, halt |-> TRUE] 50 | 51 | \* Set of initial locations 52 | InitActive == {[min |-> 0, halt |-> FALSE], 53 | [min |-> 1, halt |-> FALSE], 54 | [min |-> 2, halt |-> FALSE]} 55 | 56 | \* type invariant 57 | TypeOK == 58 | /\ loc1 \in Loc 59 | /\ loc2 \in Loc 60 | /\ locOther \in SUBSET(Loc) 61 | /\ msgs \in [IndexNonFailed -> [IndexNonFailed -> AM]] 62 | /\ phase \in {"msgs", "trans"} 63 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 64 | /\ pclean \in BOOLEAN 65 | /\ decisionRound \in BOOLEAN 66 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : min(u) = 2} -> SUBSET(BOOLEAN)] 67 | /\ someP \in [{l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 2} -> BOOLEAN] 68 | 69 | 70 | \* initial predicate of the environment 71 | InitEnvironment == 72 | /\ phase = "msgs" \* current phase of the algorithm 73 | /\ decisionRound = FALSE \* predicate for the decision round 74 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] \* crash array 75 | /\ pclean = FALSE \* predicate for the clean round 76 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : min(u) = 2} -> ((SUBSET(BOOLEAN)) \ {{}})] \* receivers array 77 | /\ someP = [l \in {k \in locOther : crash[k] # {TRUE} /\ k.min = 2} |-> FALSE] 78 | 79 | \* initial predicate of the algorithm 80 | InitAlgorithm == 81 | /\ loc1 \in InitActive \* first fixed process 82 | /\ loc2 \in InitActive \* second fixed process 83 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of locations witnessing the other N - 2 processes 84 | /\ msgs = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> {unknown}]] \* two-dimensional messages array 85 | 86 | \* environment transition in the message exchage phase 87 | MsgsEnvironment == 88 | /\ phase' = "trans" 89 | /\ pclean' = IF \E l \in DOMAIN crash : (TRUE \in crash[l] /\ \A k \in DOMAIN crash : l # k => TRUE \notin crash[k]) 90 | THEN TRUE 91 | ELSE pclean 92 | /\ decisionRound' \in IF pclean' THEN {TRUE, FALSE} ELSE {FALSE} 93 | /\ someP' \in [{l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 2} -> BOOLEAN] 94 | /\ UNCHANGED <> 95 | 96 | \* environment transition in the state update phase 97 | TransEnvironment == 98 | /\ phase' = "msgs" 99 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 100 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} \X {u \in TLCEval(Correct') : min(u)' = 2} -> ((SUBSET(BOOLEAN)) \ {{}})] \* /\ (l.W # loc1'.W \/ l.W # loc2'.W) \/ \E l1 \in locOther' : l.W # l1.W 101 | /\ someP' = [l \in {l \in locOther : ~l.halt /\ crash[l] # {TRUE} /\ l.min = 2}' |-> FALSE] 102 | /\ UNCHANGED <> 103 | 104 | \* message generation function of a correct process 105 | SendMessage(u, v) == 106 | min(u) 107 | 108 | \* update function of a correct process 109 | \* (that received the same messages as the abstract location that witnesses it) 110 | Update(l, u) == 111 | LET m == IF l.min = 2 /\ \E v \in IndexNonFailed : 1 \in msgs[v][u] 112 | THEN IF \E v \in IndexNonFailed : 0 \in msgs[v][u] 113 | THEN 0 114 | ELSE 1 115 | ELSE IF l.min = 1 /\ \E v \in IndexNonFailed : 0 \in msgs[v][u] 116 | THEN 0 117 | ELSE l.min IN 118 | LET h == IF decisionRound 119 | THEN TRUE 120 | ELSE FALSE IN 121 | [min |-> m, halt |-> h] 122 | 123 | \* update function of a correct process 124 | \* (that received messages different from the ones received by abstract location that witnesses it) 125 | UpdateOther(l, m) == 126 | LET h == IF decisionRound 127 | THEN TRUE 128 | ELSE FALSE IN 129 | [min |-> m, halt |-> h] 130 | 131 | \* update of a process location witnessing correct processes 132 | UpdateCorrect(l, u) == 133 | IF l.min = 2 /\ loc1.min = l.min /\ loc2.min = l.min 134 | THEN IF \A v \in IndexNonFailed : v \notin {u1, u2} /\ min(v) # l.min => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 135 | THEN {UpdateOther(l, l.min)} 136 | ELSE IF someP[l] 137 | THEN {Update(l, u), UpdateOther(l, l.min)} 138 | ELSE {Update(l, u)} 139 | ELSE {Update(l, u)} 140 | 141 | \* delivery of messages by the environment 142 | EnvSemMsg(m, u, v) == 143 | IF u \in {u1, u2} 144 | THEN {m} 145 | ELSE LET l == location(u) IN 146 | IF crash[l] = {TRUE, FALSE} 147 | THEN IF min(v) = 2 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 148 | THEN IF receivers[l,v] = {TRUE} 149 | THEN {m} 150 | ELSE {unknown, m} 151 | ELSE {unknown} 152 | ELSE IF crash[l] = {TRUE} 153 | THEN IF min(v) = 2 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 154 | THEN IF receivers[l,v] = {TRUE} 155 | THEN {m} 156 | ELSE IF receivers[l,v] = {FALSE} 157 | THEN {unknown} 158 | ELSE {unknown, m} 159 | ELSE {unknown} 160 | ELSE IF min(v) = 2 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 161 | THEN {m} 162 | ELSE {unknown} 163 | 164 | \* state update of the fixed processes w.r.t. the environment 165 | EnvSemState(l, u) == 166 | IF l.halt 167 | THEN l 168 | ELSE TLCEval(Update(l, u)) 169 | 170 | \* state update of the other processes w.r.t. the environment 171 | EnvSemStateOther(l) == 172 | IF l.halt 173 | THEN {l} 174 | ELSE IF crash[l] = {TRUE} 175 | THEN {failedLocation(l)} \* all processes witnessed by l crashed 176 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes witnessed by l crashed, and some not 177 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} \* partially correct 178 | ELSE UpdateCorrect(l, index(l)) \* no processes witnessed by l crashed 179 | 180 | \* algorithm transition in the message exchange phase 181 | MsgsAlgorithm == 182 | /\ msgs' = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> EnvSemMsg(SendMessage(u, v), u, v)]] 183 | /\ UNCHANGED <> 184 | 185 | \* algorithm transition in the state update phase 186 | TransAlgorithm == 187 | /\ loc1' = EnvSemState(loc1, u1) 188 | /\ loc2' = EnvSemState(loc2, u2) 189 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 190 | /\ msgs' = [u \in IndexNonFailed' |-> [v \in IndexNonFailed' |-> {unknown}]] 191 | 192 | NextEnvironment == 193 | \/ phase = "msgs" /\ MsgsEnvironment 194 | \/ phase = "trans" /\ TransEnvironment 195 | 196 | NextAlgorithm == 197 | \/ phase = "msgs" /\ MsgsAlgorithm 198 | \/ phase = "trans" /\ TransAlgorithm 199 | 200 | Init == InitAlgorithm /\ InitEnvironment 201 | 202 | Next == NextAlgorithm /\ NextEnvironment 203 | 204 | \* constraints 205 | Fairness == /\ WF_vars(Next) 206 | /\ <>[](\E l \in DOMAIN crash : (TRUE \in crash[l] /\ \A k \in DOMAIN crash : l # k => TRUE \notin crash[k])) 207 | /\ <>decisionRound 208 | 209 | \* specification 210 | Spec == Init /\ [][Next]_vars /\ Fairness 211 | 212 | \* safety properties 213 | \* k-Agreement: There is a subset W of V of cardinality K, such that all decision 214 | \* values are in W 215 | Agreement == \E W \in SUBSET(V) : Cardinality(W) = K /\ 216 | [](loc1.halt /\ loc2.halt => 217 | (loc1.min \in W /\ loc2.min \in W)) 218 | \* k-Validity: Any decision value for any process is the initial value of some process 219 | Validity == \A W \in SUBSET(V) : W = {min(u) : u \in IndexNonFailed} => 220 | [](loc1.halt /\ loc2.halt => 221 | (loc1.min \in W /\ loc2.min \in W)) 222 | \* k-Termination: All correct processes eventually decide 223 | Termination == <>(loc1.halt /\ loc2.halt) 224 | 225 | ============================================================================= 226 | \* Modification History 227 | \* Last modified Tue May 19 16:23:43 CEST 2020 by ilina 228 | \* Last modified Fri Oct 13 18:34:05 CEST 2017 by stoilkov 229 | \* Created Thu Sep 28 17:05:26 CEST 2017 by stoilkov 230 | -------------------------------------------------------------------------------- /floodset/floodset.tla: -------------------------------------------------------------------------------- 1 | ------------------------------ MODULE floodset ------------------------------ 2 | EXTENDS Naturals, FiniteSets, TLC 3 | 4 | CONSTANTS N, T, F 5 | 6 | VARIABLES state, msgs, round, phase, 7 | crash, failed, receivers 8 | 9 | vars == <> 10 | 11 | P == 1 .. N 12 | unknown == 2 13 | V == {0, 1} 14 | v0 == 0 15 | 16 | C == [ W : {{0}, {1}, {0, 1}}, decision : {0, 1, unknown}] 17 | InitC == [ W : {{0}, {1}}, decision : {unknown}] 18 | 19 | 20 | InitEnvironment == 21 | /\ phase = "msgs" 22 | /\ round = 0 23 | /\ crash \in SUBSET(P) 24 | /\ failed = {} 25 | /\ Cardinality(failed \cup crash) <= F 26 | /\ receivers \in [crash -> SUBSET(P)] 27 | 28 | InitAlgorithm == 29 | /\ state \in [P -> InitC] 30 | /\ msgs = [p \in P |-> [q \in P |-> {}]] \* two-dimensional messages array 31 | 32 | Msgs(p) == IF p \in failed 33 | THEN {} 34 | ELSE UNION{m \in SUBSET(V) : \E q \in P : msgs[q][p] = m} 35 | 36 | SendMessage(p, q) == 37 | state[p].W 38 | 39 | EnvSemMsg(m, p, q) == 40 | IF \/ p \in failed 41 | \/ p \in crash /\ q \notin receivers[p] 42 | THEN {} 43 | ELSE m 44 | 45 | EnvSemState(p, s1, s2) == 46 | IF p \in failed \/ p \in crash \/ s2.decision # unknown 47 | THEN s2 48 | ELSE s1 49 | 50 | Update(s, X) == 51 | LET w == (s.W \cup X) IN 52 | LET d == IF round >= T + 1 53 | THEN IF w = {0} 54 | THEN 0 55 | ELSE IF w = {1} 56 | THEN 1 57 | ELSE v0 58 | ELSE unknown IN 59 | [W |-> w, decision |-> d] 60 | 61 | 62 | MsgsEnvironment == 63 | IF round <= T 64 | THEN 65 | /\ phase' = "trans" 66 | /\ round' = round+1 67 | /\ UNCHANGED <> 68 | ELSE UNCHANGED vars 69 | 70 | TransEnvironment == 71 | /\ phase' = "msgs" 72 | /\ failed' = failed \cup crash 73 | /\ crash' \in SUBSET(P \ failed') 74 | /\ Cardinality(failed' \cup crash') <= F 75 | /\ receivers' \in [crash' -> SUBSET(P)] 76 | /\ UNCHANGED round 77 | 78 | MsgsAlgorithm == 79 | IF round <= T 80 | THEN 81 | /\ msgs' = [p \in P |-> [q \in P |-> EnvSemMsg(SendMessage(p, q), p, q)]] 82 | /\ UNCHANGED state 83 | ELSE UNCHANGED vars 84 | 85 | TransAlgorithm == 86 | /\ state' = [p \in P |-> EnvSemState(p, Update(state[p], Msgs(p)), state[p])] 87 | /\ msgs' = [p \in P |-> [q \in P |-> {}]] 88 | 89 | 90 | \* next state action predicates 91 | 92 | NextEnvironment == 93 | \/ phase = "msgs" /\ MsgsEnvironment 94 | \/ phase = "trans" /\ TransEnvironment 95 | 96 | NextAlgorithm == 97 | \/ phase = "msgs" /\ MsgsAlgorithm 98 | \/ phase = "trans" /\ TransAlgorithm 99 | 100 | Init == InitAlgorithm /\ InitEnvironment 101 | Next == NextAlgorithm /\ NextEnvironment 102 | 103 | \* fairness constraint 104 | Fairness == WF_vars(Next) 105 | 106 | \* specification 107 | Spec == Init /\ [][Next]_vars /\ Fairness 108 | 109 | \* safety properties 110 | Validity == \A v \in V : (\A p \in P : state[p].W = {v}) => [](\A q \in P : (q \notin failed /\ state[q].decision # unknown) => state[q].decision = v) 111 | 112 | Agreement == [](\A p \in P : \A q \in P : (state[p].decision # unknown /\ state[q].decision # unknown => state[p].decision = state[q].decision)) 113 | 114 | \* liveness property 115 | Termination == <>(\A p \in P : p \in failed \/ state[p].decision # unknown) 116 | 117 | ============================================================================= 118 | \* Modification History 119 | \* Last modified Thu Sep 28 18:12:11 CEST 2017 by stoilkov 120 | \* Created Thu Apr 20 10:58:48 CEST 2017 by stoilkov 121 | 122 | -------------------------------------------------------------------------------- /floodset/floodset_abstract.tla: -------------------------------------------------------------------------------- 1 | ----------------------- MODULE floodset_abstract ----------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, loc2, locOther, msgs, phase, crash, pclean, decisionRound, receivers, someP 6 | 7 | vars == <> 8 | 9 | v0 == 0 \* default decision value 10 | V == {0, 1} \* set of values 11 | I == 1 .. 6 \* indices corresponding to process locations 12 | U == 1 .. 8 \* array indices (process locations + 2 concrete processes) 13 | u1 == 7 \* index for process 1 14 | u2 == 8 \* index for process 2 15 | Loc == [ W : {{0}, {1}, {0, 1}}, halt : BOOLEAN] \* possible process locations 16 | AM == {W \in SUBSET(SUBSET(V)) : W = {} \/ Cardinality(W) = 1 \/ (Cardinality(W) = 2 /\ {} \in W)} \* abstract message alphabet 17 | 18 | \* translate index i \in I to location l \in Loc 19 | location(i) == 20 | LET x == i - 1 IN 21 | LET w == IF x \div 2 = 0 THEN {0} ELSE IF x \div 2 = 1 THEN {1} ELSE {0, 1} IN 22 | LET h == IF x % 2 = 0 THEN FALSE ELSE TRUE IN 23 | [W |-> w, halt |-> h] 24 | 25 | \* translate location l \in Loc to index i \in I 26 | index(l) == 27 | LET f == IF l.halt = FALSE THEN 0 ELSE 1 IN 28 | LET w == IF l.W = {0} THEN 0 ELSE IF l.W = {1} THEN 1 ELSE 2 IN 29 | 2 * w + f + 1 30 | 31 | \* get value set, given index u \in U 32 | valueSet(u) == 33 | IF u = u1 34 | THEN loc1.W 35 | ELSE IF u = u2 36 | THEN loc2.W 37 | ELSE location(u).W 38 | 39 | \* Set of indices witnessing non-failed processes 40 | IndexNonFailed == {u1, u2} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt}} 41 | \* Set of locations of active processes 42 | Active == {loc1, loc2} \cup locOther 43 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 44 | Correct == {u1, u2} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt /\ crash[l1] # {TRUE}}} 45 | 46 | \* set failure flag of l to TRUE 47 | failedLocation(l) == 48 | [W |-> l.W, halt |-> TRUE] 49 | 50 | \* Set of initial locations 51 | InitActive == {[W |-> {0}, halt |-> FALSE], 52 | [W |-> {1}, halt |-> FALSE]} 53 | 54 | \* type invariant 55 | TypeOK == 56 | /\ loc1 \in Loc 57 | /\ loc2 \in Loc 58 | /\ locOther \in SUBSET(Loc) 59 | /\ msgs \in [IndexNonFailed -> [IndexNonFailed -> AM]] 60 | /\ phase \in {"msgs", "trans"} 61 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 62 | /\ pclean \in BOOLEAN 63 | /\ decisionRound \in BOOLEAN 64 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : Cardinality(valueSet(u)) = 1} -> SUBSET(BOOLEAN)] 65 | /\ someP \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 66 | 67 | \* initial predicate of the environment 68 | InitEnvironment == 69 | /\ phase = "msgs" \* current phase of the algorithm 70 | /\ decisionRound = FALSE \* predicate for the decision round 71 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] \* crash array 72 | /\ pclean = FALSE \* predicate for the clean round 73 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X Correct -> ((SUBSET(BOOLEAN)) \ {{}})] \* receivers array 74 | /\ someP = [l \in {k \in locOther : crash[k] # {TRUE}} |-> FALSE] 75 | 76 | \* initial predicate of the algorithm 77 | InitAlgorithm == 78 | /\ loc1 \in InitActive \* first fixed process 79 | /\ loc2 \in InitActive \* second fixed process 80 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of locations witnessing the other N - 2 processes 81 | /\ msgs = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> {{}}]] \* two-dimensional messages array 82 | 83 | \* environment transition in the message exchage phase 84 | MsgsEnvironment == 85 | /\ phase' = "trans" 86 | /\ pclean' = IF \A l \in DOMAIN crash : TRUE \notin crash[l] THEN TRUE ELSE pclean 87 | /\ decisionRound' \in IF pclean' THEN {TRUE, FALSE} ELSE {FALSE} 88 | /\ someP' \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 89 | /\ UNCHANGED <> 90 | 91 | \* environment transition in the state update phase 92 | TransEnvironment == 93 | /\ phase' = "msgs" 94 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 95 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} \X {u \in Correct' : Cardinality(valueSet(u)') = 1} -> (SUBSET(BOOLEAN) \ {{}})] 96 | /\ someP' = [l \in {l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}}' |-> FALSE] 97 | /\ UNCHANGED <> 98 | 99 | \* message generation function of a correct process 100 | SendMessage(u, v) == 101 | valueSet(u) 102 | 103 | \* update function of a correct process 104 | \* (that received the same messages as the abstract location that witnesses it) 105 | Update(l, u) == 106 | LET x == IF \/ /\ l.W = {0} 107 | /\ \E m \in {{1}, {0, 1}} : \E v \in IndexNonFailed : m \in msgs[v][u] 108 | \/ /\ l.W = {1} 109 | /\ \E m \in {{0}, {0, 1}} : \E v \in IndexNonFailed : m \in msgs[v][u] 110 | THEN {0, 1} 111 | ELSE l.W IN 112 | LET w == IF decisionRound 113 | THEN IF x = {0} 114 | THEN {0} 115 | ELSE IF x = {1} 116 | THEN {1} 117 | ELSE {v0} 118 | ELSE x IN 119 | LET h == IF decisionRound 120 | THEN TRUE 121 | ELSE FALSE IN 122 | [W |-> w, halt |-> h] 123 | 124 | \* update function of a correct process 125 | \* (that received messages different from the ones received by abstract location that witnesses it) 126 | UpdateOther(l, X) == 127 | LET w == IF decisionRound 128 | THEN IF l.W \cup X = {0} 129 | THEN {0} 130 | ELSE IF l.W \cup X = {1} 131 | THEN {1} 132 | ELSE {v0} 133 | ELSE l.W \cup X IN 134 | LET h == IF decisionRound 135 | THEN TRUE 136 | ELSE FALSE IN 137 | [W |-> w, halt |-> h] 138 | 139 | \* update of a process location witnessing correct processes 140 | UpdateCorrect(l, u) == 141 | IF Cardinality(l.W) = 1 /\ loc1.W = l.W /\ loc2.W = l.W 142 | THEN IF \A v \in IndexNonFailed : v \notin {u1, u2} /\ location(v).W # l.W => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 143 | THEN {UpdateOther(l, l.W)} 144 | ELSE IF someP[l] 145 | THEN {Update(l, u), UpdateOther(l, l.W)} 146 | ELSE {Update(l, u)} 147 | ELSE {Update(l, u)} 148 | 149 | \* delivery of messages by the environment 150 | EnvSemMsg(m, u, v) == 151 | IF u \in {u1, u2} 152 | THEN {m} 153 | ELSE LET l == location(u) IN 154 | IF crash[l] = {TRUE, FALSE} 155 | THEN IF Cardinality(valueSet(v)) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 156 | THEN IF receivers[l,v] = {TRUE} 157 | THEN {m} 158 | ELSE {{}, m} 159 | ELSE {{}} 160 | ELSE IF crash[l] = {TRUE} 161 | THEN IF Cardinality(valueSet(v)) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 162 | THEN IF receivers[l,v] = {TRUE} 163 | THEN {m} 164 | ELSE IF receivers[l,v] = {FALSE} 165 | THEN {{}} 166 | ELSE {{}, m} 167 | ELSE {{}} 168 | ELSE IF Cardinality(valueSet(v)) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 169 | THEN {m} 170 | ELSE {{}} 171 | 172 | \* state update of the fixed processes w.r.t. the environment 173 | EnvSemState(l, u) == 174 | IF l.halt 175 | THEN l 176 | ELSE Update(l, u) 177 | 178 | \* state update of the other processes w.r.t. the environment 179 | EnvSemStateOther(l) == 180 | IF l.halt 181 | THEN {l} 182 | ELSE IF crash[l] = {TRUE} 183 | THEN {failedLocation(l)} \* all processes witnessed by l crashed 184 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes witnessed by l crashed, and some not 185 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} 186 | ELSE UpdateCorrect(l, index(l)) \* no processes witnessed by l crashed 187 | 188 | \* algorithm transition in the message exchange phase 189 | MsgsAlgorithm == 190 | /\ msgs' = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> EnvSemMsg(SendMessage(u, v), u, v)]] 191 | /\ UNCHANGED <> 192 | 193 | \* algorithm transition in the state update phase 194 | TransAlgorithm == 195 | /\ loc1' = EnvSemState(loc1, u1) 196 | /\ loc2' = EnvSemState(loc2, u2) 197 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 198 | /\ msgs' = [u \in IndexNonFailed' |-> [v \in IndexNonFailed' |-> {{}}]] 199 | 200 | NextEnvironment == 201 | \/ phase = "msgs" /\ MsgsEnvironment 202 | \/ phase = "trans" /\ TransEnvironment 203 | 204 | NextAlgorithm == 205 | \/ phase = "msgs" /\ MsgsAlgorithm 206 | \/ phase = "trans" /\ TransAlgorithm 207 | 208 | Init == InitAlgorithm /\ InitEnvironment 209 | 210 | Next == NextAlgorithm /\ NextEnvironment 211 | 212 | \* constraints 213 | Fairness == 214 | /\ WF_vars(Next) 215 | /\ <>[](\A l \in DOMAIN crash : TRUE \notin crash[l]) 216 | /\ <>decisionRound 217 | 218 | \* specification 219 | Spec == Init /\ [][Next]_vars /\ Fairness 220 | 221 | \* safety properties 222 | Validity0 == ((\A l \in Active : l.W = {0}) => 223 | [](/\ loc1.halt => loc1.W = {0} 224 | /\ loc2.halt => loc2.W = {0})) 225 | Validity1 == ((\A l \in Active : l.W = {1}) => 226 | [](/\ loc1.halt => loc1.W = {1} 227 | /\ loc2.halt => loc2.W = {1})) 228 | \* Validity: if all processes start with the same value, then this is the only 229 | \* possible decision value 230 | Validity == Validity0 /\ Validity1 231 | 232 | \* Agreement: no two correct processes decide on a different value 233 | Agreement == [](loc1.halt /\ loc2.halt => loc1.W = loc2.W) 234 | 235 | \* liveness property 236 | \* Termination: all correct processes eventually decide 237 | Termination == <>(loc1.halt /\ loc2.halt) 238 | 239 | ============================================================================= 240 | \* Modification History 241 | \* Last modified Fri Oct 13 16:57:22 CEST 2017 by stoilkov 242 | \* Created Wed Jul 12 13:59:16 CEST 2017 by stoilkov 243 | -------------------------------------------------------------------------------- /floodset/floodset_abstract_m1.tla: -------------------------------------------------------------------------------- 1 | --------------------- MODULE floodset_abstract_m1 --------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, locOther, msgs, phase, crash, decisionRound, receivers, someP, pclean 6 | 7 | vars == <> 8 | 9 | v0 == 0 \* default decision value 10 | V == {0, 1} \* set of values 11 | I == 1 .. 6 \* indices of process locations 12 | U == 1 .. 7 \* message array indices (process locations + 2 concrete processes) 13 | u1 == 7 \* index for process 1 14 | Loc == [ W : {{0}, {1}, {0, 1}}, halt : BOOLEAN] \* possible process locations 15 | AM == {W \in SUBSET(SUBSET(V)) : W = {} \/ Cardinality(W) = 1 \/ (Cardinality(W) = 2 /\ {} \in W)} 16 | 17 | \* translate index i \in I to location l \in Loc 18 | location(i) == 19 | LET x == i - 1 IN 20 | LET w == IF x \div 2 = 0 THEN {0} ELSE IF x \div 2 = 1 THEN {1} ELSE {0, 1} IN 21 | LET h == IF x % 2 = 0 THEN FALSE ELSE TRUE IN 22 | [W |-> w, halt |-> h] 23 | 24 | \* translate location l \in Loc to index i \in I 25 | index(l) == 26 | LET f == IF l.halt = FALSE THEN 0 ELSE 1 IN 27 | LET w == IF l.W = {0} THEN 0 ELSE IF l.W = {1} THEN 1 ELSE 2 IN 28 | 2 * w + f + 1 29 | 30 | \* get value set, given index u \in U 31 | valueSet(u) == 32 | IF u = u1 33 | THEN loc1.W 34 | ELSE location(u).W 35 | 36 | \* Set of indices witnessing non-failed processes 37 | IndexNonFailed == {u1} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt}} 38 | \* Set of locations of active processes 39 | Active == {loc1} \cup locOther 40 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 41 | Correct == {u1} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt /\ crash[l1] # {TRUE}}} 42 | 43 | \* set failure flag of l to TRUE 44 | failedLocation(l) == 45 | [W |-> l.W, halt |-> TRUE] 46 | 47 | \* Set of initial locations 48 | InitActive == {[W |-> {0}, halt |-> FALSE], 49 | [W |-> {1}, halt |-> FALSE]} 50 | 51 | \* type invariant 52 | TypeOK == 53 | /\ loc1 \in Loc 54 | /\ locOther \in SUBSET(Loc) 55 | /\ msgs \in [IndexNonFailed -> [IndexNonFailed -> AM]] 56 | /\ phase \in {"msgs", "trans"} 57 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 58 | /\ pclean \in BOOLEAN 59 | /\ decisionRound \in BOOLEAN 60 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : Cardinality(valueSet(u)) = 1} -> SUBSET(BOOLEAN)] 61 | /\ someP \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 62 | 63 | \* initial predicate of the environment 64 | InitEnvironment == 65 | /\ phase = "msgs" \* current phase of the algorithm 66 | /\ decisionRound = FALSE \* is the current round the decision round, after a clean round has occurred 67 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] \* crash array 68 | /\ pclean = FALSE \* predicate for the clean round 69 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X Correct -> ((SUBSET(BOOLEAN)) \ {{}})] \* receivers array 70 | /\ someP = [l \in {k \in locOther : crash[k] # {TRUE}} |-> FALSE] 71 | 72 | \* initial predicate of the algorithm 73 | InitAlgorithm == 74 | /\ loc1 \in InitActive \* first fixed process 75 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of witnesses for the other N - 2 processes 76 | /\ msgs = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> {{}}]] \* two-dimensional messages array 77 | 78 | \* environment transition in the message exchage phase 79 | MsgsEnvironment == 80 | /\ phase' = "trans" 81 | /\ pclean' = IF \A l \in DOMAIN crash : TRUE \notin crash[l] THEN TRUE ELSE pclean 82 | /\ decisionRound' \in IF pclean' THEN {TRUE, FALSE} ELSE {FALSE} 83 | /\ someP' \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 84 | /\ UNCHANGED <> 85 | 86 | \* environment transition in the state update phase 87 | TransEnvironment == 88 | /\ phase' = "msgs" 89 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 90 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} \X {u \in Correct' : Cardinality(valueSet(u)') = 1} -> ((SUBSET(BOOLEAN)) \ {{}})] 91 | /\ someP' = [l \in {l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}}' |-> FALSE] 92 | /\ UNCHANGED <> 93 | 94 | \* message generation function of a correct process 95 | SendMessage(u, v) == 96 | valueSet(u) 97 | 98 | \* update function of a correct process 99 | \* (that received the same messages as the abstract location that witnesses it) 100 | Update(l, u) == 101 | LET x == IF \/ /\ l.W = {0} 102 | /\ \E m \in {{1}, {0, 1}} : \E v \in IndexNonFailed : m \in msgs[v][u] 103 | \/ /\ l.W = {1} 104 | /\ \E m \in {{0}, {0, 1}} : \E v \in IndexNonFailed : m \in msgs[v][u] 105 | THEN {0, 1} 106 | ELSE l.W IN 107 | LET w == IF decisionRound 108 | THEN IF x = {0} 109 | THEN {0} 110 | ELSE IF x = {1} 111 | THEN {1} 112 | ELSE {v0} 113 | ELSE x IN 114 | LET h == IF decisionRound 115 | THEN TRUE 116 | ELSE FALSE IN 117 | [W |-> w, halt |-> h] 118 | 119 | \* update function of a correct process 120 | \* (that received messages different from the ones received by abstract location that witnesses it) 121 | UpdateOther(l, X) == 122 | LET w == IF decisionRound 123 | THEN IF l.W \cup X = {0} 124 | THEN {0} 125 | ELSE IF l.W \cup X = {1} 126 | THEN {1} 127 | ELSE {v0} 128 | ELSE l.W \cup X IN 129 | LET h == IF decisionRound 130 | THEN TRUE 131 | ELSE FALSE IN 132 | [W |-> w, halt |-> h] 133 | 134 | \* update of a process location witnessing correct processes 135 | UpdateCorrect(l, u) == 136 | IF Cardinality(l.W) = 1 /\ loc1.W = l.W 137 | THEN IF \A v \in IndexNonFailed : v \notin {u1} /\ location(v).W # l.W => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 138 | THEN {UpdateOther(l, l.W)} 139 | ELSE IF someP[l] 140 | THEN {Update(l, u), UpdateOther(l, l.W)} 141 | ELSE {Update(l, u)} 142 | ELSE {Update(l, u)} 143 | 144 | \* delivery of messages by the environment 145 | EnvSemMsg(m, u, v) == 146 | IF u \in {u1} 147 | THEN {m} 148 | ELSE LET l == location(u) IN 149 | IF crash[l] = {TRUE, FALSE} 150 | THEN IF Cardinality(valueSet(v)) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 151 | THEN IF receivers[l,v] = {TRUE} 152 | THEN {m} 153 | ELSE {{}, m} 154 | ELSE {{}} 155 | ELSE IF crash[l] = {TRUE} 156 | THEN IF Cardinality(valueSet(v)) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 157 | THEN IF receivers[l,v] = {TRUE} 158 | THEN {m} 159 | ELSE IF receivers[l,v] = {FALSE} 160 | THEN {{}} 161 | ELSE {{}, m} 162 | ELSE {{}} 163 | ELSE IF Cardinality(valueSet(v)) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 164 | THEN {m} 165 | ELSE {{}} 166 | 167 | \* state update of the fixed processes w.r.t. the environment 168 | EnvSemState(l, u) == 169 | IF l.halt 170 | THEN l 171 | ELSE Update(l, u) 172 | 173 | \* state update of the other processes w.r.t. the environment 174 | EnvSemStateOther(l) == 175 | IF l.halt 176 | THEN {l} 177 | ELSE IF crash[l] = {TRUE} 178 | THEN {failedLocation(l)} \* all processes witnessed by l crashed 179 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes witnessed by l crashed, and some not 180 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} 181 | ELSE UpdateCorrect(l, index(l)) \* no processes witnessed by l crashed 182 | 183 | \* algorithm transition in the message exchange phase 184 | MsgsAlgorithm == 185 | /\ msgs' = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> EnvSemMsg(SendMessage(u, v), u, v)]] 186 | /\ UNCHANGED <> 187 | 188 | \* algorithm transition in the state update phase 189 | TransAlgorithm == 190 | /\ loc1' = EnvSemState(loc1, u1) 191 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 192 | /\ msgs' = [u \in IndexNonFailed' |-> [v \in IndexNonFailed' |-> {{}}]] 193 | 194 | NextEnvironment == 195 | \/ phase = "msgs" /\ MsgsEnvironment 196 | \/ phase = "trans" /\ TransEnvironment 197 | 198 | NextAlgorithm == 199 | \/ phase = "msgs" /\ MsgsAlgorithm 200 | \/ phase = "trans" /\ TransAlgorithm 201 | 202 | Init == InitAlgorithm /\ InitEnvironment 203 | 204 | Next == NextAlgorithm /\ NextEnvironment 205 | 206 | \* constraints 207 | Fairness == 208 | /\ WF_vars(Next) 209 | /\ <>[](\A l \in DOMAIN crash : TRUE \notin crash[l]) 210 | /\ <>decisionRound 211 | 212 | \* specification 213 | Spec == Init /\ [][Next]_vars /\ Fairness 214 | 215 | \* safety properties 216 | Validity0 == ((\A l \in Active : l.W = {0}) => 217 | [](loc1.halt => loc1.W = {0})) 218 | Validity1 == ((\A l \in Active : l.W = {1}) => 219 | [](loc1.halt => loc1.W = {1})) 220 | \* Validity: if all processes start with the same value, then this is the only 221 | \* possible decision value 222 | Validity == Validity0 /\ Validity1 223 | 224 | \* liveness property 225 | \* Termination: all correct processes eventually decide 226 | Termination == <>(loc1.halt) 227 | 228 | ============================================================================= 229 | \* Modification History 230 | \* Last modified Fri Oct 13 17:17:15 CEST 2017 by stoilkov 231 | \* Created Fri Sep 22 14:29:20 CEST 2017 by stoilkov 232 | -------------------------------------------------------------------------------- /nbac/nbac.tla: -------------------------------------------------------------------------------- 1 | -------------------------------- MODULE nbac -------------------------------- 2 | 3 | EXTENDS Naturals, FiniteSets 4 | 5 | CONSTANTS N, T, F 6 | 7 | VARIABLES state, msgs, round, phase, crash, receivers 8 | 9 | vars == <> 10 | 11 | P == 1..N 12 | O == 3..N 13 | unknown == 2 14 | v0 == 0 15 | V == {0, 1} 16 | C == [W : {{0}, {1}, {0, 1}}, decision : {0, 1, unknown}] 17 | InitC == [W : {{0}, {1}}, decision : {unknown}] 18 | 19 | InitEnvironment == 20 | /\ phase = "msgs_nbac" 21 | /\ round = 0 22 | /\ crash \in SUBSET(O) 23 | /\ Cardinality(crash) <= F 24 | /\ receivers \in [crash -> SUBSET(P)] 25 | 26 | InitAlgorithm == 27 | /\ state \in [P -> InitC] 28 | /\ msgs = [p \in P |-> [q \in P |-> {}]] 29 | 30 | EnvSemMsg(m, p, q) == 31 | IF \/ p \in crash /\ p \notin DOMAIN receivers 32 | \/ p \in crash /\ q \notin receivers[p] 33 | THEN {} 34 | ELSE m 35 | 36 | SendMessage(p) == 37 | state[p].W 38 | 39 | EnvSemStateNBAC(p) == 40 | IF p \in crash 41 | THEN state[p] 42 | ELSE IF \A q \in P : msgs[q][p] # {} /\ msgs[q][p] = {1} 43 | THEN [W |-> {1}, decision |-> unknown] 44 | ELSE [W |-> {0}, decision |-> unknown] 45 | 46 | Msgs(p) == 47 | IF p \in crash 48 | THEN {} 49 | ELSE UNION{m \in SUBSET(V) : \E q \in P : msgs[q][p] = m} 50 | 51 | Update(s, M) == 52 | LET w == s.W \cup M IN 53 | LET d == IF round = T + 1 54 | THEN IF w = {0} 55 | THEN 0 56 | ELSE IF w = {1} 57 | THEN 1 58 | ELSE v0 59 | ELSE unknown IN 60 | [W |-> w, decision |-> d] 61 | 62 | 63 | EnvSemStateConsensus(p, s1, s2) == 64 | IF p \in crash 65 | THEN s2 66 | ELSE s1 67 | 68 | MsgsEnvironment == 69 | IF round <= T 70 | THEN 71 | /\ \/ /\ phase = "msgs_nbac" 72 | /\ phase' = "trans_nbac" 73 | /\ UNCHANGED round 74 | \/ /\ phase = "msgs" 75 | /\ phase' = "trans" 76 | /\ round' = round + 1 77 | /\ UNCHANGED <> 78 | ELSE UNCHANGED vars 79 | 80 | TransEnvironment == 81 | /\ phase' = "msgs" 82 | /\ crash' \in SUBSET(O) 83 | /\ crash \subseteq crash' 84 | /\ Cardinality(crash') <= F 85 | /\ receivers' \in [crash' \ crash -> SUBSET(P)] 86 | /\ UNCHANGED round 87 | 88 | MsgsNBAC == 89 | /\ msgs' = [p \in P |-> [q \in P |-> EnvSemMsg(SendMessage(p), p, q)]] 90 | /\ UNCHANGED state 91 | 92 | TransNBAC == 93 | /\ state' = [p \in P |-> EnvSemStateNBAC(p)] 94 | /\ msgs' = [p \in P |-> [q \in P |-> {}]] 95 | 96 | MsgsConsensus == 97 | IF round <= T 98 | THEN 99 | /\ msgs' = [p \in P |-> [q \in P |-> EnvSemMsg(SendMessage(p), p, q)]] 100 | /\ UNCHANGED state 101 | ELSE UNCHANGED vars 102 | 103 | TransConsensus == 104 | /\ state' = [p \in P |-> EnvSemStateConsensus(p, Update(state[p], Msgs(p)), state[p])] 105 | /\ msgs' = [p \in P |-> [q \in P |-> {}]] 106 | 107 | NextEnvironment == 108 | \/ phase = "msgs_nbac" /\ MsgsEnvironment 109 | \/ phase = "trans_nbac" /\ TransEnvironment 110 | \/ phase = "msgs" /\ MsgsEnvironment 111 | \/ phase = "trans" /\ TransEnvironment 112 | 113 | NextAlgorithm == 114 | \/ phase = "msgs_nbac" /\ MsgsNBAC 115 | \/ phase = "trans_nbac" /\ TransNBAC 116 | \/ phase = "msgs" /\ MsgsConsensus 117 | \/ phase = "trans" /\ TransConsensus 118 | 119 | Init == InitAlgorithm /\ InitEnvironment 120 | Next == NextAlgorithm /\ NextEnvironment 121 | 122 | Fairness == WF_vars(Next) 123 | 124 | Spec == Init /\ [][Next]_vars /\ Fairness 125 | 126 | Agreement == 127 | [](\A p \in P : \A q \in P : p \notin crash /\ q \notin crash /\ state[p].decision # unknown /\ state[q].decision # unknown => 128 | state[p].decision = state[q].decision) 129 | 130 | Justification == 131 | ([](\A p \in P : state[p].decision # unknown => state[p].decision = 1)) 132 | => (\A p \in P : state[p].W = {1}) 133 | 134 | Obligation == 135 | (\A p \in P : state[p].W = {1}) /\ crash = {} => [](\A p \in P : state[p].decision # unknown => state[p].decision = 1) 136 | 137 | Termination == 138 | <>(\A p \in P : p \in crash \/ state[p].decision # unknown) 139 | 140 | 141 | 142 | ============================================================================= 143 | \* Modification History 144 | \* Last modified Fri Aug 18 17:40:56 CEST 2017 by ilina 145 | \* Created Thu Aug 17 19:43:16 CEST 2017 by ilina 146 | -------------------------------------------------------------------------------- /nbac/nbac_abstract.tla: -------------------------------------------------------------------------------- 1 | ------------------------- MODULE nbac_abstract ------------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, loc2, locOther, msgs, phase, crash, pclean, decisionRound, receivers, someP 6 | 7 | vars == <> 8 | 9 | v0 == 0 \* default decision value 10 | V == {0, 1} \* set of values 11 | I == 1 .. 6 \* indices corresponding to process locations 12 | U == 1 .. 8 \* array indices (process locations + 2 concrete processes) 13 | u1 == 7 \* index for process 1 14 | u2 == 8 \* index for process 2 15 | Loc == [ W : {{0}, {1}, {0, 1}}, halt : BOOLEAN] \* possible process locations 16 | AM == {W \in SUBSET(SUBSET(V)) : W = {} \/ Cardinality(W) = 1 \/ (Cardinality(W) = 2 /\ {} \in W)} \* abstract message alphabet 17 | 18 | \* translate index i \in I to location l \in Loc 19 | location(i) == 20 | LET x == i - 1 IN 21 | LET w == IF x \div 2 = 0 THEN {0} ELSE IF x \div 2 = 1 THEN {1} ELSE {0, 1} IN 22 | LET h == IF x % 2 = 0 THEN FALSE ELSE TRUE IN 23 | [W |-> w, halt |-> h] 24 | 25 | \* translate location l \in Loc to index i \in I 26 | index(l) == 27 | LET f == IF l.halt = FALSE THEN 0 ELSE 1 IN 28 | LET w == IF l.W = {0} THEN 0 ELSE IF l.W = {1} THEN 1 ELSE 2 IN 29 | 2 * w + f + 1 30 | 31 | \* get value set, given index u \in U 32 | valueSet(u) == 33 | IF u = u1 34 | THEN loc1.W 35 | ELSE IF u = u2 36 | THEN loc2.W 37 | ELSE location(u).W 38 | 39 | \* Set of indices witnessing non-failed processes 40 | IndexNonFailed == {u1, u2} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt}} 41 | \* Set of locations of active processes 42 | Active == {loc1, loc2} \cup locOther 43 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 44 | Correct == {u1, u2} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt /\ crash[l1] # {TRUE}}} 45 | 46 | \* set failure flag of l to TRUE 47 | failedLocation(l) == 48 | [W |-> l.W, halt |-> TRUE] 49 | 50 | \* Set of initial locations 51 | InitActive == {[W |-> {0}, halt |-> FALSE], 52 | [W |-> {1}, halt |-> FALSE]} 53 | 54 | \* type invariant 55 | TypeOK == 56 | /\ loc1 \in Loc 57 | /\ loc2 \in Loc 58 | /\ locOther \in SUBSET(Loc) 59 | /\ msgs \in [IndexNonFailed -> [IndexNonFailed -> AM]] 60 | /\ phase \in {"msgs", "trans"} 61 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 62 | /\ pclean \in BOOLEAN 63 | /\ decisionRound \in BOOLEAN 64 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : Cardinality(valueSet(u)) = 1} -> SUBSET(BOOLEAN)] 65 | /\ someP \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 66 | 67 | \* initial predicate of the environment 68 | InitEnvironment == 69 | /\ phase = "msgs_nbac" \* current phase of the algorithm 70 | /\ decisionRound = FALSE \* is the current round the decision round, after a clean round has occurred 71 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] 72 | /\ pclean = FALSE 73 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X Correct -> ((SUBSET(BOOLEAN)) \ {{}})] 74 | /\ someP = [l \in locOther |-> FALSE] 75 | 76 | \* initial predicate of the algorithm 77 | InitAlgorithm == 78 | /\ loc1 \in InitActive \* first fixed process 79 | /\ loc2 \in InitActive \* second fixed process 80 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of locations witnessing the other N - 2 processes 81 | /\ msgs = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> {{}}]] \* two-dimensional messages array 82 | 83 | \* environment transition in the message exchage phase 84 | MsgsEnvironment == 85 | \/ /\ phase = "msgs_nbac" 86 | /\ phase' = "trans_nbac" 87 | /\ UNCHANGED <> 88 | \/ /\ phase = "msgs" 89 | /\ phase' = "trans" 90 | /\ pclean' = IF \A l \in DOMAIN crash : TRUE \notin crash[l] THEN TRUE ELSE pclean 91 | /\ decisionRound' \in IF pclean' THEN {TRUE, FALSE} ELSE {FALSE} 92 | /\ someP' \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1} -> BOOLEAN] 93 | /\ UNCHANGED <> 94 | 95 | \* environment transition in the state update phase 96 | TransEnvironment == 97 | /\ phase' = "msgs" 98 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 99 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} 100 | \times {u \in Correct' : Cardinality(valueSet(u)') = 1} 101 | -> (SUBSET(BOOLEAN) \ {{}})] 102 | /\ someP' = [l \in {l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}}' |-> FALSE] 103 | /\ UNCHANGED <> 104 | 105 | \* message generation function of a correct process 106 | SendMessage(u, v) == 107 | valueSet(u) 108 | 109 | \* update function of a correct process 110 | \* (that received the same messages as the abstract location that witnesses it) 111 | Update(l, u) == 112 | LET x == IF \/ /\ l.W = {0} 113 | /\ \E m \in {{1}, {0, 1}} : \E v \in IndexNonFailed : m \in msgs[v][u] 114 | \/ /\ l.W = {1} 115 | /\ \E m \in {{0}, {0, 1}} : \E v \in IndexNonFailed : m \in msgs[v][u] 116 | THEN {0, 1} 117 | ELSE l.W IN 118 | LET w == IF decisionRound 119 | THEN IF x = {0} 120 | THEN {0} 121 | ELSE IF x = {1} 122 | THEN {1} 123 | ELSE {v0} 124 | ELSE x IN 125 | LET h == IF decisionRound 126 | THEN TRUE 127 | ELSE FALSE IN 128 | [W |-> w, halt |-> h] 129 | 130 | \* update function of a correct process 131 | \* (that received messages different from the ones received by abstract location that witnesses it) 132 | UpdateOther(l, X) == 133 | LET w == IF decisionRound 134 | THEN IF l.W \cup X = {0} 135 | THEN {0} 136 | ELSE IF l.W \cup X = {1} 137 | THEN {1} 138 | ELSE {v0} 139 | ELSE l.W \cup X IN 140 | LET h == IF decisionRound 141 | THEN TRUE 142 | ELSE FALSE IN 143 | [W |-> w, halt |-> h] 144 | 145 | \* update of a process location witnessing correct processes 146 | UpdateCorrect(l, u) == 147 | IF Cardinality(l.W) = 1 /\ loc1.W = l.W /\ loc2.W = l.W 148 | THEN IF \A v \in IndexNonFailed : v \notin {u1, u2} /\ location(v).W # l.W => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 149 | THEN {UpdateOther(l, l.W)} 150 | ELSE IF someP[l] 151 | THEN {Update(l, u), UpdateOther(l, l.W)} 152 | ELSE {Update(l, u)} 153 | ELSE {Update(l, u)} 154 | 155 | \* delivery of messages by the environment 156 | EnvSemMsg(m, u, v) == 157 | IF u \in {u1, u2} 158 | THEN {m} 159 | ELSE LET l == location(u) IN 160 | IF crash[l] = {TRUE, FALSE} 161 | THEN IF Cardinality(valueSet(v)) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 162 | THEN IF receivers[l,v] = {TRUE} 163 | THEN {m} 164 | ELSE {{}, m} 165 | ELSE {{}} 166 | ELSE IF crash[l] = {TRUE} 167 | THEN IF Cardinality(valueSet(v)) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 168 | THEN IF receivers[l,v] = {TRUE} 169 | THEN {m} 170 | ELSE IF receivers[l,v] = {FALSE} 171 | THEN {{}} 172 | ELSE {{}, m} 173 | ELSE {{}} 174 | ELSE IF Cardinality(valueSet(v)) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 175 | THEN {m} 176 | ELSE {{}} 177 | 178 | \* state update of the fixed processes w.r.t. the environment 179 | EnvSemState(l, u) == 180 | IF l.halt 181 | THEN l 182 | ELSE Update(l, u) 183 | 184 | \* state update of the other processes w.r.t. the environment 185 | EnvSemStateOther(l) == 186 | IF l.halt 187 | THEN {l} 188 | ELSE IF crash[l] = {TRUE} 189 | THEN {failedLocation(l)} \* all processes witnessed by l crashed 190 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes witnessed by l crashed, and some not 191 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} 192 | ELSE UpdateCorrect(l, index(l)) \* no processes witnessed by l crashed 193 | 194 | \* state update in the first round 195 | UpdateNBAC(l, u) == 196 | IF \A v \in IndexNonFailed : {} \notin msgs[v][u] /\ msgs[v][u] = {{1}} 197 | THEN [W |-> {1}, halt |-> FALSE] 198 | ELSE [W |-> {0}, halt |-> FALSE] 199 | 200 | \* state update in the first round w.r.t. the environment 201 | EnvSemStateNBAC(l, u) == 202 | IF crash[l] = {TRUE} 203 | THEN {failedLocation(l)} 204 | ELSE IF crash[l] = {TRUE, FALSE} 205 | THEN {Update(l, u), failedLocation(l)} 206 | ELSE {Update(l, u)} 207 | 208 | \* message exchage phase in the first round 209 | MsgsNBAC == 210 | /\ msgs' = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> EnvSemMsg(SendMessage(u, v), u, v)]] 211 | /\ UNCHANGED <> 212 | 213 | \* state transition phase in the first round 214 | TransNBAC == 215 | /\ loc1' = UpdateNBAC(loc1, u1) 216 | /\ loc2' = UpdateNBAC(loc2, u2) 217 | /\ locOther' = UNION{EnvSemStateNBAC(l, index(l)) : l \in locOther} 218 | /\ msgs' = [u \in IndexNonFailed' |-> [v \in IndexNonFailed' |-> {{}}]] 219 | 220 | \* message exchange phase in the remaining rounds 221 | MsgsConsensus == 222 | /\ msgs' = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> EnvSemMsg(SendMessage(u, v), u, v)]] 223 | /\ UNCHANGED <> 224 | 225 | \* state transition phase in the remaining rounds 226 | TransConsensus == 227 | /\ loc1' = EnvSemState(loc1, u1) 228 | /\ loc2' = EnvSemState(loc2, u2) 229 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 230 | /\ msgs' = [u \in IndexNonFailed' |-> [v \in IndexNonFailed' |-> {{}}]] 231 | 232 | NextEnvironment == 233 | \/ phase = "msgs_nbac" /\ MsgsEnvironment 234 | \/ phase = "trans_nbac" /\ TransEnvironment 235 | \/ phase = "msgs" /\ MsgsEnvironment 236 | \/ phase = "trans" /\ TransEnvironment 237 | 238 | NextAlgorithm == 239 | \/ phase = "msgs_nbac" /\ MsgsNBAC 240 | \/ phase = "trans_nbac" /\ TransNBAC 241 | \/ phase = "msgs" /\ MsgsConsensus 242 | \/ phase = "trans" /\ TransConsensus 243 | 244 | Init == InitAlgorithm /\ InitEnvironment 245 | 246 | Next == NextAlgorithm /\ NextEnvironment 247 | 248 | \* constraints 249 | Fairness == 250 | /\ WF_vars(Next) 251 | /\ <>[](\A l \in DOMAIN crash : TRUE \notin crash[l]) 252 | /\ <>decisionRound 253 | 254 | \* specification 255 | Spec == Init /\ [][Next]_vars /\ Fairness 256 | 257 | \* safety properties 258 | \* Justification: If a process decides commit, then all processes have proposed commit 259 | Justification == ([](/\ loc1.halt => loc1.W = {1} 260 | /\ loc2.halt => loc2.W = {1})) => (\A l \in Active : l.W = {1}) 261 | 262 | \* Obligation: If all processes have proposed commit and no process has crashed, then abort cannot be decided 263 | Obligation == ((\A l \in Active : l.W = {1}) /\ (\A k \in locOther : k \in DOMAIN crash /\ TRUE \notin crash[k])) => 264 | [](/\ loc1.halt => loc1.W # {0} 265 | /\ loc2.halt => loc2.W # {0}) 266 | 267 | \* Agreement: No two correct processes decide on a different value 268 | Agreement == [](loc1.halt /\ loc2.halt => loc1.W = loc2.W) 269 | 270 | \* liveness property 271 | \* Termination: All correct processes eventually decide 272 | Termination == <>(loc1.halt /\ loc2.halt) 273 | 274 | 275 | 276 | ============================================================================= 277 | \* Modification History 278 | \* Last modified Tue Oct 17 13:38:18 CEST 2017 by stoilkov 279 | \* Created Fri Aug 18 17:51:01 CEST 2017 by stoilkov 280 | -------------------------------------------------------------------------------- /nbac/nbac_abstract_m1.tla: -------------------------------------------------------------------------------- 1 | ----------------------- MODULE nbac_abstract_m1 ----------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, locOther, msgs, phase, crash, pclean, decisionRound, receivers, someP 6 | 7 | vars == <> 8 | 9 | v0 == 0 \* default decision value 10 | V == {0, 1} \* set of values 11 | I == 1 .. 6 \* indices corresponding to process locations 12 | U == 1 .. 7 \* array indices (process locations + 2 concrete processes) 13 | u1 == 7 \* index for process 1 14 | Loc == [ W : {{0}, {1}, {0, 1}}, halt : BOOLEAN] \* possible process locations 15 | AM == {W \in SUBSET(SUBSET(V)) : W = {} \/ Cardinality(W) = 1 \/ (Cardinality(W) = 2 /\ {} \in W)} \* abstract message alphabet 16 | 17 | \* translate index i \in I to location l \in Loc 18 | location(i) == 19 | LET x == i - 1 IN 20 | LET w == IF x \div 2 = 0 THEN {0} ELSE IF x \div 2 = 1 THEN {1} ELSE {0, 1} IN 21 | LET h == IF x % 2 = 0 THEN FALSE ELSE TRUE IN 22 | [W |-> w, halt |-> h] 23 | 24 | \* translate location l \in Loc to index i \in I 25 | index(l) == 26 | LET f == IF l.halt = FALSE THEN 0 ELSE 1 IN 27 | LET w == IF l.W = {0} THEN 0 ELSE IF l.W = {1} THEN 1 ELSE 2 IN 28 | 2 * w + f + 1 29 | 30 | \* get value set, given index u \in U 31 | valueSet(u) == 32 | IF u = u1 33 | THEN loc1.W 34 | ELSE location(u).W 35 | 36 | \* Set of indices witnessing non-failed processes 37 | IndexNonFailed == {u1} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt}} 38 | \* Set of locations of active processes 39 | Active == {loc1} \cup locOther 40 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 41 | Correct == {u1} \cup {index(l) : l \in {l1 \in locOther : ~l1.halt /\ crash[l1] # {TRUE}}} 42 | 43 | \* set failure flag of l to TRUE 44 | failedLocation(l) == 45 | [W |-> l.W, halt |-> TRUE] 46 | 47 | \* Set of initial locations 48 | InitActive == {[W |-> {0}, halt |-> FALSE], 49 | [W |-> {1}, halt |-> FALSE]} 50 | 51 | \* type invariant 52 | TypeOK == 53 | /\ loc1 \in Loc 54 | /\ locOther \in SUBSET(Loc) 55 | /\ msgs \in [IndexNonFailed -> [IndexNonFailed -> AM]] 56 | /\ phase \in {"msgs", "trans"} 57 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 58 | /\ pclean \in BOOLEAN 59 | /\ decisionRound \in BOOLEAN 60 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : Cardinality(valueSet(u)) = 1} -> SUBSET(BOOLEAN)] 61 | /\ someP \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 62 | 63 | \* initial predicate of the environment 64 | InitEnvironment == 65 | /\ phase = "msgs_nbac" \* current phase of the algorithm 66 | /\ decisionRound = FALSE \* is the current round the decision round, after a clean round has occurred 67 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] 68 | /\ pclean = FALSE 69 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X Correct -> ((SUBSET(BOOLEAN)) \ {{}})] 70 | /\ someP = [l \in locOther |-> FALSE] 71 | 72 | \* initial predicate of the algorithm 73 | InitAlgorithm == 74 | /\ loc1 \in InitActive \* first fixed process 75 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of locations witnessing the other N - 2 processes 76 | /\ msgs = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> {{}}]] \* two-dimensional messages array 77 | 78 | \* environment transition in the message exchage phase 79 | MsgsEnvironment == 80 | \/ /\ phase = "msgs_nbac" 81 | /\ phase' = "trans_nbac" 82 | /\ UNCHANGED <> 83 | \/ /\ phase = "msgs" 84 | /\ phase' = "trans" 85 | /\ pclean' = IF \A l \in DOMAIN crash : TRUE \notin crash[l] THEN TRUE ELSE pclean 86 | /\ decisionRound' \in IF pclean' THEN {TRUE, FALSE} ELSE {FALSE} 87 | /\ someP' \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1} -> BOOLEAN] 88 | /\ UNCHANGED <> 89 | 90 | \* environment transition in the state update phase 91 | TransEnvironment == 92 | /\ phase' = "msgs" 93 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 94 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} 95 | \times {u \in Correct' : Cardinality(valueSet(u)') = 1} 96 | -> (SUBSET(BOOLEAN) \ {{}})] 97 | /\ someP' = [l \in {l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}}' |-> FALSE] 98 | /\ UNCHANGED <> 99 | 100 | \* message generation function of a correct process 101 | SendMessage(u, v) == 102 | valueSet(u) 103 | 104 | \* update function of a correct process 105 | \* (that received the same messages as the abstract location that witnesses it) 106 | Update(l, u) == 107 | LET x == IF \/ /\ l.W = {0} 108 | /\ \E m \in {{1}, {0, 1}} : \E v \in IndexNonFailed : m \in msgs[v][u] 109 | \/ /\ l.W = {1} 110 | /\ \E m \in {{0}, {0, 1}} : \E v \in IndexNonFailed : m \in msgs[v][u] 111 | THEN {0, 1} 112 | ELSE l.W IN 113 | LET w == IF decisionRound 114 | THEN IF x = {0} 115 | THEN {0} 116 | ELSE IF x = {1} 117 | THEN {1} 118 | ELSE {v0} 119 | ELSE x IN 120 | LET h == IF decisionRound 121 | THEN TRUE 122 | ELSE FALSE IN 123 | [W |-> w, halt |-> h] 124 | 125 | \* update function of a correct process 126 | \* (that received messages different from the ones received by abstract location that witnesses it) 127 | UpdateOther(l, X) == 128 | LET w == IF decisionRound 129 | THEN IF l.W \cup X = {0} 130 | THEN {0} 131 | ELSE IF l.W \cup X = {1} 132 | THEN {1} 133 | ELSE {v0} 134 | ELSE l.W \cup X IN 135 | LET h == IF decisionRound 136 | THEN TRUE 137 | ELSE FALSE IN 138 | [W |-> w, halt |-> h] 139 | 140 | \* update of a process location witnessing correct processes 141 | UpdateCorrect(l, u) == 142 | IF Cardinality(l.W) = 1 /\ loc1.W = l.W 143 | THEN IF \A v \in IndexNonFailed : v \notin {u1} /\ location(v).W # l.W => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 144 | THEN {UpdateOther(l, l.W)} 145 | ELSE IF someP[l] 146 | THEN {Update(l, u), UpdateOther(l, l.W)} 147 | ELSE {Update(l, u)} 148 | ELSE {Update(l, u)} 149 | 150 | \* delivery of messages by the environment 151 | EnvSemMsg(m, u, v) == 152 | IF u \in {u1} 153 | THEN {m} 154 | ELSE LET l == location(u) IN 155 | IF crash[l] = {TRUE, FALSE} 156 | THEN IF Cardinality(valueSet(v)) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 157 | THEN IF receivers[l,v] = {TRUE} 158 | THEN {m} 159 | ELSE {{}, m} 160 | ELSE {{}} 161 | ELSE IF crash[l] = {TRUE} 162 | THEN IF Cardinality(valueSet(v)) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 163 | THEN IF receivers[l,v] = {TRUE} 164 | THEN {m} 165 | ELSE IF receivers[l,v] = {FALSE} 166 | THEN {{}} 167 | ELSE {{}, m} 168 | ELSE {{}} 169 | ELSE IF Cardinality(valueSet(v)) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 170 | THEN {m} 171 | ELSE {{}} 172 | 173 | \* state update of the fixed processes w.r.t. the environment 174 | EnvSemState(l, u) == 175 | IF l.halt 176 | THEN l 177 | ELSE Update(l, u) 178 | 179 | \* state update of the other processes w.r.t. the environment 180 | EnvSemStateOther(l) == 181 | IF l.halt 182 | THEN {l} 183 | ELSE IF crash[l] = {TRUE} 184 | THEN {failedLocation(l)} \* all processes witnessed by l crashed 185 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes witnessed by l crashed, and some not 186 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} 187 | ELSE UpdateCorrect(l, index(l)) \* no processes witnessed by l crashed 188 | 189 | \* state update in the first round 190 | UpdateNBAC(l, u) == 191 | IF \A v \in IndexNonFailed : {} \notin msgs[v][u] /\ msgs[v][u] = {{1}} 192 | THEN [W |-> {1}, halt |-> FALSE] 193 | ELSE [W |-> {0}, halt |-> FALSE] 194 | 195 | \* state update in the first round w.r.t. the environment 196 | EnvSemStateNBAC(l, u) == 197 | IF crash[l] = {TRUE} 198 | THEN {failedLocation(l)} 199 | ELSE IF crash[l] = {TRUE, FALSE} 200 | THEN {Update(l, u), failedLocation(l)} 201 | ELSE {Update(l, u)} 202 | 203 | \* message exchage phase in the first round 204 | MsgsNBAC == 205 | /\ msgs' = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> EnvSemMsg(SendMessage(u, v), u, v)]] 206 | /\ UNCHANGED <> 207 | 208 | \* state transition phase in the first round 209 | TransNBAC == 210 | /\ loc1' = UpdateNBAC(loc1, u1) 211 | /\ locOther' = UNION{EnvSemStateNBAC(l, index(l)) : l \in locOther} 212 | /\ msgs' = [u \in IndexNonFailed' |-> [v \in IndexNonFailed' |-> {{}}]] 213 | 214 | \* message exchange phase in the remaining rounds 215 | MsgsConsensus == 216 | /\ msgs' = [u \in IndexNonFailed |-> [v \in IndexNonFailed |-> EnvSemMsg(SendMessage(u, v), u, v)]] 217 | /\ UNCHANGED <> 218 | 219 | \* state transition phase in the remaining rounds 220 | TransConsensus == 221 | /\ loc1' = EnvSemState(loc1, u1) 222 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 223 | /\ msgs' = [u \in IndexNonFailed' |-> [v \in IndexNonFailed' |-> {{}}]] 224 | 225 | NextEnvironment == 226 | \/ phase = "msgs_nbac" /\ MsgsEnvironment 227 | \/ phase = "trans_nbac" /\ TransEnvironment 228 | \/ phase = "msgs" /\ MsgsEnvironment 229 | \/ phase = "trans" /\ TransEnvironment 230 | 231 | NextAlgorithm == 232 | \/ phase = "msgs_nbac" /\ MsgsNBAC 233 | \/ phase = "trans_nbac" /\ TransNBAC 234 | \/ phase = "msgs" /\ MsgsConsensus 235 | \/ phase = "trans" /\ TransConsensus 236 | 237 | Init == InitAlgorithm /\ InitEnvironment 238 | 239 | Next == NextAlgorithm /\ NextEnvironment 240 | 241 | \* constraints 242 | Fairness == 243 | /\ WF_vars(Next) 244 | /\ <>[](\A l \in DOMAIN crash : TRUE \notin crash[l]) 245 | /\ <>decisionRound 246 | 247 | \* specification 248 | Spec == Init /\ [][Next]_vars /\ Fairness 249 | 250 | \* safety properties 251 | \* Justification: If a process decides commit, then all processes have proposed commit 252 | Justification == ([](loc1.halt => loc1.W = {1})) => (\A l \in Active : l.W = {1}) 253 | 254 | \* Obligation: If all processes have proposed commit and no process has crashed, then abort cannot be decided 255 | Obligation == ((\A l \in Active : l.W = {1}) /\ (\A k \in locOther : k \in DOMAIN crash /\ TRUE \notin crash[k])) => 256 | [](loc1.halt => loc1.W # {0}) 257 | 258 | \* liveness property 259 | \* Termination: All correct processes eventually decide 260 | Termination == <>(loc1.halt) 261 | 262 | ============================================================================= 263 | \* Modification History 264 | \* Last modified Tue Oct 17 13:42:32 CEST 2017 by stoilkov 265 | \* Created Thu Sep 28 17:41:07 CEST 2017 by stoilkov 266 | -------------------------------------------------------------------------------- /pdif/pdif.tla: -------------------------------------------------------------------------------- 1 | -------------------------------- MODULE pdif -------------------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | CONSTANTS N, T, F 6 | 7 | VARIABLES state, msgs, nb, round, phase, 8 | crash, failed, receivers 9 | 10 | vars == <> 11 | 12 | P == 1 .. N \* set of processes 13 | unknown == 2 14 | V == {0, 1} 15 | Messages == BOOLEAN \times V 16 | 17 | C == [ est : V, halt : BOOLEAN, early : BOOLEAN ] 18 | InitC == [ est : V, halt : {FALSE}, early : {FALSE} ] 19 | 20 | InitEnvironment == 21 | /\ phase = "msgs" 22 | /\ round = 0 23 | /\ crash \in SUBSET(P) 24 | /\ failed = {} 25 | /\ Cardinality(failed \cup crash) <= F 26 | /\ receivers \in [crash -> SUBSET(P)] 27 | 28 | InitAlgorithm == 29 | /\ state \in [P -> InitC] 30 | /\ msgs = [p \in P |-> [q \in P |-> <<>>]] \* two-dimensional messages array 31 | /\ nb = [p \in P |-> N] 32 | 33 | Rcv(p) == {q \in P : msgs[q][p] # <<>>} 34 | 35 | SendMessage(p, q) == 36 | <> 37 | 38 | EnvSemMsg(m, p, q) == 39 | IF \/ p \in failed 40 | \/ state[p].halt 41 | \/ (p \in crash /\ q \notin receivers[p]) 42 | THEN <<>> 43 | ELSE m 44 | 45 | EnvSemState(p, s1, s2) == 46 | IF p \in failed \/ p \in crash \/ s2.halt 47 | THEN s2 48 | ELSE s1 49 | 50 | Update(p) == 51 | LET decide == \E m \in V : \E q \in P : msgs[q][p] = <> IN 52 | LET e == IF state[p].est = 1 /\ \E d \in BOOLEAN : \E q \in P : msgs[q][p] = <> 53 | THEN 0 54 | ELSE state[p].est IN 55 | LET h == IF state[p].early \/ round >= T + 1 56 | THEN TRUE 57 | ELSE FALSE IN 58 | LET d == IF decide \/ nb[p] = Cardinality(Rcv(p)) 59 | THEN TRUE 60 | ELSE FALSE IN 61 | [est |-> e, halt |-> h, early |-> d] 62 | 63 | MsgsEnvironment == 64 | IF round > T 65 | THEN UNCHANGED vars 66 | ELSE 67 | /\ phase' = "trans" 68 | /\ round' = round+1 69 | /\ UNCHANGED <> 70 | 71 | TransEnvironment == 72 | /\ phase' = "msgs" 73 | /\ failed' = failed \cup crash 74 | /\ crash' \in SUBSET(P \ failed') 75 | /\ Cardinality(failed' \cup crash') <= F 76 | /\ receivers' \in [crash' -> SUBSET(P)] 77 | /\ UNCHANGED round 78 | 79 | MsgsAlgorithm == 80 | IF round > T 81 | THEN UNCHANGED vars 82 | ELSE 83 | /\ msgs' = [p \in P |-> [q \in P |-> EnvSemMsg(SendMessage(p, q), p, q)]] 84 | /\ UNCHANGED <> 85 | 86 | TransAlgorithm == 87 | /\ state' = [p \in P |-> EnvSemState(p, Update(p), state[p])] 88 | /\ nb' = [p \in P |-> IF ~state[p].halt THEN Cardinality(Rcv(p)) ELSE nb[p]] 89 | /\ msgs' = [p \in P |-> [q \in P |-> <<>>]] 90 | 91 | 92 | \* next state action predicates 93 | NextEnvironment == 94 | \/ phase = "msgs" /\ MsgsEnvironment 95 | \/ phase = "trans" /\ TransEnvironment 96 | 97 | NextAlgorithm == 98 | \/ phase = "msgs" /\ MsgsAlgorithm 99 | \/ phase = "trans" /\ TransAlgorithm 100 | 101 | Init == InitAlgorithm /\ InitEnvironment 102 | Next == NextAlgorithm /\ NextEnvironment 103 | 104 | \* fairness constraint 105 | Fairness == WF_vars(Next) 106 | 107 | \* specification 108 | Spec == Init /\ [][Next]_vars /\ Fairness 109 | 110 | \* safety properties 111 | Validity == \A v \in V : (\A p \in P : state[p].est = v) => [](\A q \in P : (q \notin failed /\ state[q].halt) => state[q].est = v) 112 | Agreement == [](\A p \in P : \A q \in P : (state[p].halt /\ state[q].halt => 113 | state[p].est = state[q].est)) 114 | 115 | \* liveness property 116 | Termination == <>(\A p \in P : p \in failed \/ state[p].halt) 117 | 118 | 119 | ============================================================================= 120 | \* Modification History 121 | \* Last modified Thu Sep 28 19:24:55 CEST 2017 by stoilkov 122 | \* Created Thu Sep 28 18:58:45 CEST 2017 by stoilkov 123 | -------------------------------------------------------------------------------- /pdif/pdif_abstract.tla: -------------------------------------------------------------------------------- 1 | ------------------------- MODULE pdif_abstract ------------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, loc2, locOther, msgs, previous, phase, crash, decisionRound, receivers, someP, pclean, globalDecisionRound 6 | 7 | vars == <> 8 | 9 | v0 == 0 \* default decision value 10 | V == {0, 1} \* set of values 11 | I == 1 .. 8 \* indices corresponding to process locations 12 | U == 1 .. 10 \* message array indices (process locations + 2 concrete processes) 13 | u1 == 9 \* index for process 1 14 | u2 == 10 \* index for process 2 15 | Loc == [est : V, halt : BOOLEAN, early : BOOLEAN] \* possible process locations 16 | CM == {<> : v \in V, d \in BOOLEAN} \* concrete message alphabet 17 | AM == {W \in SUBSET(CM) : W = {} \/ Cardinality(W) = 1 \/ (Cardinality(W) = 2 /\ <<>> \in W)} \* abstract message alphabet 18 | 19 | \* translate index i \in I to location l \in Loc 20 | location(i) == 21 | LET x == i - 1 IN 22 | LET e == IF x \div 4 = 0 THEN 0 ELSE 1 IN 23 | LET y == x % 4 IN 24 | LET h == IF y \div 2 = 0 THEN FALSE ELSE TRUE IN 25 | LET d == IF y % 2 = 0 THEN FALSE ELSE TRUE IN 26 | [est |-> e, halt |-> h, early |-> d] 27 | 28 | \* translate location l \in Loc to index i \in I 29 | index(l) == 30 | LET d == IF l.early = FALSE THEN 0 ELSE 1 IN 31 | LET h == IF l.halt = FALSE THEN 0 ELSE 1 IN 32 | LET e == IF l.est = 0 THEN 0 ELSE 1 IN 33 | 4 * e + 2 * h + d + 1 34 | 35 | \* get value, given index u \in U 36 | estValue(u) == 37 | IF u = u1 38 | THEN loc1.est 39 | ELSE IF u = u2 40 | THEN loc2.est 41 | ELSE location(u).est 42 | \* get early flag, given index u \in U 43 | early(u) == 44 | IF u = u1 45 | THEN loc1.early 46 | ELSE IF u = u2 47 | THEN loc2.early 48 | ELSE location(u).early 49 | \* get halted flag, given index u \in U 50 | halted(u) == 51 | IF u = u1 52 | THEN loc1.halt 53 | ELSE IF u = u2 54 | THEN loc2.halt 55 | ELSE location(u).halt 56 | 57 | \* Set of locations of active processes 58 | Active == {loc1, loc2} \cup locOther 59 | \* Set of indices of active processes 60 | IndexActive == {u1, u2} \cup {index(l) : l \in locOther} 61 | \* Set of indices witnessing non-halted processes 62 | IndexNonHalted == {u \in IndexActive : ~halted(u)} 63 | \* Set of indices witnessing undecided processes 64 | IndexUndecided == {u \in IndexActive : ~halted(u) /\ ~early(u)} 65 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 66 | Correct == {u \in IndexActive : ~halted(u) /\ ~early(u) /\ (u \in {u1, u2} \/ crash[location(u)] # {TRUE})} 67 | 68 | \* set failure flag of l to TRUE 69 | failedLocation(l) == 70 | [est |-> l.est, halt |-> TRUE, early |-> l.early] 71 | 72 | \* a process in a decided location stops participating in the algorithm 73 | decidedLocation(l) == 74 | [est |-> l.est, halt |-> TRUE, early |-> TRUE] 75 | 76 | \* Set of initial locations 77 | InitActive == {[est |-> 0, halt |-> FALSE, early |-> FALSE], 78 | [est |-> 1, halt |-> FALSE, early |-> FALSE]} 79 | 80 | \* type invariant 81 | TypeOK == 82 | /\ loc1 \in Loc 83 | /\ loc2 \in Loc 84 | /\ locOther \in SUBSET(Loc) 85 | /\ msgs \in [IndexNonHalted -> [IndexNonHalted -> AM]] 86 | /\ phase \in {"msgs", "trans"} 87 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 88 | /\ decisionRound \in [Correct -> BOOLEAN] 89 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : estValue(u) = 1} -> SUBSET(BOOLEAN)] 90 | /\ someP \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 91 | 92 | \* initial predicate of the environment 93 | InitEnvironment == 94 | /\ phase = "msgs" \* current phase of the algorithm 95 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] \* crash array 96 | /\ decisionRound = [u \in Correct |-> FALSE] \* early decision predicates for the correct processes 97 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X Correct -> ((SUBSET(BOOLEAN)) \ {{}})] \* receivers array 98 | /\ someP = [l \in {k \in locOther : crash[k] # {TRUE}} |-> FALSE] 99 | /\ pclean = FALSE \* clean round predicate 100 | /\ globalDecisionRound = FALSE \* termination round predicate 101 | 102 | \* initial predicate of the algorithm 103 | InitAlgorithm == 104 | /\ loc1 \in InitActive \* first process kept explicitly 105 | /\ loc2 \in InitActive \* second process kept explicitly 106 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of witnesses for the other N - 2 processes 107 | /\ msgs = [u \in IndexNonHalted |-> [v \in IndexNonHalted |-> {<<>>}]] \* two-dimensional messages array 108 | /\ previous = [u \in IndexNonHalted |-> [v \in IndexUndecided |-> {<<>>}]] \* {} ]] \* two-dimensional messages array from the previous round 109 | 110 | \* equality of messages between the previous and current round 111 | equal(u, v) == 112 | IF <<>> \in msgs[u][v]' 113 | THEN previous[u][v] = msgs[u][v]' 114 | ELSE previous[u][v] # {<<>>} /\ msgs[u][v]' \subseteq previous[u][v] 115 | 116 | \* check for equality of messages received in the previous and the current round 117 | \* by processes witnessed by v 118 | isDecisionRound(v) == 119 | \A u \in IndexNonHalted : equal(u, v) 120 | 121 | \* environment transition in the message exchage phase 122 | MsgsEnvironment == 123 | /\ phase' = "trans" 124 | /\ decisionRound' = [v \in Correct |-> isDecisionRound(v)] 125 | /\ someP' \in [{l \in locOther : ~l.halt /\ l.est = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 126 | /\ pclean' = IF \A l \in DOMAIN crash : TRUE \notin crash[l] THEN TRUE ELSE pclean 127 | /\ globalDecisionRound' \in IF pclean' THEN {TRUE, FALSE} ELSE {FALSE} 128 | /\ UNCHANGED <> 129 | 130 | \* environment transition in the state update phase 131 | TransEnvironment == 132 | /\ phase' = "msgs" 133 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 134 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} 135 | \times {u \in Correct' : estValue(u)' = 1} -> (SUBSET(BOOLEAN) \ {{}})] 136 | /\ someP' = [l \in {k \in locOther : ~k.halt /\ k.est = 1 /\ crash[k] # {TRUE}}' |-> FALSE] 137 | /\ UNCHANGED <> 138 | 139 | \* message generation function of a correct process 140 | SendMessage(u, v) == 141 | <> 142 | 143 | \* update function of a correct process 144 | \* (that received the same messages as the abstract location that witnesses it) 145 | Update(l, u) == 146 | LET decide == \E m \in V : \E v \in IndexNonHalted : <> \in msgs[v][u] IN 147 | LET e == IF l.est = 1 /\ \E d \in BOOLEAN : \E v \in IndexNonHalted : <<0, d>> \in msgs[v][u] 148 | THEN 0 149 | ELSE l.est IN 150 | LET h == IF globalDecisionRound 151 | THEN TRUE 152 | ELSE FALSE IN 153 | LET d == IF decide \/ decisionRound[u] 154 | THEN TRUE 155 | ELSE FALSE IN 156 | [est |-> e, halt |-> h, early |-> d] 157 | 158 | \* update function of a correct process 159 | \* (that received messages different from the ones received by abstract location that witnesses it) 160 | UpdateOther(l, u, e) == 161 | LET decide == \E m \in V : \E v \in IndexNonHalted : <> \in msgs[v][u] IN 162 | LET h == IF globalDecisionRound \* l.early \/ 163 | THEN TRUE 164 | ELSE FALSE IN 165 | LET d == IF decide \/ decisionRound[u] 166 | THEN TRUE 167 | ELSE FALSE IN 168 | [est |-> e, halt |-> h, early |-> d] 169 | 170 | \* update of a process location witnessing correct processes 171 | UpdateCorrect(l, u) == 172 | IF \A m \in V : \A v \in IndexNonHalted : <> \notin msgs[v][u] 173 | THEN IF l.est = 1 /\ loc1.est = l.est /\ loc2.est = l.est 174 | THEN IF \A v \in IndexNonHalted : v \notin {u1, u2} /\ location(v).est # l.est => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 175 | THEN {UpdateOther(l, u, l.est)} 176 | ELSE IF someP[l] 177 | THEN {Update(l, u), UpdateOther(l, u, l.est)} 178 | ELSE {Update(l, u)} 179 | ELSE {Update(l, u)} 180 | ELSE {Update(l, u)} 181 | 182 | \* delivery of messages by the environment 183 | EnvSemMsg(m, u, v) == 184 | IF u \in {u1, u2} 185 | THEN {m} 186 | ELSE LET l == location(u) IN 187 | IF crash[l] = {TRUE, FALSE} 188 | THEN IF ~early(v) /\ estValue(v) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 189 | THEN IF receivers[l,v] = {TRUE} 190 | THEN {m} 191 | ELSE {<<>>, m} 192 | ELSE {<<>>} 193 | ELSE IF crash[l] = {TRUE} 194 | THEN IF ~early(v) /\ estValue(v) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 195 | THEN IF receivers[l,v] = {TRUE} 196 | THEN {m} 197 | ELSE IF receivers[l,v] = {FALSE} 198 | THEN {<<>>} 199 | ELSE {<<>>, m} 200 | ELSE {<<>>} 201 | ELSE IF ~early(v) /\ estValue(v) = 1 /\ (v \in {u1, u2} \/ crash[location(v)] # {TRUE}) 202 | THEN {m} 203 | ELSE {<<>>} 204 | 205 | \* state update of the fixed processes w.r.t. the environment 206 | EnvSemState(l, u) == 207 | IF l.halt 208 | THEN l 209 | ELSE IF l.early 210 | THEN decidedLocation(l) 211 | ELSE Update(l, u) 212 | 213 | \* state update of the other processes w.r.t. the environment 214 | EnvSemStateOther(l) == 215 | IF l.halt 216 | THEN {l} \* halted processes do not update their location 217 | ELSE IF l.early \* if processes have decided, there is no need in processing received messages 218 | THEN {decidedLocation(l)} \* processes that decided in the previous round halt in this round 219 | ELSE IF crash[l] = {TRUE} \* all processes in l have crashed in this round 220 | THEN {failedLocation(l)} \* they are flagged as failed in the next rounds 221 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes in l crashed, and some did not 222 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} \* partially correct, partially failed 223 | ELSE UpdateCorrect(l, index(l)) \* no failed (fully correct) 224 | 225 | \* update of old messages w.r.t. location updates 226 | UpdatePrevious(u, v) == 227 | LET E == IF u \in {u1, u2} 228 | THEN {u} 229 | ELSE {index(k) : k \in {l \in locOther : location(u) \in EnvSemStateOther(l)}} IN 230 | LET F == IF v \in {u1, u2} 231 | THEN {v} 232 | ELSE {index(k) : k \in {l \in locOther : location(v) \in EnvSemStateOther(l)}} IN 233 | UNION({msgs[e][f] : e \in E, f \in F}) 234 | 235 | \* algorithm transition in the message exchange phase 236 | MsgsAlgorithm == 237 | /\ msgs' = [u \in IndexNonHalted |-> [v \in IndexNonHalted |-> EnvSemMsg(SendMessage(u, v), u, v)]] 238 | /\ UNCHANGED <> 239 | 240 | \* local state transition phase of the algorithm module 241 | TransAlgorithm == 242 | /\ loc1' = EnvSemState(loc1, u1) 243 | /\ loc2' = EnvSemState(loc2, u2) 244 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 245 | /\ previous' = [u \in IndexNonHalted' |-> [v \in IndexUndecided' |-> UpdatePrevious(u, v)]] 246 | /\ msgs' = [u \in IndexNonHalted' |-> [v \in IndexNonHalted' |-> {<<>>}]] 247 | 248 | NextEnvironment == 249 | \/ phase = "msgs" /\ MsgsEnvironment 250 | \/ phase = "trans" /\ TransEnvironment 251 | 252 | NextAlgorithm == 253 | \/ phase = "msgs" /\ MsgsAlgorithm 254 | \/ phase = "trans" /\ TransAlgorithm 255 | 256 | Init == InitAlgorithm /\ InitEnvironment 257 | 258 | Next == NextAlgorithm /\ NextEnvironment 259 | 260 | \* constraints 261 | Fairness == 262 | /\ WF_vars(Next) 263 | /\ <>[](\A c \in DOMAIN crash : TRUE \notin crash[c]) 264 | /\ <>globalDecisionRound 265 | 266 | \* specification 267 | Spec == Init /\ [][Next]_vars /\ Fairness 268 | 269 | \* safety properties 270 | Validity0 == ((\A l \in Active : l.est = 0) => 271 | [](/\ loc1.halt => loc1.est = 0 272 | /\ loc2.halt => loc2.est = 0)) 273 | Validity1 == ((\A l \in Active : l.est = 1) => 274 | [](/\ loc1.halt => loc1.est = 1 275 | /\ loc2.halt => loc2.est = 1)) 276 | \* Validity: if all processes start with the same value, then this is the only 277 | \* possible decision value 278 | Validity == Validity0 /\ Validity1 279 | 280 | \* Agreement: no two correct processes decide on a different value 281 | Agreement == [](loc1.halt /\ loc2.halt => loc1.est = loc2.est) 282 | 283 | \* liveness property 284 | \* Termination: all correct processes eventually decide 285 | Termination == <>(loc1.halt /\ loc2.halt) 286 | 287 | 288 | ============================================================================= 289 | \* Modification History 290 | \* Last modified Tue Oct 17 14:48:46 CEST 2017 by stoilkov 291 | \* Created Tue Sep 12 16:17:07 CEST 2017 by stoilkov 292 | -------------------------------------------------------------------------------- /pdif/pdif_abstract_m1.tla: -------------------------------------------------------------------------------- 1 | ----------------------- MODULE pdif_abstract_m1 ----------------------- 2 | 3 | EXTENDS Naturals, FiniteSets, TLC 4 | 5 | VARIABLES loc1, locOther, msgs, previous, phase, crash, decisionRound, receivers, someP, pclean, globalDecisionRound 6 | 7 | vars == <> 8 | 9 | v0 == 0 \* default decision value 10 | V == {0, 1} \* set of values 11 | I == 1 .. 8 \* indices corresponding to process locations 12 | U == 1 .. 9 \* message array indices (process locations + 1 concrete process) 13 | u1 == 9 \* index for process 1 14 | Loc == [est : V, halt : BOOLEAN, early : BOOLEAN] \* possible process locations 15 | CM == {<> : v \in V, d \in BOOLEAN} \* concrete message alphabet 16 | AM == {W \in SUBSET(CM) : W = {} \/ Cardinality(W) = 1 \/ (Cardinality(W) = 2 /\ <<>> \in W)} \* abstract message alphabet 17 | 18 | \* translate index i \in I to location l \in Loc 19 | location(i) == 20 | LET x == i - 1 IN 21 | LET e == IF x \div 4 = 0 THEN 0 ELSE 1 IN 22 | LET y == x % 4 IN 23 | LET h == IF y \div 2 = 0 THEN FALSE ELSE TRUE IN 24 | LET d == IF y % 2 = 0 THEN FALSE ELSE TRUE IN 25 | [est |-> e, halt |-> h, early |-> d] 26 | 27 | \* translate location l \in Loc to index i \in I 28 | index(l) == 29 | LET d == IF l.early = FALSE THEN 0 ELSE 1 IN 30 | LET h == IF l.halt = FALSE THEN 0 ELSE 1 IN 31 | LET e == IF l.est = 0 THEN 0 ELSE 1 IN 32 | 4 * e + 2 * h + d + 1 33 | 34 | \* get value, given index u \in U 35 | estValue(u) == 36 | IF u = u1 37 | THEN loc1.est 38 | ELSE location(u).est 39 | \* get early flag, given index u \in U 40 | early(u) == 41 | IF u = u1 42 | THEN loc1.early 43 | ELSE location(u).early 44 | \* get halted flag, given index u \in U 45 | halted(u) == 46 | IF u = u1 47 | THEN loc1.halt 48 | ELSE location(u).halt 49 | 50 | \* Set of locations of active processes 51 | Active == {loc1} \cup locOther 52 | \* Set of indices of active processes 53 | IndexActive == {u1} \cup {index(l) : l \in locOther} 54 | \* Set of indices witnessing non-halted processes 55 | IndexNonHalted == {u \in IndexActive : ~halted(u)} 56 | \* Set of indices witnessing undecided processes 57 | IndexUndecided == {u \in IndexActive : ~halted(u) /\ ~early(u)} 58 | \* Set of indices of correct processes (i.e., non-failed and non-crashed) 59 | Correct == {u \in IndexActive : ~halted(u) /\ ~early(u) /\ (u \in {u1} \/ crash[location(u)] # {TRUE})} 60 | 61 | \* set failure flag of l to TRUE 62 | failedLocation(l) == 63 | [est |-> l.est, halt |-> TRUE, early |-> l.early] 64 | 65 | \* a process in a decided location stops participating in the algorithm 66 | decidedLocation(l) == 67 | [est |-> l.est, halt |-> TRUE, early |-> TRUE] 68 | 69 | \* Set of initial locations 70 | InitActive == {[est |-> 0, halt |-> FALSE, early |-> FALSE], 71 | [est |-> 1, halt |-> FALSE, early |-> FALSE]} 72 | 73 | \* type invariant 74 | TypeOK == 75 | /\ loc1 \in Loc 76 | /\ locOther \in SUBSET(Loc) 77 | /\ msgs \in [IndexNonHalted -> [IndexNonHalted -> AM]] 78 | /\ phase \in {"msgs", "trans"} 79 | /\ crash \in [{l \in locOther : ~l.halt} -> SUBSET(BOOLEAN)] 80 | /\ decisionRound \in [Correct -> BOOLEAN] 81 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X {u \in Correct : estValue(u) = 1} -> SUBSET(BOOLEAN)] 82 | /\ someP \in [{l \in locOther : ~l.halt /\ Cardinality(l.W) = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 83 | 84 | \* initial predicate of the environment 85 | InitEnvironment == 86 | /\ phase = "msgs" \* current phase of the algorithm 87 | /\ crash \in [locOther -> ((SUBSET(BOOLEAN)) \ {{}})] \* crash array 88 | /\ decisionRound = [u \in Correct |-> FALSE] \* early decision predicates for the correct processes 89 | /\ receivers \in [{l \in DOMAIN crash : TRUE \in crash[l]} \X Correct -> ((SUBSET(BOOLEAN)) \ {{}})] \* receivers array 90 | /\ someP = [l \in {k \in locOther : crash[k] # {TRUE}} |-> FALSE] 91 | /\ pclean = FALSE \* clean round predicate 92 | /\ globalDecisionRound = FALSE \* termination round predicate 93 | 94 | \* initial predicate of the algorithm 95 | InitAlgorithm == 96 | /\ loc1 \in InitActive \* first process kept explicitly 97 | /\ locOther \in ((SUBSET(InitActive)) \ {{}}) \* set of witnesses for the other N - 2 processes 98 | /\ msgs = [u \in IndexNonHalted |-> [v \in IndexNonHalted |-> {<<>>}]] \* two-dimensional messages array 99 | /\ previous = [u \in IndexNonHalted |-> [v \in IndexUndecided |-> {<<>>}]] \* {} ]] \* two-dimensional messages array from the previous round 100 | 101 | \* equality of messages between the previous and current round 102 | equal(u, v) == 103 | IF <<>> \in msgs[u][v]' 104 | THEN previous[u][v] = msgs[u][v]' 105 | ELSE previous[u][v] # {<<>>} /\ msgs[u][v]' \subseteq previous[u][v] 106 | 107 | \* check for equality of messages received in the previous and the current round 108 | \* by processes witnessed by v 109 | isDecisionRound(v) == 110 | \A u \in IndexNonHalted : equal(u, v) 111 | 112 | \* environment transition in the message exchage phase 113 | MsgsEnvironment == 114 | /\ phase' = "trans" 115 | /\ decisionRound' = [v \in Correct |-> isDecisionRound(v)] 116 | /\ someP' \in [{l \in locOther : ~l.halt /\ l.est = 1 /\ crash[l] # {TRUE}} -> BOOLEAN] 117 | /\ pclean' = IF \A l \in DOMAIN crash : TRUE \notin crash[l] THEN TRUE ELSE pclean 118 | /\ globalDecisionRound' \in IF pclean' THEN {TRUE, FALSE} ELSE {FALSE} 119 | /\ UNCHANGED <> 120 | 121 | \* environment transition in the state update phase 122 | TransEnvironment == 123 | /\ phase' = "msgs" 124 | /\ crash' \in [{l \in locOther' : ~l.halt} -> ((SUBSET(BOOLEAN)) \ {{}})] 125 | /\ receivers' \in [{l \in DOMAIN crash' : TRUE \in crash[l]'} 126 | \times {u \in Correct' : estValue(u)' = 1} -> (SUBSET(BOOLEAN) \ {{}})] 127 | /\ someP' = [l \in {k \in locOther : ~k.halt /\ k.est = 1 /\ crash[k] # {TRUE}}' |-> FALSE] 128 | /\ UNCHANGED <> 129 | 130 | \* message generation function of a correct process 131 | SendMessage(u, v) == 132 | <> 133 | 134 | \* update function of a correct process 135 | \* (that received the same messages as the abstract location that witnesses it) 136 | Update(l, u) == 137 | LET decide == \E m \in V : \E v \in IndexNonHalted : <> \in msgs[v][u] IN 138 | LET e == IF l.est = 1 /\ \E d \in BOOLEAN : \E v \in IndexNonHalted : <<0, d>> \in msgs[v][u] 139 | THEN 0 140 | ELSE l.est IN 141 | LET h == IF globalDecisionRound 142 | THEN TRUE 143 | ELSE FALSE IN 144 | LET d == IF decide \/ decisionRound[u] 145 | THEN TRUE 146 | ELSE FALSE IN 147 | [est |-> e, halt |-> h, early |-> d] 148 | 149 | \* update function of a correct process 150 | \* (that received messages different from the ones received by abstract location that witnesses it) 151 | UpdateOther(l, u, e) == 152 | LET decide == \E m \in V : \E v \in IndexNonHalted : <> \in msgs[v][u] IN 153 | LET h == IF globalDecisionRound \* l.early \/ 154 | THEN TRUE 155 | ELSE FALSE IN 156 | LET d == IF decide \/ decisionRound[u] 157 | THEN TRUE 158 | ELSE FALSE IN 159 | [est |-> e, halt |-> h, early |-> d] 160 | 161 | \* update of a process location witnessing correct processes 162 | UpdateCorrect(l, u) == 163 | IF \A m \in V : \A v \in IndexNonHalted : <> \notin msgs[v][u] 164 | THEN IF l.est = 1 /\ loc1.est = l.est 165 | THEN IF \A v \in IndexNonHalted : v \notin {u1} /\ location(v).est # l.est => crash[location(v)] = {TRUE} /\ receivers[location(v), u] = {FALSE} 166 | THEN {UpdateOther(l, u, l.est)} 167 | ELSE IF someP[l] 168 | THEN {Update(l, u), UpdateOther(l, u, l.est)} 169 | ELSE {Update(l, u)} 170 | ELSE {Update(l, u)} 171 | ELSE {Update(l, u)} 172 | 173 | \* delivery of messages by the environment 174 | EnvSemMsg(m, u, v) == 175 | IF u \in {u1} 176 | THEN {m} 177 | ELSE LET l == location(u) IN 178 | IF crash[l] = {TRUE, FALSE} 179 | THEN IF ~early(v) /\ estValue(v) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 180 | THEN IF receivers[l,v] = {TRUE} 181 | THEN {m} 182 | ELSE {<<>>, m} 183 | ELSE {<<>>} 184 | ELSE IF crash[l] = {TRUE} 185 | THEN IF ~early(v) /\ estValue(v) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 186 | THEN IF receivers[l,v] = {TRUE} 187 | THEN {m} 188 | ELSE IF receivers[l,v] = {FALSE} 189 | THEN {<<>>} 190 | ELSE {<<>>, m} 191 | ELSE {<<>>} 192 | ELSE IF ~early(v) /\ estValue(v) = 1 /\ (v \in {u1} \/ crash[location(v)] # {TRUE}) 193 | THEN {m} 194 | ELSE {<<>>} 195 | 196 | \* state update of the fixed processes w.r.t. the environment 197 | EnvSemState(l, u) == 198 | IF l.halt 199 | THEN l 200 | ELSE IF l.early 201 | THEN decidedLocation(l) 202 | ELSE Update(l, u) 203 | 204 | \* state update of the other processes w.r.t. the environment 205 | EnvSemStateOther(l) == 206 | IF l.halt 207 | THEN {l} \* halted processes do not update their location 208 | ELSE IF l.early \* if processes have decided, there is no need in processing received messages 209 | THEN {decidedLocation(l)} \* processes that decided in the previous round halt in this round 210 | ELSE IF crash[l] = {TRUE} \* all processes in l have crashed in this round 211 | THEN {failedLocation(l)} \* they are flagged as failed in the next rounds 212 | ELSE IF crash[l] = {TRUE, FALSE} \* some processes in l crashed, and some did not 213 | THEN UpdateCorrect(l, index(l)) \cup {failedLocation(l)} \* partially correct, partially failed 214 | ELSE UpdateCorrect(l, index(l)) \* no failed (fully correct) 215 | 216 | \* update of old messages w.r.t. location updates 217 | UpdatePrevious(u, v) == 218 | LET E == IF u \in {u1} 219 | THEN {u} 220 | ELSE {index(k) : k \in {l \in locOther : location(u) \in EnvSemStateOther(l)}} IN 221 | LET F == IF v \in {u1} 222 | THEN {v} 223 | ELSE {index(k) : k \in {l \in locOther : location(v) \in EnvSemStateOther(l)}} IN 224 | UNION({msgs[e][f] : e \in E, f \in F}) 225 | 226 | \* algorithm transition in the message exchange phase 227 | MsgsAlgorithm == 228 | /\ msgs' = [u \in IndexNonHalted |-> [v \in IndexNonHalted |-> EnvSemMsg(SendMessage(u, v), u, v)]] 229 | /\ UNCHANGED <> 230 | 231 | \* local state transition phase of the algorithm module 232 | TransAlgorithm == 233 | /\ loc1' = EnvSemState(loc1, u1) 234 | /\ locOther' = UNION{EnvSemStateOther(l) : l \in locOther} 235 | /\ previous' = [u \in IndexNonHalted' |-> [v \in IndexUndecided' |-> UpdatePrevious(u, v)]] 236 | /\ msgs' = [u \in IndexNonHalted' |-> [v \in IndexNonHalted' |-> {<<>>}]] 237 | 238 | NextEnvironment == 239 | \/ phase = "msgs" /\ MsgsEnvironment 240 | \/ phase = "trans" /\ TransEnvironment 241 | 242 | NextAlgorithm == 243 | \/ phase = "msgs" /\ MsgsAlgorithm 244 | \/ phase = "trans" /\ TransAlgorithm 245 | 246 | Init == InitAlgorithm /\ InitEnvironment 247 | 248 | Next == NextAlgorithm /\ NextEnvironment 249 | 250 | \* constraints 251 | Fairness == 252 | /\ WF_vars(Next) 253 | /\ <>[](\A c \in DOMAIN crash : TRUE \notin crash[c]) 254 | /\ <>globalDecisionRound 255 | 256 | \* specification 257 | Spec == Init /\ [][Next]_vars /\ Fairness 258 | 259 | \* safety properties 260 | Validity0 == ((\A l \in Active : l.est = 0) => 261 | [](loc1.halt => loc1.est = 0)) 262 | Validity1 == ((\A l \in Active : l.est = 1) => 263 | [](loc1.halt => loc1.est = 1)) 264 | \* Validity: if all processes start with the same value, then this is the only 265 | \* possible decision value 266 | Validity == Validity0 /\ Validity1 267 | 268 | \* liveness property 269 | \* Termination: all correct processes eventually decide 270 | Termination == <>(loc1.halt) 271 | 272 | ============================================================================= 273 | \* Modification History 274 | \* Last modified Tue Oct 17 14:52:49 CEST 2017 by stoilkov 275 | \* Created Thu Sep 28 17:36:56 CEST 2017 by stoilkov 276 | --------------------------------------------------------------------------------