class M1M2MCC(MMCC): """ Class to simulate M1/M2/M/C/C system """ def run(self, total_servers: int, arrival_total: int, threshold: int): """ Modified run function that adds threshold value :param total_servers: Number of servers :param arrival_total: Number of events :param threshold: Servers reserved for handover calls """ # Setup servers, event handler and add first events self.servers = Servers(total_servers) self.events = EventHandlerVariant() self.events.start() # Start counter and iteration self.arrival_number = 0 self.arrival = {"handover": 0, "newcall": 0} while (sum(self.arrival_number) < arrival_total): # Iterate to next event with handler and update sim time current_event = self.events.next() self.simulation_time = current_event.time() # If arrival, update counter and add to appropriate list if current_event.event_type == "arrival": priority = current_event.path self.arrival_number += 1 self.arrival[priority] += 1 self.events.add( EventVariant(priority, "arrival", current_event.time())) # Check server availability by priority and threshold if (len(self.servers) > threshold) or ( priority == "handover" and self.servers.is_free()): # Assign server to event current_event.served_by(self.servers.allocate()) self.events.add(current_event) continue # Arrival has been blocked self.events.block(current_event) # If departure, free server and depart event else: self.servers.deallocate(current_event.served_by()) self.events.depart(current_event) def blocking_probability(self): """ Obtain aggregated blocking probability of previous run :return: Blocking probability """ HFP = len(self.events.blocked_handover) / self.arrival["handover"] \ if self.arrival["handover"] else 0 CBP = len(self.events.blocked_newcall) / self.arrival["newcall"] \ if self.arrival["newcall"] else 0 return CBP + (10 * HFP)
class MMCC: """ Class to simulate M/M/C/C system """ def run(self, server_number: int, arrival_total: int): """ Run simulation with specified parameters :param server_number: Number of servers :param arrival_total: Number of events """ # Initialise Servers and EventHandler self.servers = Servers(server_number) self.events = EventHandler() # Create and add initial event starting_event = Event("arrival", 0) starting_event.departure_time -= starting_event.arrival_time starting_event.arrival_time = 0 self.events.add(starting_event) # Run simulation until number of events handled self.arrival_number = 0 while (self.arrival_number < arrival_total): # Iterate to next event and update simulation time current_event = self.events.next() self.simulation_time = current_event.time() # If arrival, update counter and add to appropriate list if current_event.event_type == "arrival": self.arrival_number += 1 self.events.add(Event("arrival", current_event.time())) # If no servers free, block event if not self.servers.is_free(): self.events.block(current_event) continue # Assign server to event current_event.served_by(self.servers.allocate()) self.events.add(current_event) # If departure, free server and depart else: self.servers.deallocate(current_event.served_by()) self.events.depart(current_event) def blocking_probability(self) -> float: """ Obtain blocking probability of previous run :return: Blocking probability """ return len(self.events.blocked) / self.arrival_number def server_utilisation(self) -> float: """ Obtain server utilisation of previous run :return: Server utilisation """ return sum([e.service_time() for e in self.events.departed]) / self.simulation_time