Skip to content

Commit 9259c22

Browse files
committed
add cycle routing object
1 parent 17407f2 commit 9259c22

3 files changed

Lines changed: 64 additions & 1 deletion

File tree

ciw/routing/routing.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import ciw
2+
import itertools
23

34
class NetworkRouting:
45
"""
@@ -248,3 +249,29 @@ def get_queue_size(self, node_index):
248249
Gets the size of the queue at the node_index.
249250
"""
250251
return self.simulation.nodes[node_index].number_of_individuals
252+
253+
254+
class Cycle(NodeRouting):
255+
"""
256+
A router that cycles through destinations, repeating the cycle once ended.
257+
"""
258+
def __init__(self, cycle):
259+
"""
260+
Initialises the routing object.
261+
262+
Takes:
263+
- cycle: an ordered sequence of nodes.
264+
"""
265+
self.cycle = cycle
266+
self.generator = itertools.cycle(self.cycle)
267+
268+
def error_check_at_initialise(self):
269+
if not set(self.cycle).issubset(set([nd.id_number for nd in self.simulation.nodes[1:]])):
270+
raise ValueError("Routing destinations should be a subset of the nodes in the network.")
271+
272+
def next_node(self, ind):
273+
"""
274+
Chooses the node 'to' with probability 1.
275+
"""
276+
next_node_index = next(self.generator)
277+
return self.simulation.nodes[next_node_index]

ciw/tests/test_routing.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,3 +309,27 @@ def test_load_balancing(self):
309309
self.assertEqual([samples_1[i] for i in [1, 2, 3, -1]], [507, 493, 0, 0])
310310
self.assertTrue(all(r == 1 for r in samples_2))
311311
self.assertTrue(all(r == 2 for r in samples_3))
312+
313+
314+
def test_cycle_routing(self):
315+
ciw.seed(0)
316+
Q = ciw.Simulation(N)
317+
R1 = ciw.routing.Cycle(cycle=[2, 3, 3])
318+
R2 = ciw.routing.Cycle(cycle=[1, 2])
319+
R3 = ciw.routing.Cycle(cycle=[1, -1, 2, -1])
320+
R1.initialise(Q, 1)
321+
R2.initialise(Q, 2)
322+
R3.initialise(Q, 3)
323+
ind = ciw.Individual(1)
324+
samples_1 = [r.id_number for r in [R1.next_node(ind) for _ in range(20)]]
325+
samples_2 = [r.id_number for r in [R2.next_node(ind) for _ in range(20)]]
326+
samples_3 = [r.id_number for r in [R3.next_node(ind) for _ in range(20)]]
327+
self.assertEqual([2, 3, 3, 2, 3, 3, 2, 3, 3, 2, 3, 3, 2, 3, 3, 2, 3, 3, 2, 3], samples_1)
328+
self.assertEqual([1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2], samples_2)
329+
self.assertEqual([1, -1, 2, -1, 1, -1, 2, -1, 1, -1, 2, -1, 1, -1, 2, -1, 1, -1, 2, -1], samples_3)
330+
331+
def test_cycle_routing_raises_errors(self):
332+
ciw.seed(0)
333+
Q = ciw.Simulation(N)
334+
R1 = ciw.routing.Cycle(cycle=[1, 2, 7])
335+
self.assertRaises(ValueError, R1.initialise, Q, 1)

docs/Reference/routers.rst

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ The following node routers are currently supported:
1818
- :ref:`probabilistic`
1919
- :ref:`jsq`
2020
- :ref:`load_balancing`
21+
- :ref:`cycle`
2122

2223

2324

@@ -126,7 +127,6 @@ The :code:`tie_break` argument is optional, and can take one of two strings: :co
126127

127128
.. _load_balancing:
128129

129-
130130
--------------
131131
Load Balancing
132132
--------------
@@ -136,3 +136,15 @@ The customer goes :ref:`joins the node with the least amount of customers presen
136136
ciw.routing.LoadBalancing(destinations=[1, 3], tie_break='random')
137137

138138
The :code:`tie_break` argument is optional, and can take one of two strings: :code:`'random'` or :code:`'order'`. When there is a tie between the nodes with the least amount of customers present, tie breaks are either dealt with by choosing randomly between the ties (:code:`'random'`), or take precedence by the order listed in the :code:`destinations` list (:code:`'order'`). If omitted, random tie-breaking is used.
139+
140+
141+
.. _cycle:
142+
143+
-----
144+
Cycle
145+
-----
146+
147+
The customers' destinations out of the node cycles through a given list. For example, the first customer is routed to Node 1, the second to Node 1, the third to Node 3, the fourth to Node 2, then henceforth the order cycles, so the fifth is routed to Node 1, the sixth to Node 1, and so on::
148+
149+
ciw.routing.Cycle(cycle=[1, 1, 3, 2])
150+

0 commit comments

Comments
 (0)