|
7 | 7 | from decimal import Decimal, getcontext
|
8 | 8 | from collections import namedtuple
|
9 | 9 |
|
| 10 | +import tqdm |
10 | 11 | import yaml
|
11 | 12 | import numpy.random as nprandom
|
12 | 13 |
|
|
20 | 21 | from .state_tracker import *
|
21 | 22 | from .deadlock_detector import *
|
22 | 23 |
|
23 |
| - |
24 | 24 | Record = namedtuple('Record', 'id_number customer_class node arrival_date waiting_time service_start_date service_time service_end_date time_blocked exit_date destination queue_size_at_arrival queue_size_at_departure')
|
25 | 25 |
|
26 | 26 | class Simulation(object):
|
@@ -86,6 +86,31 @@ def choose_tracker(self, tracker, deadlock_detector):
|
86 | 86 | return NaiveTracker(self)
|
87 | 87 | return StateTracker(self)
|
88 | 88 |
|
| 89 | + def detect_deadlock(self): |
| 90 | + """ |
| 91 | + Detects whether the system is in a deadlocked state, |
| 92 | + that is, is there a knot. Note that this code is taken |
| 93 | + and adapted from the NetworkX Developer Zone Ticket |
| 94 | + #663 knot.py (09/06/2015) |
| 95 | + """ |
| 96 | + knots = [] |
| 97 | + for subgraph in nx.strongly_connected_component_subgraphs(self.digraph): |
| 98 | + nodes = set(subgraph.nodes()) |
| 99 | + if len(nodes) == 1: |
| 100 | + n = nodes.pop() |
| 101 | + nodes.add(n) |
| 102 | + if set(self.digraph.successors(n)) == nodes: |
| 103 | + knots.append(subgraph) |
| 104 | + else: |
| 105 | + for n in nodes: |
| 106 | + successors = nx.descendants(self.digraph, n) |
| 107 | + if successors <= nodes: |
| 108 | + knots.append(subgraph) |
| 109 | + break |
| 110 | + if len(knots) > 0: |
| 111 | + return True |
| 112 | + return False |
| 113 | + |
89 | 114 | def choose_deadlock_detection(self, deadlock_detector):
|
90 | 115 | """
|
91 | 116 | Chooses the deadlock detection mechanism to use for the
|
@@ -236,20 +261,35 @@ def simulate_until_deadlock(self):
|
236 | 261 | time_of_deadlock - self.times_dictionary[state]
|
237 | 262 | for state in self.times_dictionary.keys()}
|
238 | 263 |
|
239 |
| - def simulate_until_max_time(self, max_simulation_time): |
| 264 | + def simulate_until_max_time(self, max_simulation_time, progress_bar=False): |
240 | 265 | """
|
241 | 266 | Runs the simulation until max_simulation_time is reached.
|
242 | 267 | """
|
243 | 268 | self.nodes[0].update_next_event_date()
|
244 | 269 | next_active_node = self.find_next_active_node()
|
245 | 270 | current_time = next_active_node.next_event_date
|
| 271 | + |
| 272 | + if progress_bar is not False: |
| 273 | + self.progress_bar = tqdm.tqdm(total=max_simulation_time) |
| 274 | + |
246 | 275 | while current_time < max_simulation_time:
|
247 | 276 | next_active_node.have_event()
|
248 | 277 | for node in self.transitive_nodes:
|
249 | 278 | node.update_next_event_date(current_time)
|
250 | 279 | next_active_node = self.find_next_active_node()
|
| 280 | + |
| 281 | + if progress_bar: |
| 282 | + remaining_time = max_simulation_time - self.progress_bar.n |
| 283 | + time_increment = next_active_node.next_event_date - current_time |
| 284 | + self.progress_bar.update(min(time_increment, remaining_time)) |
| 285 | + |
251 | 286 | current_time = next_active_node.next_event_date
|
252 | 287 |
|
| 288 | + if progress_bar: |
| 289 | + remaining_time = max(max_simulation_time - self.progress_bar.n, 0) |
| 290 | + self.progress_bar.update(remaining_time) |
| 291 | + self.progress_bar.close() |
| 292 | + |
253 | 293 | def source(self, c, n, kind):
|
254 | 294 | """
|
255 | 295 | Returns the location of class c node n's arrival or
|
|
0 commit comments