Source code for manpy.simulation.core.Source

# ===========================================================================
# Copyright 2013 University of Limerick
#
# This file is part of DREAM.
#
# DREAM is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# DREAM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with DREAM.  If not, see <http://www.gnu.org/licenses/>.
# ===========================================================================
"""
Created on 8 Nov 2012

@author: George
"""
from manpy.simulation.core.Entity import Entity



# from SimPy.Simulation import now, Process, Resource, infinity, hold, SimEvent, activate, waitevent
import simpy
from manpy.simulation.RandomNumberGenerator import RandomNumberGenerator
from manpy.simulation.core.CoreObject import CoreObject
from manpy.simulation.core.Globals import G
from manpy.simulation.core import Globals


[docs] class EntityGenerator(object): """ models the source object that generates the entities """ def __init__(self, victim=None): self.env = G.env self.type = "EntityGenerator" self.victim = victim
[docs] def run(self): while 1: # if the Source is empty create the Entity if len(self.victim.getActiveObjectQueue()) == 0: # create the Entity object and assign its name entity = self.victim.createEntity() # assign the current simulation time as the Entity's creation time entity.creationTime = self.env.now # assign the current simulation time as the Entity's start time entity.startTime = self.env.now # update the current station of the Entity entity.currentStation = self.victim G.EntityList.append(entity) #self.victim.outputTrace( # entity_name=entity.name, entity_id=entity.id, message="generated" #) self.victim.getActiveObjectQueue().append(entity) self.victim.numberOfArrivals += 1 G.numberOfEntities += 1 self.victim.appendEntity(entity) if self.victim.expectedSignals["entityCreated"]: succeedTupple = (entity, self.env.now) self.victim.entityCreated.succeed(succeedTupple) self.victim.expectedSignals["entityCreated"] = 0 # else put it on the time list for scheduled Entities else: # this is used just ot output the trace correctly entityCounter = G.numberOfEntities + len(self.victim.scheduledEntities) self.victim.scheduledEntities.append(self.env.now) """ self.victim.outputTrace( f"{self.victim.item.type}{entityCounter}", f"{self.victim.item.type}{entityCounter}", "generated", )""" # wait until the next arrival yield self.env.timeout( self.victim.calculateInterArrivalTime() )
# ============================================================================ # The Source object is a Process # ============================================================================
[docs] class Source(CoreObject): """Spawns new entities for the simulations. :param id: Internal ID :param name: Name of the Source :param interArrivalTime: Time until the next Entity is spawned :param entity: Type of Entity that's generated. One of "manpy.{Part, Batch, Frame, Job, CapacityEntity, CapacityProject}". :param capacity: Capacity of the generated Entities, Only relevant for entity="manpy.Frame" """ def __init__(self, id, name, cost=0, interArrivalTime=None, entity="manpy.Part", capacity=1, **kw): if not interArrivalTime: interArrivalTime = {"Fixed": {"mean": 1}} if ( "Normal" in list(interArrivalTime.keys()) and interArrivalTime["Normal"].get("max", None) is None ): interArrivalTime["Normal"]["max"] = ( interArrivalTime["Normal"]["mean"] + 5 * interArrivalTime["Normal"]["stdev"] ) CoreObject.__init__(self, id, name, cost) # properties used for statistics self.totalinterArrivalTime = 0 # the number of entities that were created self.numberOfArrivals = 0 # String that shows the type of object self.type = "Source" self.isNext = False self.isPrevious = True self.rng = RandomNumberGenerator(self, interArrivalTime) self.capacity = capacity if isinstance(entity, str): self.item = Globals.getClassFromName(entity) elif isinstance(entity, Entity) or issubclass(entity, Entity): self.item = entity # list of creations that are scheduled. pattern is [timeOfCreation, EntityCounter] self.scheduledEntities = [] from manpy.simulation.core.Globals import G G.SourceList.append(self) # =========================================================================== # The initialize method of the Source class # ===========================================================================
[docs] def initialize(self): # using the Process __init__ and not the CoreObject __init__ CoreObject.initialize(self) # initialize the internal Queue (type Resource) of the Source self.Res = simpy.Resource(self.env, capacity=float("inf")) self.Res.users = [] # the EntityGenerator of the Source self.entityGenerator = EntityGenerator(victim=self) self.numberOfArrivals = 0 self.env.process(self.entityGenerator.run()) self.entityCreated = self.env.event() # event used by router self.loadOperatorAvailable = self.env.event() # list of creations that are scheduled self.scheduledEntities = [] self.expectedSignals["entityCreated"] = 1 self.expectedSignals["loadOperatorAvailable"] = 1 self.expectedSignals["canDispose"] = 1
[docs] def run(self): # get active object and its queue activeObject = self.getActiveObject() activeObjectQueue = self.getActiveObjectQueue() while 1: # wait for any event (entity creation or request for disposal of entity) self.expectedSignals["canDispose"] = 1 self.expectedSignals["entityCreated"] = 1 self.expectedSignals["loadOperatorAvailable"] = 1 receivedEvent = yield self.env.any_of( [self.entityCreated, self.canDispose, self.loadOperatorAvailable] ) self.printTrace(self.id, received="") # if an entity is created try to signal the receiver and continue if self.entityCreated in receivedEvent: transmitter, eventTime = self.entityCreated.value self.entityCreated = self.env.event() # otherwise, if the receiver requests availability then try to signal him if there is anything to dispose of if self.canDispose in receivedEvent: transmitter, eventTime = self.canDispose.value self.canDispose = self.env.event() if self.loadOperatorAvailable in receivedEvent: transmitter, eventTime = self.loadOperatorAvailable.value self.loadOperatorAvailable = self.env.event() if self.haveToDispose(): if self.signalReceiver(): continue
[docs] def appendEntity(self, entity): """add newly created entity to pendingEntities""" from manpy.simulation.core.Globals import G assert entity, "cannot append None entity" activeEntity = entity if G.RouterList: G.pendingEntities.append(activeEntity)
[docs] def defineRouting(self, successorList=[]): """sets the routing out element for the Source""" self.next = successorList
[docs] def definePrevious(self, **kw): """Safeguarding to avoid setting predecessors to sources"""
[docs] def appendPrevious(self, previous): """Safeguarding to avoid setting predecessors to sources"""
[docs] def createEntity(self): """creates an Entity""" from manpy.simulation.core.Globals import G self.printTrace(self.id, create="") if self.item.type == "Frame": return self.item( id=self.item.type + str(G.numberOfEntities), name=self.item.type + str(self.numberOfArrivals), capacity=self.capacity ) # return the newly created Entity else: return self.item( id=self.item.type + str(G.numberOfEntities), name=self.item.type + str(self.numberOfArrivals), ) # return the newly created Entity
[docs] def calculateInterArrivalTime(self): """calculates the processing time""" # this is if we have a default interarrival time for all the entities return self.rng.generateNumber()
[docs] def removeEntity(self, entity=None): """removes an entity from the Source""" if len(self.getActiveObjectQueue()) == 1 and len(self.scheduledEntities): # create the Entity object and assign its name newEntity = self.createEntity() # assign the current simulation time as the Entity's creation time newEntity.creationTime = self.scheduledEntities.pop(0) # assign the current simulation time as the Entity's start time newEntity.startTime = newEntity.creationTime # update the current station of the Entity newEntity.currentStation = self G.EntityList.append(newEntity) # append the entity to the resource self.getActiveObjectQueue().append(newEntity) self.numberOfArrivals += 1 # we have one new arrival G.numberOfEntities += 1 self.appendEntity(newEntity) # run the default method activeEntity = CoreObject.removeEntity(self, entity) if len(self.getActiveObjectQueue()) == 1: if self.expectedSignals["entityCreated"]: self.sendSignal(receiver=self, signal=self.entityCreated) return activeEntity