Skip to content

Commit 1d606d8

Browse files
cclausspoyea
authored andcommitted
Dijkstra's Bankers algorithm (TheAlgorithms#1650)
* Dijkstra's Bankers algorithm @bluedistro, Your review please. A second shot at TheAlgorithms#1645 Implementation of the Dijkstra's Banker's algorithm with test examples and a comprehensible description. * fixup! Format Python code with psf/black push * Delete back_propagation_neural_network.py * Create back_propagation_neural_network.py * fixup! Format Python code with psf/black push
1 parent 28419cf commit 1d606d8

File tree

1 file changed

+222
-0
lines changed

1 file changed

+222
-0
lines changed

other/dijkstra_bankers_algorithm.py

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
# A Python implementation of the Banker's Algorithm in Operating Systems using
2+
# Processes and Resources
3+
# {
4+
# "Author: "Biney Kingsley (bluedistro@github.io), bineykingsley36@gmail.com",
5+
# "Date": 28-10-2018
6+
# }
7+
"""
8+
The Banker's algorithm is a resource allocation and deadlock avoidance algorithm
9+
developed by Edsger Dijkstra that tests for safety by simulating the allocation of
10+
predetermined maximum possible amounts of all resources, and then makes a "s-state"
11+
check to test for possible deadlock conditions for all other pending activities,
12+
before deciding whether allocation should be allowed to continue.
13+
[Source] Wikipedia
14+
[Credit] Rosetta Code C implementation helped very much.
15+
(https://rosettacode.org/wiki/Banker%27s_algorithm)
16+
"""
17+
18+
import time
19+
from typing import Dict, List
20+
21+
import numpy as np
22+
23+
test_claim_vector = [8, 5, 9, 7]
24+
test_allocated_res_table = [
25+
[2, 0, 1, 1],
26+
[0, 1, 2, 1],
27+
[4, 0, 0, 3],
28+
[0, 2, 1, 0],
29+
[1, 0, 3, 0],
30+
]
31+
test_maximum_claim_table = [
32+
[3, 2, 1, 4],
33+
[0, 2, 5, 2],
34+
[5, 1, 0, 5],
35+
[1, 5, 3, 0],
36+
[3, 0, 3, 3],
37+
]
38+
39+
40+
class BankersAlgorithm:
41+
def __init__(
42+
self,
43+
claim_vector: List[int],
44+
allocated_resources_table: List[List[int]],
45+
maximum_claim_table: List[List[int]],
46+
) -> None:
47+
"""
48+
:param claim_vector: A nxn/nxm list depicting the amount of each resources
49+
(eg. memory, interface, semaphores, etc.) available.
50+
:param allocated_resources_table: A nxn/nxm list depicting the amount of each
51+
resource each process is currently holding
52+
:param maximum_claim_table: A nxn/nxm list depicting how much of each resource
53+
the system currently has available
54+
"""
55+
self.__claim_vector = claim_vector
56+
self.__allocated_resources_table = allocated_resources_table
57+
self.__maximum_claim_table = maximum_claim_table
58+
59+
def __processes_resource_summation(self) -> List[int]:
60+
"""
61+
Check for allocated resources in line with each resource in the claim vector
62+
"""
63+
return [
64+
sum(p_item[i] for p_item in self.__allocated_resources_table)
65+
for i in range(len(self.__allocated_resources_table[0]))
66+
]
67+
68+
def __available_resources(self) -> List[int]:
69+
"""
70+
Check for available resources in line with each resource in the claim vector
71+
"""
72+
return np.array(self.__claim_vector) - np.array(
73+
self.__processes_resource_summation()
74+
)
75+
76+
def __need(self) -> List[List[int]]:
77+
"""
78+
Implement safety checker that calculates the needs by ensuring that
79+
max_claim[i][j] - alloc_table[i][j] <= avail[j]
80+
"""
81+
return [
82+
list(np.array(self.__maximum_claim_table[i]) - np.array(allocated_resource))
83+
for i, allocated_resource in enumerate(self.__allocated_resources_table)
84+
]
85+
86+
def __need_index_manager(self) -> Dict[int, List[int]]:
87+
"""
88+
This function builds an index control dictionary to track original ids/indices
89+
of processes when altered during execution of method "main"
90+
Return: {0: [a: int, b: int], 1: [c: int, d: int]}
91+
>>> BankersAlgorithm(test_claim_vector, test_allocated_res_table,
92+
... test_maximum_claim_table)._BankersAlgorithm__need_index_manager()
93+
{0: [1, 2, 0, 3], 1: [0, 1, 3, 1], 2: [1, 1, 0, 2], 3: [1, 3, 2, 0], 4: [2, 0, 0, 3]}
94+
"""
95+
return {self.__need().index(i): i for i in self.__need()}
96+
97+
def main(self, **kwargs) -> None:
98+
"""
99+
Utilize various methods in this class to simulate the Banker's algorithm
100+
Return: None
101+
>>> BankersAlgorithm(test_claim_vector, test_allocated_res_table,
102+
... test_maximum_claim_table).main(describe=True)
103+
Allocated Resource Table
104+
P1 2 0 1 1
105+
<BLANKLINE>
106+
P2 0 1 2 1
107+
<BLANKLINE>
108+
P3 4 0 0 3
109+
<BLANKLINE>
110+
P4 0 2 1 0
111+
<BLANKLINE>
112+
P5 1 0 3 0
113+
<BLANKLINE>
114+
System Resource Table
115+
P1 3 2 1 4
116+
<BLANKLINE>
117+
P2 0 2 5 2
118+
<BLANKLINE>
119+
P3 5 1 0 5
120+
<BLANKLINE>
121+
P4 1 5 3 0
122+
<BLANKLINE>
123+
P5 3 0 3 3
124+
<BLANKLINE>
125+
Current Usage by Active Processes: 8 5 9 7
126+
Initial Available Resources: 1 2 2 2
127+
__________________________________________________
128+
<BLANKLINE>
129+
Process 3 is executing.
130+
Updated available resource stack for processes: 5 2 2 5
131+
The process is in a safe state.
132+
<BLANKLINE>
133+
Process 1 is executing.
134+
Updated available resource stack for processes: 7 2 3 6
135+
The process is in a safe state.
136+
<BLANKLINE>
137+
Process 2 is executing.
138+
Updated available resource stack for processes: 7 3 5 7
139+
The process is in a safe state.
140+
<BLANKLINE>
141+
Process 4 is executing.
142+
Updated available resource stack for processes: 7 5 6 7
143+
The process is in a safe state.
144+
<BLANKLINE>
145+
Process 5 is executing.
146+
Updated available resource stack for processes: 8 5 9 7
147+
The process is in a safe state.
148+
<BLANKLINE>
149+
"""
150+
need_list = self.__need()
151+
alloc_resources_table = self.__allocated_resources_table
152+
available_resources = self.__available_resources()
153+
need_index_manager = self.__need_index_manager()
154+
for kw, val in kwargs.items():
155+
if kw and val is True:
156+
self.__pretty_data()
157+
print("_" * 50 + "\n")
158+
while need_list:
159+
safe = False
160+
for each_need in need_list:
161+
execution = True
162+
for index, need in enumerate(each_need):
163+
if need > available_resources[index]:
164+
execution = False
165+
break
166+
if execution:
167+
safe = True
168+
# get the original index of the process from ind_ctrl db
169+
for original_need_index, need_clone in need_index_manager.items():
170+
if each_need == need_clone:
171+
process_number = original_need_index
172+
print(f"Process {process_number + 1} is executing.")
173+
# remove the process run from stack
174+
need_list.remove(each_need)
175+
# update available/freed resources stack
176+
available_resources = np.array(available_resources) + np.array(
177+
alloc_resources_table[process_number]
178+
)
179+
print(
180+
"Updated available resource stack for processes: "
181+
+ " ".join([str(x) for x in available_resources])
182+
)
183+
break
184+
if safe:
185+
print("The process is in a safe state.\n")
186+
else:
187+
print("System in unsafe state. Aborting...\n")
188+
break
189+
190+
def __pretty_data(self):
191+
"""
192+
Properly align display of the algorithm's solution
193+
"""
194+
print(" " * 9 + "Allocated Resource Table")
195+
for item in self.__allocated_resources_table:
196+
print(
197+
f"P{self.__allocated_resources_table.index(item) + 1}"
198+
+ " ".join(f"{it:>8}" for it in item)
199+
+ "\n"
200+
)
201+
print(" " * 9 + "System Resource Table")
202+
for item in self.__maximum_claim_table:
203+
print(
204+
f"P{self.__maximum_claim_table.index(item) + 1}"
205+
+ " ".join(f"{it:>8}" for it in item)
206+
+ "\n"
207+
)
208+
print(
209+
"Current Usage by Active Processes: "
210+
+ " ".join(str(x) for x in self.__claim_vector)
211+
)
212+
print(
213+
"Initial Available Resources: "
214+
+ " ".join(str(x) for x in self.__available_resources())
215+
)
216+
time.sleep(1)
217+
218+
219+
if __name__ == "__main__":
220+
import doctest
221+
222+
doctest.testmod()

0 commit comments

Comments
 (0)