Skip to content

Commit e22d145

Browse files
florianschandaahelwer
authored andcommitted
Add a variant of the Prisoner's puzzle
This version has a single switch. There are two variants, one where the initial position of the light switch is known, and another one where it is not. Signed-off-by: Florian Schanda <[email protected]>
1 parent ad3d3e4 commit e22d145

File tree

8 files changed

+354
-0
lines changed

8 files changed

+354
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Here is a list of specs included in this repository, with links to the relevant
3535
| [The Car Talk Puzzle](specifications/CarTalkPuzzle) | Leslie Lamport || | || |
3636
| [The Die Hard Problem](specifications/DieHard) | Leslie Lamport || | || |
3737
| [The Prisoners & Switches Puzzle](specifications/Prisoners) | Leslie Lamport || | || |
38+
| [The Prisoners & Switch Puzzle](specifications/Prisoners_Single_Switch) | Florian Schanda || | || |
3839
| [Specs from Specifying Systems](specifications/SpecifyingSystems) | Leslie Lamport || | || |
3940
| [The Tower of Hanoi Puzzle](specifications/tower_of_hanoi) | Markus Kuppe, Alexander Niederbühl || | || |
4041
| [Missionaries and Cannibals](specifications/MissionariesAndCannibals) | Leslie Lamport || | || |

manifest.json

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1855,6 +1855,68 @@
18551855
}
18561856
]
18571857
},
1858+
{
1859+
"path": "specifications/Prisoners_Single_Switch",
1860+
"title": "The Prisoners & Switch Puzzle",
1861+
"description": "Given a room containing a single light switch prisoners enter one by one, they must develop a strategy to free themselves.",
1862+
"sources": [],
1863+
"authors": [
1864+
"Florian Schanda"
1865+
],
1866+
"tags": [
1867+
"beginner"
1868+
],
1869+
"modules": [
1870+
{
1871+
"path": "specifications/Prisoners_Single_Switch/Prisoner.tla",
1872+
"communityDependencies": [],
1873+
"tlaLanguageVersion": 2,
1874+
"features": [],
1875+
"models": [
1876+
{
1877+
"path": "specifications/Prisoners_Single_Switch/Prisoner.cfg",
1878+
"runtime": "00:00:01",
1879+
"size": "small",
1880+
"mode": "exhaustive search",
1881+
"features": [
1882+
"liveness"
1883+
],
1884+
"result": "success"
1885+
},
1886+
{
1887+
"path": "specifications/Prisoners_Single_Switch/PrisonerLightUnknown.cfg",
1888+
"runtime": "00:00:01",
1889+
"size": "small",
1890+
"mode": "exhaustive search",
1891+
"features": [
1892+
"liveness"
1893+
],
1894+
"result": "success"
1895+
},
1896+
{
1897+
"path": "specifications/Prisoners_Single_Switch/SoloPrisoner.cfg",
1898+
"runtime": "00:00:01",
1899+
"size": "small",
1900+
"mode": "exhaustive search",
1901+
"features": [
1902+
"liveness"
1903+
],
1904+
"result": "success"
1905+
},
1906+
{
1907+
"path": "specifications/Prisoners_Single_Switch/SoloPrisonerLightUnknown.cfg",
1908+
"runtime": "00:00:01",
1909+
"size": "small",
1910+
"mode": "exhaustive search",
1911+
"features": [
1912+
"liveness"
1913+
],
1914+
"result": "success"
1915+
}
1916+
]
1917+
}
1918+
]
1919+
},
18581920
{
18591921
"path": "specifications/ReadersWriters",
18601922
"title": "The Readers-Writers Problem",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CONSTANTS
2+
Prisoner = {"Alice", "Bob", "Eve"}
3+
Light_Unknown = FALSE
4+
5+
SPECIFICATION Spec
6+
PROPERTY Terminating
7+
8+
INVARIANT TypeOK
9+
INVARIANT VictoryOK
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
The prisoner puzzle. A set of N prisoners, all in solitary cells, is
2+
offered a game. One of them is randomly selected and placed in a
3+
special cell. This cell has a lamp and prisoners can turn it off or
4+
on. Afterwards the prisoner is returned back to their cell.
5+
6+
At any point a prisoner can announce to the warden that they have all
7+
been in the cell at least once. If they are right everyone is
8+
released. If they are wrong the game ends and they remain in prison
9+
forever.
10+
11+
The prisoners are allowed to communicate and design a strategy before
12+
the game starts. Afterwards they can no longer communicate.
13+
14+
There is a variant of the puzzle where the initial state of the light
15+
in the cell is not known.
16+
17+
In either case the strategy is:
18+
19+
* One prisoner is designated as the counter.
20+
21+
* Other prisoners, when they enter the cell turn the light on if its
22+
off. They do this at most once (or twice in the variant).
23+
24+
* If the designated counter sees the light, they turn it off and
25+
increment their count. Once they count to N (or 2N - 1 for the
26+
variant), they know that everyone (including themselves) must have
27+
entered the cell and can announce victory.
28+
29+
Note: This puzzle is a variant of other prisoner puzzle here that I
30+
was not aware of when I wrote this model.
31+
https://github.com/tlaplus/Examples/tree/master/specifications/Prisoners
32+
33+
The setup is different: here there is only one switch, and the initial
34+
status of it might be known, and the prisoners are not required to do
35+
anything if they enter the room.
36+
37+
The solution is the same however (except we don't have the busy-work
38+
switch), and our models are very similar.
39+
40+
---- MODULE Prisoner ----
41+
42+
EXTENDS FiniteSets, Naturals
43+
44+
CONSTANTS
45+
\* The set of prisoners playing the game. Has to be at least one.
46+
Prisoner,
47+
48+
\* Configuration if the initial state of the light is "off" or
49+
\* unknown. The puzzle is harder (takes more steps) if we don't know
50+
\* the initial state.
51+
Light_Unknown
52+
53+
ASSUME Light_Unknown \in BOOLEAN
54+
55+
VARIABLES
56+
\* The counter's current count
57+
count,
58+
59+
\* If the announcement has been made
60+
announced,
61+
62+
\* How often other prisoners have signalled
63+
signalled,
64+
65+
\* Current status of the light
66+
light,
67+
68+
\* The warden's view on who has actually been to the cell
69+
has_visited
70+
71+
vars == <<count, announced, signalled, light, has_visited>>
72+
73+
------------------------------------------------------------------------------
74+
75+
\* The strategy differs slightly if the initial state of the light is
76+
\* known or not. If it's "off" then a simple count to N is
77+
\* sufficient. If the state is unknown we count to 2N - 1, and each
78+
\* prisoner will signal up to two times.
79+
80+
SignalLimit == IF Light_Unknown THEN 2 ELSE 1
81+
82+
VictoryThreshold ==
83+
IF Light_Unknown
84+
THEN Cardinality(Prisoner) * 2 - 1
85+
ELSE Cardinality(Prisoner)
86+
87+
------------------------------------------------------------------------------
88+
89+
\* We pick somebody at random to be the counter
90+
DesignatedCounter == CHOOSE p \in Prisoner: TRUE
91+
92+
\* The other prisoners
93+
NormalPrisoner == Prisoner \ {DesignatedCounter}
94+
95+
\* The only thing to note here is that the count starts at one. Since
96+
\* only the counter will make an announcement if they are in the cell,
97+
\* this 1 means they have already counted themselves. We could also
98+
\* model this with a separate variable to note when the counter has
99+
\* visited the cell for the very first time, but this is not
100+
\* necessary.
101+
Init ==
102+
/\ count = 1
103+
/\ announced = FALSE
104+
/\ signalled = [ p \in NormalPrisoner |-> 0 ]
105+
/\ \/ Light_Unknown /\ light \in { "off", "on" }
106+
\/ ~Light_Unknown /\ light = "off"
107+
/\ has_visited = {}
108+
109+
------------------------------------------------------------------------------
110+
111+
\* The action taken by the designated counter, if they are placed in
112+
\* the cell
113+
\*
114+
\* Note: we could simplify this change the IF to just be a
115+
\* precondition to the action, and while that would be a more elegant
116+
\* spec, I think this better models the decision procedure of the
117+
\* prisoner.
118+
CounterAction(p) ==
119+
/\ p = DesignatedCounter
120+
/\ IF light = "on"
121+
THEN
122+
/\ light' = "off"
123+
/\ count' = count + 1
124+
ELSE
125+
UNCHANGED <<light, count>>
126+
/\ announced' = (count' >= VictoryThreshold)
127+
/\ UNCHANGED <<signalled>>
128+
129+
\* The action taken by the other prisoners, if they are placed in the
130+
\* cell
131+
\*
132+
\* Same note on the IF applies here.
133+
StandardAction(p) ==
134+
/\ p \in NormalPrisoner
135+
/\ IF light = "off" /\ signalled[p] < SignalLimit
136+
THEN
137+
/\ light' = "on"
138+
/\ signalled' = [signalled EXCEPT ![p] = @ + 1]
139+
ELSE
140+
UNCHANGED <<light, signalled>>
141+
/\ UNCHANGED <<count, announced>>
142+
143+
\* The action performed by the warden: place a prisoner in the cell
144+
\* and maintain our own view of who's been selected (so we can judge
145+
\* if a victory announcement is correct)
146+
WardenAction(p) ==
147+
\* Put one of the prisoners in the cell
148+
/\ \/ CounterAction(p)
149+
\/ StandardAction(p)
150+
151+
\* Maintain the warden's view
152+
/\ has_visited' = has_visited \union {p}
153+
154+
Next == \E p \in Prisoner: WardenAction(p)
155+
156+
Spec ==
157+
/\ Init
158+
/\ [][Next]_vars
159+
160+
\* Base assumption in the game: the warden eventually has to choose
161+
\* everyone in a way progress is possible
162+
/\ \A p \in Prisoner: WF_vars(WardenAction(p))
163+
164+
------------------------------------------------------------------------------
165+
166+
\* Goal of the game: eventually the prisoners will win
167+
Terminating == <>announced
168+
169+
------------------------------------------------------------------------------
170+
171+
\* Type invariant. Note it's possible to over-count in the lights
172+
\* unknown version, if the initial state of the light is "on". Hence
173+
\* the slightly more relaxed upper bound on count.
174+
TypeOK ==
175+
/\ count \in 1 .. VictoryThreshold + 1
176+
/\ announced \in BOOLEAN
177+
/\ signalled \in [ NormalPrisoner -> 0 .. 2 ]
178+
/\ light \in {"off", "on"}
179+
/\ has_visited \subseteq Prisoner
180+
181+
\* Invariant to make sure victory is never declared in error
182+
VictoryOK == announced => (has_visited = Prisoner)
183+
184+
====
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CONSTANTS
2+
Prisoner = {"Alice", "Bob", "Eve"}
3+
Light_Unknown = TRUE
4+
5+
SPECIFICATION Spec
6+
PROPERTY Terminating
7+
8+
INVARIANT TypeOK
9+
INVARIANT VictoryOK
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# The Prisoners & Switch Puzzle
2+
3+
A set of N prisoners, all in solitary cells, is offered a game. One of
4+
them is randomly selected and placed in a special cell. This cell has
5+
a lamp and prisoners can turn it off or on. Afterwards the prisoner is
6+
returned back to their cell.
7+
8+
At any point a prisoner can announce to the warden that they have all
9+
been in the cell at least once. If they are right everyone is
10+
released. If they are wrong the game ends and they remain in prison
11+
forever.
12+
13+
The prisoners are allowed to communicate and design a strategy before
14+
the game starts. Afterwards they can no longer communicate.
15+
16+
The default version where the initial state of the light is off is
17+
checked in [Prisoner.cfg](Prisoner.cfg).
18+
19+
There is a variant of the puzzle where the initial state of the light
20+
in the cell is not known. This is checked in
21+
[PrisonerLightUnknown.cfg](PrisonerLightUnknown.cfg).
22+
23+
## Note on the spec
24+
25+
The spec could be more compact by replacing the do nothing ELSE clause
26+
in the actions with stutter steps, like so:
27+
28+
```TLA+
29+
StandardAction(p) ==
30+
/\ p \in NormalPrisoner
31+
/\ light = "off"
32+
/\ signalled[p] < SignalLimit
33+
/\ light' = "on"
34+
/\ signalled' = [signalled EXCEPT ![p] = @ + 1]
35+
/\ UNCHANGED <<count, announced>>
36+
37+
CounterAction(p) ==
38+
/\ p = Designated_Counter
39+
/\ light = "on"
40+
/\ light' = "off"
41+
/\ count' = count + 1
42+
/\ announced' = (count' >= VictoryThreshold)
43+
/\ UNCHANGED <<signalled>>
44+
```
45+
46+
In the end I decided against this as I wanted to model the individual
47+
decision procedure of a prisoner as closely as possible.
48+
49+
I also did not want to remove the `p` from the `CounterAction` for a
50+
similar reason - it's the counter's job to know what they are doing,
51+
not the warden's.
52+
53+
## Note on the other prisoner puzzle
54+
55+
The light unknown variant is very similar to the other [prisoner
56+
puzzle](../Prisoners) in this repository. I was not aware of this when
57+
I created my version. This puzzle has a slightly different setup, but
58+
at their core they are identical.
59+
60+
This puzzle has one light switch and prisoners are not forced to use
61+
it.
62+
63+
The other puzzle has two switches, and prisoners are forced to use
64+
exactly one. The puzzles are identical since you treat one switch as
65+
the signal switch, and the other one is used if you want to "do
66+
nothing".
67+
68+
One final difference is that this spec also works for a single
69+
prisoner, which is of course trivial but still an interesting
70+
corner-case. These are checked in [SoloPrisoner.cfg](SoloPrisoner.cfg)
71+
and [SoloPrisonerLightUnknown.cfg](SoloPrisonerLightUnknown.cfg).
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CONSTANTS
2+
Prisoner = {"Alice"}
3+
Light_Unknown = FALSE
4+
5+
SPECIFICATION Spec
6+
PROPERTY Terminating
7+
8+
INVARIANT TypeOK
9+
INVARIANT VictoryOK
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CONSTANTS
2+
Prisoner = {"Alice"}
3+
Light_Unknown = TRUE
4+
5+
SPECIFICATION Spec
6+
PROPERTY Terminating
7+
8+
INVARIANT TypeOK
9+
INVARIANT VictoryOK

0 commit comments

Comments
 (0)