Commit 69065e15 authored by Ioannis Papagiannopoulos's avatar Ioannis Papagiannopoulos Committed by Jérome Perrin

OperatorRouterManaged clean-up

parent c148a1f1
......@@ -120,13 +120,6 @@ class Job(Entity): # inherits from the Entity c
except SetWipTypeError as setWipError:
print 'WIP definition error: {0}'.format(setWipError)
#===========================================================================
# check if the entity can proceed to an operated machine, for use by Router
#===========================================================================
def canProceed(self):
activeObject=self.currentStation
return activeObject.canDeliver(self)
#===========================================================================
# check if the requireParts of the entity next step sequence (route) have
# have concluded the steps with sequence numbers smaller than the sequence
......@@ -236,7 +229,7 @@ class Job(Entity): # inherits from the Entity c
router.entitiesWithOccupiedReceivers.append(self)
availableReceiver=None
# if the sorting flag is not set then the sorting of each queue must prevail in case of operators conflict
if not router.sorting and not availableReceiver and bool(availableReceivers):
if not availableReceiver and bool(availableReceivers):
availableReceiver=self.currentStation.selectReceiver(self.candidateReceivers)
if not self in router.conflictingEntities:
router.conflictingEntities.append(self)
......
......@@ -84,7 +84,7 @@ class OperatorManagedJob(Operator):
#=======================================================================
def findCandidateEntities(self, pendingEntities=[]):
if pendingEntities:
for entity in [x for x in pendingEntities if x.canProceed and x.manager==self]:
for entity in [x for x in pendingEntities if x.currentStation.canDeliver(x) and x.manager==self]:
self.candidateEntities.append(entity)
#===========================================================================
......@@ -117,7 +117,6 @@ class OperatorManagedJob(Operator):
router=G.Router
# pick a candidateEntity
candidateEntity=self.findAvailableEntity()
if not router.sorting:
if not candidateEntity:
candidateEntity=next(x for x in self.candidateEntities)
router.conflictingEntities.append(candidateEntity)
......
......@@ -39,14 +39,12 @@ class Router(ObjectInterruption):
# The Broker is initiated within the Machine and considered as
# black box for the ManPy end Developer
# =======================================================================
def __init__(self,sorting=False):
def __init__(self):
ObjectInterruption.__init__(self)
self.type = "Router"
self.isInitialized=False
self.isActivated=False
self.candidateOperators=[]
# boolean flag to check whether the Router should perform sorting on operators and on pendingEntities
self.sorting=sorting
# list of objects to be signalled by the Router
self.toBeSignalled=[]
# flag to notify whether the router is already invoked
......
......@@ -46,12 +46,9 @@ class RouterManaged(Router):
# TODO: we should maybe define a global schedulingRule criterion that will be
# chosen in case of multiple criteria for different Operators
# =======================================================================
def __init__(self,sorting=False):
def __init__(self):
Router.__init__(self)
self.multipleCriterionList=[]
self.schedulingRule='WT'
# boolean flag to check whether the Router should perform sorting on operators and on pendingEntities
self.sorting=sorting
self.entitiesWithOccupiedReceivers=[] # list of entities that have no available receivers
#===========================================================================
......@@ -61,13 +58,6 @@ class RouterManaged(Router):
Router.initialize(self)
# list that holds all the objects that can receive
self.pendingObjects=[]
self.calledOperator=[]
# list of the operators that may handle a machine at the current simulation time
self.candidateOperators=[]
# list of criteria
self.multipleCriterionList=[]
# TODO: find out which must be the default for the scheduling Rule
self.schedulingRule='WT'
self.entitiesWithOccupiedReceivers=[]
# =======================================================================
......@@ -99,24 +89,38 @@ class RouterManaged(Router):
break
self.printTrace('','=-'*15)
# entry actions
self.entry()
# run the routine that allocates operators to machines
self.allocateOperators()
# assign operators to stations
self.assignOperators()
# unAssign exits
self.unAssignExits()
# signal the stations that ought to be signalled
self.signalOperatedStations()
self.printTrace('', 'router exiting')
self.printTrace('','=-'*20)
# exit actions
self.exit()
def entry(self):
pass
def allocateOperators(self):
# find the pending objects
self.findPendingObjects()
# find the pending entities
self.findPendingEntities()
# find the operators that can start working now
self.findCandidateOperators()
# sort the pendingEntities list
if self.sorting:
self.sortPendingEntities()
# find the operators candidateEntities
self.sortCandidateEntities()
# find the entity that will occupy the resource, and the station that will receive it (if any available)
# entities that are already in stations have already a receiver
self.findCandidateReceivers()
# assign operators to stations
self.assignOperators()
def unAssignExits(self):
for operator in [x for x in self.candidateOperators if x.isAssignedTo()]:
if not operator.isAssignedTo() in self.pendingObjects:
if operator.candidateEntity.currentStation.exitIsAssignedTo():
......@@ -126,33 +130,6 @@ class RouterManaged(Router):
for object in self.pendingQueues:
if not object in self.toBeSignalled:
object.unAssignExit()
# signal the stations that ought to be signalled
self.signalOperatedStations()
self.printTrace('', 'router exiting')
self.printTrace('','=-'*20)
self.exit()
#===========================================================================
# assigning operators to machines
#===========================================================================
def assignOperators(self):
#------------------------------------------------------------------------------
# for all the operators that are requested
for operator in self.candidateOperators:
# check if the candidateOperators are available, if the are requested and reside in the pendingObjects list
#------------------------------------------------------------------------------
if operator.checkIfResourceIsAvailable():
if operator.candidateEntity:
# and if the priorityObject is indeed pending
if (operator.candidateEntity.currentStation in self.pendingObjects)\
and (not operator in self.conflictingOperators)\
and operator.candidateEntity.candidateReceiver:
# assign an operator to the priorityObject
self.printTrace('router', 'will assign '+operator.id+' to --> '+operator.candidateEntity.candidateReceiver.id)
operator.assignTo(operator.candidateEntity.candidateReceiver)
if not operator.candidateEntity.currentStation in self.toBeSignalled:
self.toBeSignalled.append(operator.candidateEntity.currentStation)
self.printTrace('objects to be signalled:'+' '*11, [str(object.id) for object in self.toBeSignalled])
# =======================================================================
# return control to the Machine.run
......@@ -176,16 +153,34 @@ class RouterManaged(Router):
del self.pendingMachines[:]
del self.pendingQueues[:]
del self.toBeSignalled[:]
del self.multipleCriterionList[:]
del self.conflictingOperators[:]
del self.conflictingStations[:]
del self.conflictingEntities[:]
del self.occupiedReceivers[:]
del self.entitiesWithOccupiedReceivers[:]
self.schedulingRule='WT'
self.invoked=False
#===========================================================================
# assigning operators to machines
#===========================================================================
def assignOperators(self):
# for all the operators that are requested
for operator in self.candidateOperators:
# check if the candidateOperators are available, if the are requested and reside in the pendingObjects list
if operator.checkIfResourceIsAvailable():
if operator.candidateEntity:
# and if the priorityObject is indeed pending
if (operator.candidateEntity.currentStation in self.pendingObjects)\
and (not operator in self.conflictingOperators)\
and operator.candidateEntity.candidateReceiver:
# assign an operator to the priorityObject
self.printTrace('router', 'will assign '+operator.id+' to --> '+operator.candidateEntity.candidateReceiver.id)
operator.assignTo(operator.candidateEntity.candidateReceiver)
if not operator.candidateEntity.currentStation in self.toBeSignalled:
self.toBeSignalled.append(operator.candidateEntity.currentStation)
self.printTrace('objects to be signalled:'+' '*11, [str(object.id) for object in self.toBeSignalled])
#===========================================================================
# signal stations that wait for load operators
#===========================================================================
......@@ -195,7 +190,6 @@ class RouterManaged(Router):
station=operator.isAssignedTo()
if station:
# if the router deals with simple entities
if station in self.pendingMachines and station in self.toBeSignalled:
# signal this station's broker that the resource is available
self.printTrace('router','signalling broker of'+' '*50+operator.isAssignedTo().id)
......@@ -213,21 +207,11 @@ class RouterManaged(Router):
if operator.candidateEntity.currentStation.expectedSignals['loadOperatorAvailable']:
self.sendSignal(receiver=operator.candidateEntity.currentStation, signal=operator.candidateEntity.currentStation.loadOperatorAvailable)
#===========================================================================
# 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
#===========================================================================
def findPendingObjects(self):
from Globals import G
self.clearPendingObjects()
for entity in G.pendingEntities:
if entity.currentStation in G.MachineList:
if entity.currentStation.broker.waitForOperator:
......@@ -238,7 +222,6 @@ class RouterManaged(Router):
self.pendingQueues.append(entity.currentStation)
self.pendingObjects.append(entity.currentStation)
break
# self.pendingMachines=[machine for machine in G.MachineList if machine.broker.waitForOperator]
self.pendingObjects=self.pendingQueues+self.pendingMachines
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])
......@@ -282,15 +265,12 @@ class RouterManaged(Router):
# if the entity is ready to move to a machine and its manager is available
if entity.manager.checkIfResourceIsAvailable():
# check whether the entity canProceed and update the its candidateReceivers
if entity.canProceed()\
if entity.currentStation.canDeliver(entity)\
and not entity.manager in self.candidateOperators:
self.candidateOperators.append(entity.manager)
# TODO: check if preemption can be implemented for the managed case
# find the candidateEntities for each operator
self.findCandidateEntities()
# update the schedulingRule/multipleCriterionList of the Router
if self.sorting:
self.updateSchedulingRule()
self.printTrace('router found candidate operators'+' '*3,
[(operator.id, [station.id for station in operator.candidateStations]) for operator in self.candidateOperators])
......@@ -302,25 +282,6 @@ class RouterManaged(Router):
# find which pendingEntities that can move to machines is the operator managing
operator.findCandidateEntities(self.pending)
#=======================================================================
# find the schedulingRules of the candidateOperators
#=======================================================================
def updateSchedulingRule(self):
if self.candidateOperators:
for operator in self.candidateOperators:
if operator.multipleCriterionList:
for criterion in operator.multipleCriterionList:
if not criterion in self.multipleCriterionList:
self.multipleCriterionList.append(criterion)
else: # if operator has only simple scheduling Rule
if not operator.schedulingRule in self.multipleCriterionList:
self.multipleCriterionList.append(operator.schedulingRule)
# TODO: For the moment all operators should have only one scheduling rule and the same among them
# added for testing
assert len(self.multipleCriterionList)==1,'The operators must have the same (one) scheduling rule'
if len(self.multipleCriterionList)==1:
self.schedulingRule=self.multipleCriterionList[0]
#=======================================================================
# Find the candidateEntities for each candidateOperator
# find the candidateEntities of each candidateOperator and sort them according
......@@ -329,17 +290,6 @@ class RouterManaged(Router):
#=======================================================================
def sortCandidateEntities(self):
from Globals import G
# TODO: sort according to the number of pending Jobs
# 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
# and as the operators chooses the sorting of the queue (if they do reside in the same queue is not taken into account)
......@@ -347,46 +297,10 @@ class RouterManaged(Router):
for operator in [x for x in self.candidateOperators if x.candidateEntities]:
operator.sortCandidateEntities()
# if there operators that have only one option then sort the candidateOperators according to the first one of these
# TODO: find out what happens if there are many operators with one option
# TODO: incorporate that to
# self.sortOperators()
if self.sorting:
# sort the operators according to their waiting time
self.candidateOperators.sort(key=lambda x: x.totalWorkingTime)
# sort according to the number of options
if operatorsWithOneOption:
self.candidateOperators.sort(key=lambda x: x in operatorsWithOneOption, reverse=True)
self.printTrace('candidateEntities for each operator',\
[(str(operator.id),[str(x.id) for x in operator.candidateEntities])
for operator in self.candidateOperators])
#=======================================================================
# Sort pendingEntities
# TODO: sorting them according to the operators schedulingRule
#=======================================================================
def sortPendingEntities(self):
if self.candidateOperators:
from Globals import G
candidateList=self.pending
self.activeQSorter(criterion=self.schedulingRule,candList=candidateList)
self.printTrace('router', ' sorted pending entities')
#=======================================================================
# Sort candidateOperators
# TODO: consider if there must be an argument set for the schedulingRules of the Router
# TODO: consider if the scheduling rule for the operators must be global for all of them
#=======================================================================
def sortOperators(self):
# TODO: there must be criteria for sorting the cadidateOperators
#if we have sorting according to multiple criteria we have to call the sorter many times
# TODO: find out what happens in case of multiple criteria
if self.candidateOperators:
candidateList=self.candidateOperators
self.activeQSorter(criterion=self.schedulingRule,candList=candidateList)
#=======================================================================
# Find candidate entities and their receivers
# TODO: if there is a critical entity, its manager should be served first
......@@ -408,7 +322,6 @@ class RouterManaged(Router):
operator.candidateEntity.candidateReceiver=operator.candidateEntity.findCandidateReceiver()
# find the resources that are 'competing' for the same station
if not self.sorting:
# if there are entities that have conflicting receivers
if len(self.conflictingEntities):
# find the conflictingOperators
......@@ -439,151 +352,3 @@ class RouterManaged(Router):
str(entity.candidateReceiver.id))
for entity in self.pending if entity.candidateReceiver])
\ No newline at end of file
# =======================================================================
# sorts the Operators of the Queue according to the scheduling rule
# =======================================================================
def activeQSorter(self, criterion=None, candList=[]):
activeObjectQ=candList
if not activeObjectQ:
assert False, "empty candidateOperators list"
if criterion==None:
criterion=self.multipleCriterionList[0]
#if the schedulingRule is first in first out
if criterion=="FIFO":
# FIFO sorting has no meaning when sorting candidateEntities
self.activeQSorter(criterion='WT',candList=activeObjectQ)
#if the schedulingRule is based on a pre-defined priority
elif criterion=="Priority":
# if the activeObjectQ is a list of entities then perform the default sorting
try:
activeObjectQ.sort(key=lambda x: x.priority)
# if the activeObjectQ is a list of operators then sort them according to their candidateEntities
except:
activeObjectQ.sort(key=lambda x: x.candidateEntity.priority)
#if the scheduling rule is time waiting (time waiting of machine
# TODO: consider that the timeLastEntityEnded is not a
# indicative identifier of how long the station was waiting
elif criterion=='WT':
try:
activeObjectQ.sort(key=lambda x: x.schedule[-1][1])
except:
activeObjectQ.sort(key=lambda x: x.candidateEntity.schedule[-1][1])
#if the schedulingRule is earliest due date
elif criterion=="EDD":
try:
activeObjectQ.sort(key=lambda x: x.dueDate)
except:
activeObjectQ.sort(key=lambda x: x.candidateEntity.dueDate)
#if the schedulingRule is earliest order date
elif criterion=="EOD":
try:
activeObjectQ.sort(key=lambda x: x.orderDate)
except:
activeObjectQ.sort(key=lambda x: x.candidateEntity.orderDate)
#if the schedulingRule is to sort Entities according to the stations they have to visit
elif criterion=="NumStages":
try:
activeObjectQ.sort(key=lambda x: len(x.remainingRoute), reverse=True)
except:
activeObjectQ.sort(key=lambda x: len(x.candidateEntity.remainingRoute), reverse=True)
#if the schedulingRule is to sort Entities according to the their remaining processing time in the system
elif criterion=="RPC":
try:
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)
except:
for entity in [operator.candidateEntity for operator 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.candidateEntity.remainingProcessingTime, reverse=True)
#if the schedulingRule is to sort Entities according to longest processing time first in the next station
elif criterion=="LPT":
try:
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)
except:
for entity in [operator.candidateEntity for operator 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.candidateEntity.processingTimeInNextStation, reverse=True)
#if the schedulingRule is to sort Entities according to shortest processing time first in the next station
elif criterion=="SPT":
try:
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)
except:
for entity in [operator.candidateEntity for operator 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.candidateEntity.processingTimeInNextStation)
#if the schedulingRule is to sort Entities based on the minimum slackness
elif criterion=="MS":
try:
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))
except:
for entity in [operator.candidateEntity for operator 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.candidateEntity.dueDate-x.candidateEntity.remainingProcessingTime))
#if the schedulingRule is to sort Entities based on the length of the following Queue
elif criterion=="WINQ":
try:
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)
except:
from Globals import G
for entity in [operator.candidateEntity for operator 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.candidateEntity.nextQueueLength)
else:
assert False, "Unknown scheduling criterion %r" % (criterion, )
\ No newline at end of file
......@@ -58,7 +58,6 @@ class SkilledRouter(Router):
self.waitEndProcess=False
self.pendingQueues=[]
self.pendingMachines=[]
self.pendingObjects=[]
self.previousSolution={}
# =======================================================================
......@@ -268,32 +267,14 @@ class SkilledRouter(Router):
# default behaviour
#===================================================================
else:
# find the pending objects
self.findPendingObjects()
# find the pending entities
self.findPendingEntities()
# find the operators that can start working now
self.findCandidateOperators()
# sort the pendingEntities list
if self.sorting:
self.sortPendingEntities()
# find the operators candidateEntities
self.sortCandidateEntities()
# find the entity that will occupy the resource, and the station that will receive it (if any available)
# entities that are already in stations have already a receiver
self.findCandidateReceivers()
# entry actions
self.entry()
# run the routine that allocates operators to machines
self.allocateOperators()
# assign operators to stations
self.assignOperators()
for operator in [x for x in self.candidateOperators if x.isAssignedTo()]:
if not operator.isAssignedTo() in self.pendingObjects:
for object in [x for x in operator.isAssignedTo().previous if x.exitIsAssignedTo()]:
if object.exitIsAssignedTo()!=operator.isAssignedTo():
object.unAssignExit()
# if an object cannot proceed with getEntity, unAssign the exit of its giver
for object in self.pendingQueues:
if not object in self.toBeSignalled:
object.unAssignExit()
# unAssign exits
self.unAssignExits()
# signal the stations that ought to be signalled
self.signalOperatedStations()
......
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