Skip to content

Commit 0e01f09

Browse files
committed
loop over sevrers only when determining next_event_date
1 parent f4e8b7b commit 0e01f09

4 files changed

Lines changed: 59 additions & 66 deletions

File tree

ciw/node.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,6 @@ def all_individuals(self):
6767
return [i for priority_class in self.individuals
6868
for i in priority_class]
6969

70-
# @property
71-
# def number_of_individuals(self):
72-
# return len(self.all_individuals)
73-
74-
7570
def __repr__(self):
7671
"""
7772
Representation of a node.
@@ -108,6 +103,7 @@ def attach_server(self, server, individual):
108103
server.cust = individual
109104
server.busy = True
110105
individual.server = server
106+
server.next_end_service_date = individual.service_end_date
111107
self.simulation.deadlock_detector.action_at_attach_server(
112108
self, server, individual)
113109

@@ -122,24 +118,24 @@ def begin_service_if_possible_accept(self,
122118
next_individual.service_time = self.get_service_time(
123119
next_individual.customer_class, current_time)
124120
if self.free_server():
125-
if self.c < float('Inf'):
126-
self.attach_server(self.find_free_server(),
127-
next_individual)
128121
next_individual.service_start_date = self.get_now(current_time)
129122
next_individual.service_end_date = self.increment_time(
130123
current_time, next_individual.service_time)
124+
if self.c < float('Inf'):
125+
self.attach_server(self.find_free_server(),
126+
next_individual)
131127

132128
def begin_interrupted_individuals_service(self, current_time, srvr):
133129
"""
134130
Restarts the next interrupted individual's service (by
135131
resampking service time)
136132
"""
137133
ind = [i for i in self.interrupted_individuals][0]
138-
self.attach_server(srvr, ind)
139134
ind.service_time = self.get_service_time(ind.customer_class,
140135
current_time)
141136
ind.service_end_date = self.increment_time(self.get_now(current_time),
142137
ind.service_time)
138+
self.attach_server(srvr, ind)
143139
self.interrupted_individuals.remove(ind)
144140

145141
def begin_service_if_possible_change_shift(self, current_time):
@@ -153,10 +149,10 @@ def begin_service_if_possible_change_shift(self, current_time):
153149
self.begin_interrupted_individuals_service(current_time, srvr)
154150
elif len([i for i in self.all_individuals if not i.server]) > 0:
155151
ind = [i for i in self.all_individuals if not i.server][0]
156-
self.attach_server(srvr, ind)
157152
ind.service_start_date = self.get_now(current_time)
158153
ind.service_end_date = self.increment_time(
159154
ind.service_start_date, ind.service_time)
155+
self.attach_server(srvr, ind)
160156

161157
def begin_service_if_possible_release(self, current_time):
162158
"""
@@ -169,10 +165,10 @@ def begin_service_if_possible_release(self, current_time):
169165
self.begin_interrupted_individuals_service(current_time, srvr)
170166
elif len([i for i in self.all_individuals if not i.server]) > 0:
171167
ind = [i for i in self.all_individuals if not i.server][0]
172-
self.attach_server(srvr, ind)
173168
ind.service_start_date = self.get_now(current_time)
174169
ind.service_end_date = self.increment_time(
175170
ind.service_start_date, ind.service_time)
171+
self.attach_server(srvr, ind)
176172

177173
def block_individual(self, individual, next_node):
178174
"""
@@ -301,6 +297,8 @@ def finish_service(self):
301297
self.change_customer_class(next_individual)
302298
next_node = self.next_node(next_individual.customer_class)
303299
next_individual.destination = next_node.id_number
300+
if self.c < float('Inf'):
301+
next_individual.server.next_end_service_date = float('Inf')
304302
if next_node.number_of_individuals < next_node.node_capacity:
305303
self.release(next_individual_index, next_node,
306304
self.next_event_date)
@@ -422,10 +420,14 @@ def update_next_event_date(self, current_time):
422420
"""
423421
Finds the time of the next event at this node
424422
"""
425-
next_end_service = min([ind.service_end_date
426-
for ind in self.all_individuals
427-
if not ind.is_blocked
428-
if ind.service_end_date >= current_time] + [float("Inf")])
423+
if self.c != float('Inf'):
424+
next_end_service = min([s.next_end_service_date
425+
for s in self.servers] + [float("Inf")])
426+
else:
427+
next_end_service = min([ind.service_end_date
428+
for ind in self.all_individuals
429+
if not ind.is_blocked
430+
if ind.service_end_date >= current_time] + [float("Inf")])
429431
if self.schedule:
430432
next_shift_change = self.next_shift_change
431433
self.next_event_date = min(

ciw/server.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def __init__(self, node, id_number, start_date=0.0):
1818
self.busy_time = False
1919
self.total_time = False
2020
self.shift_end = False
21+
self.next_end_service_date = float('Inf')
2122

2223
@property
2324
def utilisation(self):

ciw/tests/test_node.py

Lines changed: 30 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -194,18 +194,28 @@ def test_release_method(self):
194194
[['Individual 1', 'Individual 2', 'Individual 3']])
195195
N.update_next_event_date(0.03)
196196
self.assertEqual(round(N.next_event_date, 5), 0.03604)
197-
N.all_individuals[1].exit_date = 0.04
198-
N.update_next_event_date(N.next_event_date + 0.00001)
199-
self.assertEqual(round(N.next_event_date, 5), 0.03708)
197+
198+
N.servers[1].next_end_service_date = float('Inf')
200199
N.release(1, Q.transitive_nodes[1], N.next_event_date)
201200
self.assertEqual([str(obs) for obs in N.all_individuals],
202201
['Individual 1', 'Individual 3'])
203202
self.assertEqual(
204203
[[str(obs) for obs in pr_cls] for pr_cls in N.individuals],
205204
[['Individual 1', 'Individual 3']])
206-
N.update_next_event_date(N.next_event_date + 0.00001)
205+
N.update_next_event_date(N.next_event_date)
206+
self.assertEqual(round(N.next_event_date, 5), 0.03708)
207+
208+
N.servers[0].next_end_service_date = float('Inf')
209+
N.release(0, Q.transitive_nodes[1], N.next_event_date)
210+
self.assertEqual([str(obs) for obs in N.all_individuals],
211+
['Individual 3'])
212+
self.assertEqual(
213+
[[str(obs) for obs in pr_cls] for pr_cls in N.individuals],
214+
[['Individual 3']])
215+
N.update_next_event_date(N.next_event_date)
207216
self.assertEqual(round(N.next_event_date, 5), 0.06447)
208217

218+
209219
def test_begin_service_if_possible_release_method(self):
210220
ciw.seed(50)
211221
Q = ciw.Simulation(ciw.create_network_from_yml(
@@ -402,8 +412,12 @@ def test_begin_service_if_possible_accept_method(self):
402412
self.assertEqual(round(ind.service_end_date, 5), 300.03382)
403413

404414
def test_update_next_event_date_method(self):
405-
Q = ciw.Simulation(ciw.create_network_from_yml(
406-
'ciw/tests/testing_parameters/params.yml'))
415+
Net = ciw.create_network(
416+
Arrival_distributions=[['Deterministic', 10.0]],
417+
Service_distributions=[['Sequential', [0.5, 0.2]]],
418+
Number_of_servers=[5]
419+
)
420+
Q = ciw.Simulation(Net)
407421
N = Q.transitive_nodes[0]
408422
self.assertEqual(N.next_event_date, float('Inf'))
409423
self.assertEqual(N.all_individuals, [])
@@ -412,49 +426,25 @@ def test_update_next_event_date_method(self):
412426

413427
ind1 = ciw.Individual(1)
414428
ind1.arrival_date = 0.3
415-
ind1.service_time = 0.2
416-
ind1.service_end_date = 0.5
417429
N.next_event_date = 0.3
418-
N.individuals = [[ind1]]
419-
N.update_next_event_date(N.next_event_date + 0.000001)
420-
self.assertEqual(N.next_event_date, 0.5)
430+
N.accept(ind1, 0.3)
431+
N.update_next_event_date(N.next_event_date)
432+
self.assertEqual(N.next_event_date, 0.8)
421433

422434
ind2 = ciw.Individual(2)
423435
ind2.arrival_date = 0.4
424-
ind2.service_time = 0.2
425-
ind2.service_end_date = 0.6
426-
ind2.exit_date = False
427-
428-
N.individuals = [[ind1, ind2]]
436+
N.accept(ind2, 0.4)
429437
N.update_next_event_date(N.next_event_date + 0.000001)
430-
self.assertEqual(N.next_event_date, 0.6)
438+
self.assertEqual(round(N.next_event_date, 4), 0.6)
431439

432-
ind2.exit_date = 0.9
440+
N.finish_service()
441+
N.update_next_event_date(N.next_event_date)
442+
self.assertEqual(N.next_event_date, 0.8)
433443

434-
N.update_next_event_date(N.next_event_date + 0.000001)
444+
N.finish_service()
445+
N.update_next_event_date(N.next_event_date)
435446
self.assertEqual(N.next_event_date, float('Inf'))
436447

437-
438-
Q = ciw.Simulation(ciw.create_network_from_yml(
439-
'ciw/tests/testing_parameters/params_schedule.yml'))
440-
N = Q.transitive_nodes[0]
441-
self.assertEqual(N.next_event_date, 30)
442-
self.assertEqual(N.individuals, [[]])
443-
N.update_next_event_date(0.0)
444-
self.assertEqual(N.next_event_date, 30)
445-
446-
ind1 = ciw.Individual(1)
447-
ind1.arrival_date = 0.3
448-
ind1.service_time = 0.2
449-
ind1.service_end_date = 0.5
450-
N.next_event_date = 0.3
451-
N.individuals = [[ind1]]
452-
N.update_next_event_date(N.next_event_date + 0.000001)
453-
self.assertEqual(N.next_event_date, 0.5)
454-
455-
N.update_next_event_date(N.next_event_date + 0.000001)
456-
self.assertEqual(N.next_event_date, 30)
457-
458448
def test_next_node_method(self):
459449
ciw.seed(6)
460450
Q = ciw.Simulation(ciw.create_network_from_yml(

ciw/tests/test_simulation.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -180,24 +180,25 @@ def test_simulate_until_max_customers_with_pbar_method(self):
180180
N = ciw.create_network_from_yml(
181181
'ciw/tests/testing_parameters/params.yml')
182182

183+
max_custs = 250
184+
183185
ciw.seed(1)
184186
Q1 = ciw.Simulation(N)
185-
Q1.simulate_until_max_customers(10, progress_bar=True, method='Finish')
186-
self.assertEqual(Q1.progress_bar.total, 10)
187-
self.assertEqual(Q1.progress_bar.n, 10)
187+
Q1.simulate_until_max_customers(max_custs, progress_bar=True, method='Finish')
188+
self.assertEqual(Q1.progress_bar.total, max_custs)
189+
self.assertEqual(Q1.progress_bar.n, max_custs)
188190

189191
ciw.seed(1)
190192
Q2 = ciw.Simulation(N)
191-
Q2.simulate_until_max_customers(10, progress_bar=True, method='Arrive')
192-
self.assertEqual(Q2.progress_bar.total, 10)
193-
self.assertEqual(Q2.progress_bar.n, 10)
193+
Q2.simulate_until_max_customers(max_custs, progress_bar=True, method='Arrive')
194+
self.assertEqual(Q2.progress_bar.total, max_custs)
195+
self.assertEqual(Q2.progress_bar.n, max_custs)
194196

195197
ciw.seed(1)
196198
Q3 = ciw.Simulation(N)
197-
Q3.simulate_until_max_customers(10, progress_bar=True, method='Accept')
198-
self.assertEqual(Q3.progress_bar.total, 10)
199-
self.assertEqual(Q3.progress_bar.n, 10)
200-
199+
Q3.simulate_until_max_customers(max_custs, progress_bar=True, method='Accept')
200+
self.assertEqual(Q3.progress_bar.total, max_custs)
201+
self.assertEqual(Q3.progress_bar.n, max_custs)
201202

202203
def test_simulate_until_deadlock_method(self):
203204
ciw.seed(3)
@@ -341,7 +342,6 @@ def test_writing_data_files(self):
341342
self.assertEqual(len(data[0]), len(ciw.data_record.DataRecord._fields))
342343
os.remove('ciw/tests/testing_parameters/data_2.csv')
343344

344-
345345
def test_simultaneous_events_example(self):
346346
# This should yield 3 or 2 customers finishing service.
347347
# Due to randomly choosing the order of events, the seed has

0 commit comments

Comments
 (0)