TheAlgorithms-Python

Форк
0
/
bankers_algorithm.py 
222 строки · 8.2 Кб
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
from __future__ import annotations
19

20
import numpy as np
21

22
test_claim_vector = [8, 5, 9, 7]
23
test_allocated_res_table = [
24
    [2, 0, 1, 1],
25
    [0, 1, 2, 1],
26
    [4, 0, 0, 3],
27
    [0, 2, 1, 0],
28
    [1, 0, 3, 0],
29
]
30
test_maximum_claim_table = [
31
    [3, 2, 1, 4],
32
    [0, 2, 5, 2],
33
    [5, 1, 0, 5],
34
    [1, 5, 3, 0],
35
    [3, 0, 3, 3],
36
]
37

38

39
class BankersAlgorithm:
40
    def __init__(
41
        self,
42
        claim_vector: list[int],
43
        allocated_resources_table: list[list[int]],
44
        maximum_claim_table: list[list[int]],
45
    ) -> None:
46
        """
47
        :param claim_vector: A nxn/nxm list depicting the amount of each resources
48
         (eg. memory, interface, semaphores, etc.) available.
49
        :param allocated_resources_table: A nxn/nxm list depicting the amount of each
50
         resource each process is currently holding
51
        :param maximum_claim_table: A nxn/nxm list depicting how much of each resource
52
         the system currently has available
53
        """
54
        self.__claim_vector = claim_vector
55
        self.__allocated_resources_table = allocated_resources_table
56
        self.__maximum_claim_table = maximum_claim_table
57

58
    def __processes_resource_summation(self) -> list[int]:
59
        """
60
        Check for allocated resources in line with each resource in the claim vector
61
        """
62
        return [
63
            sum(p_item[i] for p_item in self.__allocated_resources_table)
64
            for i in range(len(self.__allocated_resources_table[0]))
65
        ]
66

67
    def __available_resources(self) -> list[int]:
68
        """
69
        Check for available resources in line with each resource in the claim vector
70
        """
71
        return np.array(self.__claim_vector) - np.array(
72
            self.__processes_resource_summation()
73
        )
74

75
    def __need(self) -> list[list[int]]:
76
        """
77
        Implement safety checker that calculates the needs by ensuring that
78
        max_claim[i][j] - alloc_table[i][j] <= avail[j]
79
        """
80
        return [
81
            list(np.array(self.__maximum_claim_table[i]) - np.array(allocated_resource))
82
            for i, allocated_resource in enumerate(self.__allocated_resources_table)
83
        ]
84

85
    def __need_index_manager(self) -> dict[int, list[int]]:
86
        """
87
        This function builds an index control dictionary to track original ids/indices
88
        of processes when altered during execution of method "main"
89
            Return: {0: [a: int, b: int], 1: [c: int, d: int]}
90
        >>> (BankersAlgorithm(test_claim_vector, test_allocated_res_table,
91
        ...     test_maximum_claim_table)._BankersAlgorithm__need_index_manager()
92
        ...     )  # doctest: +NORMALIZE_WHITESPACE
93
        {0: [1, 2, 0, 3], 1: [0, 1, 3, 1], 2: [1, 1, 0, 2], 3: [1, 3, 2, 0],
94
         4: [2, 0, 0, 3]}
95
        """
96
        return {self.__need().index(i): i for i in self.__need()}
97

98
    def main(self, **kwargs) -> None:
99
        """
100
        Utilize various methods in this class to simulate the Banker's algorithm
101
        Return: None
102
        >>> BankersAlgorithm(test_claim_vector, test_allocated_res_table,
103
        ...    test_maximum_claim_table).main(describe=True)
104
                 Allocated Resource Table
105
        P1       2        0        1        1
106
        <BLANKLINE>
107
        P2       0        1        2        1
108
        <BLANKLINE>
109
        P3       4        0        0        3
110
        <BLANKLINE>
111
        P4       0        2        1        0
112
        <BLANKLINE>
113
        P5       1        0        3        0
114
        <BLANKLINE>
115
                 System Resource Table
116
        P1       3        2        1        4
117
        <BLANKLINE>
118
        P2       0        2        5        2
119
        <BLANKLINE>
120
        P3       5        1        0        5
121
        <BLANKLINE>
122
        P4       1        5        3        0
123
        <BLANKLINE>
124
        P5       3        0        3        3
125
        <BLANKLINE>
126
        Current Usage by Active Processes: 8 5 9 7
127
        Initial Available Resources:       1 2 2 2
128
        __________________________________________________
129
        <BLANKLINE>
130
        Process 3 is executing.
131
        Updated available resource stack for processes: 5 2 2 5
132
        The process is in a safe state.
133
        <BLANKLINE>
134
        Process 1 is executing.
135
        Updated available resource stack for processes: 7 2 3 6
136
        The process is in a safe state.
137
        <BLANKLINE>
138
        Process 2 is executing.
139
        Updated available resource stack for processes: 7 3 5 7
140
        The process is in a safe state.
141
        <BLANKLINE>
142
        Process 4 is executing.
143
        Updated available resource stack for processes: 7 5 6 7
144
        The process is in a safe state.
145
        <BLANKLINE>
146
        Process 5 is executing.
147
        Updated available resource stack for processes: 8 5 9 7
148
        The process is in a safe state.
149
        <BLANKLINE>
150
        """
151
        need_list = self.__need()
152
        alloc_resources_table = self.__allocated_resources_table
153
        available_resources = self.__available_resources()
154
        need_index_manager = self.__need_index_manager()
155
        for kw, val in kwargs.items():
156
            if kw and val is True:
157
                self.__pretty_data()
158
        print("_" * 50 + "\n")
159
        while need_list:
160
            safe = False
161
            for each_need in need_list:
162
                execution = True
163
                for index, need in enumerate(each_need):
164
                    if need > available_resources[index]:
165
                        execution = False
166
                        break
167
                if execution:
168
                    safe = True
169
                    # get the original index of the process from ind_ctrl db
170
                    for original_need_index, need_clone in need_index_manager.items():
171
                        if each_need == need_clone:
172
                            process_number = original_need_index
173
                    print(f"Process {process_number + 1} is executing.")
174
                    # remove the process run from stack
175
                    need_list.remove(each_need)
176
                    # update available/freed resources stack
177
                    available_resources = np.array(available_resources) + np.array(
178
                        alloc_resources_table[process_number]
179
                    )
180
                    print(
181
                        "Updated available resource stack for processes: "
182
                        + " ".join([str(x) for x in available_resources])
183
                    )
184
                    break
185
            if safe:
186
                print("The process is in a safe state.\n")
187
            else:
188
                print("System in unsafe state. Aborting...\n")
189
                break
190

191
    def __pretty_data(self):
192
        """
193
        Properly align display of the algorithm's solution
194
        """
195
        print(" " * 9 + "Allocated Resource Table")
196
        for item in self.__allocated_resources_table:
197
            print(
198
                f"P{self.__allocated_resources_table.index(item) + 1}"
199
                + " ".join(f"{it:>8}" for it in item)
200
                + "\n"
201
            )
202
        print(" " * 9 + "System Resource Table")
203
        for item in self.__maximum_claim_table:
204
            print(
205
                f"P{self.__maximum_claim_table.index(item) + 1}"
206
                + " ".join(f"{it:>8}" for it in item)
207
                + "\n"
208
            )
209
        print(
210
            "Current Usage by Active Processes: "
211
            + " ".join(str(x) for x in self.__claim_vector)
212
        )
213
        print(
214
            "Initial Available Resources:       "
215
            + " ".join(str(x) for x in self.__available_resources())
216
        )
217

218

219
if __name__ == "__main__":
220
    import doctest
221

222
    doctest.testmod()
223

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.