Banker's algorithm
Banker
StructureClaims and allocations of processes#✓fully proved
A system with processes \(P\) and resource types \(R\) consists of two maps \(\mathrm{claim}, \mathrm{alloc} : P \to (R \to \mathbb{N})\), where \(\mathrm{claim}(p)\) is the maximum demand of process \(p\) for each resource type and \(\mathrm{alloc}(p)\) is the amount of each resource type currently allocated to \(p\). No inequality between the two is required.
@[ext]
structure System (P R : Type*) where
/-- The maximum demand of each process. -/
claim : P → R → ℕ
/-- The resources currently allocated to each process. -/
alloc : P → R → ℕ
Used by 15
System
DefinitionRemaining need#✓fully proved
The remaining need of a process \(p\) in a system \(S\) is the resource vector \(\mathrm{claim}(p) - \mathrm{alloc}(p)\): the maximum claim of \(p\) minus its current allocation, computed for each resource type by truncated subtraction of natural numbers, so it is \(0\) for every resource type where the allocation exceeds the claim.
def need (p : P) : R → ℕ := S.claim p - S.alloc p
Uses 1 · Used by 11
DefinitionSafe sequence#✓fully proved
Let \(S\) be a system with processes \(P\) and resource types \(R\), where process \(p\) has maximum claim \(\mathrm{claim}(p)\) and allocation \(\mathrm{alloc}(p)\) in \(R \to \mathbb{N}\). A list \(p_1, \dots, p_k\) of processes is a safe sequence from the free resource vector \(w : R \to \mathbb{N}\) when, for each \(i\), the remaining need \(\mathrm{claim}(p_i) - \mathrm{alloc}(p_i)\) (truncated at zero) is at most \(w + \mathrm{alloc}(p_1) + \cdots + \mathrm{alloc}(p_{i-1})\) componentwise. In particular the empty list is a safe sequence from every \(w\).
Thus each process in turn can be given its remaining need from what is free, finish, and release its allocation.
def SafeSeq : (R → ℕ) → List P → Prop
| _, [] => True
| work, p :: rest => S.need p ≤ work ∧ SafeSeq (work + S.alloc p) rest
Uses 2 · Used by 6
DefinitionSafe state#✓fully proved
Let \(S\) be a system of claims and allocations with processes \(P\) and resource types \(R\). A list of pending processes is safe from the free resource vector \(w : R \to \mathbb{N}\) when it has no repetitions and some permutation of it is a safe sequence from \(w\): the pending processes can all finish, one after another, in some order.
def Safe (work : R → ℕ) (pending : List P) : Prop :=
pending.Nodup ∧ ∃ σ, σ.Perm pending ∧ S.SafeSeq work σ
Uses 2 · Used by 5
TheoremSafe sequences are monotone in the free resources#✓fully proved
Let \(S\) be a system of processes with maximum claims and current allocations, and let \(\sigma\) be a list of processes. If \(\sigma\) is a safe sequence for \(S\) from a vector \(w\) of free resources (a natural number for each resource type), and \(w \le w'\) componentwise, then \(\sigma\) is also a safe sequence for \(S\) from \(w'\).
theorem SafeSeq.mono {work work' : R → ℕ} (hle : work ≤ work') {σ : List P}
(h : S.SafeSeq work σ) : S.SafeSeq work' σ
Uses 3
TheoremRemoving a process from a safe sequence#✓fully proved
Let \(S\) be a system of processes with maximum claims and current allocations, let \(w\) be a vector of free resources (a natural number for each resource type), and let \(\sigma\) be a list of processes that is a safe sequence for \(S\) from \(w\). If \(p\) occurs in \(\sigma\), then the list obtained from \(\sigma\) by deleting the first occurrence of \(p\) is a safe sequence for \(S\) from \(w + \mathrm{alloc}(p)\), where \(\mathrm{alloc}(p)\) is the current allocation of \(p\) and the sum is taken componentwise.
In other words, letting a member of a safe sequence finish first and release its allocation leaves the rest of the sequence safe. This is why the greedy safety check is complete.
theorem SafeSeq.erase {work : R → ℕ} {σ : List P} {p : P} (h : S.SafeSeq work σ)
(hp : p ∈ σ) : S.SafeSeq (work + S.alloc p) (σ.erase p)
Uses 3 · Used by 1
TheoremA safe state is not deadlocked#✓fully proved
Let \(S\) be a system of processes with maximum claims and current allocations, let \(w\) be a vector of free resources (a natural number for each resource type), and let \(L\) be a nonempty list of pending processes. If \(S\) is safe from \(w\) for \(L\), then some process \(p\) in \(L\) has remaining need \(\mathrm{need}(p) \le w\) componentwise, so it can be given its whole remaining need.
theorem Safe.exists_runnable {work : R → ℕ} {pending : List P} (h : S.Safe work pending)
(hne : pending ≠ []) : ∃ p ∈ pending, S.need p ≤ work
Uses 4 · Used by 1
TheoremLetting a process that fits finish preserves safety#✓fully proved
Let \(S\) be a system of processes with maximum claims and current allocations, \(w\) a vector of free resources (a natural number for each resource type) and \(L\) a list of pending processes without repetitions. If \(p\) occurs in \(L\) and its remaining need \(\mathrm{need}(p)\) in \(S\) satisfies \(\mathrm{need}(p) \le w\) componentwise, then \(S\) is safe from \(w\) for \(L\) if and only if \(S\) is safe from \(w + \mathrm{alloc}(p)\) for the list obtained from \(L\) by removing \(p\), where \(\mathrm{alloc}(p)\) is the current allocation of \(p\) and the sum is taken componentwise.
theorem safe_iff_safe_erase {work : R → ℕ} {pending : List P} {p : P} (hnd : pending.Nodup)
(hp : p ∈ pending) (hfit : S.need p ≤ work) :
S.Safe work pending ↔ S.Safe (work + S.alloc p) (pending.erase p)
Uses 5 · Used by 1
DefinitionBanker's safety algorithm with fuel#✓fully proved
Let \(S\) be a system with processes \(P\) and a finite set \(R\) of resource types, where process \(p\) has maximum claim \(\mathrm{claim}(p)\) and allocation \(\mathrm{alloc}(p)\) in \(R \to \mathbb{N}\). Given a fuel \(n \in \mathbb{N}\), a free resource vector \(w : R \to \mathbb{N}\) and a list of pending processes, the algorithm succeeds if the list is empty. Otherwise, if \(n > 0\) and some pending process \(q\) has remaining need \(\mathrm{claim}(q) - \mathrm{alloc}(q)\) (truncated at zero) at most \(w\) componentwise, it takes the first such process \(p\) in the list, removes that occurrence of \(p\) from the list, adds \(\mathrm{alloc}(p)\) to \(w\) and continues with fuel \(n - 1\); if \(n = 0\) or no pending process fits, it fails.
def safetyCheckAux : ℕ → (R → ℕ) → List P → Bool
| 0, _, pending => pending.isEmpty
| fuel + 1, work, pending =>
match pending.find? (fun p => decide (S.need p ≤ work)) with
| none => pending.isEmpty
| some p => safetyCheckAux fuel (work + S.alloc p) (pending.erase p)
Uses 2 · Used by 2
DefinitionBanker's safety algorithm#✓fully proved
Let \(S\) be a system of claims and allocations with processes \(P\) and a finite set \(R\) of resource types. Given a free resource vector \(w : R \to \mathbb{N}\) and a list of pending processes, the algorithm fails if the list has a repetition. Otherwise it runs the safety algorithm with fuel equal to the length of the list: it repeatedly lets the first pending process whose remaining need (claim minus allocation, truncated at zero) is at most the free resources componentwise finish and adds its allocation to the free resources, for at most one round per pending process, and it succeeds exactly when no pending process is left at the end.
TheoremCorrectness of the safety algorithm#✓fully proved
For every system \(S\) of claims and allocations over a finite set \(R\) of resource types, every free resource vector \(w : R \to \mathbb{N}\) and every list of pending processes, the banker's safety algorithm succeeds on \(w\) and the list if and only if the list is a safe state from \(w\).
theorem safetyCheck_iff (work : R → ℕ) (pending : List P) :
S.safetyCheck work pending = true ↔ S.Safe work pending
Uses 8 · Used by 1
DefinitionGranting a request#✓fully proved
For a system \(S\) of processes with maximum claims and current allocations, a process \(p\) and a resource vector \(r\) (a natural number for each resource type), the system obtained by granting \(r\) to \(p\) has the same maximum claims as \(S\), gives \(p\) the allocation \(\mathrm{alloc}(p) + r\) (componentwise sum, where \(\mathrm{alloc}(p)\) is the current allocation of \(p\) in \(S\)), and leaves the allocation of every other process unchanged.
def grant (S : System P R) (p : P) (req : R → ℕ) : System P R :=
⟨S.claim, Function.update S.alloc p (S.alloc p + req)⟩
@[ext]
structure System (P R : Type*) where
/-- The maximum demand of each process. -/
claim : P → R → ℕ
/-- The resources currently allocated to each process. -/
alloc : P → R → ℕ
CSLibExt/Algorithms/Concurrency/Banker.lean:61
TheoremRemaining need after a grant#✓fully proved
For a system \(S\) of processes with maximum claims and current allocations, a process \(p\) and a resource vector \(r\) (a natural number for each resource type), the remaining need of \(p\) in the system obtained by granting \(r\) to \(p\) equals \(\mathrm{need}(p) - r\), where \(\mathrm{need}(p)\) is the remaining need of \(p\) in \(S\) and the subtraction is truncated subtraction of natural numbers, taken componentwise.
@[simp] theorem need_grant_self (S : System P R) (p : P) (req : R → ℕ) :
(S.grant p req).need p = S.need p - req
@[ext]
structure System (P R : Type*) where
/-- The maximum demand of each process. -/
claim : P → R → ℕ
/-- The resources currently allocated to each process. -/
alloc : P → R → ℕ
CSLibExt/Algorithms/Concurrency/Banker.lean:61
Uses 3
DefinitionResource-request algorithm#✓fully proved
Let \(S\) be a system of claims and allocations with processes \(P\) and a finite set \(R\) of resource types, let \(a : R \to \mathbb{N}\) be the vector of free resources, \(L\) a list of pending processes, \(p\) a process and \(r : R \to \mathbb{N}\) the resources that \(p\) requests. The request is granted when \(p\) occurs in \(L\), \(L\) has no repetitions, \(r \le \mathrm{need}(p)\) and \(r \le a\) componentwise, where \(\mathrm{need}(p)\) is the remaining need of \(p\) in \(S\), and the banker's safety algorithm succeeds for the system obtained from \(S\) by granting \(r\) to \(p\), from the free vector \(a - r\) (componentwise truncated subtraction) and the list \(L\). A granted request returns the free vector \(a - r\) and that system; otherwise the algorithm returns no result.
No result covers the error case of the textbook algorithm (a request beyond the remaining claim), the cases where the process must wait, and malformed input (a requester that is not pending, or a pending list with repetitions).
def request (S : System P R) (available : R → ℕ) (pending : List P) (p : P)
(req : R → ℕ) : Option ((R → ℕ) × System P R) :=
if p ∈ pending ∧ pending.Nodup ∧ req ≤ S.need p ∧ req ≤ available ∧
(S.grant p req).safetyCheck (available - req) pending
then some (available - req, S.grant p req)
else none
@[ext]
structure System (P R : Type*) where
/-- The maximum demand of each process. -/
claim : P → R → ℕ
/-- The resources currently allocated to each process. -/
alloc : P → R → ℕ
CSLibExt/Algorithms/Concurrency/Banker.lean:61
TheoremThe request algorithm grants exactly the safe requests within the claim and the free resources#✓fully proved
The request algorithm grants exactly the safe requests within the claim and the free resources. Let \(S\) be a system of claims and allocations with processes \(P\) and a finite set \(R\) of resource types, let \(a : R \to \mathbb{N}\) be the vector of free resources, \(L\) a list of pending processes, \(p\) a process and \(r : R \to \mathbb{N}\) the resources that \(p\) requests. Write \(\mathrm{need}(p)\) for the remaining need of \(p\) in \(S\), \(T\) for the system obtained from \(S\) by granting \(r\) to \(p\), and \(a - r\) for componentwise truncated subtraction. The resource-request algorithm grants the request and returns the free vector \(a'\) and the system \(S'\) if and only if \(p\) occurs in \(L\), \(L\) has no repetitions, both \(r \le \mathrm{need}(p)\) and \(r \le a\) hold componentwise, \(T\) is safe from \(a - r\) for \(L\), \(a' = a - r\), and \(S' = T\).
theorem request_eq_some_iff {available : R → ℕ} {pending : List P} {p : P} {req : R → ℕ}
{available' : R → ℕ} {S' : System P R} :
request S available pending p req = some (available', S') ↔
p ∈ pending ∧ pending.Nodup ∧ req ≤ S.need p ∧ req ≤ available ∧
(S.grant p req).Safe (available - req) pending ∧
available' = available - req ∧ S' = S.grant p req
@[ext]
structure System (P R : Type*) where
/-- The maximum demand of each process. -/
claim : P → R → ℕ
/-- The resources currently allocated to each process. -/
alloc : P → R → ℕ
CSLibExt/Algorithms/Concurrency/Banker.lean:61
def request (S : System P R) (available : R → ℕ) (pending : List P) (p : P)
(req : R → ℕ) : Option ((R → ℕ) × System P R) :=
if p ∈ pending ∧ pending.Nodup ∧ req ≤ S.need p ∧ req ≤ available ∧
(S.grant p req).safetyCheck (available - req) pending
then some (available - req, S.grant p req)
else none
CSLibExt/Algorithms/Concurrency/Banker.lean:234
Uses 7 · Used by 1
TheoremGranted requests lead to safe states#✓fully proved
Let \(S\) be a system of processes with maximum claims and current allocations, \(a\) the vector of free resources, \(L\) the list of pending processes, \(p\) a process and \(r\) a resource vector. If the resource-request algorithm grants the request of \(r\) by \(p\), returning the free vector \(a'\) and the system \(S'\), then \(S'\) is safe from \(a'\) for \(L\).
theorem request_safe {available : R → ℕ} {pending : List P} {p : P} {req : R → ℕ}
{available' : R → ℕ} {S' : System P R}
(h : request S available pending p req = some (available', S')) :
S'.Safe available' pending
@[ext]
structure System (P R : Type*) where
/-- The maximum demand of each process. -/
claim : P → R → ℕ
/-- The resources currently allocated to each process. -/
alloc : P → R → ℕ
CSLibExt/Algorithms/Concurrency/Banker.lean:61
def request (S : System P R) (available : R → ℕ) (pending : List P) (p : P)
(req : R → ℕ) : Option ((R → ℕ) × System P R) :=
if p ∈ pending ∧ pending.Nodup ∧ req ≤ S.need p ∧ req ≤ available ∧
(S.grant p req).safetyCheck (available - req) pending
then some (available - req, S.grant p req)
else none
CSLibExt/Algorithms/Concurrency/Banker.lean:234
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.