Source code for pydsol.model.resource

""" """
"""
Created on: 9-8-2021 17:02

@author: IvS
"""
import itertools

from pydsol.model.basic_logger import get_module_logger
from pydsol.model.entities import Entity

logger = get_module_logger(__name__)

__all__ = ["Resource"]


[docs]class Resource(object): """This class defines a basic resource for a discrete event simulation. An object (often an entity) can seize a resource. If the resource is seized, other objects cannot seize it anymore until it is released after the processing time. The remaining objects are put into a queue.""" id_iter = itertools.count(1) def __init__(self, id, simulator, queue, distribution, processing_time, transfer_in_time, **kwargs): """ Parameters ---------- simulator: Simulator object simulator of the model. queue: Queue object queue where the remaining objects are places when the resource is seized. distribution: distribution from which the processing time is drawn processing_time: Union[int, str] time it takes for the resource to process an object. Default is np.random.triangular(0.1, 0.2, 0.3). transfer_in_time: int time it takes to transfer an object into the resource. Default is 0. kwargs: kwargs are the keyword arguments that are used to expand the resource class. *name: str user-specified name for the resource. """ self.simulator = simulator self.id = id self.name = "{0} {1}".format(self.__class__.__name__, str(self.id)) self.distribution = distribution self.processing_time = processing_time self.transfer_in_time = transfer_in_time self.kwargs = kwargs self.server = object # Create queue self.input_queue = queue self.resource_seized = False self.processing_entity = None
[docs] def exit_input_node(self): """Schedules the event to enter the resource when the input node is exited. To ensure that the right resource is called, the resource key is given. Parameters ---------- entity: Entity the target on which a state change is scheduled. """ logger.debug( "Time {0:.2f}: {1} seized {2}".format(self.simulator.simulator_time, self.processing_entity.name, self.name)) self.simulator.schedule_event_now(self, "enter_resource")
[docs] def enter_resource(self): """Schedules the event to transfer into the resource and starts processing. Parameters ---------- entity: object the target on which a state change is scheduled. """ self.simulator.schedule_event_rel(self.transfer_in_time, self, "processing")
[docs] def processing(self, **kwargs): """Schedules the event to process the entity and exit the resource. Parameters ---------- entity: object the target on which a state change is scheduled. kwargs: kwargs are the keyword arguments that are used to expand the function. """ processing_time_dist = self.set_processing_time() if "processing_entity" in kwargs: self.processing_entity = kwargs["processing_entity"] self.simulator.schedule_event_rel(processing_time_dist, self, "exit_resource", **kwargs)
[docs] def set_processing_time(self): """Draws a processing time from the distribution and parameter processing time. """ if (self.distribution is None) & (isinstance(self.processing_time, (int, float))): processing_time_dist = self.processing_time elif isinstance(self.processing_time, (int, float)): processing_time_dist = self.distribution(self.processing_time) else: try: processing_time_dist = self.distribution(*self.processing_time) except TypeError: raise "Wrong types for processing time ({1}) and/or distribution ({0}) for scheduling an event".format( self.processing_time, self.distribution) processing_time_dist = max(0, processing_time_dist) return processing_time_dist
[docs] def exit_resource(self, **kwargs): """Exits the resource. The resource is released and the queue attached to this resource is checked. Parameters ---------- entity: the target on which a state change is scheduled. kwargs: kwargs are the keyword arguments that are used to expand the function. """ logger.info( "Time {0:.2f}: {1} is processed by {2} of {3}".format(self.simulator.simulator_time, self.processing_entity, self.name, self.server.name)) self.simulator.schedule_event_now(self.server, "enter_output_node", entity=self.processing_entity) # Release resource and check queue self.simulator.schedule_event_now(self, "check_queue", priority=1)
[docs] def check_queue(self, **kwargs): """Checks whether there are objects in the queue to seize the resource. If there are no objects in the queue, the resource stays free. If there are objects in the queue, the first object seizes the resource. Parameters ---------- obj: optional kwargs: kwargs are the keyword arguments that are used to expand the function. """ logger.info( "Time {0:.2f}: Length of queue attached to {1} is {2}".format(self.simulator.simulator_time, self.name, len(self.input_queue.contents))) if len(self.input_queue.contents) == 0: self.resource_seized = False pass else: self.resource_seized = True self.processing_entity = self.input_queue.contents[0] self.simulator.schedule_event_now(self, "exit_input_node") self.input_queue.contents.pop(0)