Skip to content

Commit 077fe55

Browse files
committed
Add tqdm progress bar (and tests).
Closes #52 Some careful checks for the increment need to be included so that the end value of the progress bar is correct.
1 parent ec7203e commit 077fe55

File tree

4 files changed

+61
-4
lines changed

4 files changed

+61
-4
lines changed

ciw/simulation.py

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from decimal import Decimal, getcontext
88
from collections import namedtuple
99

10+
import tqdm
1011
import yaml
1112
import numpy.random as nprandom
1213

@@ -20,7 +21,6 @@
2021
from .state_tracker import *
2122
from .deadlock_detector import *
2223

23-
2424
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')
2525

2626
class Simulation(object):
@@ -86,6 +86,31 @@ def choose_tracker(self, tracker, deadlock_detector):
8686
return NaiveTracker(self)
8787
return StateTracker(self)
8888

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+
89114
def choose_deadlock_detection(self, deadlock_detector):
90115
"""
91116
Chooses the deadlock detection mechanism to use for the
@@ -236,20 +261,35 @@ def simulate_until_deadlock(self):
236261
time_of_deadlock - self.times_dictionary[state]
237262
for state in self.times_dictionary.keys()}
238263

239-
def simulate_until_max_time(self, max_simulation_time):
264+
def simulate_until_max_time(self, max_simulation_time, progress_bar=False):
240265
"""
241266
Runs the simulation until max_simulation_time is reached.
242267
"""
243268
self.nodes[0].update_next_event_date()
244269
next_active_node = self.find_next_active_node()
245270
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+
246275
while current_time < max_simulation_time:
247276
next_active_node.have_event()
248277
for node in self.transitive_nodes:
249278
node.update_next_event_date(current_time)
250279
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+
251286
current_time = next_active_node.next_event_date
252287

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+
253293
def source(self, c, n, kind):
254294
"""
255295
Returns the location of class c node n's arrival or

ciw/tests/test_simulation.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,22 @@ def test_simulate_until_max_time_method(self):
104104
drl.append((dr.customer_class, dr.service_time))
105105
self.assertEqual(drl, [(1, 10.0), (0, 5.0), (0, 5.0)])
106106

107+
def test_simulate_until_max_time_with_pbar_method(self):
108+
set_seed(2)
109+
Q = ciw.Simulation(ciw.create_network(
110+
'ciw/tests/testing_parameters/params.yml'))
111+
Q.simulate_until_max_time(150, progress_bar=True)
112+
self.assertEqual(Q.progress_bar.total, 150)
113+
self.assertEqual(Q.progress_bar.n, 150)
114+
115+
# Check that results are the same
116+
L = Q.get_all_records()
117+
self.assertEqual(round(
118+
L[300].service_start_date, 8), 2.49842838)
119+
120+
121+
122+
107123
def test_simulate_until_deadlock_method(self):
108124
ciw.seed(3)
109125
Q = ciw.Simulation(ciw.create_network(

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
PyYAML
22
networkx
33
hypothesis
4-
numpy
4+
numpy
5+
tqdm

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@
1818
packages=['ciw'],
1919
description='A discrete event simulation library for open queueing networks',
2020
long_description=readme + '\n\n' + changes + '\n\n' + authors,
21-
install_requires=["PyYAML", "networkx", "hypothesis", "numpy"],
21+
install_requires=["PyYAML", "networkx", "hypothesis", "numpy", "tqdm"]
2222
)

0 commit comments

Comments
 (0)