Skip to content

Commit e05cbb1

Browse files
committed
add NodePopulation tracker
1 parent 8a755e9 commit e05cbb1

4 files changed

Lines changed: 116 additions & 6 deletions

File tree

ciw/tests/test_simulation.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,8 @@ def test_simulate_until_max_customers_with_pbar_method(self):
197197
self.assertEqual(Q3.progress_bar.total, max_custs)
198198
self.assertEqual(Q3.progress_bar.n, max_custs)
199199

200-
def test_simulate_until_deadlock_method_naiveblocking(self):
200+
def test_simulate_until_deadlock_method(self):
201+
# NaiveBlocking tracker
201202
ciw.seed(3)
202203
Q = ciw.Simulation(ciw.create_network_from_yml(
203204
'ciw/tests/testing_parameters/params_deadlock.yml'),
@@ -206,7 +207,7 @@ def test_simulate_until_deadlock_method_naiveblocking(self):
206207
Q.simulate_until_deadlock()
207208
self.assertEqual(round(Q.times_to_deadlock[((0, 0), (0, 0))], 8), 53.88526441)
208209

209-
def test_simulate_until_deadlock_method_systempopulation(self):
210+
# SystemPopulation tracker
210211
ciw.seed(3)
211212
Q = ciw.Simulation(ciw.create_network_from_yml(
212213
'ciw/tests/testing_parameters/params_deadlock.yml'),
@@ -215,6 +216,15 @@ def test_simulate_until_deadlock_method_systempopulation(self):
215216
Q.simulate_until_deadlock()
216217
self.assertEqual(round(Q.times_to_deadlock[0], 8), 53.88526441)
217218

219+
# NodePopulation tracker
220+
ciw.seed(3)
221+
Q = ciw.Simulation(ciw.create_network_from_yml(
222+
'ciw/tests/testing_parameters/params_deadlock.yml'),
223+
deadlock_detector=ciw.deadlock.StateDigraph(),
224+
tracker=ciw.trackers.NodePopulation())
225+
Q.simulate_until_deadlock()
226+
self.assertEqual(round(Q.times_to_deadlock[(0, 0)], 8), 53.88526441)
227+
218228
def test_detect_deadlock_method(self):
219229
Q = ciw.Simulation(ciw.create_network_from_yml(
220230
'ciw/tests/testing_parameters/params_deadlock.yml'),

ciw/tests/test_state_tracker.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,3 +521,40 @@ def test_one_node_deterministic_systempopulation(self):
521521
[Decimal('15.0'), 0]
522522
]
523523
self.assertEqual(Q.statetracker.history, expected_history)
524+
525+
526+
def test_one_node_deterministic_nodepopulation(self):
527+
N = ciw.create_network(
528+
arrival_distributions=[ciw.dists.Sequential([1.5, 0.3, 2.4, 1.1])],
529+
service_distributions=[ciw.dists.Sequential([1.8, 2.2, 0.2, 0.2, 0.2, 0.2])],
530+
number_of_servers=[1]
531+
)
532+
B = ciw.trackers.NodePopulation()
533+
Q = ciw.Simulation(N, tracker=B, exact=26)
534+
Q.simulate_until_max_time(15.5)
535+
expected_history = [
536+
[Decimal('0.0'), (0,)],
537+
[Decimal('1.5'), (1,)],
538+
[Decimal('1.8'), (2,)],
539+
[Decimal('3.3'), (1,)],
540+
[Decimal('4.2'), (2,)],
541+
[Decimal('5.3'), (3,)],
542+
[Decimal('5.5'), (2,)],
543+
[Decimal('5.7'), (1,)],
544+
[Decimal('5.9'), (0,)],
545+
[Decimal('6.8'), (1,)],
546+
[Decimal('7.0'), (0,)],
547+
[Decimal('7.1'), (1,)],
548+
[Decimal('7.3'), (0,)],
549+
[Decimal('9.5'), (1,)],
550+
[Decimal('10.6'), (2,)],
551+
[Decimal('11.3'), (1,)],
552+
[Decimal('12.1'), (2,)],
553+
[Decimal('12.4'), (3,)],
554+
[Decimal('13.5'), (2,)],
555+
[Decimal('13.7'), (1,)],
556+
[Decimal('13.9'), (0,)],
557+
[Decimal('14.8'), (1,)],
558+
[Decimal('15.0'), (0,)]
559+
]
560+
self.assertEqual(Q.statetracker.history, expected_history)

ciw/trackers/state_tracker.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class SystemPopulation(StateTracker):
4848
4949
Example:
5050
3
51-
This denotes 3 customers at in the whole system.
51+
This denotes 3 customers in the whole system.
5252
"""
5353
def initialise(self, simulation):
5454
"""
@@ -84,6 +84,50 @@ def hash_state(self):
8484
return self.state
8585

8686

87+
class NodePopulation(StateTracker):
88+
"""
89+
The node population tracker records the number of customers at each node.
90+
91+
Example:
92+
(3, 1)
93+
This denotes 3 customers at the first node, and 1 customer at the
94+
second node.
95+
"""
96+
def initialise(self, simulation):
97+
"""
98+
Initialises the state tracker class.
99+
"""
100+
self.simulation = simulation
101+
self.state = [0 for i in range(
102+
self.simulation.network.number_of_nodes)]
103+
self.history = []
104+
self.timestamp()
105+
106+
def change_state_accept(self, node_id, cust_clss):
107+
"""
108+
Changes the state of the system when a customer is accepted.
109+
"""
110+
self.state[node_id-1] += 1
111+
112+
def change_state_block(self, node_id, destination, cust_clss):
113+
"""
114+
Changes the state of the system when a customer gets blocked.
115+
"""
116+
pass
117+
118+
def change_state_release(self, node_id, destination, cust_clss, blocked):
119+
"""
120+
Changes the state of the system when a customer is released.
121+
"""
122+
self.state[node_id-1] -= 1
123+
124+
def hash_state(self):
125+
"""
126+
Returns a hashable state.
127+
"""
128+
return tuple(self.state)
129+
130+
87131
class NaiveBlocking(StateTracker):
88132
"""
89133
The naive blocking tracker records the number of customers at each node,

docs/Reference/state_trackers.rst

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
.. _refs-statetrackers:
22

3-
=========================================================
4-
List of Implemented State Trackers for Deadlock Detection
5-
=========================================================
3+
==================================
4+
List of Implemented State Trackers
5+
==================================
66

77
Currently Ciw has the following state trackers:
88

99
- :ref:`population`
10+
- :ref:`nodepop`
1011
- :ref:`naive`
1112
- :ref:`matrix`
1213

@@ -29,6 +30,24 @@ The Simulation object takes in the optional argument :code:`tracker` used as fol
2930
>>> Q = ciw.Simulation(N, tracker=ciw.trackers.SystemPopulation()) # doctest:+SKIP
3031

3132

33+
.. _nodepop:
34+
35+
----------------------------
36+
The NodePopulation Tracker
37+
----------------------------
38+
39+
The NodePopulation Tracker records the number of customers at each node.
40+
States take the form of list of numbers. An example for a three node queueing network is shown below::
41+
42+
[2, 0, 5]
43+
44+
This denotes that there are two customers at the first node, no customers at the second node, and five customers at the third node.
45+
46+
The Simulation object takes in the optional argument :code:`tracker` used as follows::
47+
48+
>>> Q = ciw.Simulation(N, tracker=ciw.trackers.NodePopulation()) # doctest:+SKIP
49+
50+
3251

3352
.. _naive:
3453

0 commit comments

Comments
 (0)