Commit 5beb1e5c authored by Ioannis Papagiannopoulos's avatar Ioannis Papagiannopoulos Committed by Jérome Perrin

router minor-cleanup

parent 3ccefa64
...@@ -1111,17 +1111,17 @@ class Machine(CoreObject): ...@@ -1111,17 +1111,17 @@ class Machine(CoreObject):
return self.loadRng.generateNumber() return self.loadRng.generateNumber()
#=========================================================================== # #===========================================================================
# find candidate operators within the free operators # # find candidate operators within the free operators
#=========================================================================== # #===========================================================================
def findCandidateOperator(self): # def findCandidateOperator(self):
# TODO: this way no sorting is performed # # TODO: this way no sorting is performed
# find an available operator # # find an available operator
candidateOperator=self.operatorPool.findAvailableOperator() # candidateOperator=self.operatorPool.findAvailableOperator()
# append the station into its candidateStations # # append the station into its candidateStations
if candidateOperator: # if there was an operator found append the Machine on his candidateStations # if candidateOperator: # if there was an operator found append the Machine on his candidateStations
candidateOperator.candidateStations.append(self) # candidateOperator.candidateStations.append(self)
return candidateOperator # return candidateOperator
#=========================================================================== #===========================================================================
# checks whether the entity can proceed to a successor object # checks whether the entity can proceed to a successor object
......
...@@ -202,12 +202,16 @@ class Operator(ObjectResource): ...@@ -202,12 +202,16 @@ class Operator(ObjectResource):
machine.timeWaiting=self.env.now-machine.broker.timeWaitForOperatorStarted machine.timeWaiting=self.env.now-machine.broker.timeWaitForOperatorStarted
else: else:
machine.timeWaiting=self.env.now-machine.timeLastEntityLeft machine.timeWaiting=self.env.now-machine.timeLastEntityLeft
# find the stations that hold critical entities # find the stations that hold or are about to be delivered critical entities
if self in router.preemptiveOperators: if self in router.preemptiveOperators:
for entity in station.getActiveObjectQueue(): for entity in machine.getActiveObjectQueue():
if entity.isCritical: if entity in router.pending and entity.isCritical:
machine.critical=True machine.critical=True
break break
for previous in machine.previous:
for entity in previous.getActiveObjectQueue():
if entity in router.pending and entity.isCritical:
machine.critical=True
# sort the stations according their timeWaiting # sort the stations according their timeWaiting
self.candidateStations.sort(key= lambda x: x.timeWaiting, reverse=True) self.candidateStations.sort(key= lambda x: x.timeWaiting, reverse=True)
# sort the stations if they hold critical entities # sort the stations if they hold critical entities
......
...@@ -56,14 +56,16 @@ class Router(ObjectInterruption): ...@@ -56,14 +56,16 @@ class Router(ObjectInterruption):
# flag to notify whether the router is already invoked # flag to notify whether the router is already invoked
self.invoked=False self.invoked=False
self.criticalPending=[] # list of critical entities that are pending # self.criticalPending=[] # list of critical entities that are pending
self.preemptiveOperators=[] # list of preemptiveOperators that should preempt their machines self.preemptiveOperators=[] # list of preemptiveOperators that should preempt their machines
self.conflictingOperators=[] # list with the operators that have candidateEntity with conflicting candidateReceivers self.conflictingOperators=[] # list with the operators that have candidateEntity with conflicting candidateReceivers
self.conflictingEntities=[] # entities with conflictingReceivers self.conflictingEntities=[] # entities with conflictingReceivers
self.conflictingStations=[] # stations with conflicting operators self.conflictingStations=[] # stations with conflicting operators
self.occupiedReceivers=[] # occupied candidateReceivers of a candidateEntity self.occupiedReceivers=[] # occupied candidateReceivers of a candidateEntity
self.entitiesWithOccupiedReceivers=[] # list of entities that have no available receivers
self.criticalQueues=[]
# self.entitiesWithOccupiedReceivers=[] # list of entities that have no available receivers
#=========================================================================== #===========================================================================
# the initialize method # the initialize method
...@@ -73,8 +75,10 @@ class Router(ObjectInterruption): ...@@ -73,8 +75,10 @@ class Router(ObjectInterruption):
# signal used to initiate the generator of the Router # signal used to initiate the generator of the Router
self.isCalled=self.env.event() self.isCalled=self.env.event()
# list that holds all the objects that can receive # list that holds all the objects that can receive
self.pendingObjects=[] # self.pendingObjects=[]
self.calledOperator=[] self.pendingMachines=[]
self.pendingQueues=[]
# self.calledOperator=[]
# list of the operators that may handle a machine at the current simulation time # list of the operators that may handle a machine at the current simulation time
self.candidateOperators=[] self.candidateOperators=[]
# list of criteria # list of criteria
...@@ -86,7 +90,7 @@ class Router(ObjectInterruption): ...@@ -86,7 +90,7 @@ class Router(ObjectInterruption):
self.invoked=False self.invoked=False
self.criticalPending=[] # self.criticalPending=[]
self.preemptiveOperators=[] self.preemptiveOperators=[]
self.toBeSignalled=[] self.toBeSignalled=[]
...@@ -94,7 +98,9 @@ class Router(ObjectInterruption): ...@@ -94,7 +98,9 @@ class Router(ObjectInterruption):
self.conflictingEntities=[] self.conflictingEntities=[]
self.conflictingStations=[] self.conflictingStations=[]
self.occupiedReceivers=[] self.occupiedReceivers=[]
self.entitiesWithOccupiedReceivers=[] # self.entitiesWithOccupiedReceivers=[]
self.criticalQueues=[]
# ======================================================================= # =======================================================================
# the run method # the run method
...@@ -128,8 +134,9 @@ class Router(ObjectInterruption): ...@@ -128,8 +134,9 @@ class Router(ObjectInterruption):
# find the pending objects # find the pending objects
self.findPendingObjects() self.findPendingObjects()
# find the pending entities
self.findPendingEntities() # # find the pending entities
# self.findPendingEntities()
# find the operators that can start working now # find the operators that can start working now
self.findCandidateOperators() self.findCandidateOperators()
# # sort the pendingEntities list # # sort the pendingEntities list
...@@ -144,7 +151,7 @@ class Router(ObjectInterruption): ...@@ -144,7 +151,7 @@ class Router(ObjectInterruption):
self.assignOperators() self.assignOperators()
for operator in [x for x in self.candidateOperators if x.isAssignedTo()]: for operator in [x for x in self.candidateOperators if x.isAssignedTo()]:
if not operator.isAssignedTo() in self.pendingObjects: if not operator.isAssignedTo() in list(self.pendingMachines+self.pendingQueues):
for object in [x for x in operator.isAssignedTo().previous if x.exitIsAssignedTo()]: for object in [x for x in operator.isAssignedTo().previous if x.exitIsAssignedTo()]:
if object.exitIsAssignedTo()!=operator.isAssignedTo(): if object.exitIsAssignedTo()!=operator.isAssignedTo():
object.unAssignExit() object.unAssignExit()
...@@ -152,7 +159,7 @@ class Router(ObjectInterruption): ...@@ -152,7 +159,7 @@ class Router(ObjectInterruption):
for object in self.pendingQueues: for object in self.pendingQueues:
if not object in self.toBeSignalled: if not object in self.toBeSignalled:
object.unAssignExit() object.unAssignExit()
# signal the stations that ought to be signalled # signal the stations that ought to be signaled
self.signalOperatedStations() self.signalOperatedStations()
self.printTrace('', 'router exiting') self.printTrace('', 'router exiting')
self.printTrace('','=-'*20) self.printTrace('','=-'*20)
...@@ -162,7 +169,6 @@ class Router(ObjectInterruption): ...@@ -162,7 +169,6 @@ class Router(ObjectInterruption):
# assigning operators to machines # assigning operators to machines
#=========================================================================== #===========================================================================
def assignOperators(self): def assignOperators(self):
#------------------------------------------------------------------------------
# for all the operators that are requested # for all the operators that are requested
for operator in self.candidateOperators: for operator in self.candidateOperators:
# check if the candidateOperators are available, if the are requested and reside in the pendingObjects list # check if the candidateOperators are available, if the are requested and reside in the pendingObjects list
...@@ -182,7 +188,7 @@ class Router(ObjectInterruption): ...@@ -182,7 +188,7 @@ class Router(ObjectInterruption):
operator.assignTo(operator.candidateStation) operator.assignTo(operator.candidateStation)
if not operator.candidateStation in self.toBeSignalled: if not operator.candidateStation in self.toBeSignalled:
self.toBeSignalled.append(operator.candidateStation) self.toBeSignalled.append(operator.candidateStation)
self.printTrace('objects to be signalled:'+' '*11, [str(object.id) for object in self.toBeSignalled]) self.printTrace('objects to be signaled:'+' '*11, [str(object.id) for object in self.toBeSignalled])
# ======================================================================= # =======================================================================
# return control to the Machine.run # return control to the Machine.run
...@@ -200,9 +206,9 @@ class Router(ObjectInterruption): ...@@ -200,9 +206,9 @@ class Router(ObjectInterruption):
entity.candidateReceivers=[] entity.candidateReceivers=[]
entity.candidateReceiver=None entity.candidateReceiver=None
del self.candidateOperators[:] del self.candidateOperators[:]
del self.criticalPending[:] # del self.criticalPending[:]
del self.preemptiveOperators[:] del self.preemptiveOperators[:]
del self.pendingObjects[:] # del self.pendingObjects[:]
del self.pendingMachines[:] del self.pendingMachines[:]
del self.pendingQueues[:] del self.pendingQueues[:]
del self.toBeSignalled[:] del self.toBeSignalled[:]
...@@ -211,7 +217,8 @@ class Router(ObjectInterruption): ...@@ -211,7 +217,8 @@ class Router(ObjectInterruption):
del self.conflictingStations[:] del self.conflictingStations[:]
del self.conflictingEntities[:] del self.conflictingEntities[:]
del self.occupiedReceivers[:] del self.occupiedReceivers[:]
del self.entitiesWithOccupiedReceivers[:] del self.criticalQueues[:]
# del self.entitiesWithOccupiedReceivers[:]
self.schedulingRule='WT' self.schedulingRule='WT'
self.invoked=False self.invoked=False
...@@ -251,57 +258,62 @@ class Router(ObjectInterruption): ...@@ -251,57 +258,62 @@ class Router(ObjectInterruption):
self.sendSignal(receiver=station, signal=station.loadOperatorAvailable) self.sendSignal(receiver=station, signal=station.loadOperatorAvailable)
self.printTrace('router', 'signalling'+' '*50+operator.isAssignedTo().id) self.printTrace('router', 'signalling'+' '*50+operator.isAssignedTo().id)
#===========================================================================
# clear the pending lists of the router
#===========================================================================
def clearPendingObjects(self):
self.pendingQueues=[]
self.pendingMachines=[]
self.pendingObjects=[]
#=========================================================================== #===========================================================================
# find the stations that can be signalled by the router # find the stations that can be signalled by the router
#=========================================================================== #===========================================================================
def findPendingObjects(self): def findPendingObjects(self):
from Globals import G from Globals import G
self.clearPendingObjects() self.pending=[] # list of entities that require operators now
# self.clearPendingObjects()
for entity in G.pendingEntities: for entity in G.pendingEntities:
if entity.currentStation in G.MachineList: if entity.currentStation in G.MachineList:
if entity.currentStation.broker.waitForOperator: if entity.currentStation.broker.waitForOperator:
self.pendingMachines.append(entity.currentStation) self.pendingMachines.append(entity.currentStation)
self.pending.append(entity)
for machine in entity.currentStation.next: for machine in entity.currentStation.next:
if machine in G.MachineList: if machine in G.MachineList:
if any(type=='Load' for type in machine.multOperationTypeList) and not entity.currentStation in self.pendingQueues: if any(type=='Load' for type in machine.multOperationTypeList) and not entity.currentStation in self.pendingQueues:
self.pendingQueues.append(entity.currentStation) self.pendingQueues.append(entity.currentStation)
self.pendingObjects.append(entity.currentStation) self.pending.append(entity)
break break
# self.pendingMachines=[machine for machine in G.MachineList if machine.broker.waitForOperator]
self.pendingObjects=self.pendingQueues+self.pendingMachines self.findCriticalQueues()
self.printTrace('router found pending objects'+'-'*6+'>', [str(object.id) for object in self.pendingObjects])
self.printTrace('pendingMachines'+'-'*19+'>', [str(object.id) for object in self.pendingMachines]) self.printTrace('pendingMachines'+'-'*19+'>', [str(object.id) for object in self.pendingMachines])
self.printTrace('pendingQueues'+'-'*21+'>', [str(object.id) for object in self.pendingQueues]) self.printTrace('pendingQueues'+'-'*21+'>', [str(object.id) for object in self.pendingQueues])
self.printTrace('found pending entities'+'-'*12+'>', [str(entity.id) for entity in self.pending if not entity.type=='Part'])
# if self.criticalPending:
# self.printTrace('found pending critical'+'-'*12+'>', [str(entity.id) for entity in self.criticalPending if not entity.type=='Part'])
#=========================================================================== #===========================================================================
# finding the entities that require manager now # find the pending queues that hold critical pending entities
#=========================================================================== #===========================================================================
def findPendingEntities(self): def findCriticalQueues(self):
from Globals import G for queue in self.pendingQueues:
self.pending=[] # list of entities that are pending for entity in queue.getActiveObjectQueue():
for machine in self.pendingMachines: if entity in self.pending and entity.isCritical:
self.pending.append(machine.currentEntity) # self.criticalPending.append(entity)
for entity in G.pendingEntities: self.criticalQueues.append(queue)
if entity.currentStation in G.QueueList or entity.currentStation in G.SourceList:
for machine in entity.currentStation.next: #===========================================================================
if any(type=='Load' for type in machine.multOperationTypeList): # find operators that can perform preemption for a critical pending entity
self.pending.append(entity) #===========================================================================
# if the entity is critical add it to the criticalPending List def findPreemptiveOperators(self):
if entity.isCritical and not entity in self.criticalPending: # for every queue that holds critical pending entities
self.criticalPending.append(entity) for queue in self.criticalQueues:
break # if no receiver can be found
self.printTrace('found pending entities'+'-'*12+'>', [str(entity.id) for entity in self.pending if not entity.type=='Part']) if not queue.findReceiversFor(queue):
if self.criticalPending: for nextobject in queue.next:
self.printTrace('found pending critical'+'-'*12+'>', [str(entity.id) for entity in self.criticalPending if not entity.type=='Part']) for operator in nextobject.operatorPool.operators:
currentStation=operator.workingStation
if not currentStation.getActiveObjectQueue()[0].isCritical:
preemptiveOperator=operator
preemptiveOperator.candidateStations.append(nextobject)
if not preemptiveOperator in self.candidateOperators:
self.candidateOperators.append(preemptiveOperator)
self.preemptiveOperators.append(preemptiveOperator)
break
#======================================================================== #========================================================================
# Find candidate Operators # Find candidate Operators
# find the operators that can start working now even if they are not called # find the operators that can start working now even if they are not called
...@@ -311,50 +323,42 @@ class Router(ObjectInterruption): ...@@ -311,50 +323,42 @@ class Router(ObjectInterruption):
# . the candidate receivers of the entities (the stations the operators will be working at) # . the candidate receivers of the entities (the stations the operators will be working at)
#======================================================================== #========================================================================
def findCandidateOperators(self): def findCandidateOperators(self):
# find stations that may be candidates
candidateMachines = [next for queue in self.pendingQueues for next in queue.findReceiversFor(queue)]
# for each pendingMachine # for each pendingMachine
for object in self.pendingMachines: for station in candidateMachines+self.pendingMachines:
# find candidateOperators for each object operator # find candidateOperators for each object
candidateOperators=object.operatorPool.availableOperators() candidateOperators=station.operatorPool.availableOperators()
# append the station into its candidateStations if candidateOperators: # if there was an operator found append the Machine on his candidateStations
if candidateOperators: # if there was an operator found append the Machine on his candidateStations
for candidateOperator in candidateOperators: for candidateOperator in candidateOperators:
if not object in candidateOperator.candidateStations: if not station in candidateOperator.candidateStations:
candidateOperator.candidateStations.append(object) candidateOperator.candidateStations.append(object)
# if there is candidateOperator that is not already in self.candidateOperators add him # if there is candidateOperator that is not already in self.candidateOperators add him
# TODO: this way no sorting is performed # TODO: this way no sorting is performed
if not candidateOperator in self.candidateOperators: if not candidateOperator in self.candidateOperators:
self.candidateOperators.append(candidateOperator) self.candidateOperators.append(candidateOperator)
# for each pendingQueue
for object in self.pendingQueues: self.findPreemptiveOperators()
# find available operator for then machines that follow # # for each pendingQueue
for nextobject in object.findReceiversFor(object): # for object in self.pendingQueues:
candidateOperators=nextobject.operatorPool.availableOperators() # # check the option of preemption if there are critical entities and no available operators
# append the station into its candidateStations # if not object.findReceiversFor(object) and\
if candidateOperators: # if there was an operator found append the Machine on his candidateStations # any(entity for entity in object.getActiveObjectQueue() if entity.isCritical and entity in self.pending):
for candidateOperator in candidateOperators: # # for each of the following objects
if not nextobject in candidateOperator.candidateStations: # for nextObject in object.next:
candidateOperator.candidateStations.append(nextobject) # # if an operator is occupied by a critical entity then that operator can preempt
if not candidateOperator in self.candidateOperators: # # This way the first operator that is not currently on a critical entity is invoked
self.candidateOperators.append(candidateOperator) # # TODO: consider picking an operator more wisely by sorting
# for operator in nextObject.operatorPool.operators:
# check the option of preemption if there are critical entities and no available operators # currentStation=operator.workingStation
if not object.findReceiversFor(object) and\ # if not currentStation.getActiveObjectQueue()[0].isCritical:
any(entity for entity in object.getActiveObjectQueue() if entity.isCritical): # preemptiveOperator=operator
# for each of the following objects # preemptiveOperator.candidateStations.append(nextObject)
for nextObject in object.next: # if not preemptiveOperator in self.candidateOperators:
# if an operator is occupied by a critical entity then that operator can preempt # self.candidateOperators.append(preemptiveOperator)
# This way the first operator that is not currently on a critical entity is invoked # self.preemptiveOperators.append(preemptiveOperator)
# TODO: consider picking an operator more wisely by sorting # break
for operator in nextObject.operatorPool.operators:
currentStation=operator.workingStation
if not currentStation.getActiveObjectQueue()[0].isCritical:
preemptiveOperator=operator
preemptiveOperator.candidateStations.append(nextObject)
if not preemptiveOperator in self.candidateOperators:
self.candidateOperators.append(preemptiveOperator)
self.preemptiveOperators.append(preemptiveOperator)
break
# # update the schedulingRule/multipleCriterionList of the Router # # update the schedulingRule/multipleCriterionList of the Router
# if self.sorting: # if self.sorting:
...@@ -365,14 +369,6 @@ class Router(ObjectInterruption): ...@@ -365,14 +369,6 @@ class Router(ObjectInterruption):
[(operator.id, [station.id for station in operator.candidateStations]) for operator in self.candidateOperators]) [(operator.id, [station.id for station in operator.candidateStations]) for operator in self.candidateOperators])
else: else:
self.printTrace('router', 'found NO candidate operators') self.printTrace('router', 'found NO candidate operators')
# #===========================================================================
# # find the candidate entities for each candidateOperator
# #===========================================================================
# def findCandidateEntities(self):
# for operator in self.candidateOperators:
# # find which pendingEntities that can move to machines is the operator managing
# operator.findCandidateEntities(self.pending)
# #======================================================================= # #=======================================================================
# # find the schedulingRules of the candidateOperators # # find the schedulingRules of the candidateOperators
...@@ -404,19 +400,10 @@ class Router(ObjectInterruption): ...@@ -404,19 +400,10 @@ class Router(ObjectInterruption):
# TODO: sort according to the number of pending Jobs # TODO: sort according to the number of pending Jobs
# TODO Have to sort again according to the priority used by the operators # TODO Have to sort again according to the priority used by the operators
# initialise the operatorsWithOneOption and operatorsWithOneCandidateEntity lists
operatorsWithOneOption=[]
# for all the candidateOperators
for operator in self.candidateOperators:
# sort the candidate operators so that those who have only one option be served first
# if the candidate entity has only one receiver then append the operator to operatorsWithOneOption list
if operator.hasOneOption():
operatorsWithOneOption.append(operator)
# TODO: the operator here actually chooses entity. This may pose a problem as two entities may be equivalent # TODO: the operator here actually chooses entity. This may pose a problem as two entities may be equivalent
# and as the operators chooses the sorting of the queue (if they do reside in the same queue is not taken into account) # and as the operators chooses the sorting of the queue (if they do reside in the same queue is not taken into account)
# sort the candidateEntities list of each operator according to its schedulingRule # sort the candidateEntities list of each operator according to its schedulingRule
for operator in [x for x in self.candidateOperators if x.candidateEntities]: for operator in [x for x in self.candidateOperators if x.candidateStations]:
operator.sortCandidateEntities() operator.sortCandidateEntities()
# if there operators that have only one option then sort the candidateOperators according to the first one of these # if there operators that have only one option then sort the candidateOperators according to the first one of these
...@@ -425,6 +412,16 @@ class Router(ObjectInterruption): ...@@ -425,6 +412,16 @@ class Router(ObjectInterruption):
# self.sortOperators() # self.sortOperators()
if self.sorting: if self.sorting:
# initialise the operatorsWithOneOption and operatorsWithOneCandidateEntity lists
operatorsWithOneOption=[]
# for all the candidateOperators
for operator in self.candidateOperators:
# sort the candidate operators so that those who have only one option be served first
# if the candidate entity has only one receiver then append the operator to operatorsWithOneOption list
if operator.hasOneOption():
operatorsWithOneOption.append(operator)
# sort the operators according to their waiting time # sort the operators according to their waiting time
self.candidateOperators.sort(key=lambda x: x.totalWorkingTime) self.candidateOperators.sort(key=lambda x: x.totalWorkingTime)
# sort according to the number of options # sort according to the number of options
......
...@@ -52,6 +52,7 @@ class RouterManaged(Router): ...@@ -52,6 +52,7 @@ class RouterManaged(Router):
self.schedulingRule='WT' self.schedulingRule='WT'
# boolean flag to check whether the Router should perform sorting on operators and on pendingEntities # boolean flag to check whether the Router should perform sorting on operators and on pendingEntities
self.sorting=sorting self.sorting=sorting
self.entitiesWithOccupiedReceivers=[] # list of entities that have no available receivers
#=========================================================================== #===========================================================================
# the initialize method # the initialize method
...@@ -67,6 +68,7 @@ class RouterManaged(Router): ...@@ -67,6 +68,7 @@ class RouterManaged(Router):
self.multipleCriterionList=[] self.multipleCriterionList=[]
# TODO: find out which must be the default for the scheduling Rule # TODO: find out which must be the default for the scheduling Rule
self.schedulingRule='WT' self.schedulingRule='WT'
self.entitiesWithOccupiedReceivers=[]
# ======================================================================= # =======================================================================
# the run method # the run method
...@@ -248,6 +250,7 @@ class RouterManaged(Router): ...@@ -248,6 +250,7 @@ class RouterManaged(Router):
def findPendingEntities(self): def findPendingEntities(self):
from Globals import G from Globals import G
self.pending=[] # list of entities that are pending self.pending=[] # list of entities that are pending
self.criticalPending=[]
for machine in self.pendingMachines: for machine in self.pendingMachines:
self.pending.append(machine.currentEntity) self.pending.append(machine.currentEntity)
for entity in G.pendingEntities: for entity in G.pendingEntities:
......
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