Skip to content

Commit f95ab8f

Browse files
committed
service disciplines now take current time, add test for a linger discipline
1 parent b112058 commit f95ab8f

3 files changed

Lines changed: 82 additions & 18 deletions

File tree

ciw/disciplines.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,47 @@
44
from ciw.auxiliary import random_choice
55

66

7-
def FIFO(individuals: List[Individual]) -> Individual:
7+
def FIFO(individuals: List[Individual], t: float) -> Individual:
88
"""
99
FIFO: First In, First Out (FIFO)
1010
1111
Returns the individual at the head of the queue.
1212
1313
Parameters:
1414
- individuals (List[Individual]): List of individuals in the queue.
15+
- t (float): The current simulation time
1516
1617
Returns:
1718
- Individual: The individual at the head of the queue.
1819
"""
1920
return individuals[0]
2021

2122

22-
def SIRO(individuals: List[Individual]) -> Individual:
23+
def SIRO(individuals: List[Individual], t: float) -> Individual:
2324
"""
2425
SIRO: Service In Random Order (SIRO)
2526
2627
Returns a random individual from the queue.
2728
2829
Parameters:
2930
- individuals (List[Individual]): List of individuals in the queue.
31+
- t (float): The current simulation time
3032
3133
Returns:
3234
- Individual: A randomly selected individual from the queue.
3335
"""
3436
return random_choice(individuals)
3537

3638

37-
def LIFO(individuals: List[Individual]) -> Individual:
39+
def LIFO(individuals: List[Individual], t: float) -> Individual:
3840
"""
3941
LIFO: Last In, First Out (LIFO)
4042
4143
Returns the individual who joined the queue most recently.
4244
4345
Parameters:
4446
- individuals (List[Individual]): List of individuals in the queue.
47+
- t (float): The current simulation time
4548
4649
Returns:
4750
- Individual: The individual who joined the queue most recently.

ciw/node.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -144,20 +144,21 @@ def begin_service_if_possible_accept(self, next_individual):
144144
ind = next_individual
145145
else:
146146
ind = self.choose_next_customer()
147-
148-
free_server = self.find_free_server(ind)
149-
if free_server is None and isinf(self.c) is False and self.c > 0:
150-
self.decide_preempt(ind)
151-
if free_server is not None or isinf(self.c):
152-
if isinf(self.c) is False:
153-
self.attach_server(free_server, ind)
154-
ind.service_start_date = self.now
155-
ind.service_time = self.get_service_time(ind)
156-
ind.service_end_date = self.now + ind.service_time
157-
self.number_in_service += 1
158-
self.reset_class_change(ind)
159-
if not isinf(self.c):
160-
free_server.next_end_service_date = ind.service_end_date
147+
148+
if ind is not None:
149+
free_server = self.find_free_server(ind)
150+
if free_server is None and isinf(self.c) is False and self.c > 0:
151+
self.decide_preempt(ind)
152+
if free_server is not None or isinf(self.c):
153+
if isinf(self.c) is False:
154+
self.attach_server(free_server, ind)
155+
ind.service_start_date = self.now
156+
ind.service_time = self.get_service_time(ind)
157+
ind.service_end_date = self.now + ind.service_time
158+
self.number_in_service += 1
159+
self.reset_class_change(ind)
160+
if not isinf(self.c):
161+
free_server.next_end_service_date = ind.service_end_date
161162

162163
def begin_interrupted_individuals_service(self, srvr):
163164
"""
@@ -349,7 +350,7 @@ def choose_next_customer(self):
349350
for priority_individuals in self.individuals:
350351
waiting_individuals = [ind for ind in priority_individuals if not ind.server]
351352
if len(waiting_individuals) > 0:
352-
return self.service_discipline(waiting_individuals)
353+
return self.service_discipline(waiting_individuals, self.now)
353354

354355
def create_starting_servers(self):
355356
"""

ciw/tests/test_simulation.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,66 @@ def test_mixed_service_disciplines(self):
12401240
)
12411241

12421242

1243+
def test_custom_service_discipline(self):
1244+
"""
1245+
First test for a given linger time, no person waited less than the linger time.
1246+
"""
1247+
def linger(individuals, t):
1248+
individuals_who_lingered = [ind for ind in individuals if (t - ind.arrival_date) >= 3]
1249+
if len(individuals_who_lingered) == 0:
1250+
return None
1251+
return individuals_who_lingered[0]
1252+
1253+
N = ciw.create_network(
1254+
arrival_distributions=[ciw.dists.Exponential(3)],
1255+
service_distributions=[ciw.dists.Exponential(5)],
1256+
number_of_servers=[1],
1257+
service_disciplines=[linger]
1258+
)
1259+
Q = ciw.Simulation(N)
1260+
Q.simulate_until_max_time(100)
1261+
recs = Q.get_all_records()
1262+
waits = [r.waiting_time for r in recs]
1263+
self.assertTrue(min(waits) >= 3)
1264+
1265+
"""
1266+
Now test a specific example:
1267+
Customers arrive every 1.31
1268+
Services last 1.9 and 0.2 alternatively
1269+
Customers must linger for at least 3
1270+
1271+
ID Arrive Linger Start Service End
1272+
-----------------------------------------
1273+
1 01.31 04.31 05.24 1.9 07.14
1274+
2 02.62 05.62 07.14 0.2 07.34
1275+
3 03.93 06.93 07.34 1.9 09.24
1276+
4 05.24 08.24 09.24 0.2 09.44
1277+
5 06.55 09.55 10.48 1.9 12.38
1278+
6 07.86 10.86 12.38 0.2 12.58
1279+
7 09.17 12.17 12.58 1.9 14.48
1280+
8 10.48 13.48 14.48 0.2 14.68
1281+
-----------------------------------------
1282+
"""
1283+
N = ciw.create_network(
1284+
arrival_distributions=[ciw.dists.Deterministic(value=1.31)],
1285+
service_distributions=[ciw.dists.Sequential([1.9, 0.2])],
1286+
number_of_servers=[1],
1287+
service_disciplines=[linger]
1288+
)
1289+
Q = ciw.Simulation(N)
1290+
Q.simulate_until_max_customers(8, method='Finish')
1291+
recs = Q.get_all_records()
1292+
self.assertEqual(len(recs), 8)
1293+
1294+
arrivals = [round(r.arrival_date, 2) for r in recs]
1295+
start_dates = [round(r.service_start_date, 2) for r in recs]
1296+
end_dates = [round(r.service_end_date, 2) for r in recs]
1297+
1298+
self.assertEqual(arrivals, [1.31, 2.62, 3.93, 5.24, 6.55, 7.86, 9.17, 10.48])
1299+
self.assertEqual(start_dates, [5.24, 7.14, 7.34, 9.24, 10.48, 12.38, 12.58, 14.48])
1300+
self.assertEqual(end_dates, [7.14, 7.34, 9.24, 9.44, 12.38, 12.58, 14.48, 14.68])
1301+
1302+
12431303
def test_names_for_customer_classes(self):
12441304
N = ciw.create_network(
12451305
arrival_distributions={

0 commit comments

Comments
 (0)