Dining philosophers problem
AbbreviationDining-philosophers state#✓fully proved
A state of the three dining philosophers is a triple \((s_0, s_1, s_2)\) with each \(s_i \in \{0, 1, 2\}\) the phase of philosopher \(i\): \(0\) thinking, \(1\) holding the first fork, \(2\) eating (holding both forks).
Used by 26
DefinitionPhase of a philosopher#✓fully proved
For a state \(s = (s_0, s_1, s_2)\) of the three dining philosophers and a philosopher \(i \in \{0, 1, 2\}\), the phase of philosopher \(i\) in \(s\) is the component \(s_i\).
def phase (s : State) : Fin 3 → Fin 3
| 0 => s.1
| 1 => s.2.1
| 2 => s.2.2
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
Uses 1 · Used by 20
DefinitionUpdating the phase of a philosopher#✓fully proved
For a state \(s = (s_0, s_1, s_2)\) of the three dining philosophers, a philosopher \(i \in \{0, 1, 2\}\) and a phase \(p \in \{0, 1, 2\}\), setting the phase of philosopher \(i\) to \(p\) gives the state obtained from \(s\) by replacing the component \(s_i\) by \(p\) and keeping the other two components.
def setPhase (s : State) (i : Fin 3) (p : Fin 3) : State :=
match i with
| 0 => (p, s.2.1, s.2.2)
| 1 => (s.1, p, s.2.2)
| 2 => (s.1, s.2.1, p)
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
Uses 1 · Used by 2
StructureDining-philosophers protocol#✓fully proved
A protocol for three philosophers \(i \in \{0, 1, 2\}\) sitting between forks \(0, 1, 2\) consists of two maps \(\mathrm{first}, \mathrm{second}\) from \(\{0, 1, 2\}\) to itself, the fork philosopher \(i\) picks up first and the one it picks up second, such that for every \(i\) these are its two neighbouring forks \(i\) and \(i + 1\) (modulo \(3\)) in some order: either \(\mathrm{first}(i) = i\) and \(\mathrm{second}(i) = i + 1\), or \(\mathrm{first}(i) = i + 1\) and \(\mathrm{second}(i) = i\).
structure Protocol where
/-- The fork picked up first. -/
first : Fin 3 → Fin 3
/-- The fork picked up second. -/
second : Fin 3 → Fin 3
/-- The two forks are the two neighbouring forks, in some order. -/
neighbours : ∀ i, (first i = i ∧ second i = i + 1) ∨
(first i = i + 1 ∧ second i = i)
first : Fin 3 → Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:74
second : Fin 3 → Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:76
Used by 11
DefinitionHeld forks#✓fully proved
Given a protocol and a state, fork \(f\) is held exactly when some philosopher \(i\) either has \(f\) as its first fork and is in phase \(1\) or \(2\), or has \(f\) as its second fork and is in phase \(2\) (eating).
def held (P : Protocol) (s : State) (f : Fin 3) : Bool :=
[0, 1, 2].any fun (i : Fin 3) =>
(P.first i == f && decide (1 ≤ (phase s i).val)) || (P.second i == f && phase s i == 2)
structure Protocol where
/-- The fork picked up first. -/
first : Fin 3 → Fin 3
/-- The fork picked up second. -/
second : Fin 3 → Fin 3
/-- The two forks are the two neighbouring forks, in some order. -/
neighbours : ∀ i, (first i = i ∧ second i = i + 1) ∨
(first i = i + 1 ∧ second i = i)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:72
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
def phase (s : State) : Fin 3 → Fin 3
| 0 => s.1
| 1 => s.2.1
| 2 => s.2.2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:57
Uses 3 · Used by 2
DefinitionWhen a philosopher can move#✓fully proved
Given a protocol and a state, philosopher \(i\) can move exactly when it is thinking (phase \(0\)) and its first fork is not held by any philosopher, or it holds its first fork (phase \(1\)) and its second fork is not held by any philosopher, or it is eating (phase \(2\)), in which case its move puts both forks down.
def canMove (P : Protocol) (s : State) (i : Fin 3) : Bool :=
match (phase s i).val with
| 0 => !held P s (P.first i)
| 1 => !held P s (P.second i)
| _ => true
structure Protocol where
/-- The fork picked up first. -/
first : Fin 3 → Fin 3
/-- The fork picked up second. -/
second : Fin 3 → Fin 3
/-- The two forks are the two neighbouring forks, in some order. -/
neighbours : ∀ i, (first i = i ∧ second i = i + 1) ∨
(first i = i + 1 ∧ second i = i)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:72
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
def phase (s : State) : Fin 3 → Fin 3
| 0 => s.1
| 1 => s.2.1
| 2 => s.2.2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:57
Uses 4 · Used by 8
DefinitionMove of a philosopher#✓fully proved
The state obtained from \(s\) when philosopher \(i\) moves: the phase of \(i\) advances from thinking (\(0\)) to holding its first fork (\(1\)), from \(1\) to eating (\(2\)), and from eating back to thinking; the phases of the other philosophers are unchanged. Whether the move is allowed is not checked here.
def move (s : State) (i : Fin 3) : State :=
setPhase s i (match (phase s i).val with | 0 => 1 | 1 => 2 | _ => 0)
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
def setPhase (s : State) (i : Fin 3) (p : Fin 3) : State :=
match i with
| 0 => (p, s.2.1, s.2.2)
| 1 => (s.1, p, s.2.2)
| 2 => (s.1, s.2.1, p)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:63
def phase (s : State) : Fin 3 → Fin 3
| 0 => s.1
| 1 => s.2.1
| 2 => s.2.2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:57
Uses 3 · Used by 11
DefinitionTransition system of a dining-philosophers protocol#✓fully proved
For a protocol \(P\), the labelled transition system on the states whose labels are the philosophers: there is a transition from \(s\) to \(t\) labelled \(i\) exactly when philosopher \(i\) can move in \(s\) under \(P\) and \(t\) is the state obtained from \(s\) by the move of philosopher \(i\).
def lts (P : Protocol) : LTS State (Fin 3) where
Tr s i t := canMove P s i = true ∧ t = move s i
structure Protocol where
/-- The fork picked up first. -/
first : Fin 3 → Fin 3
/-- The fork picked up second. -/
second : Fin 3 → Fin 3
/-- The two forks are the two neighbouring forks, in some order. -/
neighbours : ∀ i, (first i = i ∧ second i = i + 1) ∨
(first i = i + 1 ∧ second i = i)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:72
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
def canMove (P : Protocol) (s : State) (i : Fin 3) : Bool :=
match (phase s i).val with
| 0 => !held P s (P.first i)
| 1 => !held P s (P.second i)
| _ => true
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:88
def move (s : State) (i : Fin 3) : State :=
setPhase s i (match (phase s i).val with | 0 => 1 | 1 => 2 | _ => 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:96
Uses 4 · Used by 6
DefinitionThe eating valuation#✓fully proved
The valuation of the atoms \(i \in \{0, 1, 2\}\) on the states of the dining philosophers: atom \(i\) holds at a state exactly when philosopher \(i\) is eating there, that is, when its phase is \(2\).
def eating : State → Fin 3 → Prop := fun s i => phase s i = 2
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
def phase (s : State) : Fin 3 → Fin 3
| 0 => s.1
| 1 => s.2.1
| 2 => s.2.2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:57
Uses 2 · Used by 12
DefinitionInitial state of the dining philosophers#✓fully proved
The state in which all three philosophers are thinking, that is, every phase is \(0\).
def initial : State := (0, 0, 0)
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
Uses 1 · Used by 11
DefinitionNaive dining-philosophers protocol#✓fully proved
The protocol in which every philosopher \(i \in \{0, 1, 2\}\) picks up fork \(i\) (its left fork) first and fork \(i + 1\) (modulo \(3\)) second.
def naive : Protocol := ⟨fun i => i, fun i => i + 1, fun _ => Or.inl ⟨rfl, rfl⟩⟩
structure Protocol where
/-- The fork picked up first. -/
first : Fin 3 → Fin 3
/-- The fork picked up second. -/
second : Fin 3 → Fin 3
/-- The two forks are the two neighbouring forks, in some order. -/
neighbours : ∀ i, (first i = i ∧ second i = i + 1) ∨
(first i = i + 1 ∧ second i = i)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:72
Uses 1 · Used by 5
DefinitionResource-ordered dining-philosophers protocol#✓fully proved
The protocol in which every philosopher \(i \in \{0, 1, 2\}\) picks up the lower-numbered of its two forks \(i\) and \(i + 1\) (modulo \(3\)) first and the higher-numbered one second: philosophers \(0\) and \(1\) take fork \(i\) first, and philosopher \(2\) takes fork \(0\) first and fork \(2\) second.
def ordered : Protocol :=
⟨fun i => min i (i + 1), fun i => max i (i + 1), by decide⟩
structure Protocol where
/-- The fork picked up first. -/
first : Fin 3 → Fin 3
/-- The fork picked up second. -/
second : Fin 3 → Fin 3
/-- The two forks are the two neighbouring forks, in some order. -/
neighbours : ∀ i, (first i = i ∧ second i = i + 1) ∨
(first i = i + 1 ∧ second i = i)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:72
DefinitionThe deadlock formula#✓fully proved
The CTL formula \(\neg\,\mathsf{EX}\,\top\) over the philosophers as atoms. It holds at a state exactly when the state has no successor; in the transition system of a protocol, exactly when no philosopher can move.
def deadlock : Formula (Fin 3) := .not (.existsNext .top)
inductive Formula (Atom : Type u) : Type u where
| atom (a : Atom) : Formula Atom
| top : Formula Atom
| not (φ : Formula Atom) : Formula Atom
| and (φ ψ : Formula Atom) : Formula Atom
| existsNext (φ : Formula Atom) : Formula Atom
| existsUntil (φ ψ : Formula Atom) : Formula Atom
| existsGlobally (φ : Formula Atom) : Formula Atom
| forallUntil (φ ψ : Formula Atom) : Formula Atom
CSLibExt/Logics/CTL/Basic.lean:70
Uses 1 · Used by 2
DefinitionNeighbours-apart formula#✓fully proved
For a philosopher \(i \in \{0, 1, 2\}\), the CTL formula \(\neg(p_i \wedge p_{i+1})\) over the atoms \(p_0, p_1, p_2\) (one per philosopher), with indices modulo \(3\). Under the valuation in which \(p_j\) holds when philosopher \(j\) eats, it says that the neighbouring philosophers \(i\) and \(i + 1\) do not eat at the same time.
def neighboursApart (i : Fin 3) : Formula (Fin 3) :=
.not (.and (.atom i) (.atom (i + 1)))
inductive Formula (Atom : Type u) : Type u where
| atom (a : Atom) : Formula Atom
| top : Formula Atom
| not (φ : Formula Atom) : Formula Atom
| and (φ ψ : Formula Atom) : Formula Atom
| existsNext (φ : Formula Atom) : Formula Atom
| existsUntil (φ ψ : Formula Atom) : Formula Atom
| existsGlobally (φ : Formula Atom) : Formula Atom
| forallUntil (φ ψ : Formula Atom) : Formula Atom
CSLibExt/Logics/CTL/Basic.lean:70
Uses 1 · Used by 4
TheoremThe naive protocol can deadlock#✓fully proved
Consider the transition system of the naive protocol, in which every philosopher \(i\) picks up fork \(i\) first and fork \(i + 1\) second (indices modulo \(3\)), with atom \(i\) read as "philosopher \(i\) is eating". Its initial state, where all philosophers are thinking, satisfies the CTL formula \(\mathsf{EF}\) applied to the deadlock formula: from it, a state in which no philosopher can move is reachable.
theorem naive_deadlock_reachable :
Satisfies (lts naive) eating initial (Formula.existsFinally deadlock)
def Satisfies (lts : LTS State Label)
(valuation : State → Atom → Prop) (state : State) :
Formula Atom → Prop
| .atom a => valuation state a
| .top => True
| .not φ => ¬Satisfies lts valuation state φ
| .and φ ψ =>
Satisfies lts valuation state φ ∧ Satisfies lts valuation state ψ
| .existsNext φ =>
∃ label next, lts.Tr state label next ∧
Satisfies lts valuation next φ
| .existsUntil φ ψ =>
⋯
CSLibExt/Logics/CTL/Basic.lean:128
def lts (P : Protocol) : LTS State (Fin 3) where
Tr s i t := canMove P s i = true ∧ t = move s i
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:101
def naive : Protocol := ⟨fun i => i, fun i => i + 1, fun _ => Or.inl ⟨rfl, rfl⟩⟩
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:118
def eating : State → Fin 3 → Prop := fun s i => phase s i = 2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:109
def initial : State := (0, 0, 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:115
def existsFinally (φ : Formula Atom) : Formula Atom :=
.existsUntil .top φ
CSLibExt/Logics/CTL/Basic.lean:99
def deadlock : Formula (Fin 3) := .not (.existsNext .top)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:125
TheoremA deadlock state of the naive protocol#✓fully proved
In the transition system of the naive protocol, with atom \(i\) read as "philosopher \(i\) is eating", the state in which every philosopher holds its first fork (every phase is \(1\)) satisfies the deadlock formula: no philosopher can move there.
theorem naive_deadlock_state : Satisfies (lts naive) eating (1, 1, 1) deadlock
def Satisfies (lts : LTS State Label)
(valuation : State → Atom → Prop) (state : State) :
Formula Atom → Prop
| .atom a => valuation state a
| .top => True
| .not φ => ¬Satisfies lts valuation state φ
| .and φ ψ =>
Satisfies lts valuation state φ ∧ Satisfies lts valuation state ψ
| .existsNext φ =>
∃ label next, lts.Tr state label next ∧
Satisfies lts valuation next φ
| .existsUntil φ ψ =>
⋯
CSLibExt/Logics/CTL/Basic.lean:128
def lts (P : Protocol) : LTS State (Fin 3) where
Tr s i t := canMove P s i = true ∧ t = move s i
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:101
def naive : Protocol := ⟨fun i => i, fun i => i + 1, fun _ => Or.inl ⟨rfl, rfl⟩⟩
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:118
def eating : State → Fin 3 → Prop := fun s i => phase s i = 2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:109
def deadlock : Formula (Fin 3) := .not (.existsNext .top)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:125
TheoremResource ordering prevents deadlock for the dining philosophers#✓fully proved
In the transition system of the three dining philosophers under the resource-ordered protocol, the initial state, in which everybody thinks, satisfies the CTL formula \(\mathrm{AG}\,\mathrm{EX}\,\top\): every state reachable from it has a successor, that is, some philosopher can move.
theorem ordered_deadlock_free :
Satisfies (lts ordered) eating initial (Formula.forallGlobally (.existsNext .top))
def Satisfies (lts : LTS State Label)
(valuation : State → Atom → Prop) (state : State) :
Formula Atom → Prop
| .atom a => valuation state a
| .top => True
| .not φ => ¬Satisfies lts valuation state φ
| .and φ ψ =>
Satisfies lts valuation state φ ∧ Satisfies lts valuation state ψ
| .existsNext φ =>
∃ label next, lts.Tr state label next ∧
Satisfies lts valuation next φ
| .existsUntil φ ψ =>
⋯
CSLibExt/Logics/CTL/Basic.lean:128
def lts (P : Protocol) : LTS State (Fin 3) where
Tr s i t := canMove P s i = true ∧ t = move s i
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:101
def ordered : Protocol :=
⟨fun i => min i (i + 1), fun i => max i (i + 1), by decide⟩
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:121
def eating : State → Fin 3 → Prop := fun s i => phase s i = 2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:109
def initial : State := (0, 0, 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:115
def forallGlobally (φ : Formula Atom) : Formula Atom :=
.not (existsFinally (.not φ))
CSLibExt/Logics/CTL/Basic.lean:112
TheoremEvery philosopher can still eat under resource ordering#✓fully proved
In the transition system of the three dining philosophers under the resource-ordered protocol, with the atom \(p_j\) holding when philosopher \(j\) eats, the initial state, in which everybody thinks, satisfies the CTL formula \(\mathrm{AG}\,\mathrm{EF}\,p_i\) for every philosopher \(i \in \{0, 1, 2\}\): from every state reachable from the initial state, some state in which philosopher \(i\) eats is reachable.
theorem ordered_can_eat (i : Fin 3) :
Satisfies (lts ordered) eating initial
(Formula.forallGlobally (Formula.existsFinally (.atom i)))
def Satisfies (lts : LTS State Label)
(valuation : State → Atom → Prop) (state : State) :
Formula Atom → Prop
| .atom a => valuation state a
| .top => True
| .not φ => ¬Satisfies lts valuation state φ
| .and φ ψ =>
Satisfies lts valuation state φ ∧ Satisfies lts valuation state ψ
| .existsNext φ =>
∃ label next, lts.Tr state label next ∧
Satisfies lts valuation next φ
| .existsUntil φ ψ =>
⋯
CSLibExt/Logics/CTL/Basic.lean:128
def lts (P : Protocol) : LTS State (Fin 3) where
Tr s i t := canMove P s i = true ∧ t = move s i
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:101
def ordered : Protocol :=
⟨fun i => min i (i + 1), fun i => max i (i + 1), by decide⟩
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:121
def eating : State → Fin 3 → Prop := fun s i => phase s i = 2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:109
def initial : State := (0, 0, 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:115
def forallGlobally (φ : Formula Atom) : Formula Atom :=
.not (existsFinally (.not φ))
CSLibExt/Logics/CTL/Basic.lean:112
def existsFinally (φ : Formula Atom) : Formula Atom :=
.existsUntil .top φ
CSLibExt/Logics/CTL/Basic.lean:99
Uses 15
TheoremMutual exclusion under the naive protocol#✓fully proved
For every philosopher \(i\), in the transition system of the naive protocol, with atom \(j\) read as "philosopher \(j\) is eating", the initial state satisfies \(\mathsf{AG}\) applied to the formula that philosophers \(i\) and \(i + 1\) (indices modulo \(3\)) do not both eat: in no state reachable from the initial state, where all philosophers are thinking, are philosophers \(i\) and \(i + 1\) both eating.
theorem naive_mutex (i : Fin 3) :
Satisfies (lts naive) eating initial (Formula.forallGlobally (neighboursApart i))
def Satisfies (lts : LTS State Label)
(valuation : State → Atom → Prop) (state : State) :
Formula Atom → Prop
| .atom a => valuation state a
| .top => True
| .not φ => ¬Satisfies lts valuation state φ
| .and φ ψ =>
Satisfies lts valuation state φ ∧ Satisfies lts valuation state ψ
| .existsNext φ =>
∃ label next, lts.Tr state label next ∧
Satisfies lts valuation next φ
| .existsUntil φ ψ =>
⋯
CSLibExt/Logics/CTL/Basic.lean:128
def lts (P : Protocol) : LTS State (Fin 3) where
Tr s i t := canMove P s i = true ∧ t = move s i
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:101
def naive : Protocol := ⟨fun i => i, fun i => i + 1, fun _ => Or.inl ⟨rfl, rfl⟩⟩
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:118
def eating : State → Fin 3 → Prop := fun s i => phase s i = 2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:109
def initial : State := (0, 0, 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:115
def forallGlobally (φ : Formula Atom) : Formula Atom :=
.not (existsFinally (.not φ))
CSLibExt/Logics/CTL/Basic.lean:112
def neighboursApart (i : Fin 3) : Formula (Fin 3) :=
.not (.and (.atom i) (.atom (i + 1)))
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:128
TheoremNeighbours never eat together under resource ordering#✓fully proved
In the transition system of the three dining philosophers under the resource-ordered protocol, with the atom \(p_j\) holding when philosopher \(j\) eats, the initial state, in which everybody thinks, satisfies the CTL formula \(\mathrm{AG}\,\neg(p_i \wedge p_{i+1})\) for every philosopher \(i \in \{0, 1, 2\}\), with indices modulo \(3\): in no state reachable from the initial state do philosophers \(i\) and \(i + 1\) both eat.
theorem ordered_mutex (i : Fin 3) :
Satisfies (lts ordered) eating initial (Formula.forallGlobally (neighboursApart i))
def Satisfies (lts : LTS State Label)
(valuation : State → Atom → Prop) (state : State) :
Formula Atom → Prop
| .atom a => valuation state a
| .top => True
| .not φ => ¬Satisfies lts valuation state φ
| .and φ ψ =>
Satisfies lts valuation state φ ∧ Satisfies lts valuation state ψ
| .existsNext φ =>
∃ label next, lts.Tr state label next ∧
Satisfies lts valuation next φ
| .existsUntil φ ψ =>
⋯
CSLibExt/Logics/CTL/Basic.lean:128
def lts (P : Protocol) : LTS State (Fin 3) where
Tr s i t := canMove P s i = true ∧ t = move s i
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:101
def ordered : Protocol :=
⟨fun i => min i (i + 1), fun i => max i (i + 1), by decide⟩
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:121
def eating : State → Fin 3 → Prop := fun s i => phase s i = 2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:109
def initial : State := (0, 0, 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:115
def forallGlobally (φ : Formula Atom) : Formula Atom :=
.not (existsFinally (.not φ))
CSLibExt/Logics/CTL/Basic.lean:112
def neighboursApart (i : Fin 3) : Formula (Fin 3) :=
.not (.and (.atom i) (.atom (i + 1)))
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:128
Uses 15
DefinitionEnabled moves under atomic acquisition#✓fully proved
Philosopher \(i\) can move in state \(s\) when it thinks and neither of its forks \(i\) and \(i + 1\) (modulo \(3\)) is held in \(s\), or when it eats (it then puts both forks down); a philosopher holding only its first fork cannot move. A fork is held as in the naive protocol: philosopher \(j\) holds fork \(j\) when it holds its first fork or eats, and holds fork \(j + 1\) when it eats.
def canMoveAtomic (s : State) (i : Fin 3) : Bool :=
match (phase s i).val with
| 0 => !held naive s i && !held naive s (i + 1)
| 1 => false
| _ => true
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
def phase (s : State) : Fin 3 → Fin 3
| 0 => s.1
| 1 => s.2.1
| 2 => s.2.2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:57
def naive : Protocol := ⟨fun i => i, fun i => i + 1, fun _ => Or.inl ⟨rfl, rfl⟩⟩
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:118
Uses 4 · Used by 4
DefinitionMove of a philosopher under atomic acquisition#✓fully proved
In a state \(s\) (the phases of the three philosophers), the move of philosopher \(i\) changes only the phase of \(i\): if \(i\) is thinking, it starts eating, picking up both forks at once; otherwise it goes back to thinking. The phases of the other two philosophers are unchanged.
def moveAtomic (s : State) (i : Fin 3) : State :=
setPhase s i (if (phase s i).val = 0 then 2 else 0)
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
def setPhase (s : State) (i : Fin 3) (p : Fin 3) : State :=
match i with
| 0 => (p, s.2.1, s.2.2)
| 1 => (s.1, p, s.2.2)
| 2 => (s.1, s.2.1, p)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:63
def phase (s : State) : Fin 3 → Fin 3
| 0 => s.1
| 1 => s.2.1
| 2 => s.2.2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:57
Uses 3 · Used by 4
DefinitionDining philosophers with atomic fork acquisition#✓fully proved
The labelled transition system on the states of the three philosophers, labelled by the philosopher that moves: there is a step labelled \(i\) from \(s\) to \(t\) exactly when either philosopher \(i\) thinks in \(s\), neither of its forks \(i\) and \(i + 1\) (modulo \(3\)) is held in \(s\), and \(t\) is \(s\) with philosopher \(i\) eating; or philosopher \(i\) eats in \(s\) and \(t\) is \(s\) with philosopher \(i\) thinking. A fork is held as in the naive protocol: philosopher \(j\) holds fork \(j\) when it holds its first fork or eats, and holds fork \(j + 1\) when it eats.
def atomicLts : LTS State (Fin 3) where
Tr s i t := canMoveAtomic s i = true ∧ t = moveAtomic s i
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
def canMoveAtomic (s : State) (i : Fin 3) : Bool :=
match (phase s i).val with
| 0 => !held naive s i && !held naive s (i + 1)
| 1 => false
| _ => true
CSLibExt/Algorithms/Concurrency/DiningPhilosophersVariants.lean:44
def moveAtomic (s : State) (i : Fin 3) : State :=
setPhase s i (if (phase s i).val = 0 then 2 else 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophersVariants.lean:52
Uses 3 · Used by 3
DefinitionNumber of seated philosophers#✓fully proved
The number of seated philosophers in a state \(s\) is the number of philosophers that hold at least one fork in \(s\), that is, whose phase is either holding the first fork or eating.
def seated (s : State) : ℕ :=
([0, 1, 2] : List (Fin 3)).countP fun i => decide (1 ≤ (phase s i).val)
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
def phase (s : State) : Fin 3 → Fin 3
| 0 => s.1
| 1 => s.2.1
| 2 => s.2.2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:57
Uses 2 · Used by 1
DefinitionEnabled moves under a butler#✓fully proved
Philosopher \(i\) can move in state \(s\) when it can move in \(s\) under the naive protocol and, if it is thinking, fewer than two philosophers hold at least one fork in \(s\). Under the naive protocol each philosopher \(i\) picks up the left fork \(i\) first and then the right fork \(i + 1\) (modulo \(3\)), each only when no philosopher holds it, and an eating philosopher can always put both forks down.
def canMoveButler (s : State) (i : Fin 3) : Bool :=
canMove naive s i && ((phase s i).val != 0 || decide (seated s < 2))
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
def canMove (P : Protocol) (s : State) (i : Fin 3) : Bool :=
match (phase s i).val with
| 0 => !held P s (P.first i)
| 1 => !held P s (P.second i)
| _ => true
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:88
def naive : Protocol := ⟨fun i => i, fun i => i + 1, fun _ => Or.inl ⟨rfl, rfl⟩⟩
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:118
def phase (s : State) : Fin 3 → Fin 3
| 0 => s.1
| 1 => s.2.1
| 2 => s.2.2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:57
def seated (s : State) : ℕ :=
([0, 1, 2] : List (Fin 3)).countP fun i => decide (1 ≤ (phase s i).val)
CSLibExt/Algorithms/Concurrency/DiningPhilosophersVariants.lean:63
Uses 5 · Used by 4
DefinitionDining philosophers with a butler#✓fully proved
The labelled transition system on the states of the three philosophers, labelled by the philosopher that moves: there is a step labelled \(i\) from \(s\) to \(t\) exactly when philosopher \(i\) can move in \(s\) under the naive protocol, if philosopher \(i\) is thinking then fewer than two philosophers hold a fork in \(s\), and \(t\) is \(s\) with philosopher \(i\) advanced one phase (thinking to holding its first fork, to eating, to thinking). Under the naive protocol each philosopher \(i\) picks up the left fork \(i\) first and then the right fork \(i + 1\) (modulo \(3\)), each only when no philosopher holds it, and an eating philosopher can always put both forks down.
def butlerLts : LTS State (Fin 3) where
Tr s i t := canMoveButler s i = true ∧ t = move s i
abbrev State := Fin 3 × Fin 3 × Fin 3
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:54
def canMoveButler (s : State) (i : Fin 3) : Bool :=
canMove naive s i && ((phase s i).val != 0 || decide (seated s < 2))
CSLibExt/Algorithms/Concurrency/DiningPhilosophersVariants.lean:68
def move (s : State) (i : Fin 3) : State :=
setPhase s i (match (phase s i).val with | 0 => 1 | 1 => 2 | _ => 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:96
Uses 3 · Used by 3
TheoremAtomic acquisition prevents deadlock#✓fully proved
In the dining philosophers transition system with atomic acquisition of both forks, every state reachable from the initial state (all three philosophers thinking) has a successor: some philosopher can move.
theorem atomic_deadlock_free :
Satisfies atomicLts eating initial (Formula.forallGlobally (.existsNext .top))
def Satisfies (lts : LTS State Label)
(valuation : State → Atom → Prop) (state : State) :
Formula Atom → Prop
| .atom a => valuation state a
| .top => True
| .not φ => ¬Satisfies lts valuation state φ
| .and φ ψ =>
Satisfies lts valuation state φ ∧ Satisfies lts valuation state ψ
| .existsNext φ =>
∃ label next, lts.Tr state label next ∧
Satisfies lts valuation next φ
| .existsUntil φ ψ =>
⋯
CSLibExt/Logics/CTL/Basic.lean:128
def atomicLts : LTS State (Fin 3) where
Tr s i t := canMoveAtomic s i = true ∧ t = moveAtomic s i
CSLibExt/Algorithms/Concurrency/DiningPhilosophersVariants.lean:56
def eating : State → Fin 3 → Prop := fun s i => phase s i = 2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:109
def initial : State := (0, 0, 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:115
def forallGlobally (φ : Formula Atom) : Formula Atom :=
.not (existsFinally (.not φ))
CSLibExt/Logics/CTL/Basic.lean:112
TheoremUnder atomic acquisition every philosopher can always still eat#✓fully proved
In the dining philosophers transition system with atomic acquisition of both forks, for each philosopher \(i \in \{0, 1, 2\}\), from every state reachable from the initial state (all three philosophers thinking) a state in which philosopher \(i\) eats is reachable, in zero or more steps.
theorem atomic_can_eat (i : Fin 3) :
Satisfies atomicLts eating initial
(Formula.forallGlobally (Formula.existsFinally (.atom i)))
def Satisfies (lts : LTS State Label)
(valuation : State → Atom → Prop) (state : State) :
Formula Atom → Prop
| .atom a => valuation state a
| .top => True
| .not φ => ¬Satisfies lts valuation state φ
| .and φ ψ =>
Satisfies lts valuation state φ ∧ Satisfies lts valuation state ψ
| .existsNext φ =>
∃ label next, lts.Tr state label next ∧
Satisfies lts valuation next φ
| .existsUntil φ ψ =>
⋯
CSLibExt/Logics/CTL/Basic.lean:128
def atomicLts : LTS State (Fin 3) where
Tr s i t := canMoveAtomic s i = true ∧ t = moveAtomic s i
CSLibExt/Algorithms/Concurrency/DiningPhilosophersVariants.lean:56
def eating : State → Fin 3 → Prop := fun s i => phase s i = 2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:109
def initial : State := (0, 0, 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:115
def forallGlobally (φ : Formula Atom) : Formula Atom :=
.not (existsFinally (.not φ))
CSLibExt/Logics/CTL/Basic.lean:112
def existsFinally (φ : Formula Atom) : Formula Atom :=
.existsUntil .top φ
CSLibExt/Logics/CTL/Basic.lean:99
TheoremMutual exclusion under atomic acquisition#✓fully proved
In the dining philosophers transition system with atomic acquisition of both forks, for each philosopher \(i \in \{0, 1, 2\}\), in no state reachable from the initial state (all three philosophers thinking) do philosopher \(i\) and its neighbour \(i + 1\) (modulo \(3\)) both eat.
theorem atomic_mutex (i : Fin 3) :
Satisfies atomicLts eating initial (Formula.forallGlobally (neighboursApart i))
def Satisfies (lts : LTS State Label)
(valuation : State → Atom → Prop) (state : State) :
Formula Atom → Prop
| .atom a => valuation state a
| .top => True
| .not φ => ¬Satisfies lts valuation state φ
| .and φ ψ =>
Satisfies lts valuation state φ ∧ Satisfies lts valuation state ψ
| .existsNext φ =>
∃ label next, lts.Tr state label next ∧
Satisfies lts valuation next φ
| .existsUntil φ ψ =>
⋯
CSLibExt/Logics/CTL/Basic.lean:128
def atomicLts : LTS State (Fin 3) where
Tr s i t := canMoveAtomic s i = true ∧ t = moveAtomic s i
CSLibExt/Algorithms/Concurrency/DiningPhilosophersVariants.lean:56
def eating : State → Fin 3 → Prop := fun s i => phase s i = 2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:109
def initial : State := (0, 0, 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:115
def forallGlobally (φ : Formula Atom) : Formula Atom :=
.not (existsFinally (.not φ))
CSLibExt/Logics/CTL/Basic.lean:112
def neighboursApart (i : Fin 3) : Formula (Fin 3) :=
.not (.and (.atom i) (.atom (i + 1)))
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:128
TheoremA butler prevents deadlock#✓fully proved
In the dining philosophers transition system of the naive protocol under a butler, every state reachable from the initial state (all three philosophers thinking) has a successor: some philosopher can move.
theorem butler_deadlock_free :
Satisfies butlerLts eating initial (Formula.forallGlobally (.existsNext .top))
def Satisfies (lts : LTS State Label)
(valuation : State → Atom → Prop) (state : State) :
Formula Atom → Prop
| .atom a => valuation state a
| .top => True
| .not φ => ¬Satisfies lts valuation state φ
| .and φ ψ =>
Satisfies lts valuation state φ ∧ Satisfies lts valuation state ψ
| .existsNext φ =>
∃ label next, lts.Tr state label next ∧
Satisfies lts valuation next φ
| .existsUntil φ ψ =>
⋯
CSLibExt/Logics/CTL/Basic.lean:128
def butlerLts : LTS State (Fin 3) where
Tr s i t := canMoveButler s i = true ∧ t = move s i
CSLibExt/Algorithms/Concurrency/DiningPhilosophersVariants.lean:72
def eating : State → Fin 3 → Prop := fun s i => phase s i = 2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:109
def initial : State := (0, 0, 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:115
def forallGlobally (φ : Formula Atom) : Formula Atom :=
.not (existsFinally (.not φ))
CSLibExt/Logics/CTL/Basic.lean:112
TheoremUnder a butler every philosopher can always still eat#✓fully proved
In the dining philosophers transition system of the naive protocol under a butler, for each philosopher \(i \in \{0, 1, 2\}\), from every state reachable from the initial state (all three philosophers thinking) a state in which philosopher \(i\) eats is reachable, in zero or more steps.
theorem butler_can_eat (i : Fin 3) :
Satisfies butlerLts eating initial
(Formula.forallGlobally (Formula.existsFinally (.atom i)))
def Satisfies (lts : LTS State Label)
(valuation : State → Atom → Prop) (state : State) :
Formula Atom → Prop
| .atom a => valuation state a
| .top => True
| .not φ => ¬Satisfies lts valuation state φ
| .and φ ψ =>
Satisfies lts valuation state φ ∧ Satisfies lts valuation state ψ
| .existsNext φ =>
∃ label next, lts.Tr state label next ∧
Satisfies lts valuation next φ
| .existsUntil φ ψ =>
⋯
CSLibExt/Logics/CTL/Basic.lean:128
def butlerLts : LTS State (Fin 3) where
Tr s i t := canMoveButler s i = true ∧ t = move s i
CSLibExt/Algorithms/Concurrency/DiningPhilosophersVariants.lean:72
def eating : State → Fin 3 → Prop := fun s i => phase s i = 2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:109
def initial : State := (0, 0, 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:115
def forallGlobally (φ : Formula Atom) : Formula Atom :=
.not (existsFinally (.not φ))
CSLibExt/Logics/CTL/Basic.lean:112
def existsFinally (φ : Formula Atom) : Formula Atom :=
.existsUntil .top φ
CSLibExt/Logics/CTL/Basic.lean:99
TheoremMutual exclusion under a butler#✓fully proved
In the dining philosophers transition system of the naive protocol under a butler, for each philosopher \(i \in \{0, 1, 2\}\), in no state reachable from the initial state (all three philosophers thinking) do philosopher \(i\) and its neighbour \(i + 1\) (modulo \(3\)) both eat.
theorem butler_mutex (i : Fin 3) :
Satisfies butlerLts eating initial (Formula.forallGlobally (neighboursApart i))
def Satisfies (lts : LTS State Label)
(valuation : State → Atom → Prop) (state : State) :
Formula Atom → Prop
| .atom a => valuation state a
| .top => True
| .not φ => ¬Satisfies lts valuation state φ
| .and φ ψ =>
Satisfies lts valuation state φ ∧ Satisfies lts valuation state ψ
| .existsNext φ =>
∃ label next, lts.Tr state label next ∧
Satisfies lts valuation next φ
| .existsUntil φ ψ =>
⋯
CSLibExt/Logics/CTL/Basic.lean:128
def butlerLts : LTS State (Fin 3) where
Tr s i t := canMoveButler s i = true ∧ t = move s i
CSLibExt/Algorithms/Concurrency/DiningPhilosophersVariants.lean:72
def eating : State → Fin 3 → Prop := fun s i => phase s i = 2
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:109
def initial : State := (0, 0, 0)
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:115
def forallGlobally (φ : Formula Atom) : Formula Atom :=
.not (existsFinally (.not φ))
CSLibExt/Logics/CTL/Basic.lean:112
def neighboursApart (i : Fin 3) : Formula (Fin 3) :=
.not (.and (.atom i) (.atom (i + 1)))
CSLibExt/Algorithms/Concurrency/DiningPhilosophers.lean:128
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.