new branch-Union papatempop&gtemp. Changes to mirror the updates of gtemp into papatempop

parent 447e2a06
...@@ -179,8 +179,8 @@ class Assembly(CoreObject): ...@@ -179,8 +179,8 @@ class Assembly(CoreObject):
return len(self.getActiveObjectQueue())>0 and self.waitToDispose return len(self.getActiveObjectQueue())>0 and self.waitToDispose
#removes an entity from the Assembly #removes an entity from the Assembly
def removeEntity(self): def removeEntity(self, entity=None):
activeEntity=CoreObject.removeEntity(self) #run the default method activeEntity=CoreObject.removeEntity(self, entity) #run the default method
self.waitToDispose=False self.waitToDispose=False
return activeEntity #the object does not wait to dispose now return activeEntity #the object does not wait to dispose now
...@@ -196,11 +196,11 @@ class Assembly(CoreObject): ...@@ -196,11 +196,11 @@ class Assembly(CoreObject):
if(type=="Part"): if(type=="Part"):
activeObjectQueue[0].getFrameQueue().append(activeEntity) #get the part from the giver and append it to the frame! activeObjectQueue[0].getFrameQueue().append(activeEntity) #get the part from the giver and append it to the frame!
giverObject.removeEntity() #remove the part from the previews object giverObject.removeEntity(activeEntity) #remove the part from the previews object
self.outputTrace(activeEntity.name, "got into "+ self.objName) self.outputTrace(activeEntity.name, "got into "+ self.objName)
elif(type=="Frame"): elif(type=="Frame"):
activeObjectQueue.append(giverObjectQueue[0]) #get the frame from the giver activeObjectQueue.append(giverObjectQueue[0]) #get the frame from the giver
giverObject.removeEntity() #remove the frame from the previews object giverObject.removeEntity(activeEntity) #remove the frame from the previews object
self.outputTrace(activeEntity.name, "got into "+ self.objName) self.outputTrace(activeEntity.name, "got into "+ self.objName)
self.nameLastEntityEntered=activeEntity.name self.nameLastEntityEntered=activeEntity.name
self.timeLastEntityEntered=now() self.timeLastEntityEntered=now()
......
...@@ -40,11 +40,11 @@ class BatchDecompositionStartTime(BatchDecomposition): ...@@ -40,11 +40,11 @@ class BatchDecompositionStartTime(BatchDecomposition):
''' '''
#removes an entity from the object #removes an entity from the object
def removeEntity(self): def removeEntity(self, entity=None):
# if it is the first sub-batch of the parent batch that leaves # if it is the first sub-batch of the parent batch that leaves
# assign it as the batch start time # assign it as the batch start time
if len(self.getActiveObjectQueue())==self.numberOfSubBatches: if len(self.getActiveObjectQueue())==self.numberOfSubBatches:
batch=self.getActiveObjectQueue()[0].parentBatch batch=self.getActiveObjectQueue()[0].parentBatch
batch.startTime=now() batch.startTime=now()
activeEntity=BatchDecomposition.removeEntity(self) activeEntity=BatchDecomposition.removeEntity(self, entity)
return activeEntity return activeEntity
...@@ -59,8 +59,8 @@ class BatchScrapMachine(Machine): ...@@ -59,8 +59,8 @@ class BatchScrapMachine(Machine):
self.scrapRng.max=scrMax self.scrapRng.max=scrMax
def removeEntity(self): def removeEntity(self, entity=None):
activeEntity = Machine.removeEntity(self) activeEntity = Machine.removeEntity(self, entity)
scrapQuantity=self.scrapRng.generateNumber() scrapQuantity=self.scrapRng.generateNumber()
activeEntity.numberOfUnits-=scrapQuantity activeEntity.numberOfUnits-=scrapQuantity
if activeEntity.numberOfUnits<0: if activeEntity.numberOfUnits<0:
......
...@@ -224,8 +224,8 @@ class Conveyer(CoreObject): ...@@ -224,8 +224,8 @@ class Conveyer(CoreObject):
#removes an entity from the Conveyer #removes an entity from the Conveyer
def removeEntity(self): def removeEntity(self, entity=None):
activeEntity=CoreObject.removeEntity(self) #run the default method activeEntity=CoreObject.removeEntity(self, entity) #run the default method
self.position.pop(0) self.position.pop(0)
......
...@@ -131,22 +131,31 @@ class CoreObject(Process): ...@@ -131,22 +131,31 @@ class CoreObject(Process):
self.previous=predecessorList self.previous=predecessorList
# ======================================================================= # =======================================================================
# removes an entity from the Object # removes an Entity from the Object the Entity to be removed is passed
# as argument by getEntity of the receiver
# ======================================================================= # =======================================================================
def removeEntity(self): def removeEntity(self, entity=None):
self.addBlockage() self.addBlockage()
activeObjectQueue=self.getActiveObjectQueue() activeObjectQueue=self.getActiveObjectQueue()
activeEntity=activeObjectQueue[0] activeObjectQueue.remove(entity) #remove the Entity from the queue
activeObjectQueue.pop(0) #remove the Entity from the queue
self.failureTimeInCurrentEntity=0 self.failureTimeInCurrentEntity=0
self.downTimeInTryingToReleaseCurrentEntity=0 self.downTimeInTryingToReleaseCurrentEntity=0
self.offShiftTimeTryingToReleaseCurrentEntity=0 self.offShiftTimeTryingToReleaseCurrentEntity=0
self.timeLastEntityLeft=now() self.timeLastEntityLeft=now()
self.outputTrace(activeEntity.name, "released "+self.objName) self.outputTrace(entity.name, "released "+self.objName)
return activeEntity return entity
# =======================================================================
# called be getEntity it identifies the Entity
# to be obtained so that
# getEntity gives it to removeEntity as argument
# =======================================================================
def identifyEntityToGet(self):
giverObjectQueue=self.giver.getActiveObjectQueue()
return giverObjectQueue[0]
# ======================================================================= # =======================================================================
# adds the blockage time to totalBlockageTime # adds the blockage time to totalBlockageTime
...@@ -174,7 +183,7 @@ class CoreObject(Process): ...@@ -174,7 +183,7 @@ class CoreObject(Process):
activeObject=self.getActiveObject() activeObject=self.getActiveObject()
activeObjectQueue=self.getActiveObjectQueue() activeObjectQueue=self.getActiveObjectQueue()
# remove entity from the giver # remove entity from the giver
activeEntity = giverObject.removeEntity() activeEntity = giverObject.removeEntity(entity=self.identifyEntityToGet())
# variable that holds the last giver; used in case of preemption # variable that holds the last giver; used in case of preemption
self.lastGiver=self.giver self.lastGiver=self.giver
#get the entity from the previous object and put it in front of the activeQ #get the entity from the previous object and put it in front of the activeQ
...@@ -206,6 +215,11 @@ class CoreObject(Process): ...@@ -206,6 +215,11 @@ class CoreObject(Process):
self.receiver.preempt() self.receiver.preempt()
self.receiver.timeLastEntityEnded=now() #required to count blockage correctly in the preemptied station self.receiver.timeLastEntityEnded=now() #required to count blockage correctly in the preemptied station
# activeCallersList of an operator holds the CoreObjects that have called him
# when an Entity is obtained that has the operator as manager we need to reset this list
if activeEntity.manager and (self.type=='MachineManagedJob' or self.type=='MFStation'):
if activeEntity.manager.activeCallersList:
activeEntity.manager.activeCallersList=[]
self.outputTrace(activeEntity.name, "got into "+self.objName) self.outputTrace(activeEntity.name, "got into "+self.objName)
# # TESTING # # TESTING
# print now(), self.id, 'just received', activeEntity.id # print now(), self.id, 'just received', activeEntity.id
...@@ -415,6 +429,18 @@ class CoreObject(Process): ...@@ -415,6 +429,18 @@ 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):
# # TESTING return len(self.Res.activeQ)==0
# print now(), self.id, 'has its queue empty?', len(self.Res.activeQ)
return len(self.Res.activeQ)==0 # =======================================================================
\ No newline at end of file # checks if the object is ready to receive an Entity
# =======================================================================
def isReadyToGet(self):
return True # set to true since this control was not needed until now.
# to return canAcceptAndIsRequested() would be more logical, but also computationally expensive
#return self.canAcceptAndIsRequested()
# =======================================================================
# actions to be carried out when the processing of an Entity ends
# =======================================================================
def endProcessingActions(self):
pass
...@@ -212,9 +212,9 @@ class Dismantle(CoreObject): ...@@ -212,9 +212,9 @@ class Dismantle(CoreObject):
# ======================================================================= # =======================================================================
# removes an entity from the Dismantle # removes an entity from the Dismantle
# ======================================================================= # =======================================================================
def removeEntity(self): def removeEntity(self, entity=None):
activeObjectQueue=self.getActiveObjectQueue() activeObjectQueue=self.getActiveObjectQueue()
activeEntity=CoreObject.removeEntity(self) #run the default method activeEntity=CoreObject.removeEntity(self, entity) #run the default method
#update the flags #update the flags
if(len(activeObjectQueue)==0): if(len(activeObjectQueue)==0):
......
...@@ -90,7 +90,7 @@ class Failure(ObjectInterruption): ...@@ -90,7 +90,7 @@ class Failure(ObjectInterruption):
self.outputTrace("is down") self.outputTrace("is down")
# update the failure time # update the failure time
failTime=now() failTime=now()
if(self.repairman and self.repairman!='None'): #if the failure needs a resource to be fixed, the machine waits until the if(self.repairman and self.repairman!="None"): #if the failure needs a resource to be fixed, the machine waits until the
#resource is available #resource is available
yield request,self,self.repairman.getResource() yield request,self,self.repairman.getResource()
# update the time that the repair started # update the time that the repair started
...@@ -104,6 +104,6 @@ class Failure(ObjectInterruption): ...@@ -104,6 +104,6 @@ class Failure(ObjectInterruption):
self.reactivateVictim() # since repairing is over, the Machine is reactivated self.reactivateVictim() # since repairing is over, the Machine is reactivated
self.victim.Up=True self.victim.Up=True
self.outputTrace("is up") self.outputTrace("is up")
if(self.repairman and self.repairman!='None'): #if a resource was used, it is now released if(self.repairman and self.repairman!="None"): #if a resource was used, it is now released
yield release,self,self.repairman.getResource() yield release,self,self.repairman.getResource()
self.repairman.totalWorkingTime+=now()-timeOperationStarted self.repairman.totalWorkingTime+=now()-timeOperationStarted
...@@ -166,6 +166,7 @@ def createObjects(): ...@@ -166,6 +166,7 @@ def createObjects():
G.OperatorManagedJobsList = [] G.OperatorManagedJobsList = []
G.OperatorPoolsList = [] G.OperatorPoolsList = []
G.BrokersList = [] G.BrokersList = []
G.RoutersList = []
G.OperatedMachineList = [] G.OperatedMachineList = []
G.BatchScrapMachineList=[] G.BatchScrapMachineList=[]
G.OrderDecompositionList=[] G.OrderDecompositionList=[]
...@@ -200,6 +201,9 @@ def createObjects(): ...@@ -200,6 +201,9 @@ def createObjects():
id = element.get('id', 'not found') # get the id of the element / default 'not_found' id = element.get('id', 'not found') # get the id of the element / default 'not_found'
name = element.get('name', 'not found') # get the name of the element / default 'not_found' name = element.get('name', 'not found') # get the name of the element / default 'not_found'
capacity = int(element.get('capacity') or 1) capacity = int(element.get('capacity') or 1)
schedulingRule=element.get('schedulingRule', 'FIFO') # get the scheduling rule of the el. (how to choose which
# station to serve first) / default 'FIFO' i.e. the one that
# called first
O = Operator(element_id, name, capacity) # create an operator object O = Operator(element_id, name, capacity) # create an operator object
O.coreObjectIds=getSuccessorList(id) # update the list of objects that the operator operates O.coreObjectIds=getSuccessorList(id) # update the list of objects that the operator operates
# calling the getSuccesorList() method on the operator # calling the getSuccesorList() method on the operator
...@@ -1369,11 +1373,17 @@ def main(argv=[], input_data=None): ...@@ -1369,11 +1373,17 @@ def main(argv=[], input_data=None):
if G.maxSimTime==-1: if G.maxSimTime==-1:
simulate(until=infinity) # simulate until there are no more events. 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! # 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
if now()!=0: #do not let G.maxSimTime=0 so that there will be no crash
G.maxSimTime=now()
else:
print "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 simulate(until=G.maxSimTime) #simulate until the given maxSimTime
......
...@@ -31,6 +31,8 @@ from SimPy.Simulation import activate, passivate, waituntil, now, hold, request, ...@@ -31,6 +31,8 @@ from SimPy.Simulation import activate, passivate, waituntil, now, hold, request,
from Failure import Failure from Failure import Failure
from CoreObject import CoreObject from CoreObject import CoreObject
from OperatorRouter import Router
from OperatedPoolBroker import Broker from OperatedPoolBroker import Broker
from OperatorPool import OperatorPool from OperatorPool import OperatorPool
...@@ -145,6 +147,15 @@ class Machine(CoreObject): ...@@ -145,6 +147,15 @@ class Machine(CoreObject):
self.operatorPool.initialize() self.operatorPool.initialize()
self.broker = Broker(self) self.broker = Broker(self)
activate(self.broker,self.broker.run()) activate(self.broker,self.broker.run())
# if there is no router in G.RouterList
# initialise a new router
if len(G.RouterList)==0:
self.router=Router()
activate(self.router,self.router.run())
G.RouterList.append(self.router)
# otherwise set the already existing router as the machines Router
else:
self.router=G.RouterList[0]
for operator in self.operatorPool.operators: for operator in self.operatorPool.operators:
operator.coreObjectIds.append(self.id) operator.coreObjectIds.append(self.id)
operator.coreObjects.append(self) operator.coreObjects.append(self)
...@@ -171,6 +182,10 @@ class Machine(CoreObject): ...@@ -171,6 +182,10 @@ class Machine(CoreObject):
self.setupTimeCurrentEntity = 0 # holds the time to setup the machine before processing the current entity self.setupTimeCurrentEntity = 0 # holds the time to setup the machine before processing the current entity
# TODO: check whether the requestingEntity variable can be used in OperatorPreemptive # TODO: check whether the requestingEntity variable can be used in OperatorPreemptive
self.requestingEntity=None self.requestingEntity=None
# flag that shows if the station is ready to proceed with the getEntity
# the router must set the flag to false if the station must not proceed with getEntity
# he must also assign the operator to the station that will proceed (operatorAssignedTo)
self.canProceedWithGetEntity=True
# ======================================================================= # =======================================================================
# the main process of the machine # the main process of the machine
...@@ -178,10 +193,30 @@ class Machine(CoreObject): ...@@ -178,10 +193,30 @@ class Machine(CoreObject):
def run(self): def run(self):
# execute all through simulation time # execute all through simulation time
while 1: while 1:
# wait until the machine can accept an entity and one predecessor requests it # wait until the Router has picked the station to proceed with getEntity
# canAcceptAndIsRequested is invoked to check when the machine requested to receive an entity while self.canProceedWithGetEntity:
yield waituntil, self, self.canAcceptAndIsRequested # wait until the machine can accept an entity and one predecessor requests it
# here or in the get entity (apart from the loatTimeCurrentEntity) # canAcceptAndIsRequested is invoked to check when the machine requested to receive an entity
yield waituntil, self, self.canAcceptAndIsRequested
# TESTING
print self.id, 'will receive?'
# # wait until the Router has checked how many stations are requesting (if)
# # for operators at the same simulation time
# if (self.operatorPool!="None")\
# and any(type=="Load" for type in self.multOperationTypeList):
# self.requestRouter()
# yield waituntil, self, self.router.routerIsSet
# while 1:
# yield waituntil, self, self.canAcceptAndIsRequested
# if self.isReadyToGet():
# break
# # TODO check if the commented below is needed with operators shceduling rules
# else:
# yield hold,self,0
# here or in the getEntity (apart from the loadTimeCurrentEntity)
# in case they are placed inside the getEntity then the initialize of # in case they are placed inside the getEntity then the initialize of
# the corresponding variables should be moved to the initialize() of the CoreObject # the corresponding variables should be moved to the initialize() of the CoreObject
self.operatorWaitTimeCurrentEntity = 0 self.operatorWaitTimeCurrentEntity = 0
...@@ -578,10 +613,8 @@ class Machine(CoreObject): ...@@ -578,10 +613,8 @@ class Machine(CoreObject):
# ======================================================================= # =======================================================================
# removes an entity from the Machine # removes an entity from the Machine
# ======================================================================= # =======================================================================
def removeEntity(self): def removeEntity(self, entity=None):
activeObject=self.getActiveObject() activeEntity=CoreObject.removeEntity(self, entity) # run the default method
#activeObject.outputTrace("releases "+activeObject.objName) # output to trace that the Entity was released from the currentObject
activeEntity=CoreObject.removeEntity(self) #run the default method
activeObject.waitToDispose=False # update the waitToDispose flag activeObject.waitToDispose=False # update the waitToDispose flag
return activeEntity return activeEntity
...@@ -628,6 +661,12 @@ class Machine(CoreObject): ...@@ -628,6 +661,12 @@ class Machine(CoreObject):
def calculateLoadTime(self): def calculateLoadTime(self):
return self.loadRng.generateNumber() return self.loadRng.generateNumber()
# =======================================================================
# prepare the machine to be operated
# =======================================================================
def requestRouter(self):
self.router.invokeRouter()
# ======================================================================= # =======================================================================
# prepare the machine to be operated # prepare the machine to be operated
# ======================================================================= # =======================================================================
......
...@@ -30,6 +30,7 @@ from SimPy.Simulation import Process, Resource, activate, now ...@@ -30,6 +30,7 @@ from SimPy.Simulation import Process, Resource, activate, now
from OperatedPoolBroker import Broker from OperatedPoolBroker import Broker
from OperatorPool import OperatorPool from OperatorPool import OperatorPool
from OperatorRouter import Router
from MachineJobShop import MachineJobShop from MachineJobShop import MachineJobShop
# =========================================================================== # ===========================================================================
...@@ -42,6 +43,7 @@ class MachineManagedJob(MachineJobShop): ...@@ -42,6 +43,7 @@ class MachineManagedJob(MachineJobShop):
# ======================================================================= # =======================================================================
def initialize(self): def initialize(self):
MachineJobShop.initialize(self) MachineJobShop.initialize(self)
self.type="MachineManagedJob"
#create an empty Operator Pool. This will be updated by canAcceptAndIsRequested #create an empty Operator Pool. This will be updated by canAcceptAndIsRequested
id = self.id+'_OP' id = self.id+'_OP'
name=self.objName+'_operatorPool' name=self.objName+'_operatorPool'
...@@ -51,6 +53,18 @@ class MachineManagedJob(MachineJobShop): ...@@ -51,6 +53,18 @@ class MachineManagedJob(MachineJobShop):
#create a Broker #create a Broker
self.broker = Broker(self) self.broker = Broker(self)
activate(self.broker,self.broker.run()) activate(self.broker,self.broker.run())
#create a Router
from Globals import G
if len(G.RoutersList)==0:
self.router=Router()
activate(self.router,self.router.run())
G.RoutersList.append(self.router)
# otherwise set the already existing router as the machines Router
else:
self.router=G.RoutersList[0]
# holds the Entity that is to be obtained and will be updated by canAcceptAndIsRequested
self.entityToGet=None
# ======================================================================= # =======================================================================
# checks if the Queue can accept an entity # checks if the Queue can accept an entity
...@@ -105,28 +119,30 @@ class MachineManagedJob(MachineJobShop): ...@@ -105,28 +119,30 @@ class MachineManagedJob(MachineJobShop):
if (activeObject.operatorPool!='None' and (any(type=='Load' for type in activeObject.multOperationTypeList)\ if (activeObject.operatorPool!='None' and (any(type=='Load' for type in activeObject.multOperationTypeList)\
or any(type=='Setup' for type in activeObject.multOperationTypeList))): or any(type=='Setup' for type in activeObject.multOperationTypeList))):
if isRequested: if isRequested:
# TODO: # TODO: check whether this entity is the one to be hand in
# check whether this entity is the one to be hand in
# to be used in operatorPreemptive # to be used in operatorPreemptive
activeObject.requestingEntity=activeObject.giver.getActiveObjectQueue()[0] activeObject.requestingEntity=activeObject.giver.getActiveObjectQueue()[0]
# TODO: # TODO: update the object requesting the operator
# update the object requesting the operator
activeObject.operatorPool.requestingObject=activeObject.giver activeObject.operatorPool.requestingObject=activeObject.giver
# TODOD: # TODO: update the last object calling the operatorPool
# update the last object calling the operatorPool
activeObject.operatorPool.receivingObject=activeObject activeObject.operatorPool.receivingObject=activeObject
if activeObject.Up and len(activeObjectQueue)<activeObject.capacity\ if activeObject.Up and len(activeObjectQueue)<activeObject.capacity\
and self.checkOperator()\
and not activeObject.giver.exitIsAssigned(): and not activeObject.giver.exitIsAssigned():
activeObject.giver.assignExit() activeObject.giver.assignExit()
#make the operatorsList so that it holds only the manager of the current order # if the activeObject is not in manager's activeCallersList of the entityToGet
# activeObject.operatorPool.operatorsList=[activeObject.giver.getActiveObjectQueue()[0].manager] if self not in activeObject.giver.getActiveObjectQueue()[0].manager.activeCallersList:
# # TODO: think over the next line, this way sort entity is run multiple times throughout the life-span of # append it to the activeCallerList of the manager of the entity to be received
# # an entity in the object. Maybe would be a good idea to pick the entity to be disposed from the giver activeObject.giver.getActiveObjectQueue()[0].manager.activeCallersList.append(self)
# activeObject.giver.sortEntities() # update entityToGet
self.entityToGet=activeObject.giver.getActiveObjectQueue()[0]
#make the operators List so that it holds only the manager of the current order
activeObject.operatorPool.operators=[activeObject.giver.getActiveObjectQueue()[0].manager] activeObject.operatorPool.operators=[activeObject.giver.getActiveObjectQueue()[0].manager]
# set the variable operatorAssignedTo to activeObject, the operator is then blocked # set the variable operatorAssignedTo to activeObject, the operator is then blocked
activeObject.operatorPool.operators[0].operatorAssignedTo=activeObject activeObject.operatorPool.operators[0].operatorAssignedTo=activeObject
# # TESTING
# print now(), activeObject.operatorPool.operators[0].objName, 'got assigned to', activeObject.id
# read the load time of the machine # read the load time of the machine
self.readLoadTime() self.readLoadTime()
return True return True
...@@ -135,12 +151,55 @@ class MachineManagedJob(MachineJobShop): ...@@ -135,12 +151,55 @@ class MachineManagedJob(MachineJobShop):
else: else:
# the operator doesn't have to be present for the loading of the machine as the load operation # the operator doesn't have to be present for the loading of the machine as the load operation
# is not assigned to operators # is not assigned to operators
return activeObject.Up and len(activeObjectQueue)<activeObject.capacity and isRequested if activeObject.Up and len(activeObjectQueue)<activeObject.capacity and isRequested\
and self.checkOperator():
# update entityToGet
self.entityToGet=self.giver.getActiveObjectQueue()[0]
return activeObject.Up and len(activeObjectQueue)<activeObject.capacity and isRequested\
and self.checkOperator()
# return activeObject.Up and len(activeObjectQueue)<activeObject.capacity and isRequested
# while if the set up is performed before the (automatic) loading of the machine then the availability of the # while if the set up is performed before the (automatic) loading of the machine then the availability of the
# operator is requested # operator is requested
# return (activeObject.operatorPool=='None' or activeObject.operatorPool.checkIfResourceIsAvailable())\ # return (activeObject.operatorPool=='None' or activeObject.operatorPool.checkIfResourceIsAvailable())\
# and activeObject.Up and len(activeObjectQueue)<activeObject.capacity and isRequested # and activeObject.Up and len(activeObjectQueue)<activeObject.capacity and isRequested
# =======================================================================
# to be called by canAcceptAndIsRequested and check for the operator
# =======================================================================
def checkOperator(self):
if self.giver.getActiveObjectQueue()[0].manager:
manager=self.giver.getActiveObjectQueue()[0].manager
# print ''
# print 'Entity',self.giver.getActiveObjectQueue()[0].id
# print 'manager',manager.id
return manager.checkIfResourceIsAvailable()
else:
return True
# =======================================================================
# identifies the Entity to be obtained so that
# getEntity gives it to removeEntity as argument
# =======================================================================
def identifyEntityToGet(self):
# ToDecide
# maybe we should work this way in all CoreObjects???
return self.entityToGet
# =======================================================================
# checks if the object is ready to receive an Entity
# =======================================================================
def isReadyToGet(self):
# check if the entity that is about to be obtained has a manager (this should be true for this object)
if self.entityToGet.manager:
manager=self.entityToGet.manager
if len(manager.activeCallersList)>0:
manager.sortEntities() # sort the callers of the manager to be used for scheduling rules
# return true if the manager is available
return manager.checkIfResourceIsAvailable()
else:
return True
# ======================================================================= # =======================================================================
# prepare the machine to be released # prepare the machine to be released
# ======================================================================= # =======================================================================
......
...@@ -94,12 +94,14 @@ class MouldAssembly(MachineManagedJob): ...@@ -94,12 +94,14 @@ class MouldAssembly(MachineManagedJob):
# ======================================================================= # =======================================================================
def getEntity(self): def getEntity(self):
activeObject = self.getActiveObject() activeObject = self.getActiveObject()
giverObejct = activeObject.getGiverObject() giverObject = activeObject.getGiverObject()
# get the first entity from the predecessor # get the first entity from the predecessor
# TODO: each MachineManagedJob.getEntity is invoked, # TODO: each MachineManagedJob.getEntity is invoked,
# the self.procTime is updated. Have to decide where to assign # the self.procTime is updated. Have to decide where to assign
# the processing time of the assembler # the processing time of the assembler
activeEntity=MachineManagedJob.getEntity(self) activeEntity=MachineManagedJob.getEntity(self)
# this is kept so that in the next loop it will not try to re-get this Entity
firstObtained=activeEntity
# check weather the activeEntity is of type Mould # check weather the activeEntity is of type Mould
if activeEntity.type=='Mould': if activeEntity.type=='Mould':
# and return the mould received # and return the mould received
...@@ -116,14 +118,18 @@ class MouldAssembly(MachineManagedJob): ...@@ -116,14 +118,18 @@ class MouldAssembly(MachineManagedJob):
# append the activeEntity to the activeObjectQueue # append the activeEntity to the activeObjectQueue
activeObjectQueue = activeObject.getActiveObjectQueue() activeObjectQueue = activeObject.getActiveObjectQueue()
activeObjectQueue.append(activeEntity) activeObjectQueue.append(activeEntity)
# dummy variable to inform when the sum of needed components is received # loop through the basic/secondary components of the order that is currently obtained
# before the assembly-processing
orderGroupReceived = False
# all the components are received at the same time # all the components are received at the same time
while not orderGroupReceived: for entity in activeEntity.order.basicComponentsList\
+activeEntity.order.secondaryComponentsList:
# continue for the one that is already obtained before
if entity is firstObtained:
continue
self.entityToGet=entity
# get the next component # get the next component
activeEntity=MachineManagedJob.getEntity(self) activeEntity=MachineManagedJob.getEntity(self)
# check weather the activeEntity is of type Mould # check whether the activeEntity is of type Mould
try: try:
if activeEntity.type=='Mould': if activeEntity.type=='Mould':
# and return the mould received # and return the mould received
...@@ -136,10 +142,6 @@ class MouldAssembly(MachineManagedJob): ...@@ -136,10 +142,6 @@ class MouldAssembly(MachineManagedJob):
except AssembleMouldError as mouldError: except AssembleMouldError as mouldError:
print 'Mould Assembly Error: {0}'.format(mouldError) print 'Mould Assembly Error: {0}'.format(mouldError)
return False return False
# if the length of the internal queue is equal to the updated capacity
if len(activeObject.getActiveObjectQueue())==self.capacity:
# then exit the while loop
orderGroupReceived=True
# perform the assembly-action and return the assembled mould # perform the assembly-action and return the assembled mould
activeEntity = activeObject.assemble() activeEntity = activeObject.assemble()
return activeEntity return activeEntity
......
...@@ -59,6 +59,10 @@ class MouldAssemblyBuffer(QueueManagedJob): ...@@ -59,6 +59,10 @@ class MouldAssemblyBuffer(QueueManagedJob):
activeObjectQueue = activeObject.getActiveObjectQueue() activeObjectQueue = activeObject.getActiveObjectQueue()
# if all the components of the same mould are present then move them to the front of the activeQ # if all the components of the same mould are present then move them to the front of the activeQ
activeObjectQueue.sort(key=lambda x: x.order.componentsReadyForAssembly, reverse=True) activeObjectQueue.sort(key=lambda x: x.order.componentsReadyForAssembly, reverse=True)
'''
maybe the below lines should go after
if len(activeObjectQueue)>0:
'''
# keep the first entity of the activeQ # keep the first entity of the activeQ
activeEntity = activeObjectQueue[0] activeEntity = activeObjectQueue[0]
# bring the entities that have the same parentOrder as the first entity to the front # bring the entities that have the same parentOrder as the first entity to the front
......
...@@ -69,8 +69,8 @@ class Broker(ObjectInterruption): ...@@ -69,8 +69,8 @@ class Broker(ObjectInterruption):
# set the available resource as the currentOperator # set the available resource as the currentOperator
self.victim.currentOperator=self.victim.operatorPool.findAvailableOperator() self.victim.currentOperator=self.victim.operatorPool.findAvailableOperator()
yield request,self,self.victim.operatorPool.getResource(self.victim.currentOperator) yield request,self,self.victim.operatorPool.getResource(self.victim.currentOperator)
# # TESTING # TESTING
# print now(), self.victim.currentOperator.objName, 'started work in ', self.victim.id print now(), self.victim.currentOperator.objName, 'started work in ', self.victim.id
# self.victim.totalTimeWaitingForOperator+=now()-self.timeWaitForOperatorStarted # self.victim.totalTimeWaitingForOperator+=now()-self.timeWaitForOperatorStarted
# clear the timeWaitForOperatorStarted variable # clear the timeWaitForOperatorStarted variable
self.timeWaitForOperatorStarted = 0 self.timeWaitForOperatorStarted = 0
......
...@@ -34,8 +34,96 @@ from Repairman import Repairman ...@@ -34,8 +34,96 @@ from Repairman import Repairman
# =========================================================================== # ===========================================================================
class Operator(Repairman): class Operator(Repairman):
def __init__(self, id, name, capacity=1): def __init__(self, id, name, capacity=1, schedulingRule="FIFO"):
Repairman.__init__(self,id=id,name=name,capacity=capacity) Repairman.__init__(self,id=id,name=name,capacity=capacity)
self.type="Operator" self.type="Operator"
self.activeCallersList=[]
self.schedulingRule=schedulingRule
# =======================================================================
# sorts the Entities of the Queue according to the scheduling rule
# =======================================================================
def sortEntities(self):
#if we have sorting according to multiple criteria we have to call the sorter many times
if self.schedulingRule=="MC":
for criterion in reversed(self.multipleCriterionList):
self.activeQSorter(criterion=criterion)
#else we just use the default scheduling rule
else:
self.activeQSorter()
# =======================================================================
# sorts the Entities of the Queue according to the scheduling rule
# =======================================================================
def activeQSorter(self, criterion=None):
activeObjectQ=self.activeCallersList
if criterion==None:
criterion=self.schedulingRule
#if the schedulingRule is first in first out
if criterion=="FIFO":
pass
#if the schedulingRule is based on a pre-defined priority
elif criterion=="Priority":
activeObjectQ.sort(key=lambda x: x.priority)
#if the schedulingRule is earliest due date
elif criterion=="EDD":
activeObjectQ.sort(key=lambda x: x.dueDate)
#if the schedulingRule is earliest order date
elif criterion=="EOD":
activeObjectQ.sort(key=lambda x: x.orderDate)
#if the schedulingRule is to sort Entities according to the stations they have to visit
elif criterion=="NumStages":
activeObjectQ.sort(key=lambda x: len(x.remainingRoute), reverse=True)
#if the schedulingRule is to sort Entities according to the their remaining processing time in the system
elif criterion=="RPC":
for entity in activeObjectQ:
RPT=0
for step in entity.remainingRoute:
processingTime=step.get('processingTime',None)
if processingTime:
RPT+=float(processingTime.get('mean',0))
entity.remainingProcessingTime=RPT
activeObjectQ.sort(key=lambda x: x.remainingProcessingTime, reverse=True)
#if the schedulingRule is to sort Entities according to longest processing time first in the next station
elif criterion=="LPT":
for entity in activeObjectQ:
processingTime = entity.remainingRoute[0].get('processingTime',None)
entity.processingTimeInNextStation=float(processingTime.get('mean',0))
if processingTime:
entity.processingTimeInNextStation=float(processingTime.get('mean',0))
else:
entity.processingTimeInNextStation=0
activeObjectQ.sort(key=lambda x: x.processingTimeInNextStation, reverse=True)
#if the schedulingRule is to sort Entities according to shortest processing time first in the next station
elif criterion=="SPT":
for entity in activeObjectQ:
processingTime = entity.remainingRoute[0].get('processingTime',None)
if processingTime:
entity.processingTimeInNextStation=float(processingTime.get('mean',0))
else:
entity.processingTimeInNextStation=0
activeObjectQ.sort(key=lambda x: x.processingTimeInNextStation)
#if the schedulingRule is to sort Entities based on the minimum slackness
elif criterion=="MS":
for entity in activeObjectQ:
RPT=0
for step in entity.remainingRoute:
processingTime=step.get('processingTime',None)
if processingTime:
RPT+=float(processingTime.get('mean',0))
entity.remainingProcessingTime=RPT
activeObjectQ.sort(key=lambda x: (x.dueDate-x.remainingProcessingTime))
#if the schedulingRule is to sort Entities based on the length of the following Queue
elif criterion=="WINQ":
from Globals import G
for entity in activeObjectQ:
nextObjIds=entity.remainingRoute[1].get('stationIdsList',[])
for obj in G.ObjList:
if obj.id in nextObjIds:
nextObject=obj
entity.nextQueueLength=len(nextObject.getActiveObjectQueue())
activeObjectQ.sort(key=lambda x: x.nextQueueLength)
else:
assert False, "Unknown scheduling criterion %r" % (criterion, )
...@@ -91,7 +91,7 @@ class Queue(CoreObject): ...@@ -91,7 +91,7 @@ class Queue(CoreObject):
while 1: while 1:
yield waituntil, self, self.canAcceptAndIsRequested #wait until the Queue can accept an entity yield waituntil, self, self.canAcceptAndIsRequested #wait until the Queue can accept an entity
#and one predecessor requests it #and one predecessor requests it
self.getEntity() self.getEntity()
#if entity just got to the dummyQ set its startTime as the current time #if entity just got to the dummyQ set its startTime as the current time
...@@ -162,9 +162,9 @@ class Queue(CoreObject): ...@@ -162,9 +162,9 @@ class Queue(CoreObject):
# ======================================================================= # =======================================================================
# removes an entity from the Object # removes an entity from the Object
# ======================================================================= # =======================================================================
def removeEntity(self): def removeEntity(self, entity=None):
activeObject=self.getActiveObject() activeObject=self.getActiveObject()
activeEntity=CoreObject.removeEntity(self) #run the default method activeEntity=CoreObject.removeEntity(self, entity) #run the default method
return activeEntity return activeEntity
# ======================================================================= # =======================================================================
# checks if the Queue can accept an entity and # checks if the Queue can accept an entity and
......
...@@ -72,6 +72,10 @@ class QueueManagedJob(QueueJobShop): ...@@ -72,6 +72,10 @@ class QueueManagedJob(QueueJobShop):
activeObject.receiver=activeObject.next[0] activeObject.receiver=activeObject.next[0]
#sort the internal queue so that the Entities that have an available manager go in the front #sort the internal queue so that the Entities that have an available manager go in the front
activeObject.sortEntities() activeObject.sortEntities()
# # TESTING
# if self.id=='QEDM':
# if len(activeObjectQueue)>0 and thecaller==activeObject.receiver:
# print ' ',self.id, 'has to dispose'
return len(activeObjectQueue)>0\ return len(activeObjectQueue)>0\
and thecaller==activeObject.receiver and thecaller==activeObject.receiver
...@@ -85,6 +89,10 @@ class QueueManagedJob(QueueJobShop): ...@@ -85,6 +89,10 @@ class QueueManagedJob(QueueJobShop):
self.receiver=object # and update the receiver self.receiver=object # and update the receiver
#sort the internal queue so that the Entities that have an available manager go in the front #sort the internal queue so that the Entities that have an available manager go in the front
activeObject.sortEntities() activeObject.sortEntities()
# # TESTING
# if self.id=='QEDM':
# if len(activeObjectQueue)>0 and thecaller==activeObject.receiver:
# print ' ',self.id, 'has to dispose'
#return True if the Queue has Entities and the caller is the receiver #return True if the Queue has Entities and the caller is the receiver
return len(activeObjectQueue)>0 and (thecaller is self.receiver) return len(activeObjectQueue)>0 and (thecaller is self.receiver)
......
...@@ -58,7 +58,6 @@ from dream.simulation.MouldAssembly import MouldAssembly ...@@ -58,7 +58,6 @@ from dream.simulation.MouldAssembly import MouldAssembly
from dream.simulation.MouldAssemblyBuffer import MouldAssemblyBuffer from dream.simulation.MouldAssemblyBuffer import MouldAssemblyBuffer
from dream.simulation.OrderDecomposition import OrderDecomposition from dream.simulation.OrderDecomposition import OrderDecomposition
#Entities #Entities
from dream.simulation.Job import Job from dream.simulation.Job import Job
from dream.simulation.Part import Part from dream.simulation.Part import Part
......
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