-
Notifications
You must be signed in to change notification settings - Fork 201
/
Copy pathCigaretteSmokers.tla
57 lines (46 loc) · 2.85 KB
/
CigaretteSmokers.tla
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
-------------------------- MODULE CigaretteSmokers --------------------------
(***************************************************************************)
(* A specification of the cigarette smokers problem, originally *)
(* described in 1971 by Suhas Patil. *)
(* https://en.wikipedia.org/wiki/Cigarette_smokers_problem *)
(***************************************************************************)
EXTENDS Integers, FiniteSets
CONSTANT Ingredients, Offers
VARIABLE smokers, dealer
(***************************************************************************)
(* 'Ingredients' is a set of ingredients, originally *)
(* {matches, paper, tobacco}. 'Offers' is a subset of subsets of *)
(* ingredients, each missing just one ingredient *)
(***************************************************************************)
ASSUME /\ Offers \subseteq (SUBSET Ingredients)
/\ \A n \in Offers : Cardinality(n) = Cardinality(Ingredients) - 1
(***************************************************************************)
(* 'smokers' is a function from the ingredient the smoker has *)
(* infinite supply of, to a BOOLEAN flag signifying smoker's state *)
(* (smoking/not smoking) *)
(* 'dealer' is an element of 'Offers', or an empty set *)
(***************************************************************************)
TypeOK == /\ smokers \in [Ingredients -> [smoking: BOOLEAN]]
/\ dealer \in Offers \/ dealer = {}
vars == <<smokers, dealer>>
ChooseOne(S, P(_)) == CHOOSE x \in S : P(x) /\ \A y \in S : P(y) => y = x
Init == /\ smokers = [r \in Ingredients |-> [smoking |-> FALSE]]
/\ dealer \in Offers
startSmoking == /\ dealer /= {}
/\ smokers' = [r \in Ingredients |-> [smoking |-> {r} \cup
dealer = Ingredients]]
/\ dealer' = {}
stopSmoking == /\ dealer = {}
/\ LET r == ChooseOne(Ingredients,
LAMBDA x : smokers[x].smoking)
IN smokers' = [smokers EXCEPT ![r].smoking = FALSE]
/\ dealer' \in Offers
Next == startSmoking \/ stopSmoking
Spec == Init /\ [][Next]_vars
FairSpec == Spec /\ WF_vars(Next)
(***************************************************************************)
(* An invariant checking that at most one smoker smokes at any particular *)
(* moment *)
(***************************************************************************)
AtMostOne == Cardinality({r \in Ingredients : smokers[r].smoking}) <= 1
=============================================================================