Source code for manpy.simulation.core.Exit

# ===========================================================================
# 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 6 Feb 2013

@author: George
"""


# from SimPy.Simulation import now, Process, Resource, infinity, waituntil, waitevent
import simpy
from manpy.simulation.core.CoreObject import CoreObject

# ===========================================================================
#                            The exit object
# ===========================================================================
[docs] class Exit(CoreObject): """ models the exit of the model """ family = "Exit" def __init__(self, id, name, cost=0, cancelCondition={}, **kw): self.type = "Exit" # XXX needed ? self.isNext = True self.isPrevious = False # lists to hold statistics of multiple runs self.Exits = [] self.UnitExits = [] self.Lifespan = [] self.TaktTime = [] # if input is given in a dictionary CoreObject.__init__(self, id, name, cost) from .Globals import G G.ExitList.append(self) self.cancelCondition = cancelCondition
[docs] def initialize(self): # using the Process __init__ and not the CoreObject __init__ CoreObject.initialize(self) # initialize the internal Queue (type Resource) of the Exit self.Res = simpy.Resource(self.env, capacity=float("inf")) # The number of resource that exited through this exit. # XXX bug: cannot output as json when nothing has exited. self.numOfExits = 0 self.totalNumberOfUnitsExited = 0 self.totalLifespan = 0 self.entities = [] self.totalTaktTime = 0 # the total time between to consecutive exits self.intervalThroughPutList = [] self.expectedSignals["isRequested"] = 1
[docs] def run(self): while 1: # wait until the Queue can accept an entity and one predecessor requests it self.expectedSignals["isRequested"] = 1 yield self.isRequested self.isRequested = self.env.event() # TODO: insert extra controls to check whether the self.giver attribute is correctly updated self.entities.append(self.getEntity()) self.signalGiver()
[docs] def defineRouting(self, predecessorList=[]): """sets the routing in element for the Exit""" self.previous = predecessorList # no successorList for the Exit
[docs] def defineNext(self, successorList=[]): """Safeguarding for mistakenly trying to set the next element on an Exit object""" print("Trying to set successors for Exits does not have any effects.")
[docs] def canAccept(self, callerObject=None): """checks if the Exit can accept an entity""" return True # the exit always can accept an entity
[docs] def canAcceptAndIsRequested(self, callerObject=None): """checks if the Exit can accept an entity and there is an entity waiting for it""" # get the active object and its internal queue activeObject = self.getActiveObject() activeObjectQueue = self.getActiveObjectQueue() giverObject = callerObject assert giverObject, "there must be a caller for canAcceptAndIsRequested" return giverObject.haveToDispose(self)
[docs] def getEntity(self): """gets an entity from the predecessor""" activeEntity = CoreObject.getEntity(self) # run the default method # add to cost of entity activeEntity.cost += self.cost # if the entity is in the G.pendingEntities list then remove it from there from .Globals import G # G.pendingEntities[:]=(entity for entity in G.pendingEntities if not entity is activeEntity) if G.RouterList: if activeEntity in G.pendingEntities: G.pendingEntities.remove(activeEntity) # if activeEntity in G.EntityList: # G.EntityList.remove(activeEntity) # self.clear(activeEntity) self.totalLifespan += ( self.env.now - activeEntity.startTime ) # Add the entity's lifespan to the total one. self.numOfExits += 1 # increase the exits by one self.totalNumberOfUnitsExited += ( activeEntity.numberOfUnits ) # add the number of units that xited self.totalTaktTime += ( self.env.now - self.timeLastEntityLeft ) # add the takt time self.timeLastEntityLeft = ( self.env.now ) # update the time that the last entity left from the Exit activeObjectQueue = self.getActiveObjectQueue() del self.Res.users[:] # if there is a cancelCondition the exit may end the simulation if self.cancelCondition: if ( self.cancelCondition.get("reason", None) == "throughput" and int(self.cancelCondition.get("number", -1)) == self.numOfExits ): self.endSimulation() if ( self.cancelCondition.get("reason", None) == "empty" and self.checkIfSystemEmpty() ): self.endSimulation() return activeEntity
[docs] @staticmethod def clear(entity): from .Globals import G def deleteEntityfromlist(entity, list): if entity in list: list.remove(entity) lists = (G.EntityList, G.PartList, G.pendingEntities, G.WipList) # lists=(G.EntityList, G.PartList, G.BatchList, G.SubBatchList, # G.JobList, G.OrderList, G.OrderComponentList, G.MouldList, # G.pendingEntities, G.WipList) for list in lists: deleteEntityfromlist(entity, list)
[docs] def haveToDispose(self, callerObject=None): """haveToDispose of an exit must always return False""" return False
[docs] def postProcessing(self, MaxSimtime=None): """actions to be taken after the simulation ends""" from .Globals import G if MaxSimtime == None: MaxSimtime = G.maxSimTime # hold the numberOfExits of each replication self.Exits.append(self.numOfExits) self.UnitExits.append(self.totalNumberOfUnitsExited) try: # throw exception in case the numOfExits is zero self.Lifespan.append(((self.totalLifespan) / self.numOfExits) / G.Base) except ZeroDivisionError: # the lifespan in this case is zero self.Lifespan.append(0) try: # throw exception in case of zero division self.TaktTime.append(((self.totalTaktTime) / self.numOfExits) / G.Base) except ZeroDivisionError: # the average time between exits is zero if no Entity exited self.TaktTime.append(0)
[docs] def outputResultsJSON(self): """outputs results to JSON File""" from .Globals import G json = { "_class": "manpy.%s" % self.__class__.__name__, "id": self.id, "family": self.family, "results": {}, } json["results"]["throughput"] = self.Exits json["results"]["lifespan"] = self.Lifespan json["results"]["takt_time"] = self.TaktTime if ( self.Exits != self.UnitExits ): # output this only if there was variability in units json["results"]["unitsThroughput"] = self.UnitExits G.outputJSON["elementList"].append(json)