first changes, topology09 running

parent f9392dab
...@@ -25,15 +25,18 @@ Created on 12 Jul 2012 ...@@ -25,15 +25,18 @@ Created on 12 Jul 2012
Class that acts as an abstract. It should have no instances. All the core-objects should inherit from it Class that acts as an abstract. It should have no instances. All the core-objects should inherit from it
''' '''
from SimPy.Simulation import Process, Resource, now, SimEvent, waitevent # from SimPy.Simulation import Process, Resource, now, SimEvent, waitevent
import simpy
# =========================================================================== # ===========================================================================
# the core object # the core object
# =========================================================================== # ===========================================================================
class CoreObject(Process): class CoreObject(object):
def __init__(self, id, name, **kw): def __init__(self, id, name, **kw):
Process.__init__(self) from Globals import G
self.env=G.env
# Process.__init__(self)
self.id = id self.id = id
self.objName = name self.objName = name
# lists that hold the previous and next objects in the flow # lists that hold the previous and next objects in the flow
...@@ -54,14 +57,18 @@ class CoreObject(Process): ...@@ -54,14 +57,18 @@ class CoreObject(Process):
self.interruptCause=None self.interruptCause=None
self.gatherWipStat=False self.gatherWipStat=False
# signalizing an event that activates the generator # signalizing an event that activates the generator
self.isRequested=SimEvent('isRequested') # self.isRequested=SimEvent('isRequested')
self.canDispose=SimEvent('canDispose') self.isRequested=self.env.event()
self.interruptionEnd=SimEvent('interruptionEnd') # self.canDispose=SimEvent('canDispose')
self.interruptionStart=SimEvent('interruptionStart') self.canDispose=self.env.event()
# self.interruptionEnd=SimEvent('interruptionEnd')
self.interruptionEnd=self.env.event()
# self.interruptionStart=SimEvent('interruptionStart')
self.interruptionStart=self.env.event()
def initialize(self): def initialize(self):
# XXX why call super.__init__ outside of __init__ ? # XXX why call super.__init__ outside of __init__ ?
Process.__init__(self) # Process.__init__(self)
self.Up=True #Boolean that shows if the machine is in failure ("Down") or not ("up") self.Up=True #Boolean that shows if the machine is in failure ("Down") or not ("up")
self.onShift=True self.onShift=True
self.currentEntity=None self.currentEntity=None
...@@ -133,10 +140,14 @@ class CoreObject(Process): ...@@ -133,10 +140,14 @@ class CoreObject(Process):
# TODO, this should be also updated in Globals.setWIP (in case we have initial wip) # TODO, this should be also updated in Globals.setWIP (in case we have initial wip)
self.wipStatList=[[0,0]] self.wipStatList=[[0,0]]
# signalizing an event that activates the generator # signalizing an event that activates the generator
self.isRequested=SimEvent('isRequested') # self.isRequested=SimEvent('isRequested')
self.canDispose=SimEvent('canDispose') self.isRequested=self.env.event()
self.interruptionEnd=SimEvent('interruptionEnd') # self.canDispose=SimEvent('canDispose')
self.interruptionStart=SimEvent('interruptionStart') self.canDispose=self.env.event()
# self.interruptionEnd=SimEvent('interruptionEnd')
self.interruptionEnd=self.env.event()
# self.interruptionStart=SimEvent('interruptionStart')
self.interruptionStart=self.env.event()
# ======================================================================= # =======================================================================
# the main process of the core object # the main process of the core object
...@@ -167,7 +178,7 @@ class CoreObject(Process): ...@@ -167,7 +178,7 @@ class CoreObject(Process):
def removeEntity(self, entity=None): def removeEntity(self, entity=None):
self.addBlockage() self.addBlockage()
activeObjectQueue=self.Res.activeQ activeObjectQueue=self.Res.users
activeObjectQueue.remove(entity) #remove the Entity from the queue activeObjectQueue.remove(entity) #remove the Entity from the queue
if self.receiver: if self.receiver:
self.receiver.appendEntity(entity) self.receiver.appendEntity(entity)
...@@ -176,11 +187,11 @@ class CoreObject(Process): ...@@ -176,11 +187,11 @@ class CoreObject(Process):
self.downTimeInTryingToReleaseCurrentEntity=0 self.downTimeInTryingToReleaseCurrentEntity=0
self.offShiftTimeTryingToReleaseCurrentEntity=0 self.offShiftTimeTryingToReleaseCurrentEntity=0
self.timeLastEntityLeft=now() self.timeLastEntityLeft=self.env.now
self.outputTrace(entity.name, "released "+self.objName) self.outputTrace(entity.name, "released "+self.objName)
# update wipStatList # update wipStatList
if self.gatherWipStat: if self.gatherWipStat:
self.wipStatList.append([now(), len(activeObjectQueue)]) self.wipStatList.append([self.env.now, len(activeObjectQueue)])
return entity return entity
#=========================================================================== #===========================================================================
...@@ -188,7 +199,7 @@ class CoreObject(Process): ...@@ -188,7 +199,7 @@ class CoreObject(Process):
# this method is created to be overridden by the Assembly class in its getEntity where Frames are loaded # this method is created to be overridden by the Assembly class in its getEntity where Frames are loaded
#=========================================================================== #===========================================================================
def appendEntity(self,entity=None): def appendEntity(self,entity=None):
activeObjectQueue=self.Res.activeQ activeObjectQueue=self.Res.users
activeObjectQueue.append(entity) activeObjectQueue.append(entity)
# ======================================================================= # =======================================================================
...@@ -205,11 +216,11 @@ class CoreObject(Process): ...@@ -205,11 +216,11 @@ class CoreObject(Process):
# each time an Entity is removed # each time an Entity is removed
# ======================================================================= # =======================================================================
def addBlockage(self): def addBlockage(self):
self.totalTimeInCurrentEntity=now()-self.timeLastEntityEntered self.totalTimeInCurrentEntity=self.env.now-self.timeLastEntityEntered
self.totalTimeWaitingForOperator += self.operatorWaitTimeCurrentEntity self.totalTimeWaitingForOperator += self.operatorWaitTimeCurrentEntity
if self.timeLastEntityEnded<self.timeLastShiftStarted: if self.timeLastEntityEnded<self.timeLastShiftStarted:
self.offShiftTimeTryingToReleaseCurrentEntity=self.timeLastShiftStarted-self.timeLastShiftEnded self.offShiftTimeTryingToReleaseCurrentEntity=self.timeLastShiftStarted-self.timeLastShiftEnded
blockage=now()-(self.timeLastEntityEnded+self.downTimeInTryingToReleaseCurrentEntity+self.offShiftTimeTryingToReleaseCurrentEntity) blockage=self.env.now-(self.timeLastEntityEnded+self.downTimeInTryingToReleaseCurrentEntity+self.offShiftTimeTryingToReleaseCurrentEntity)
self.totalBlockageTime+=blockage self.totalBlockageTime+=blockage
# ======================================================================= # =======================================================================
...@@ -219,12 +230,12 @@ class CoreObject(Process): ...@@ -219,12 +230,12 @@ class CoreObject(Process):
# get active object and its queue, as well as the active (to be) entity # get active object and its queue, as well as the active (to be) entity
#(after the sorting of the entities in the queue of the giver object) #(after the sorting of the entities in the queue of the giver object)
# activeObject=self.getActiveObject() # activeObject=self.getActiveObject()
activeObjectQueue=self.Res.activeQ activeObjectQueue=self.Res.users
# get giver object, its queue, and sort the entities according to this object priorities # get giver object, its queue, and sort the entities according to this object priorities
giverObject=self.giver giverObject=self.giver
giverObject.sortEntities() #sort the Entities of the giver giverObject.sortEntities() #sort the Entities of the giver
#according to the scheduling rule if applied #according to the scheduling rule if applied
giverObjectQueue=giverObject.Res.activeQ giverObjectQueue=giverObject.Res.users
# if the giverObject is blocked then unBlock it # if the giverObject is blocked then unBlock it
if giverObject.exitIsAssignedTo(): if giverObject.exitIsAssignedTo():
giverObject.unAssignExit() giverObject.unAssignExit()
...@@ -242,10 +253,10 @@ class CoreObject(Process): ...@@ -242,10 +253,10 @@ class CoreObject(Process):
#append the time to schedule so that it can be read in the result #append the time to schedule so that it can be read in the result
#remember that every entity has it's schedule which is supposed to be updated every time #remember that every entity has it's schedule which is supposed to be updated every time
# he entity enters a new object # he entity enters a new object
activeEntity.schedule.append([self,now()]) activeEntity.schedule.append([self,self.env.now])
#update variables #update variables
activeEntity.currentStation=self activeEntity.currentStation=self
self.timeLastEntityEntered=now() self.timeLastEntityEntered=self.env.now
self.nameLastEntityEntered=activeEntity.name # this holds the name of the last entity that got into Machine self.nameLastEntityEntered=activeEntity.name # this holds the name of the last entity that got into Machine
self.downTimeProcessingCurrentEntity=0 self.downTimeProcessingCurrentEntity=0
# update the next list of the object # update the next list of the object
...@@ -265,7 +276,7 @@ class CoreObject(Process): ...@@ -265,7 +276,7 @@ class CoreObject(Process):
# and if preemption is required # and if preemption is required
#=========================================================================== #===========================================================================
def preemptReceiver(self): def preemptReceiver(self):
activeObjectQueue=self.Res.activeQ activeObjectQueue=self.Res.users
# find a critical order if any # find a critical order if any
critical=False critical=False
...@@ -296,13 +307,13 @@ class CoreObject(Process): ...@@ -296,13 +307,13 @@ class CoreObject(Process):
# if the obtained Entity is critical and the receiver is preemptive and not operated # if the obtained Entity is critical and the receiver is preemptive and not operated
# in the case that the receiver is operated the preemption is performed by the operators # in the case that the receiver is operated the preemption is performed by the operators
# if the receiver is not Up then no preemption will be performed # if the receiver is not Up then no preemption will be performed
if not receiverOperated and len(receiver.Res.activeQ)>0: if not receiverOperated and len(receiver.Res.users)>0:
#if the receiver does not hold an Entity that is also critical #if the receiver does not hold an Entity that is also critical
if not receiver.Res.activeQ[0].isCritical: if not receiver.Res.users[0].isCritical:
receiver.shouldPreempt=True receiver.shouldPreempt=True
# self.printTrace(self.id, preempt=receiver.id) # self.printTrace(self.id, preempt=receiver.id)
receiver.preempt() receiver.preempt()
receiver.timeLastEntityEnded=now() #required to count blockage correctly in the preemptied station receiver.timeLastEntityEnded=self.env.now #required to count blockage correctly in the preemptied station
# sort so that the critical entity is placed in front # sort so that the critical entity is placed in front
activeObjectQueue.sort(key=lambda x: x==activeEntity, reverse=True) activeObjectQueue.sort(key=lambda x: x==activeEntity, reverse=True)
# if there is a critical entity and the possible receivers are operated then signal the Router # if there is a critical entity and the possible receivers are operated then signal the Router
...@@ -311,7 +322,7 @@ class CoreObject(Process): ...@@ -311,7 +322,7 @@ class CoreObject(Process):
activeObjectQueue.sort(key=lambda x: x==activeEntity, reverse=True) activeObjectQueue.sort(key=lambda x: x==activeEntity, reverse=True)
# update wipStatList # update wipStatList
if self.gatherWipStat: if self.gatherWipStat:
self.wipStatList.append([now(), len(activeObjectQueue)]) self.wipStatList.append([self.env.now, len(activeObjectQueue)])
#=========================================================================== #===========================================================================
...@@ -364,7 +375,7 @@ class CoreObject(Process): ...@@ -364,7 +375,7 @@ class CoreObject(Process):
# self.printTrace(self.id, signalReceiver=self.receiver.id) # self.printTrace(self.id, signalReceiver=self.receiver.id)
# assign the entry of the receiver # assign the entry of the receiver
self.receiver.assignEntryTo() self.receiver.assignEntryTo()
self.receiver.isRequested.signal(self) self.receiver.isRequested.succeed(self)
return True return True
# if no receiver can accept then try to preempt a receive if the stations holds a critical order # if no receiver can accept then try to preempt a receive if the stations holds a critical order
self.preemptReceiver() self.preemptReceiver()
...@@ -379,8 +390,9 @@ class CoreObject(Process): ...@@ -379,8 +390,9 @@ class CoreObject(Process):
# dummy variables that help prioritize the objects requesting to give objects to the Machine (activeObject) # dummy variables that help prioritize the objects requesting to give objects to the Machine (activeObject)
maxTimeWaiting=0 # dummy variable counting the time a successor is waiting maxTimeWaiting=0 # dummy variable counting the time a successor is waiting
receiver=None receiver=None
from Globals import G
for object in candidates: for object in candidates:
timeWaiting=now()-object.timeLastEntityLeft # the time it has been waiting is updated and stored in dummy variable timeWaiting timeWaiting=G.env.now-object.timeLastEntityLeft # the time it has been waiting is updated and stored in dummy variable timeWaiting
if(timeWaiting>maxTimeWaiting or maxTimeWaiting==0):# if the timeWaiting is the maximum among the ones of the successors if(timeWaiting>maxTimeWaiting or maxTimeWaiting==0):# if the timeWaiting is the maximum among the ones of the successors
maxTimeWaiting=timeWaiting maxTimeWaiting=timeWaiting
receiver=object # set the receiver as the longest waiting possible receiver receiver=object # set the receiver as the longest waiting possible receiver
...@@ -394,13 +406,13 @@ class CoreObject(Process): ...@@ -394,13 +406,13 @@ class CoreObject(Process):
# if an operator is not assigned to the receiver then do not signal the receiver but the Router # if an operator is not assigned to the receiver then do not signal the receiver but the Router
try: try:
if not receiver.assignedOperator or\ if not receiver.assignedOperator or\
(receiver.isPreemptive and len(receiver.Res.activeQ)>0): (receiver.isPreemptive and len(receiver.Res.users)>0):
if receiver.isLoadRequested(): if receiver.isLoadRequested():
from Globals import G from Globals import G
if not G.Router.invoked: if not G.Router.invoked:
# self.printTrace(self.id, signal='router') # self.printTrace(self.id, signal='router')
G.Router.invoked=True G.Router.invoked=True
G.Router.isCalled.signal(now()) G.Router.isCalled.succeed(self.env.now)
return True return True
else: else:
return False return False
...@@ -454,7 +466,7 @@ class CoreObject(Process): ...@@ -454,7 +466,7 @@ class CoreObject(Process):
self.giver=giver self.giver=giver
self.giver.receiver=self self.giver.receiver=self
# self.printTrace(self.id, signalGiver=self.giver.id) # self.printTrace(self.id, signalGiver=self.giver.id)
self.giver.canDispose.signal(self) self.giver.canDispose.succeed(self)
return True return True
return False return False
...@@ -467,12 +479,13 @@ class CoreObject(Process): ...@@ -467,12 +479,13 @@ class CoreObject(Process):
# dummy variables that help prioritize the objects requesting to give objects to the Machine (activeObject) # dummy variables that help prioritize the objects requesting to give objects to the Machine (activeObject)
maxTimeWaiting=0 # dummy variable counting the time a predecessor is blocked maxTimeWaiting=0 # dummy variable counting the time a predecessor is blocked
giver=None giver=None
from Globals import G
# loop through the possible givers to see which have to dispose and which is the one blocked for longer # loop through the possible givers to see which have to dispose and which is the one blocked for longer
for object in candidates: for object in candidates:
if(object.downTimeInTryingToReleaseCurrentEntity>0):# and the predecessor has been down while trying to give away the Entity if(object.downTimeInTryingToReleaseCurrentEntity>0):# and the predecessor has been down while trying to give away the Entity
timeWaiting=now()-object.timeLastFailureEnded # the timeWaiting dummy variable counts the time end of the last failure of the giver object timeWaiting=self.env.now-object.timeLastFailureEnded # the timeWaiting dummy variable counts the time end of the last failure of the giver object
else: else:
timeWaiting=now()-object.timeLastEntityEnded # in any other case, it holds the time since the end of the Entity processing timeWaiting=G.env.now-object.timeLastEntityEnded # in any other case, it holds the time since the end of the Entity processing
#if more than one predecessor have to dispose take the part from the one that is blocked longer #if more than one predecessor have to dispose take the part from the one that is blocked longer
if(timeWaiting>=maxTimeWaiting): if(timeWaiting>=maxTimeWaiting):
giver=object # the object to deliver the Entity to the activeObject is set to the ith member of the previous list giver=object # the object to deliver the Entity to the activeObject is set to the ith member of the previous list
...@@ -493,7 +506,7 @@ class CoreObject(Process): ...@@ -493,7 +506,7 @@ class CoreObject(Process):
from Globals import G from Globals import G
if(G.trace=="Yes"): #output only if the user has selected to if(G.trace=="Yes"): #output only if the user has selected to
#handle the 3 columns #handle the 3 columns
G.traceSheet.write(G.traceIndex,0,str(now())) G.traceSheet.write(G.traceIndex,0,str(self.env.now))
G.traceSheet.write(G.traceIndex,1,entityName) G.traceSheet.write(G.traceIndex,1,entityName)
G.traceSheet.write(G.traceIndex,2,message) G.traceSheet.write(G.traceIndex,2,message)
G.traceIndex+=1 #increment the row G.traceIndex+=1 #increment the row
...@@ -509,7 +522,7 @@ class CoreObject(Process): ...@@ -509,7 +522,7 @@ class CoreObject(Process):
assert len(kw)==1, 'only one phrase per printTrace supported for the moment' assert len(kw)==1, 'only one phrase per printTrace supported for the moment'
from Globals import G from Globals import G
import Globals import Globals
time=now() time=self.env.now
charLimit=60 charLimit=60
remainingChar=charLimit-len(entity)-len(str(time)) remainingChar=charLimit-len(entity)-len(str(time))
if(G.console=='Yes'): if(G.console=='Yes'):
...@@ -549,7 +562,7 @@ class CoreObject(Process): ...@@ -549,7 +562,7 @@ class CoreObject(Process):
# checks if the Object can dispose an entity to the following object # checks if the Object can dispose an entity to the following object
# ======================================================================= # =======================================================================
def haveToDispose(self, callerObject=None): def haveToDispose(self, callerObject=None):
activeObjectQueue=self.Res.activeQ activeObjectQueue=self.Res.users
return len(activeObjectQueue)>0 return len(activeObjectQueue)>0
# ======================================================================= # =======================================================================
...@@ -581,7 +594,7 @@ class CoreObject(Process): ...@@ -581,7 +594,7 @@ class CoreObject(Process):
# get the activeQ of the active object. # get the activeQ of the active object.
# ======================================================================= # =======================================================================
def getActiveObjectQueue(self): def getActiveObjectQueue(self):
return self.Res.activeQ return self.Res.users
# ======================================================================= # =======================================================================
# get the giver object in a getEntity transaction. # get the giver object in a getEntity transaction.
...@@ -593,7 +606,7 @@ class CoreObject(Process): ...@@ -593,7 +606,7 @@ class CoreObject(Process):
# get the giver object queue in a getEntity transaction. # get the giver object queue in a getEntity transaction.
# ======================================================================= # =======================================================================
def getGiverObjectQueue(self): def getGiverObjectQueue(self):
return self.giver.Res.activeQ return self.giver.Res.users
# ======================================================================= # =======================================================================
# get the receiver object in a removeEntity transaction. # get the receiver object in a removeEntity transaction.
...@@ -605,7 +618,7 @@ class CoreObject(Process): ...@@ -605,7 +618,7 @@ class CoreObject(Process):
# get the receiver object queue in a removeEntity transaction. # get the receiver object queue in a removeEntity transaction.
# ======================================================================= # =======================================================================
def getReceiverObjectQueue(self): def getReceiverObjectQueue(self):
return self.receiver.Res.activeQ return self.receiver.Res.users
# ======================================================================= # =======================================================================
# calculates the processing time # calculates the processing time
...@@ -674,7 +687,7 @@ class CoreObject(Process): ...@@ -674,7 +687,7 @@ class CoreObject(Process):
# false if object holds entities in its queue # false if object holds entities in its queue
#=========================================================================== #===========================================================================
def activeQueueIsEmpty(self): def activeQueueIsEmpty(self):
return len(self.Res.activeQ)==0 return len(self.Res.users)==0
# ======================================================================= # =======================================================================
# actions to be carried out when the processing of an Entity ends # actions to be carried out when the processing of an Entity ends
...@@ -686,5 +699,5 @@ class CoreObject(Process): ...@@ -686,5 +699,5 @@ class CoreObject(Process):
# check if an entity is in the internal Queue of the object # check if an entity is in the internal Queue of the object
#=========================================================================== #===========================================================================
def isInActiveQueue(self, entity=None): def isInActiveQueue(self, entity=None):
activeObjectQueue = self.Res.activeQ activeObjectQueue = self.Res.users
return any(x==entity for x in activeObjectQueue) return any(x==entity for x in activeObjectQueue)
...@@ -25,7 +25,8 @@ Created on 6 Feb 2013 ...@@ -25,7 +25,8 @@ Created on 6 Feb 2013
models the exit of the model models the exit of the model
''' '''
from SimPy.Simulation import now, Process, Resource, infinity, waituntil, waitevent # from SimPy.Simulation import now, Process, Resource, infinity, waituntil, waitevent
import simpy
import xlwt import xlwt
from CoreObject import CoreObject from CoreObject import CoreObject
...@@ -54,7 +55,7 @@ class Exit(CoreObject): ...@@ -54,7 +55,7 @@ class Exit(CoreObject):
CoreObject.initialize(self) CoreObject.initialize(self)
# initialize the internal Queue (type Resource) of the Exit # initialize the internal Queue (type Resource) of the Exit
self.Res=Resource(capacity=infinity) self.Res=simpy.Resource(self.env, capacity=10000)
# The number of resource that exited through this exit. # The number of resource that exited through this exit.
# XXX bug: cannot output as json when nothing has exited. # XXX bug: cannot output as json when nothing has exited.
self.numOfExits=0 self.numOfExits=0
...@@ -68,7 +69,8 @@ class Exit(CoreObject): ...@@ -68,7 +69,8 @@ class Exit(CoreObject):
def run(self): def run(self):
while 1: while 1:
# wait until the Queue can accept an entity and one predecessor requests it # wait until the Queue can accept an entity and one predecessor requests it
yield waitevent, self, self.isRequested yield self.isRequested
self.isRequested=self.env.event()
# TODO: insert extra controls to check whether the self.giver attribute is correctly updated # TODO: insert extra controls to check whether the self.giver attribute is correctly updated
self.getEntity() self.getEntity()
...@@ -109,13 +111,13 @@ class Exit(CoreObject): ...@@ -109,13 +111,13 @@ class Exit(CoreObject):
# if activeEntity in G.EntityList: # if activeEntity in G.EntityList:
# G.EntityList.remove(activeEntity) # G.EntityList.remove(activeEntity)
# self.clear(activeEntity) # self.clear(activeEntity)
self.totalLifespan+=now()-activeEntity.startTime #Add the entity's lifespan to the total one. 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.numOfExits+=1 # increase the exits by one
self.totalNumberOfUnitsExited+=activeEntity.numberOfUnits # add the number of units that xited self.totalNumberOfUnitsExited+=activeEntity.numberOfUnits # add the number of units that xited
self.totalTaktTime+=now()-self.timeLastEntityLeft # add the takt time self.totalTaktTime+=self.env.now-self.timeLastEntityLeft # add the takt time
self.timeLastEntityLeft=now() # update the time that the last entity left from the Exit self.timeLastEntityLeft=self.env.now # update the time that the last entity left from the Exit
activeObjectQueue=self.getActiveObjectQueue() activeObjectQueue=self.getActiveObjectQueue()
del self.Res.activeQ[:] del self.Res.users[:]
return activeEntity return activeEntity
@staticmethod @staticmethod
......
...@@ -40,7 +40,8 @@ import numpy ...@@ -40,7 +40,8 @@ import numpy
numpy.seterr(all='raise') numpy.seterr(all='raise')
from SimPy.Simulation import activate, initialize, simulate, now, infinity # from SimPy.Simulation import activate, initialize, simulate, now, infinity
import simpy
from Globals import G from Globals import G
from Source import Source from Source import Source
from Machine import Machine from Machine import Machine
...@@ -885,11 +886,14 @@ def initializeObjects(): ...@@ -885,11 +886,14 @@ def initializeObjects():
# =========================================================================== # ===========================================================================
def activateObjects(): def activateObjects():
for element in G.ObjList: for element in G.ObjList:
activate(element, element.run()) # activate(element, element.run())
G.env.process(element.run())
for ev in G.EventGeneratorList: for ev in G.EventGeneratorList:
activate(ev, ev.run()) # activate(ev, ev.run())
G.env.process(ev.run())
for oi in G.ObjectInterruptionList: for oi in G.ObjectInterruptionList:
activate(oi, oi.run()) # activate(oi, oi.run())
G.env.process(oi.run())
# =========================================================================== # ===========================================================================
# reads the WIP of the stations # reads the WIP of the stations
...@@ -1261,6 +1265,7 @@ def main(argv=[], input_data=None): ...@@ -1261,6 +1265,7 @@ def main(argv=[], input_data=None):
#read the input from the JSON file and create the line #read the input from the JSON file and create the line
G.JSONData=json.loads(G.InputData) # create the dictionary JSONData G.JSONData=json.loads(G.InputData) # create the dictionary JSONData
readGeneralInput() readGeneralInput()
G.env=simpy.Environment() # initialize the environment
createObjects() createObjects()
createObjectInterruptions() createObjectInterruptions()
setTopology() setTopology()
...@@ -1272,7 +1277,7 @@ def main(argv=[], input_data=None): ...@@ -1272,7 +1277,7 @@ def main(argv=[], input_data=None):
G.Rnd=Random('%s%s' % (G.seed, i)) G.Rnd=Random('%s%s' % (G.seed, i))
else: else:
G.Rnd=Random() G.Rnd=Random()
initialize() #initialize the simulation # initialize() #initialize the simulation
createWIP() createWIP()
initializeObjects() initializeObjects()
Globals.setWIP(G.EntityList) Globals.setWIP(G.EntityList)
...@@ -1281,22 +1286,24 @@ def main(argv=[], input_data=None): ...@@ -1281,22 +1286,24 @@ def main(argv=[], input_data=None):
# if the simulation is ran until no more events are scheduled, # if the simulation is ran until no more events are scheduled,
# then we have to find the end time as the time the last entity ended. # then we have to find the end time as the time the last entity ended.
if G.maxSimTime==-1: if G.maxSimTime==-1:
simulate(until=infinity) # simulate until there are no more events. G.env.run(until=infinity)
# If someone does it for a model that has always events, then it will run forever! # simulate(until=infinity) # simulate until there are no more events.
# # If someone does it for a model that has always events, then it will run forever!
# # identify from the exits what is the time that the last entity has ended. # # identify from the exits what is the time that the last entity has ended.
# endList=[] # endList=[]
# for exit in G.ExitList: # for exit in G.ExitList:
# endList.append(exit.timeLastEntityLeft) # endList.append(exit.timeLastEntityLeft)
# G.maxSimTime=float(max(endList)) # G.maxSimTime=float(max(endList))
# identify the time of the last event # identify the time of the last event
if now()!=0: #do not let G.maxSimTime=0 so that there will be no crash if G.env.now!=0: #do not let G.maxSimTime=0 so that there will be no crash
G.maxSimTime=now() G.maxSimTime=env.now
else: else:
print "simulation ran for 0 time, something may have gone wrong" print "simulation ran for 0 time, something may have gone wrong"
logger.info("simulation ran for 0 time, something may have gone wrong") logger.info("simulation ran for 0 time, something may have gone wrong")
#else we simulate until the given maxSimTime #else we simulate until the given maxSimTime
else: else:
simulate(until=G.maxSimTime) #simulate until the given maxSimTime G.env.run(until=G.maxSimTime)
# simulate(until=G.maxSimTime) #simulate until the given maxSimTime
#carry on the post processing operations for every object in the topology #carry on the post processing operations for every object in the topology
for element in G.ObjList: for element in G.ObjList:
......
...@@ -25,8 +25,9 @@ Created on 8 Nov 2012 ...@@ -25,8 +25,9 @@ Created on 8 Nov 2012
Models a machine that can also have failures Models a machine that can also have failures
''' '''
from SimPy.Simulation import Process, Resource, SimEvent # from SimPy.Simulation import Process, Resource, SimEvent
from SimPy.Simulation import activate, passivate, waituntil, now, hold, request, release, waitevent # from SimPy.Simulation import activate, passivate, waituntil, now, hold, request, release, waitevent
import simpy
from Failure import Failure from Failure import Failure
from CoreObject import CoreObject from CoreObject import CoreObject
...@@ -150,12 +151,14 @@ class Machine(CoreObject): ...@@ -150,12 +151,14 @@ class Machine(CoreObject):
self.isPreemptive=isPreemptive self.isPreemptive=isPreemptive
self.resetOnPreemption=resetOnPreemption self.resetOnPreemption=resetOnPreemption
# events used by the broker # events used by the broker
self.brokerIsSet=SimEvent('brokerIsSet') # self.brokerIsSet=SimEvent('brokerIsSet')
self.brokerIsSet=self.env.event()
# this event is generated every time an operator is requested by machine for Load operation type. # this event is generated every time an operator is requested by machine for Load operation type.
# if the machine has not succeeded in getting an entity due to the resource absence # if the machine has not succeeded in getting an entity due to the resource absence
# and waits for the next event to get the entity, # and waits for the next event to get the entity,
# then it must be signalled that the operator is now available # then it must be signalled that the operator is now available
self.loadOperatorAvailable=SimEvent('loadOperatorAvailable') # self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
self.loadOperatorAvailable=self.env.event()
# flag notifying that there is operator assigned to the actievObject # flag notifying that there is operator assigned to the actievObject
self.assignedOperator=True self.assignedOperator=True
...@@ -166,7 +169,8 @@ class Machine(CoreObject): ...@@ -166,7 +169,8 @@ class Machine(CoreObject):
# using the Process __init__ and not the CoreObject __init__ # using the Process __init__ and not the CoreObject __init__
CoreObject.initialize(self) CoreObject.initialize(self)
# initialize the internal Queue (type Resource) of the Machine # initialize the internal Queue (type Resource) of the Machine
self.Res=Resource(self.capacity) #self.Res=Resource(self.capacity)
self.Res=simpy.Resource(self.env, capacity=1)
# initiate the Broker responsible to control the request/release # initiate the Broker responsible to control the request/release
# initialize the operator pool if any # initialize the operator pool if any
if (self.operatorPool!="None"): if (self.operatorPool!="None"):
...@@ -211,12 +215,14 @@ class Machine(CoreObject): ...@@ -211,12 +215,14 @@ class Machine(CoreObject):
# flag notifying that there is operator assigned to the actievObject # flag notifying that there is operator assigned to the actievObject
self.assignedOperator=True self.assignedOperator=True
self.brokerIsSet=SimEvent('brokerIsSet') # self.brokerIsSet=SimEvent('brokerIsSet')
self.brokerIsSet=self.env.event()
# this event is generated every time an operator is requested by machine for Load operation type. # this event is generated every time an operator is requested by machine for Load operation type.
# if the machine has not succeeded in getting an entity due to the resource absence # if the machine has not succeeded in getting an entity due to the resource absence
# and waits for the next event to get the entity, # and waits for the next event to get the entity,
# then it must be signalled that the operator is now available # then it must be signalled that the operator is now available
self.loadOperatorAvailable=SimEvent('loadOperatorAvailable') # self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
self.loadOperatorAvailable=self.env.event()
# ======================================================================= # =======================================================================
# the main process of the machine # the main process of the machine
...@@ -229,23 +235,29 @@ class Machine(CoreObject): ...@@ -229,23 +235,29 @@ class Machine(CoreObject):
# waitEvent isRequested /interruptionEnd/loadOperatorAvailable # waitEvent isRequested /interruptionEnd/loadOperatorAvailable
while 1: while 1:
# self.printTrace(self.id, waitEvent='') # self.printTrace(self.id, waitEvent='')
yield waitevent, self, [self.isRequested, self.interruptionEnd, self.loadOperatorAvailable] # yield waitevent, self, [self.isRequested, self.interruptionEnd, self.loadOperatorAvailable]
receivedEvent = yield self.isRequested | self.interruptionEnd | self.loadOperatorAvailable
# self.printTrace(self.id, received='') # self.printTrace(self.id, received='')
# if the machine can accept an entity and one predecessor requests it continue with receiving the entity # if the machine can accept an entity and one predecessor requests it continue with receiving the entity
if self.isRequested.signalparam: if self.isRequested in receivedEvent:
# self.printTrace(self.id, isRequested=self.isRequested.signalparam.id) # self.printTrace(self.id, isRequested=self.isRequested.value.id)
assert self.isRequested.signalparam==self.giver, 'the giver is not the requestingObject' assert self.isRequested.value==self.giver, 'the giver is not the requestingObject'
assert self.giver.receiver==self, 'the receiver of the signalling object in not the station' assert self.giver.receiver==self, 'the receiver of the signalling object in not the station'
# reset the signalparam of the isRequested event # reset the signalparam of the isRequested event
self.isRequested.signalparam=None # self.isRequested.value=None
self.isRequested=self.env.event()
break break
# if an interruption caused the control to be taken by the machine or # if an interruption caused the control to be taken by the machine or
# if an operator was rendered available while it was needed by the machine to proceed with getEntity # if an operator was rendered available while it was needed by the machine to proceed with getEntity
if self.interruptionEnd.signalparam==now() or self.loadOperatorAvailable.signalparam==now(): if self.interruptionEnd.value==self.env.now or self.loadOperatorAvailable.value==self.env.now:
# if self.interruptionEnd.signalparam==now(): if self.interruptionEnd in receivedEvent:
# self.printTrace(self.id, interruptionEnd=str(self.interruptionEnd.signalparam)) self.interruptionEnd=self.env.event()
# elif self.loadOperatorAvailable.signalparam==now(): if self.loadOperatorAvailable in receivedEvent:
# self.printTrace(self.id,loadOperatorAvailable=str(self.loadOperatorAvailable.signalparam)) self.loadOperatorAvailable=self.env.event()
# if self.interruptionEnd.value==self.env.now:
# self.printTrace(self.id, interruptionEnd=str(self.interruptionEnd.value))
# elif self.loadOperatorAvailable.value==self.env.now:
# self.printTrace(self.id,loadOperatorAvailable=str(self.loadOperatorAvailable.value))
# try to signal the Giver, otherwise wait until it is requested # try to signal the Giver, otherwise wait until it is requested
if self.signalGiver(): if self.signalGiver():
break break
...@@ -264,19 +276,20 @@ class Machine(CoreObject): ...@@ -264,19 +276,20 @@ class Machine(CoreObject):
# when it's ready to accept (canAcceptAndIsRequested) then inform the broker # when it's ready to accept (canAcceptAndIsRequested) then inform the broker
# machines waits to be operated (waits for the operator) # machines waits to be operated (waits for the operator)
self.requestOperator() self.requestOperator()
self.timeWaitForLoadOperatorStarted = now() self.timeWaitForLoadOperatorStarted = self.env.now
# wait until the Broker has waited times equal to loadTime (if any) # wait until the Broker has waited times equal to loadTime (if any)
yield waitevent, self, self.brokerIsSet yield self.brokerIsSet
self.timeWaitForLoadOperatorEnded = now() self.brokerIsSet=self.env.event()
self.timeWaitForLoadOperatorEnded = self.env.now
self.loadOperatorWaitTimeCurrentEntity += self.timeWaitForLoadOperatorEnded-self.timeWaitForLoadOperatorStarted self.loadOperatorWaitTimeCurrentEntity += self.timeWaitForLoadOperatorEnded-self.timeWaitForLoadOperatorStarted
self.totalTimeWaitingForLoadOperator += self.loadOperatorWaitTimeCurrentEntity self.totalTimeWaitingForLoadOperator += self.loadOperatorWaitTimeCurrentEntity
# ======= Load the machine if the Load is defined as one of the Operators' operation types # ======= Load the machine if the Load is defined as one of the Operators' operation types
if any(type=="Load" for type in self.multOperationTypeList) and self.isOperated(): if any(type=="Load" for type in self.multOperationTypeList) and self.isOperated():
self.timeLoadStarted = now() self.timeLoadStarted = self.env.now
yield hold,self,self.calculateLoadTime() yield self.env.timeout(self.calculateLoadTime())
# TODO: if self.interrupted(): There is the issue of failure during the Loading # TODO: if self.interrupted(): There is the issue of failure during the Loading
self.timeLoadEnded = now() self.timeLoadEnded = self.env.now
self.loadTimeCurrentEntity = self.timeLoadEnded-self.timeLoadStarted self.loadTimeCurrentEntity = self.timeLoadEnded-self.timeLoadStarted
self.totalLoadTime += self.loadTimeCurrentEntity self.totalLoadTime += self.loadTimeCurrentEntity
...@@ -290,7 +303,8 @@ class Machine(CoreObject): ...@@ -290,7 +303,8 @@ class Machine(CoreObject):
# machine has to release the operator # machine has to release the operator
self.releaseOperator() self.releaseOperator()
# wait until the Broker has finished processing # wait until the Broker has finished processing
yield waitevent, self, self.brokerIsSet yield self.brokerIsSet
self.brokerIsSet=self.env.event()
# TODO: reset the requestinEntity before receiving the currentEntity # TODO: reset the requestinEntity before receiving the currentEntity
self.requestingEntity=None self.requestingEntity=None
...@@ -310,10 +324,11 @@ class Machine(CoreObject): ...@@ -310,10 +324,11 @@ class Machine(CoreObject):
# when it's ready to accept (canAcceptAndIsRequested) then inform the broker # when it's ready to accept (canAcceptAndIsRequested) then inform the broker
# machines waits to be operated (waits for the operator) # machines waits to be operated (waits for the operator)
self.requestOperator() self.requestOperator()
self.timeWaitForOperatorStarted = now() self.timeWaitForOperatorStarted = self.env.now
# wait until the Broker has waited times equal to loadTime (if any) # wait until the Broker has waited times equal to loadTime (if any)
yield waitevent, self, self.brokerIsSet yield self.brokerIsSet
self.timeWaitForOperatorEnded = now() self.brokerIsSet=self.env.event()
self.timeWaitForOperatorEnded = self.env.now
self.operatorWaitTimeCurrentEntity += self.timeWaitForOperatorEnded-self.timeWaitForOperatorStarted self.operatorWaitTimeCurrentEntity += self.timeWaitForOperatorEnded-self.timeWaitForOperatorStarted
# variables dedicated to hold the processing times, the time when the Entity entered, # variables dedicated to hold the processing times, the time when the Entity entered,
...@@ -324,10 +339,10 @@ class Machine(CoreObject): ...@@ -324,10 +339,10 @@ class Machine(CoreObject):
# ======= setup the machine if the Setup is defined as one of the Operators' operation types # ======= setup the machine if the Setup is defined as one of the Operators' operation types
# in plantSim the setup is performed when the machine has to process a new type of Entity and only once # in plantSim the setup is performed when the machine has to process a new type of Entity and only once
if any(type=="Setup" for type in self.multOperationTypeList) and self.isOperated(): if any(type=="Setup" for type in self.multOperationTypeList) and self.isOperated():
self.timeSetupStarted = now() self.timeSetupStarted = self.env.now
yield hold,self,self.calculateSetupTime() yield self.env.timeout(self.calculateSetupTime())
# TODO: if self.interrupted(): There is the issue of failure during the setup # TODO: if self.interrupted(): There is the issue of failure during the setup
self.timeSetupEnded = now() self.timeSetupEnded = self.env.now
self.setupTimeCurrentEntity = self.timeSetupEnded-self.timeSetupStarted self.setupTimeCurrentEntity = self.timeSetupEnded-self.timeSetupStarted
self.totalSetupTime += self.setupTimeCurrentEntity self.totalSetupTime += self.setupTimeCurrentEntity
...@@ -336,10 +351,10 @@ class Machine(CoreObject): ...@@ -336,10 +351,10 @@ class Machine(CoreObject):
# but setupTime is given for the entity to be processed # but setupTime is given for the entity to be processed
# try: # try:
# if self.setupTime and not any(type=="Setup" for type in self.multOperationTypeList): # if self.setupTime and not any(type=="Setup" for type in self.multOperationTypeList):
# self.timeSetupStarted = now() # self.timeSetupStarted = self.env.now
# yield hold,self,self.calculateSetupTime() # yield hold,self,self.calculateSetupTime()
# # TODO: if self.interrupted(): There is the issue of failure during the setup # # TODO: if self.interrupted(): There is the issue of failure during the setup
# self.timeSetupEnded = now() # self.timeSetupEnded = self.env.now
# self.setupTimeCurrentEntity = self.timeSetupEnded-self.timeSetupStarted # self.setupTimeCurrentEntity = self.timeSetupEnded-self.timeSetupStarted
# self.totalSetupTime += self.setupTimeCurrentEntity # self.totalSetupTime += self.setupTimeCurrentEntity
# except: # except:
...@@ -355,7 +370,8 @@ class Machine(CoreObject): ...@@ -355,7 +370,8 @@ class Machine(CoreObject):
# machine has to release the operator # machine has to release the operator
self.releaseOperator() self.releaseOperator()
# wait until the Broker has finished processing # wait until the Broker has finished processing
yield waitevent, self, self.brokerIsSet yield self.brokerIsSet
self.brokerIsSet=self.env.event()
# variables used to flag any interruptions and the end of the processing # variables used to flag any interruptions and the end of the processing
self.interruption=False self.interruption=False
...@@ -368,13 +384,15 @@ class Machine(CoreObject): ...@@ -368,13 +384,15 @@ class Machine(CoreObject):
while processingNotFinished: while processingNotFinished:
# timeRestartingProcessing : dummy variable to keep track of the time that the processing starts after # timeRestartingProcessing : dummy variable to keep track of the time that the processing starts after
# every interruption # every interruption
self.timeRestartingProcessing=now() self.timeRestartingProcessing=self.env.now
# wait for the processing time left tinM, if no interruption occurs then change the processingEndedFlag and exit loop, # wait for the processing time left tinM, if no interruption occurs then change the processingEndedFlag and exit loop,
# else (if interrupted()) set interruption flag to true (only if tinM==0), # else (if interrupted()) set interruption flag to true (only if tinM==0),
# and recalculate the processing time left tinM, passivate while waiting for repair. # and recalculate the processing time left tinM, passivate while waiting for repair.
# if a preemption has occurred then react accordingly (proceed with getting the critical entity) # if a preemption has occurred then react accordingly (proceed with getting the critical entity)
yield hold,self, self.tinM # getting processed for remaining processing time tinM receivedEvent=yield self.env.timeout(self.tinM) | self.interruptionStart # getting processed for remaining processing time tinM
if self.interrupted(): # if a failure occurs while processing the machine is interrupted. if self.interruptionStart in receivedEvent: # if a failure occurs while processing the machine is interrupted.
assert self.interruptionStart.value==self.env.now, 'the interruption has not been processed on the time of activation'
self.interruptionStart=self.env.event()
self.interruptionActions() # execute interruption actions self.interruptionActions() # execute interruption actions
# =============== release the operator if there is interruption # =============== release the operator if there is interruption
...@@ -382,12 +400,14 @@ class Machine(CoreObject): ...@@ -382,12 +400,14 @@ class Machine(CoreObject):
and self.isOperated()\ and self.isOperated()\
and any(type=="Processing" for type in self.multOperationTypeList): and any(type=="Processing" for type in self.multOperationTypeList):
self.releaseOperator() self.releaseOperator()
yield waitevent,self,self.brokerIsSet yield self.brokerIsSet
self.brokerIsSet=self.env.event()
# if there is a failure in the machine or interruption due to preemption, it is passivated # if there is a failure in the machine or interruption due to preemption, it is passivated
# passivate the Machine for as long as there is no repair # passivate the Machine for as long as there is no repair
yield waitevent, self, self.interruptionEnd yield self.interruptionEnd
assert now()==self.interruptionEnd.signalparam, 'the victim of the failure is not the object that received it' assert self.env.now==self.interruptionEnd.value, 'the victim of the failure is not the object that received it'
self.interruptionEnd=self.env.event()
self.postInterruptionActions() self.postInterruptionActions()
...@@ -395,10 +415,11 @@ class Machine(CoreObject): ...@@ -395,10 +415,11 @@ class Machine(CoreObject):
if (self.operatorPool!="None")\ if (self.operatorPool!="None")\
and any(type=="Processing" for type in self.multOperationTypeList)\ and any(type=="Processing" for type in self.multOperationTypeList)\
and not self.interruption: and not self.interruption:
self.timeWaitForOperatorStarted = now() self.timeWaitForOperatorStarted = self.env.now
self.requestOperator() self.requestOperator()
yield waitevent,self,self.brokerIsSet yield self.brokerIsSet
self.timeWaitForOperatorEnded = now() self.brokerIsSet=self.env.event()
self.timeWaitForOperatorEnded = self.env.now
self.operatorWaitTimeCurrentEntity += self.timeWaitForOperatorEnded-self.timeWaitForOperatorStarted self.operatorWaitTimeCurrentEntity += self.timeWaitForOperatorEnded-self.timeWaitForOperatorStarted
# if the station is reactivated by the preempt method # if the station is reactivated by the preempt method
elif(self.shouldPreempt): elif(self.shouldPreempt):
...@@ -409,7 +430,8 @@ class Machine(CoreObject): ...@@ -409,7 +430,8 @@ class Machine(CoreObject):
and self.isOperated()\ and self.isOperated()\
and any(type=="Processing" for type in self.multOperationTypeList): and any(type=="Processing" for type in self.multOperationTypeList):
self.releaseOperator() self.releaseOperator()
yield waitevent,self,self.brokerIsSet yield self.brokerIsSet
self.brokerIsSet=self.env.event()
self.postInterruptionActions() self.postInterruptionActions()
break break
...@@ -426,30 +448,29 @@ class Machine(CoreObject): ...@@ -426,30 +448,29 @@ class Machine(CoreObject):
and any(type=="Processing" for type in self.multOperationTypeList)\ and any(type=="Processing" for type in self.multOperationTypeList)\
and not self.interruption: and not self.interruption:
self.releaseOperator() self.releaseOperator()
yield waitevent,self,self.brokerIsSet yield self.brokerIsSet
self.brokerIsSet=self.env.event()
# signal the receiver that the activeObject has something to dispose of # signal the receiver that the activeObject has something to dispose of
if not self.signalReceiver(): if not self.signalReceiver():
# if there was no available receiver, get into blocking control # if there was no available receiver, get into blocking control
while 1: while 1:
# wait the event canDispose, this means that the station can deliver the item to successor # wait the event canDispose, this means that the station can deliver the item to successor
event=yield waitevent, self, [self.canDispose, self.interruptionStart] receivedEvent=yield self.canDispose | self.interruptionStart
# if there was interruption # if there was interruption
#if self.interrupted(): #if self.interrupted():
# TODO not good implementation # TODO not good implementation
if self.interruptionStart.signalparam==now(): if self.interruptionStart in receivedEvent:
assert self.interruptionStart.value==self.env.now, 'the interruption has not been processed on the time of activation'
self.interruptionStart=self.env.event()
# wait for the end of the interruption # wait for the end of the interruption
self.interruptionActions() # execute interruption actions self.interruptionActions() # execute interruption actions
yield waitevent, self, self.interruptionEnd # interruptionEnd to be triggered by ObjectInterruption yield self.interruptionEnd # interruptionEnd to be triggered by ObjectInterruption
assert now()==self.interruptionEnd.signalparam, 'the victim of the failure is not the object that received it' assert self.env.now==self.interruptionEnd.value, 'the victim of the failure is not the object that received it'
self.interruptionEnd=self.env.event()
self.postInterruptionActions() self.postInterruptionActions()
#======================================================= if self.canDispose in receivedEvent:
# TODO: not sure if this is required now self.canDispose=self.env.event()
# #if during the interruption the object became empty break
# if (len(self.getActiveObjectQueue())==0 and self.shouldPreempt):
# self.shouldPreempt==False
# break
#=======================================================
# try to signal a receiver, if successful then proceed to get an other entity # try to signal a receiver, if successful then proceed to get an other entity
if self.signalReceiver(): if self.signalReceiver():
break break
...@@ -458,7 +479,7 @@ class Machine(CoreObject): ...@@ -458,7 +479,7 @@ class Machine(CoreObject):
# signals the preceding station (e.g. self.machine) and immediately after that gets the entity. # signals the preceding station (e.g. self.machine) and immediately after that gets the entity.
# the preceding machine gets the canDispose signal which is actually useless, is emptied by the following station # the preceding machine gets the canDispose signal which is actually useless, is emptied by the following station
# and then cannot exit an infinite loop. # and then cannot exit an infinite loop.
yield hold, self, 0 yield self.env.timeout(0)
# if while waiting (for a canDispose event) became free as the machines that follows emptied it, then proceed # if while waiting (for a canDispose event) became free as the machines that follows emptied it, then proceed
if not self.haveToDispose(): if not self.haveToDispose():
break break
...@@ -467,7 +488,7 @@ class Machine(CoreObject): ...@@ -467,7 +488,7 @@ class Machine(CoreObject):
# actions to be carried out when the processing of an Entity ends # actions to be carried out when the processing of an Entity ends
# ======================================================================= # =======================================================================
def endProcessingActions(self): def endProcessingActions(self):
activeObjectQueue=self.Res.activeQ activeObjectQueue=self.Res.users
activeEntity=activeObjectQueue[0] activeEntity=activeObjectQueue[0]
# self.printTrace(activeObject.getActiveObjectQueue()[0].name, processEnd=activeObject.objName) # self.printTrace(activeObject.getActiveObjectQueue()[0].name, processEnd=activeObject.objName)
# reset the variables used to handle the interruptions timing # reset the variables used to handle the interruptions timing
...@@ -498,16 +519,16 @@ class Machine(CoreObject): ...@@ -498,16 +519,16 @@ class Machine(CoreObject):
self.waitToDispose=True self.waitToDispose=True
#do this so that if it is overtime working it is not counted as off-shift time #do this so that if it is overtime working it is not counted as off-shift time
if not self.onShift: if not self.onShift:
self.timeLastShiftEnded=now() self.timeLastShiftEnded=self.env.now
# update the total working time # update the total working time
# the total processing time for this entity is what the distribution initially gave # the total processing time for this entity is what the distribution initially gave
if not self.shouldPreempt: if not self.shouldPreempt:
self.totalWorkingTime+=self.totalProcessingTimeInCurrentEntity self.totalWorkingTime+=self.totalProcessingTimeInCurrentEntity
# if the station was preemptied for a critical order then calculate the total working time accorindingly # if the station was preemptied for a critical order then calculate the total working time accorindingly
else: else:
self.totalWorkingTime+=now()-(self.timeLastEntityEntered) self.totalWorkingTime+=self.env.now-(self.timeLastEntityEntered)
# update the variables keeping track of Entity related attributes of the machine # update the variables keeping track of Entity related attributes of the machine
self.timeLastEntityEnded=now() # this holds the time that the last entity ended processing in Machine self.timeLastEntityEnded=self.env.now # this holds the time that the last entity ended processing in Machine
self.nameLastEntityEnded=self.currentEntity.name # this holds the name of the last entity that ended processing in Machine self.nameLastEntityEnded=self.currentEntity.name # this holds the name of the last entity that ended processing in Machine
self.completedJobs+=1 # Machine completed one more Job self.completedJobs+=1 # Machine completed one more Job
# reseting the shouldPreempt flag # reseting the shouldPreempt flag
...@@ -517,7 +538,7 @@ class Machine(CoreObject): ...@@ -517,7 +538,7 @@ class Machine(CoreObject):
# actions to be carried out when the processing of an Entity ends # actions to be carried out when the processing of an Entity ends
# ======================================================================= # =======================================================================
def interruptionActions(self): def interruptionActions(self):
activeObjectQueue=self.Res.activeQ activeObjectQueue=self.Res.users
activeEntity=activeObjectQueue[0] activeEntity=activeObjectQueue[0]
# self.printTrace(activeEntity.name, interrupted=self.objName) # self.printTrace(activeEntity.name, interrupted=self.objName)
# if the interrupt occured while processing an entity # if the interrupt occured while processing an entity
...@@ -528,40 +549,40 @@ class Machine(CoreObject): ...@@ -528,40 +549,40 @@ class Machine(CoreObject):
except IndexError: except IndexError:
pass pass
# recalculate the processing time left tinM # recalculate the processing time left tinM
self.tinM=self.tinM-(now()-self.timeRestartingProcessing) self.tinM=self.tinM-(self.env.now-self.timeRestartingProcessing)
if(self.tinM==0): # sometimes the failure may happen exactly at the time that the processing would finish if(self.tinM==0): # sometimes the failure may happen exactly at the time that the processing would finish
# this may produce disagreement with the simul8 because in both SimPy and Simul8 # this may produce disagreement with the simul8 because in both SimPy and Simul8
# it seems to be random which happens 1st # it seems to be random which happens 1st
# this should not appear often to stochastic models though where times are random # this should not appear often to stochastic models though where times are random
self.interruption=True self.interruption=True
# start counting the down time at breatTime dummy variable # start counting the down time at breatTime dummy variable
self.breakTime=now() # dummy variable that the interruption happened self.breakTime=self.env.now # dummy variable that the interruption happened
# ======================================================================= # =======================================================================
# actions to be carried out when the processing of an Entity ends # actions to be carried out when the processing of an Entity ends
# ======================================================================= # =======================================================================
def postInterruptionActions(self): def postInterruptionActions(self):
activeObjectQueue=self.Res.activeQ activeObjectQueue=self.Res.users
activeEntity=activeObjectQueue[0] activeEntity=activeObjectQueue[0]
# if the machine returns from an failure while processing an entity # if the machine returns from an failure while processing an entity
if not self.waitToDispose: if not self.waitToDispose:
# use the timers to count the time that Machine is down and related # use the timers to count the time that Machine is down and related
self.downTimeProcessingCurrentEntity+=now()-self.breakTime # count the time that Machine is down while processing this Entity self.downTimeProcessingCurrentEntity+=self.env.now-self.breakTime # count the time that Machine is down while processing this Entity
self.downTimeInCurrentEntity+=now()-self.breakTime # count the time that Machine is down while on currentEntity self.downTimeInCurrentEntity+=self.env.now-self.breakTime # count the time that Machine is down while on currentEntity
self.timeLastFailureEnded=now() # set the timeLastFailureEnded self.timeLastFailureEnded=self.env.now # set the timeLastFailureEnded
self.failureTimeInCurrentEntity+=now()-self.breakTime # dummy variable keeping track of the failure time self.failureTimeInCurrentEntity+=self.env.now-self.breakTime # dummy variable keeping track of the failure time
# output to trace that the Machine self.objName was passivated for the current failure time # output to trace that the Machine self.objName was passivated for the current failure time
self.outputTrace(activeObjectQueue[0].name, "passivated in "+self.objName+" for "+str(now()-self.breakTime)) self.outputTrace(activeObjectQueue[0].name, "passivated in "+self.objName+" for "+str(self.env.now-self.breakTime))
# when a machine returns from failure while trying to deliver an entity # when a machine returns from failure while trying to deliver an entity
else: else:
# count the failure while on current entity time with failureTime variable # count the failure while on current entity time with failureTime variable
self.failureTimeInCurrentEntity+=now()-self.breakTime self.failureTimeInCurrentEntity+=self.env.now-self.breakTime
# calculate the time the Machine was down while trying to dispose the current Entity, # calculate the time the Machine was down while trying to dispose the current Entity,
# and the total down time while on current Entity # and the total down time while on current Entity
self.downTimeInTryingToReleaseCurrentEntity+=now()-self.breakTime self.downTimeInTryingToReleaseCurrentEntity+=self.env.now-self.breakTime
self.downTimeInCurrentEntity+=now()-self.breakTime # already updated from failures during processing self.downTimeInCurrentEntity+=self.env.now-self.breakTime # already updated from failures during processing
# update the timeLastFailureEnded # update the timeLastFailureEnded
self.timeLastFailureEnded=now() self.timeLastFailureEnded=self.env.now
# reset the variable holding the time the failure happened # reset the variable holding the time the failure happened
self.breakTime=0 self.breakTime=0
...@@ -577,7 +598,7 @@ class Machine(CoreObject): ...@@ -577,7 +598,7 @@ class Machine(CoreObject):
# that will give the entity. # that will give the entity.
# ======================================================================= # =======================================================================
def canAccept(self, callerObject=None): def canAccept(self, callerObject=None):
activeObjectQueue=self.Res.activeQ activeObjectQueue=self.Res.users
# if we have only one predecessor just check if there is a place and the machine is up # if we have only one predecessor just check if there is a place and the machine is up
# this is done to achieve better (cpu) processing time # this is done to achieve better (cpu) processing time
# then we can also use it as a filter for a yield method # then we can also use it as a filter for a yield method
...@@ -615,7 +636,7 @@ class Machine(CoreObject): ...@@ -615,7 +636,7 @@ class Machine(CoreObject):
# also updates the giver to the one that is to be taken # also updates the giver to the one that is to be taken
# ======================================================================= # =======================================================================
def canAcceptAndIsRequested(self,callerObject=None): def canAcceptAndIsRequested(self,callerObject=None):
activeObjectQueue=self.Res.activeQ activeObjectQueue=self.Res.users
giverObject=callerObject giverObject=callerObject
assert giverObject, 'there must be a caller for canAcceptAndIsRequested' assert giverObject, 'there must be a caller for canAcceptAndIsRequested'
# check if there is a place, the machine is up and the predecessor has an entity to dispose. if the machine has to compete # check if there is a place, the machine is up and the predecessor has an entity to dispose. if the machine has to compete
...@@ -701,7 +722,7 @@ class Machine(CoreObject): ...@@ -701,7 +722,7 @@ class Machine(CoreObject):
# checks if the Machine can dispose an entity to the following object # checks if the Machine can dispose an entity to the following object
# ======================================================================= # =======================================================================
def haveToDispose(self, callerObject=None): def haveToDispose(self, callerObject=None):
activeObjectQueue=self.Res.activeQ activeObjectQueue=self.Res.users
#if we have only one successor just check if machine waits to dispose and also is up #if we have only one successor just check if machine waits to dispose and also is up
# this is done to achieve better (cpu) processing time # this is done to achieve better (cpu) processing time
if(len(self.next)==1 or callerObject==None): if(len(self.next)==1 or callerObject==None):
...@@ -796,7 +817,7 @@ class Machine(CoreObject): ...@@ -796,7 +817,7 @@ class Machine(CoreObject):
offShiftTimeInCurrentEntity=0 offShiftTimeInCurrentEntity=0
if self.interruptCause: if self.interruptCause:
if self.onShift==False and self.interruptCause.type=='ShiftScheduler': if self.onShift==False and self.interruptCause.type=='ShiftScheduler':
offShiftTimeInCurrentEntity=now()-activeObject.timeLastShiftEnded offShiftTimeInCurrentEntity=self.env.now-activeObject.timeLastShiftEnded
# if there is an entity that finished processing in a Machine but did not get to reach # if there is an entity that finished processing in a Machine but did not get to reach
# the following Object till the end of simulation, # the following Object till the end of simulation,
...@@ -805,9 +826,9 @@ class Machine(CoreObject): ...@@ -805,9 +826,9 @@ class Machine(CoreObject):
if (len(activeObjectQueue)>0) and (mightBeBlocked)\ if (len(activeObjectQueue)>0) and (mightBeBlocked)\
and ((activeObject.nameLastEntityEntered == activeObject.nameLastEntityEnded)) and self.onShift: and ((activeObject.nameLastEntityEntered == activeObject.nameLastEntityEnded)) and self.onShift:
# be careful here, might have to reconsider # be careful here, might have to reconsider
activeObject.totalBlockageTime+=now()-(activeObject.timeLastEntityEnded+activeObject.downTimeInTryingToReleaseCurrentEntity) activeObject.totalBlockageTime+=self.env.now-(activeObject.timeLastEntityEnded+activeObject.downTimeInTryingToReleaseCurrentEntity)
if activeObject.Up==False: if activeObject.Up==False:
activeObject.totalBlockageTime-=now()-activeObject.timeLastFailure activeObject.totalBlockageTime-=self.env.now-activeObject.timeLastFailure
alreadyAdded=True alreadyAdded=True
#if Machine is currently processing an entity we should count this working time #if Machine is currently processing an entity we should count this working time
...@@ -817,8 +838,8 @@ class Machine(CoreObject): ...@@ -817,8 +838,8 @@ class Machine(CoreObject):
#if Machine is down we should add this last failure time to the time that it has been down in current entity #if Machine is down we should add this last failure time to the time that it has been down in current entity
if self.Up==False: if self.Up==False:
# if(len(activeObjectQueue)>0) and (self.Up==False): # if(len(activeObjectQueue)>0) and (self.Up==False):
activeObject.downTimeProcessingCurrentEntity+=now()-activeObject.timeLastFailure activeObject.downTimeProcessingCurrentEntity+=self.env.now-activeObject.timeLastFailure
activeObject.totalWorkingTime+=now()-activeObject.timeLastEntityEntered\ activeObject.totalWorkingTime+=self.env.now-activeObject.timeLastEntityEntered\
-activeObject.downTimeProcessingCurrentEntity\ -activeObject.downTimeProcessingCurrentEntity\
-activeObject.operatorWaitTimeCurrentEntity\ -activeObject.operatorWaitTimeCurrentEntity\
-activeObject.setupTimeCurrentEntity\ -activeObject.setupTimeCurrentEntity\
...@@ -830,17 +851,17 @@ class Machine(CoreObject): ...@@ -830,17 +851,17 @@ class Machine(CoreObject):
and (activeObject.currentOperator==None): and (activeObject.currentOperator==None):
# TODO: needs further research as the time of failure while waiting for operator is not counted yet # TODO: needs further research as the time of failure while waiting for operator is not counted yet
if self.Up==False: if self.Up==False:
activeObject.downTimeProcessingCurrentEntity+=now()-activeObject.timeLastFailure activeObject.downTimeProcessingCurrentEntity+=self.env.now-activeObject.timeLastFailure
activeObject.totalTimeWaitingForOperator+=now()-activeObject.timeWaitForOperatorStarted\ activeObject.totalTimeWaitingForOperator+=self.env.now-activeObject.timeWaitForOperatorStarted\
-activeObject.downTimeProcessingCurrentEntity\ -activeObject.downTimeProcessingCurrentEntity\
-offShiftTimeInCurrentEntity -offShiftTimeInCurrentEntity
# if Machine is down we have to add this failure time to its total failure time # if Machine is down we have to add this failure time to its total failure time
# we also need to add the last blocking time to total blockage time # we also need to add the last blocking time to total blockage time
if(activeObject.Up==False): if(activeObject.Up==False):
activeObject.totalFailureTime+=now()-activeObject.timeLastFailure activeObject.totalFailureTime+=self.env.now-activeObject.timeLastFailure
# we add the value only if it hasn't already been added # we add the value only if it hasn't already been added
if((mightBeBlocked) and (activeObject.nameLastEntityEnded==activeObject.nameLastEntityEntered) and (not alreadyAdded)): if((mightBeBlocked) and (activeObject.nameLastEntityEnded==activeObject.nameLastEntityEntered) and (not alreadyAdded)):
activeObject.totalBlockageTime+=(now()-activeObject.timeLastEntityEnded)-(now()-activeObject.timeLastFailure)-activeObject.downTimeInTryingToReleaseCurrentEntity activeObject.totalBlockageTime+=(self.env.now-activeObject.timeLastEntityEnded)-(self.env.now-activeObject.timeLastFailure)-activeObject.downTimeInTryingToReleaseCurrentEntity
alreadyAdded=True alreadyAdded=True
#if the machine is off shift,add this to the off-shift time #if the machine is off shift,add this to the off-shift time
...@@ -849,12 +870,12 @@ class Machine(CoreObject): ...@@ -849,12 +870,12 @@ class Machine(CoreObject):
#add the time only if the object is interrupted because of off-shift #add the time only if the object is interrupted because of off-shift
if self.interruptCause: if self.interruptCause:
if self.interruptCause.type=='ShiftScheduler': if self.interruptCause.type=='ShiftScheduler':
self.totalOffShiftTime+=now()-self.timeLastShiftEnded self.totalOffShiftTime+=self.env.now-self.timeLastShiftEnded
elif len(self.getActiveObjectQueue())==0 or self.waitToDispose: elif len(self.getActiveObjectQueue())==0 or self.waitToDispose:
self.totalOffShiftTime+=now()-self.timeLastShiftEnded self.totalOffShiftTime+=self.env.now-self.timeLastShiftEnded
# we add the value only if it hasn't already been added # we add the value only if it hasn't already been added
if((mightBeBlocked) and (activeObject.nameLastEntityEnded==activeObject.nameLastEntityEntered) and (not alreadyAdded)): if((mightBeBlocked) and (activeObject.nameLastEntityEnded==activeObject.nameLastEntityEntered) and (not alreadyAdded)):
activeObject.totalBlockageTime+=(now()-activeObject.timeLastEntityEnded)-(now()-activeObject.timeLastShiftEnded)-offShiftTimeInCurrentEntity activeObject.totalBlockageTime+=(self.env.now-activeObject.timeLastEntityEnded)-(self.env.now-activeObject.timeLastShiftEnded)-offShiftTimeInCurrentEntity
#Machine was idle when it was not in any other state #Machine was idle when it was not in any other state
activeObject.totalWaitingTime=MaxSimtime-activeObject.totalWorkingTime-activeObject.totalBlockageTime-activeObject.totalFailureTime-activeObject.totalLoadTime-activeObject.totalSetupTime-self.totalOffShiftTime activeObject.totalWaitingTime=MaxSimtime-activeObject.totalWorkingTime-activeObject.totalBlockageTime-activeObject.totalFailureTime-activeObject.totalLoadTime-activeObject.totalSetupTime-self.totalOffShiftTime
......
...@@ -26,7 +26,8 @@ Created on 8 Nov 2012 ...@@ -26,7 +26,8 @@ Created on 8 Nov 2012
models the source object that generates the entities models the source object that generates the entities
''' '''
from SimPy.Simulation import now, Process, Resource, infinity, hold, SimEvent, activate, waitevent # from SimPy.Simulation import now, Process, Resource, infinity, hold, SimEvent, activate, waitevent
import simpy
from RandomNumberGenerator import RandomNumberGenerator from RandomNumberGenerator import RandomNumberGenerator
from CoreObject import CoreObject from CoreObject import CoreObject
from Globals import G from Globals import G
...@@ -36,20 +37,20 @@ import Globals ...@@ -36,20 +37,20 @@ import Globals
#============================================================================ #============================================================================
# the EntityGenerator object # the EntityGenerator object
#============================================================================ #============================================================================
class EntityGenerator(Process): class EntityGenerator(object):
#=========================================================================== #===========================================================================
# the __init__ method of the EntityGenerator # the __init__ method of the EntityGenerator
#=========================================================================== #===========================================================================
def __init__(self, victim=None): def __init__(self, victim=None):
Process.__init__(self) self.env=G.env
self.type="EntityGenerator" #String that shows the type of object self.type="EntityGenerator" #String that shows the type of object
self.victim=victim self.victim=victim
#=========================================================================== # #===========================================================================
# initialize method of the EntityGenerator # # initialize method of the EntityGenerator
#=========================================================================== # #===========================================================================
def initialize(self): # def initialize(self):
Process.__init__(self) # Process.__init__(self)
#=========================================================================== #===========================================================================
# the generator of the EntitiesGenerator # the generator of the EntitiesGenerator
...@@ -59,8 +60,8 @@ class EntityGenerator(Process): ...@@ -59,8 +60,8 @@ class EntityGenerator(Process):
# if the Source is empty create the Entity # if the Source is empty create the Entity
if len(self.victim.getActiveObjectQueue())==0: if len(self.victim.getActiveObjectQueue())==0:
entity=self.victim.createEntity() # create the Entity object and assign its name entity=self.victim.createEntity() # create the Entity object and assign its name
entity.creationTime=now() # 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 creation time
entity.startTime=now() # assign the current simulation time as the Entity's start time entity.startTime=self.env.now # assign the current simulation time as the Entity's start time
entity.currentStation=self.victim # update the current station of the Entity entity.currentStation=self.victim # update the current station of the Entity
G.EntityList.append(entity) G.EntityList.append(entity)
self.victim.outputTrace(entity.name, "generated") # output the trace self.victim.outputTrace(entity.name, "generated") # output the trace
...@@ -68,13 +69,13 @@ class EntityGenerator(Process): ...@@ -68,13 +69,13 @@ class EntityGenerator(Process):
self.victim.numberOfArrivals+=1 # we have one new arrival self.victim.numberOfArrivals+=1 # we have one new arrival
G.numberOfEntities+=1 G.numberOfEntities+=1
self.victim.appendEntity(entity) self.victim.appendEntity(entity)
self.victim.entityCreated.signal(entity) self.victim.entityCreated.succeed(entity)
# else put it on the time list for scheduled Entities # else put it on the time list for scheduled Entities
else: else:
#print now(), 'appending to the list' #print self.env.now, 'appending to the list'
self.victim.scheduledEntities.append(now()) self.victim.scheduledEntities.append(self.env.now)
self.victim.outputTrace(entity.name, "generated") # output the trace self.victim.outputTrace(entity.name, "generated") # output the trace
yield hold,self,self.victim.calculateInterarrivalTime() # wait until the next arrival yield self.env.timeout(self.victim.calculateInterarrivalTime()) # wait until the next arrival
#============================================================================ #============================================================================
# The Source object is a Process # The Source object is a Process
...@@ -104,9 +105,11 @@ class Source(CoreObject): ...@@ -104,9 +105,11 @@ class Source(CoreObject):
self.entityGenerator=EntityGenerator(victim=self) # the EntityGenerator of the Source self.entityGenerator=EntityGenerator(victim=self) # the EntityGenerator of the Source
self.entityCreated=SimEvent('an entity is created') # self.entityCreated=SimEvent('an entity is created')
self.entityCreated=self.env.event()
# event used by router # event used by router
self.loadOperatorAvailable=SimEvent('loadOperatorAvailable') # self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
self.loadOperatorAvailable=self.env.event()
self.scheduledEntities=[] # list of creations that are scheduled self.scheduledEntities=[] # list of creations that are scheduled
...@@ -118,15 +121,19 @@ class Source(CoreObject): ...@@ -118,15 +121,19 @@ class Source(CoreObject):
CoreObject.initialize(self) CoreObject.initialize(self)
# initialize the internal Queue (type Resource) of the Source # initialize the internal Queue (type Resource) of the Source
self.Res=Resource(capacity=infinity) # self.Res=Resource(capacity=infinity)
self.Res.activeQ=[] self.Res=simpy.Resource(self.env, capacity=10000)
self.Res.waitQ=[] self.Res.users=[]
# self.Res.waitQ=[]
self.numberOfArrivals = 0 self.numberOfArrivals = 0
self.entityGenerator.initialize() # self.entityGenerator.initialize()
activate(self.entityGenerator,self.entityGenerator.run()) # activate(self.entityGenerator,self.entityGenerator.run())
self.entityCreated=SimEvent('an entity is created') self.env.process(self.entityGenerator.run())
# self.entityCreated=SimEvent('an entity is created')
self.entityCreated=self.env.event()
# event used by router # event used by router
self.loadOperatorAvailable=SimEvent('loadOperatorAvailable') # self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
self.loadOperatorAvailable=self.env.event()
self.scheduledEntities=[] # list of creations that are scheduled self.scheduledEntities=[] # list of creations that are scheduled
#=========================================================================== #===========================================================================
...@@ -138,16 +145,18 @@ class Source(CoreObject): ...@@ -138,16 +145,18 @@ class Source(CoreObject):
activeObjectQueue=self.getActiveObjectQueue() activeObjectQueue=self.getActiveObjectQueue()
while 1: while 1:
# wait for any event (entity creation or request for disposal of entity) # wait for any event (entity creation or request for disposal of entity)
yield waitevent, self, [self.entityCreated, self.canDispose, self.loadOperatorAvailable] receivedEvent=yield self.entityCreated | self.canDispose | self.loadOperatorAvailable
# if an entity is created try to signal the receiver and continue # if an entity is created try to signal the receiver and continue
if self.entityCreated.signalparam: if self.entityCreated in receivedEvent:
self.entityCreated.signalparam=None self.entityCreated=self.env.event()
if self.signalReceiver(): if self.signalReceiver():
continue continue
# otherwise, if the receiver requests availability then try to signal him if there is anything to dispose of # otherwise, if the receiver requests availability then try to signal him if there is anything to dispose of
if self.canDispose.signalparam or self.loadOperatorAvailable.signalparam: if self.canDispose in receivedEvent or self.loadOperatorAvailable in receivedEvent:
self.canDispose.signalparam=None # self.canDispose.signalparam=None
self.loadOperatorAvailable.signalparam=None self.canDispose=self.env.event()
# self.loadOperatorAvailable.signalparam=None
self.loadOperatorAvailable=self.env.event()
if self.haveToDispose(): if self.haveToDispose():
if self.signalReceiver(): if self.signalReceiver():
continue continue
...@@ -188,7 +197,7 @@ class Source(CoreObject): ...@@ -188,7 +197,7 @@ class Source(CoreObject):
newEntity=self.createEntity() # create the Entity object and assign its name newEntity=self.createEntity() # create the Entity object and assign its name
newEntity.creationTime=self.scheduledEntities.pop(0) # 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 creation time
newEntity.startTime=newEntity.creationTime # assign the current simulation time as the Entity's start time newEntity.startTime=newEntity.creationTime # assign the current simulation time as the Entity's start time
#print now(), 'getting from the list. StartTime=',newEntity.startTime #print self.env.now, 'getting from the list. StartTime=',newEntity.startTime
newEntity.currentStation=self # update the current station of the Entity newEntity.currentStation=self # update the current station of the Entity
G.EntityList.append(newEntity) G.EntityList.append(newEntity)
self.getActiveObjectQueue().append(newEntity) # append the entity to the resource self.getActiveObjectQueue().append(newEntity) # append the entity to the resource
...@@ -197,5 +206,5 @@ class Source(CoreObject): ...@@ -197,5 +206,5 @@ class Source(CoreObject):
self.appendEntity(newEntity) self.appendEntity(newEntity)
activeEntity=CoreObject.removeEntity(self, entity) # run the default method activeEntity=CoreObject.removeEntity(self, entity) # run the default method
if len(self.getActiveObjectQueue())==1: if len(self.getActiveObjectQueue())==1:
self.entityCreated.signal(newEntity) self.entityCreated.succeed(newEntity)
return activeEntity return activeEntity
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment