Skip to content

Commit a80c7ac

Browse files
Merge pull request #203 from CiwPython/preemptive-interruption-options
Preemptive interruption options
2 parents 1155647 + d291632 commit a80c7ac

File tree

8 files changed

+473
-68
lines changed

8 files changed

+473
-68
lines changed

ciw/node.py

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ def begin_interrupted_individuals_service(self, srvr):
161161
node_blocked_to.len_blocked_queue -= 1
162162
ind.is_blocked = False
163163
self.attach_server(srvr, ind)
164-
ind.service_time = self.get_service_time(ind)
164+
self.give_service_time_after_preemption(ind)
165+
ind.service_start_date = self.get_now()
165166
ind.service_end_date = self.increment_time(self.get_now(), ind.service_time)
166167
ind.interrupted = False
167168
srvr.next_end_service_date = ind.service_end_date
@@ -185,7 +186,10 @@ def begin_service_if_possible_change_shift(self):
185186
if not ind.server:
186187
self.attach_server(srvr, ind)
187188
ind.service_start_date = self.get_now()
188-
ind.service_time = self.get_service_time(ind)
189+
if ind.service_time is False:
190+
ind.service_time = self.get_service_time(ind)
191+
else:
192+
self.give_service_time_after_preemption(ind)
189193
ind.service_end_date = self.increment_time(
190194
ind.service_start_date, ind.service_time)
191195
srvr.next_end_service_date = ind.service_end_date
@@ -210,7 +214,10 @@ def begin_service_if_possible_release(self, next_individual):
210214
if not ind.server:
211215
self.attach_server(srvr, ind)
212216
ind.service_start_date = self.get_now()
213-
ind.service_time = self.get_service_time(ind)
217+
if ind.service_time is False:
218+
ind.service_time = self.get_service_time(ind)
219+
else:
220+
self.give_service_time_after_preemption(ind)
214221
ind.service_end_date = self.increment_time(
215222
ind.service_start_date, ind.service_time)
216223
srvr.next_end_service_date = ind.service_end_date
@@ -336,7 +343,7 @@ def decide_preempt(self, individual):
336343
"""
337344
Decides if priority preemption is needed, finds the individual to preempt, and preempt them.
338345
"""
339-
if self.priority_preempt:
346+
if self.priority_preempt != False:
340347
least_priority = max(s.cust.priority_class for s in self.servers)
341348
if individual.priority_class < least_priority:
342349
least_prioritised_individuals = [s.cust for s in self.servers if s.cust.priority_class == least_priority]
@@ -428,6 +435,17 @@ def get_now(self):
428435
"""
429436
return self.simulation.current_time
430437

438+
def give_service_time_after_preemption(self, individual):
439+
"""
440+
Either resample, restart or continue service time where it was left off
441+
"""
442+
if individual.service_time == "resample":
443+
individual.service_time = self.get_service_time(individual)
444+
if individual.service_time == "restart":
445+
individual.service_time = individual.original_service_time
446+
if individual.service_time == "continue":
447+
individual.service_time = individual.time_left
448+
431449
def have_event(self):
432450
"""
433451
Has an event
@@ -485,10 +503,13 @@ def preempt(self, individual_to_preempt, next_individual):
485503
Removes individual_to_preempt from service and replaces them with next_individual
486504
"""
487505
server = individual_to_preempt.server
488-
self.detatch_server(server, individual_to_preempt)
506+
individual_to_preempt.original_service_time = individual_to_preempt.service_time
507+
self.write_interruption_record(individual_to_preempt)
489508
individual_to_preempt.service_start_date = False
490-
individual_to_preempt.service_time = False
509+
individual_to_preempt.time_left = individual_to_preempt.service_end_date - self.get_now()
510+
individual_to_preempt.service_time = self.priority_preempt
491511
individual_to_preempt.service_end_date = False
512+
self.detatch_server(server, individual_to_preempt)
492513
self.decide_class_change(individual_to_preempt)
493514
self.attach_server(server, next_individual)
494515
next_individual.service_start_date = self.get_now()
@@ -590,7 +611,7 @@ def take_servers_off_duty(self):
590611
"""
591612
Gathers servers that should be deleted.
592613
"""
593-
if not self.schedule_preempt:
614+
if self.schedule_preempt == False:
594615
to_delete = []
595616
for srvr in self.servers:
596617
srvr.shift_end = self.next_event_date
@@ -606,10 +627,12 @@ def take_servers_off_duty(self):
606627
self.interrupted_individuals.append(s.cust)
607628
s.cust.interrupted = True
608629
self.number_interrupted_individuals += 1
609-
self.interrupted_individuals[-1].service_end_date = False
610-
self.interrupted_individuals[-1].service_time = False
611-
self.interrupted_individuals.sort(key=lambda x: (x.priority_class,
612-
x.arrival_date))
630+
s.cust.service_start_date = False
631+
s.cust.original_service_time = self.interrupted_individuals[-1].service_time
632+
s.cust.time_left = self.interrupted_individuals[-1].service_end_date - self.get_now()
633+
s.cust.service_time = self.schedule_preempt
634+
s.cust.service_end_date = False
635+
self.interrupted_individuals.sort(key=lambda x: (x.priority_class, x.arrival_date))
613636
for obs in to_delete:
614637
self.kill_server(obs)
615638

@@ -703,6 +726,44 @@ def write_individual_record(self, individual):
703726
'service')
704727
individual.data_records.append(record)
705728

729+
def write_interruption_record(self, individual):
730+
"""
731+
Write a data record for an individual:
732+
- Arrival date
733+
- Wait
734+
- Service start date
735+
- Service time
736+
- Service end date
737+
- Blocked
738+
- Exit date
739+
- Node
740+
- Destination
741+
- Previous class
742+
- Queue size at arrival
743+
- Queue size at departure
744+
- Server id
745+
- Record type
746+
"""
747+
record = DataRecord(
748+
individual.id_number,
749+
individual.previous_class,
750+
individual.original_class,
751+
self.id_number,
752+
individual.arrival_date,
753+
individual.service_start_date - individual.arrival_date,
754+
individual.service_start_date,
755+
individual.original_service_time,
756+
nan,
757+
nan,
758+
self.get_now(),
759+
nan,
760+
individual.queue_size_at_arrival,
761+
individual.queue_size_at_departure,
762+
individual.server.id_number,
763+
'interrupted service')
764+
individual.data_records.append(record)
765+
766+
706767
def write_reneging_record(self, individual):
707768
"""
708769
Write a data record for an individual:

0 commit comments

Comments
 (0)