def run(self): while 1: # wait until the router is called self.expectedSignals['isCalled']=1 yield self.isCalled transmitter, eventTime=self.isCalled.value self.isCalled=self.env.event() self.printTrace('','=-'*15) self.printTrace('','router received event') # wait till there are no more events, the machines must be blocked while 1: if self.env.now==self.env.peek(): self.printTrace('', 'there are MORE events for now') yield self.env.timeout(0) else: self.printTrace('','there are NO more events for now') break self.printTrace('','=-'*15) from Globals import G if self.allocation: #=================================================================== # # XXX wait for the interval time to finish (10 minutes between reassignments #=================================================================== '''not implemented yet''' #=================================================================== # # find stations that are in position to process #=================================================================== self.availableStations=[] for station in G.MachineList: if station.checkIfActive(): self.availableStations.append(station) #=================================================================== # # XXX if the resources are still assigned then un-assign them from the machines they are currently assigned # # the same for all the objects exits #=================================================================== for operator in [x for x in G.OperatorsList if x.isAssignedTo()]: operator.unAssign() for object in [x for x in G.ObjList if x.exitIsAssignedTo()]: object.unAssignExit() #=================================================================== # # XXX un-assign all the PBs from their operatorPools #=================================================================== for station in G.MachineList: station.operatorPool.operators=[] #=================================================================== # # XXX calculate the WIP of each station #=================================================================== for station in self.availableStations: station.wip=1+(len(station.getActiveObjectQueue())/station.capacity) for predecessor in station.previous: try: station.wip+=float(len(predecessor.getActiveObjectQueue())/float(predecessor.capacity)) except: # XXX what happens in the case of sources or infinite-capacity-queues pass #=================================================================== # # stations of the line and their corresponding WIP # TODO: the WIP of the stations must be normalised to the max WIP possible on that station #=================================================================== self.availableStationsDict={} for station in self.availableStations: self.availableStationsDict[str(station.id)]={'stationID':str(station.id),'WIP':station.wip, 'lastAssignment':self.env.now} #=================================================================== # # operators and their skills set #=================================================================== self.operators={} for operator in G.OperatorsList: self.operators[str(operator.id)]=operator.skillsList #=================================================================== # # available operators #=================================================================== self.availableOperatorList=[] for operator in G.OperatorsList: if operator.available and operator.onShift: self.availableOperatorList.append(operator.id) #=================================================================== # # XXX run the LP assignment algorithm # # should return a list of correspondences # # XXX signal the stations that the assignment is complete # TODO: a constant integer must be added to all WIP before provided to the opAss_LP # as it doesn't support zero WIP levels #=================================================================== solution=opAss_LP(self.availableStationsDict, self.availableOperatorList, self.operators, previousAssignment=self.previousSolution) # print '-------' # print self.env.now, solution if self.outputSolutions: self.solutionList.append({ "time":self.env.now, "allocation":solution }) # XXX assign the operators to operatorPools # pendingStations/ available stations not yet given operator self.pendingStations=[] from Globals import findObjectById # apply the solution # loop through the entries in the solution dictionary for operatorID in solution.keys(): # obtain the operator and the station operator=findObjectById(operatorID) station=findObjectById(solution[operatorID]) if operatorID in self.previousSolution: # if the solution returned the operator that is already in the station # then no signal is needed if not self.previousSolution[operatorID] == solution[operatorID]: self.toBeSignalled.append(station) else: self.toBeSignalled.append(station) # update the operatorPool of the station station.operatorPool.operators=[operator] # assign the operator to the station operator.assignTo(station) # set that the operator is dedicated to the station operator.operatorDedicatedTo=station # set in every station the operator that it is to get station.operatorToGet=operator # remove the operator id from availableOperatorList self.availableOperatorList.remove(operatorID) #=================================================================== # # XXX signal the stations that the assignment is complete #=================================================================== # if the operator is free the station can be signalled right away stationsProcessingLast=[] toBeSignalled=list(self.toBeSignalled) for station in toBeSignalled: # check if the operator that the station waits for is free operator=station.operatorToGet if operator.workingStation: if operator.workingStation.isProcessing: stationsProcessingLast.append(operator.workingStation) continue # signal the station so that it gets the operator self.signalStation(station, operator) # else wait for signals that operator became available and signal the stations self.expectedFinishSignalsDict={} self.expectedFinishSignals=[] for station in stationsProcessingLast: signal=self.env.event() self.expectedFinishSignalsDict[station.id]=signal self.expectedFinishSignals.append(signal) while self.expectedFinishSignals: receivedEvent = yield self.env.any_of(self.expectedFinishSignals) for signal in self.expectedFinishSignals: if signal in receivedEvent: transmitter, eventTime=signal.value assert eventTime==self.env.now, 'the station finished signal must be received on the time of request' self.expectedFinishSignals.remove(signal) del self.expectedFinishSignalsDict[transmitter.id] for id in solution.keys(): operator=findObjectById(id) station=findObjectById(solution[id]) if station in self.toBeSignalled: # signal the station so that it gets the operator self.signalStation(station, operator) #=================================================================== # default behaviour #=================================================================== else: # entry actions self.entryActions() # 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.previousSolution=solution self.printTrace('', 'router exiting') self.printTrace('','=-'*20) self.exitActions()
def run(self): while 1: # wait until the router is called self.expectedSignals['isCalled']=1 yield self.isCalled transmitter, eventTime=self.isCalled.value self.isCalled=self.env.event() self.printTrace('','=-'*15) self.printTrace('','router received event') # wait till there are no more events, the machines must be blocked while 1: if self.env.now==self.env.peek(): self.printTrace('', 'there are MORE events for now') yield self.env.timeout(0) else: self.printTrace('','there are NO more events for now') break self.printTrace('','=-'*15) from Globals import G if self.allocation: #=================================================================== # # XXX wait for the interval time to finish (10 minutes between reassignments #=================================================================== '''not implemented yet''' #=================================================================== # # find stations that are in position to process #=================================================================== self.availableStations=[] for station in G.MachineList: if station.checkIfActive(): self.availableStations.append(station) #=================================================================== # # XXX if the resources are still assigned then un-assign them from the machines they are currently assigned # # the same for all the objects exits #=================================================================== for operator in [x for x in G.OperatorsList if x.isAssignedTo()]: operator.unAssign() for object in [x for x in G.ObjList if x.exitIsAssignedTo()]: object.unAssignExit() #=================================================================== # # XXX un-assign all the PBs from their operatorPools #=================================================================== for station in G.MachineList: station.operatorPool.operators=[] #=================================================================== # # XXX calculate the WIP of each station #=================================================================== for station in self.availableStations: station.wip=1+(len(station.getActiveObjectQueue())/station.capacity) for predecessor in station.previous: try: station.wip+=float(len(predecessor.getActiveObjectQueue())/float(predecessor.capacity)) except: # XXX what happens in the case of sources or infinite-capacity-queues pass #=================================================================== # # stations of the line and their corresponding WIP # TODO: the WIP of the stations must be normalised to the max WIP possible on that station #=================================================================== # identify the last time that there was an assignment maxLastAssignment=0 for record in self.solutionList: if record: maxLastAssignment=record["time"] self.availableStationsDict={} for station in self.availableStations: lastAssignmentTime=0 for record in self.solutionList: if station.id in record["allocation"].values(): lastAssignmentTime=record["time"] # normalise the lastAssignmentTime based on the maxLastAssignment. if maxLastAssignment: lastAssignmentTime=1.0-float(lastAssignmentTime/float(maxLastAssignment)) # it there is definition of 'technology' to group machines add this if station.technology: self.availableStationsDict[str(station.id)]={'stationID':station.technology,'machineID':station.id, 'WIP':station.wip,'lastAssignment':lastAssignmentTime} # otherwise add just the id else: self.availableStationsDict[str(station.id)]={'stationID':station.id, 'WIP':station.wip,'lastAssignment':lastAssignmentTime} #=================================================================== # # operators and their skills set #=================================================================== self.operators={} import Globals for operator in G.OperatorsList: newSkillsList=[] for skill in operator.skillsList: newSkill=skill mach=Globals.findObjectById(skill) # if there is 'technology' defined for the stations send this to the LP solver if mach.technology: newSkill=mach.technology if newSkill not in newSkillsList: newSkillsList.append(newSkill) self.operators[str(operator.id)]=newSkillsList #=================================================================== # # available operators #=================================================================== self.availableOperatorList=[] for operator in G.OperatorsList: if operator.available and operator.onShift and not operator.onBreak: self.availableOperatorList.append(operator.id) LPFlag=True if self.checkCondition: LPFlag=self.checkIfAllocationShouldBeCalled() #=================================================================== # # XXX run the LP assignment algorithm # # should return a list of correspondences # # XXX signal the stations that the assignment is complete # TODO: a constant integer must be added to all WIP before provided to the opAss_LP # as it doesn't support zero WIP levels #=================================================================== import time startLP=time.time() if LPFlag: if self.twoPhaseSearch: # remove all the blocked machines from the available stations # and create another dict only with them machinesForSecondPhaseDict={} for stationId in self.availableStationsDict.keys(): machine = Globals.findObjectById(stationId) if machine.isBlocked: machinesForSecondPhaseDict[stationId] = self.availableStationsDict[stationId] del self.availableStationsDict[stationId] # run the LP method only for the machines that are not blocked solution=opAss_LP(self.availableStationsDict, self.availableOperatorList, self.operators, previousAssignment=self.previousSolution, weightFactors=self.weightFactors,Tool=self.tool) # create a list with the operators that were sent to the LP but did not get allocated operatorsForSecondPhaseList=[] for operatorId in self.availableOperatorList: if operatorId not in solution.keys(): operatorsForSecondPhaseList.append(operatorId) # in case there is some station that did not get operator even if it was not blocked # add them alos for the second fail (XXX do not think there is such case) for stationId in self.availableStationsDict.keys(): if stationId not in solution.values(): machinesForSecondPhaseDict[stationId] = self.availableStationsDict[stationId] # if there are machines and operators for the second phase # run again the LP for machines and operators that are not in the former solution if machinesForSecondPhaseDict and operatorsForSecondPhaseList: secondPhaseSolution=opAss_LP(machinesForSecondPhaseDict, operatorsForSecondPhaseList, self.operators, previousAssignment=self.previousSolution, weightFactors=self.weightFactors,Tool=self.tool) # update the solution with the new LP results solution.update(secondPhaseSolution) else: solution=opAss_LP(self.availableStationsDict, self.availableOperatorList, self.operators, previousAssignment=self.previousSolution, weightFactors=self.weightFactors,Tool=self.tool) else: # if the LP is not called keep the previous solution # if there are no available operators though, remove those solution=self.previousSolution for operatorID in solution.keys(): if not operatorID in self.availableOperatorList: del solution[operatorID] # print '-------' # print self.env.now, solution # print 'time needed',time.time()-startLP self.solutionList.append({ "time":self.env.now, "allocation":solution }) # XXX assign the operators to operatorPools # pendingStations/ available stations not yet given operator self.pendingStations=[] from Globals import findObjectById # apply the solution # loop through the stations. If there is a station that should change operator # set the operator dedicated to None and also release operator for station in G.MachineList: # obtain the operator and the station if station.currentOperator: operator=station.currentOperator previousAssignment=self.previousSolution.get(operator.id,None) currentAssignment=solution.get(operator.id,None) if (not previousAssignment == currentAssignment): operator.operatorDedicatedTo=None if not station.isProcessing: station.releaseOperator() # loop through the entries in the solution dictionary for operatorID in solution.keys(): # obtain the operator and the station operator=findObjectById(operatorID) station=findObjectById(solution[operatorID]) if operatorID in self.previousSolution: # if the solution returned the operator that is already in the station # then no signal is needed if not self.previousSolution[operatorID] == solution[operatorID]: self.toBeSignalled.append(station) else: self.toBeSignalled.append(station) # update the operatorPool of the station station.operatorPool.operators=[operator] # assign the operator to the station operator.assignTo(station) # set that the operator is dedicated to the station operator.operatorDedicatedTo=station # set in every station the operator that it is to get station.operatorToGet=operator # remove the operator id from availableOperatorList self.availableOperatorList.remove(operatorID) #=================================================================== # # XXX signal the stations that the assignment is complete #=================================================================== # if the operator is free the station can be signalled right away stationsProcessingLast=[] toBeSignalled=list(self.toBeSignalled) for station in toBeSignalled: # check if the operator that the station waits for is free operator=station.operatorToGet if operator.workingStation: # if the operator is in a station that is processing or just starts processing then he/she is not free if operator.workingStation.isProcessing or (not (operator.workingStation.timeLastEntityEntered==self.env.now)): stationsProcessingLast.append(operator.workingStation) continue # signal the station so that it gets the operator self.signalStation(station, operator) # else wait for signals that operator became available and signal the stations self.expectedFinishSignalsDict={} self.expectedFinishSignals=[] for station in stationsProcessingLast: signal=self.env.event() self.expectedFinishSignalsDict[station.id]=signal self.expectedFinishSignals.append(signal) while self.expectedFinishSignals: receivedEvent = yield self.env.any_of(self.expectedFinishSignals) for signal in self.expectedFinishSignals: if signal in receivedEvent: transmitter, eventTime=signal.value assert eventTime==self.env.now, 'the station finished signal must be received on the time of request' self.expectedFinishSignals.remove(signal) del self.expectedFinishSignalsDict[transmitter.id] # signal also the other stations that should be signalled for id in solution.keys(): operator=findObjectById(id) station=findObjectById(solution[id]) signal=True # signal only the stations in the original list if station not in self.toBeSignalled: signal=False # signal only if the operator is free if operator.workingStation: if operator.workingStation.isProcessing\ or (not (operator.workingStation.timeLastEntityEntered==self.env.now)): signal=False if signal: # signal the station so that it gets the operator self.signalStation(station, operator) #=================================================================== # default behaviour #=================================================================== else: # entry actions self.entryActions() # 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.previousSolution=solution self.printTrace('', 'router exiting') self.printTrace('','=-'*20) self.exitActions()
def run(self): while 1: # wait until the router is called self.expectedSignals['isCalled']=1 yield self.isCalled transmitter, eventTime=self.isCalled.value self.isCalled=self.env.event() self.printTrace('','=-'*15) self.printTrace('','router received event') # wait till there are no more events, the machines must be blocked while 1: if self.env.now==self.env.peek(): self.printTrace('', 'there are MORE events for now') yield self.env.timeout(0) else: self.printTrace('','there are NO more events for now') break self.printTrace('','=-'*15) from Globals import G if self.allocation: #=================================================================== # # XXX wait for the interval time to finish (10 minutes between reassignments #=================================================================== '''not implemented yet''' #=================================================================== # # find stations that are in position to process #=================================================================== self.availableStations=[] for station in G.MachineList: if station.checkIfActive(): self.availableStations.append(station) #=================================================================== # # XXX if the resources are still assigned then un-assign them from the machines they are currently assigned # # the same for all the objects exits #=================================================================== for operator in [x for x in G.OperatorsList if x.isAssignedTo()]: operator.unAssign() for object in [x for x in G.ObjList if x.exitIsAssignedTo()]: object.unAssignExit() #=================================================================== # # XXX un-assign all the PBs from their operatorPools #=================================================================== for station in G.MachineList: station.operatorPool.operators=[] #=================================================================== # # XXX calculate the WIP of each station #=================================================================== for station in self.availableStations: station.wip=1+(len(station.getActiveObjectQueue())/station.capacity) for predecessor in station.previous: try: station.wip+=float(len(predecessor.getActiveObjectQueue())/float(predecessor.capacity)) except: # XXX what happens in the case of sources or infinite-capacity-queues pass #=================================================================== # # stations of the line and their corresponding WIP # TODO: the WIP of the stations must be normalised to the max WIP possible on that station #=================================================================== # identify the last time that there was an assignment maxLastAssignment=0 for record in self.solutionList: if record: maxLastAssignment=record["time"] self.availableStationsDict={} for station in self.availableStations: lastAssignmentTime=0 for record in self.solutionList: if station.id in record["allocation"].values(): lastAssignmentTime=record["time"] # normalise the lastAssignmentTime based on the maxLastAssignment. if maxLastAssignment: lastAssignmentTime=1.0-float(lastAssignmentTime/float(maxLastAssignment)) # it there is definition of 'technology' to group machines add this if station.technology: self.availableStationsDict[str(station.id)]={'stationID':station.technology,'machineID':station.id, 'WIP':station.wip,'lastAssignment':lastAssignmentTime} # otherwise add just the id else: self.availableStationsDict[str(station.id)]={'stationID':station.id, 'WIP':station.wip,'lastAssignment':lastAssignmentTime} #=================================================================== # # operators and their skills set #=================================================================== self.operators={} import Globals for operator in G.OperatorsList: newSkillsList=[] for skill in operator.skillsList: newSkill=skill mach=Globals.findObjectById(skill) # if there is 'technology' defined for the stations send this to the LP solver if mach.technology: newSkill=mach.technology if newSkill not in newSkillsList: newSkillsList.append(newSkill) self.operators[str(operator.id)]=newSkillsList #=================================================================== # # available operators #=================================================================== self.availableOperatorList=[] for operator in G.OperatorsList: if operator.available and operator.onShift and not operator.onBreak: self.availableOperatorList.append(operator.id) LPFlag=True if self.checkCondition: LPFlag=self.checkIfAllocationShouldBeCalled() #=================================================================== # # XXX run the LP assignment algorithm # # should return a list of correspondences # # XXX signal the stations that the assignment is complete # TODO: a constant integer must be added to all WIP before provided to the opAss_LP # as it doesn't support zero WIP levels #=================================================================== import time startLP=time.time() if LPFlag: if self.twoPhaseSearch: # remove all the blocked machines from the available stations # and create another dict only with them machinesForSecondPhaseDict={} for stationId in self.availableStationsDict.keys(): machine = Globals.findObjectById(stationId) nextObject = machine.next[0] nextObjectClassName = nextObject.__class__.__name__ reassemblyBlocksMachine = False if 'Reassembly' in nextObjectClassName: if nextObject.getActiveObjectQueue(): if nextObject.getActiveObjectQueue()[0].type == 'Batch': reassemblyBlocksMachine = True if machine.isBlocked or reassemblyBlocksMachine: if not len(machine.getActiveObjectQueue()) and (not reassemblyBlocksMachine): raise ValueError('empty machine considered as blocked') if machine.timeLastEntityEnded < machine.timeLastEntityEntered: raise ValueError('machine considered as blocked, while it has Entity that has not finished') if "Queue" in nextObjectClassName: if len(nextObject.getActiveObjectQueue()) != nextObject.capacity: raise ValueError('Machine considered as blocked while Queue has space') if "Clearance" in nextObjectClassName: if not nextObject.getActiveObjectQueue(): raise ValueError('Machine considered as blocked while Clearance is empty') else: subBatchMachineHolds = machine.getActiveObjectQueue()[0] subBatchLineClearanceHolds = nextObject.getActiveObjectQueue()[0] if subBatchMachineHolds.parentBatch == subBatchLineClearanceHolds.parentBatch and\ (len(nextObject.getActiveObjectQueue()) != nextObject.capacity): raise ValueError('Machine considered as blocked while Line Clearance holds same batch and has space') machinesForSecondPhaseDict[stationId] = self.availableStationsDict[stationId] del self.availableStationsDict[stationId] else: if len(machine.getActiveObjectQueue()) and (not machine.isProcessing) and\ machine.onShift and machine.currentOperator: raise ValueError('machine should be considered blocked') # run the LP method only for the machines that are not blocked solution=opAss_LP(self.availableStationsDict, self.availableOperatorList, self.operators, previousAssignment=self.previousSolution, weightFactors=self.weightFactors,Tool=self.tool) # create a list with the operators that were sent to the LP but did not get allocated operatorsForSecondPhaseList=[] for operatorId in self.availableOperatorList: if operatorId not in solution.keys(): operatorsForSecondPhaseList.append(operatorId) # in case there is some station that did not get operator even if it was not blocked # add them alos for the second fail (XXX do not think there is such case) for stationId in self.availableStationsDict.keys(): if stationId not in solution.values(): machinesForSecondPhaseDict[stationId] = self.availableStationsDict[stationId] # if there are machines and operators for the second phase # run again the LP for machines and operators that are not in the former solution if machinesForSecondPhaseDict and operatorsForSecondPhaseList: secondPhaseSolution=opAss_LP(machinesForSecondPhaseDict, operatorsForSecondPhaseList, self.operators, previousAssignment=self.previousSolution, weightFactors=self.weightFactors,Tool=self.tool) # update the solution with the new LP results solution.update(secondPhaseSolution) else: solution=opAss_LP(self.availableStationsDict, self.availableOperatorList, self.operators, previousAssignment=self.previousSolution, weightFactors=self.weightFactors,Tool=self.tool) else: # if the LP is not called keep the previous solution # if there are no available operators though, remove those solution=self.previousSolution for operatorID in solution.keys(): if not operatorID in self.availableOperatorList: del solution[operatorID] # print '-------' # print self.env.now, solution # print 'time needed',time.time()-startLP self.solutionList.append({ "time":self.env.now, "allocation":solution }) # XXX assign the operators to operatorPools # pendingStations/ available stations not yet given operator self.pendingStations=[] from Globals import findObjectById # apply the solution # loop through the stations. If there is a station that should change operator # set the operator dedicated to None and also release operator for station in G.MachineList: # obtain the operator and the station if station.currentOperator: operator=station.currentOperator previousAssignment=self.previousSolution.get(operator.id,None) currentAssignment=solution.get(operator.id,None) if (not previousAssignment == currentAssignment): operator.operatorDedicatedTo=None if not station.isProcessing: station.releaseOperator() # loop through the entries in the solution dictionary for operatorID in solution.keys(): # obtain the operator and the station operator=findObjectById(operatorID) station=findObjectById(solution[operatorID]) if operatorID in self.previousSolution: # if the solution returned the operator that is already in the station # then no signal is needed if not self.previousSolution[operatorID] == solution[operatorID]: self.toBeSignalled.append(station) else: self.toBeSignalled.append(station) # update the operatorPool of the station station.operatorPool.operators=[operator] # assign the operator to the station operator.assignTo(station) # set that the operator is dedicated to the station operator.operatorDedicatedTo=station # set in every station the operator that it is to get station.operatorToGet=operator # remove the operator id from availableOperatorList self.availableOperatorList.remove(operatorID) #=================================================================== # # XXX signal the stations that the assignment is complete #=================================================================== # if the operator is free the station can be signalled right away stationsProcessingLast=[] toBeSignalled=list(self.toBeSignalled) for station in toBeSignalled: # check if the operator that the station waits for is free operator=station.operatorToGet if operator.workingStation: # if the operator is in a station that is processing or just starts processing then he/she is not free if operator.workingStation.isProcessing or (not (operator.workingStation.timeLastEntityEntered==self.env.now)): stationsProcessingLast.append(operator.workingStation) continue # signal the station so that it gets the operator self.signalStation(station, operator) # else wait for signals that operator became available and signal the stations self.expectedFinishSignalsDict={} self.expectedFinishSignals=[] for station in stationsProcessingLast: signal=self.env.event() self.expectedFinishSignalsDict[station.id]=signal self.expectedFinishSignals.append(signal) while self.expectedFinishSignals: receivedEvent = yield self.env.any_of(self.expectedFinishSignals) for signal in self.expectedFinishSignals: if signal in receivedEvent: transmitter, eventTime=signal.value assert eventTime==self.env.now, 'the station finished signal must be received on the time of request' self.expectedFinishSignals.remove(signal) del self.expectedFinishSignalsDict[transmitter.id] # signal also the other stations that should be signalled for id in solution.keys(): operator=findObjectById(id) station=findObjectById(solution[id]) signal=True # signal only the stations in the original list if station not in self.toBeSignalled: signal=False # signal only if the operator is free if operator.workingStation: if operator.workingStation.isProcessing\ or (not (operator.workingStation.timeLastEntityEntered==self.env.now)): signal=False if signal: # signal the station so that it gets the operator self.signalStation(station, operator) #=================================================================== # default behaviour #=================================================================== else: # entry actions self.entryActions() # 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.previousSolution=solution self.printTrace('', 'router exiting') self.printTrace('','=-'*20) self.exitActions()
def run(self): while 1: # wait until the router is called self.expectedSignals['isCalled'] = 1 yield self.isCalled transmitter, eventTime = self.isCalled.value self.isCalled = self.env.event() self.printTrace('', '=-' * 15) self.printTrace('', 'router received event') # wait till there are no more events, the machines must be blocked while 1: if self.env.now == self.env.peek(): self.printTrace('', 'there are MORE events for now') yield self.env.timeout(0) else: self.printTrace('', 'there are NO more events for now') break self.printTrace('', '=-' * 15) from Globals import G if self.allocation: #=================================================================== # # XXX wait for the interval time to finish (10 minutes between reassignments #=================================================================== '''not implemented yet''' #=================================================================== # # find stations that are in position to process #=================================================================== self.availableStations = [] for station in G.MachineList: if station.checkIfActive(): self.availableStations.append(station) #=================================================================== # # XXX if the resources are still assigned then un-assign them from the machines they are currently assigned # # the same for all the objects exits #=================================================================== for operator in [ x for x in G.OperatorsList if x.isAssignedTo() ]: operator.unAssign() for object in [x for x in G.ObjList if x.exitIsAssignedTo()]: object.unAssignExit() #=================================================================== # # XXX un-assign all the PBs from their operatorPools #=================================================================== for station in G.MachineList: station.operatorPool.operators = [] #=================================================================== # # XXX calculate the WIP of each station #=================================================================== for station in self.availableStations: station.wip = 1 + (len(station.getActiveObjectQueue()) / station.capacity) for predecessor in station.previous: try: station.wip += float( len(predecessor.getActiveObjectQueue()) / float(predecessor.capacity)) except: # XXX what happens in the case of sources or infinite-capacity-queues pass #=================================================================== # # stations of the line and their corresponding WIP # TODO: the WIP of the stations must be normalised to the max WIP possible on that station #=================================================================== self.availableStationsDict = {} for station in self.availableStations: lastAssignmentTime = 0 for record in self.solutionList: if station.id in record["allocation"].values(): lastAssignmentTime = record["time"] # it there is definition of 'technology' to group machines add this if station.technology: self.availableStationsDict[str(station.id)] = { 'stationID': station.technology, 'machineID': station.id, 'WIP': station.wip, 'lastAssignment': 0 } # otherwise add just the id else: self.availableStationsDict[str(station.id)] = { 'stationID': station.id, 'WIP': station.wip, 'lastAssignment': 0 } #=================================================================== # # operators and their skills set #=================================================================== self.operators = {} import Globals for operator in G.OperatorsList: newSkillsList = [] for skill in operator.skillsList: newSkill = skill mach = Globals.findObjectById(skill) # if there is 'technology' defined for the stations send this to the LP solver if mach.technology: newSkill = mach.technology if newSkill not in newSkillsList: newSkillsList.append(newSkill) self.operators[str(operator.id)] = newSkillsList #=================================================================== # # available operators #=================================================================== self.availableOperatorList = [] for operator in G.OperatorsList: if operator.available and operator.onShift: self.availableOperatorList.append(operator.id) LPFlag = True if self.checkCondition: LPFlag = self.checkIfAllocationShouldBeCalled() # in case there are not available stations or operators there is no need to call the LP if (not self.availableStationsDict) or ( not self.availableOperatorList): LPFlag = False #=================================================================== # # XXX run the LP assignment algorithm # # should return a list of correspondences # # XXX signal the stations that the assignment is complete # TODO: a constant integer must be added to all WIP before provided to the opAss_LP # as it doesn't support zero WIP levels #=================================================================== import time startLP = time.time() if LPFlag: # print self.env.now, 'LP called' solution = opAss_LP( self.availableStationsDict, self.availableOperatorList, self.operators, previousAssignment=self.previousSolution, weightFactors=self.weightFactors, Tool=self.tool) else: # print self.env.now, 'no need to call LP' solution = {} # print '-------' # print self.env.now, solution # print 'time needed',time.time()-startLP self.solutionList.append({ "time": self.env.now, "allocation": solution }) # XXX assign the operators to operatorPools # pendingStations/ available stations not yet given operator self.pendingStations = [] from Globals import findObjectById # apply the solution # loop through the stations. If there is a station that should change operator # set the operator dedicated to None and also release operator for station in G.MachineList: # obtain the operator and the station if station.currentOperator: operator = station.currentOperator previousAssignment = self.previousSolution.get( operator.id, None) currentAssignment = solution.get(operator.id, None) if (not previousAssignment == currentAssignment): operator.operatorDedicatedTo = None if not station.isProcessing: station.releaseOperator() # loop through the entries in the solution dictionary for operatorID in solution.keys(): # obtain the operator and the station operator = findObjectById(operatorID) station = findObjectById(solution[operatorID]) if operatorID in self.previousSolution: # if the solution returned the operator that is already in the station # then no signal is needed if not self.previousSolution[operatorID] == solution[ operatorID]: self.toBeSignalled.append(station) else: self.toBeSignalled.append(station) # update the operatorPool of the station station.operatorPool.operators = [operator] # assign the operator to the station operator.assignTo(station) # set that the operator is dedicated to the station operator.operatorDedicatedTo = station # set in every station the operator that it is to get station.operatorToGet = operator # remove the operator id from availableOperatorList self.availableOperatorList.remove(operatorID) #=================================================================== # # XXX signal the stations that the assignment is complete #=================================================================== # if the operator is free the station can be signalled right away stationsProcessingLast = [] toBeSignalled = list(self.toBeSignalled) for station in toBeSignalled: # check if the operator that the station waits for is free operator = station.operatorToGet if operator.workingStation: if operator.workingStation.isProcessing: stationsProcessingLast.append( operator.workingStation) continue # signal the station so that it gets the operator self.signalStation(station, operator) # else wait for signals that operator became available and signal the stations self.expectedFinishSignalsDict = {} self.expectedFinishSignals = [] for station in stationsProcessingLast: signal = self.env.event() self.expectedFinishSignalsDict[station.id] = signal self.expectedFinishSignals.append(signal) while self.expectedFinishSignals: receivedEvent = yield self.env.any_of( self.expectedFinishSignals) for signal in self.expectedFinishSignals: if signal in receivedEvent: transmitter, eventTime = signal.value assert eventTime == self.env.now, 'the station finished signal must be received on the time of request' self.expectedFinishSignals.remove(signal) del self.expectedFinishSignalsDict[transmitter.id] for id in solution.keys(): operator = findObjectById(id) station = findObjectById(solution[id]) if station in self.toBeSignalled: # signal the station so that it gets the operator self.signalStation(station, operator) #=================================================================== # default behaviour #=================================================================== else: # entry actions self.entryActions() # 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.previousSolution = solution self.printTrace('', 'router exiting') self.printTrace('', '=-' * 20) self.exitActions()
def run(self): while 1: # wait until the router is called yield self.isCalled self.isCalled=self.env.event() self.printTrace('','=-'*15) self.printTrace('','router received event') # wait till there are no more events, the machines must be blocked while 1: if self.env.now==self.env.peek(): self.printTrace('', 'there are MORE events for now') yield self.env.timeout(0) else: self.printTrace('','there are NO more events for now') break self.printTrace('','=-'*15) from Globals import G if self.allocation: #=================================================================== # # XXX wait for the interval time to finish (10 minutes between reassignments #=================================================================== '''not implemented yet''' #=================================================================== # # find stations that are in position to process #=================================================================== self.availableStations=[] for station in G.MachineList: if station.checkIfActive(): self.availableStations.append(station) if self.waitEndProcess: #=================================================================== # # XXX wait till all the stations have finished their current WIP # # XXX find all the machines that are currently busy #=================================================================== self.busyStations=[] for station in self.availableStations: if station.getActiveObjectQueue() and not station.waitToDispose: self.busyStations.append(station) #=================================================================== # # XXX create a list of all the events (endLastProcessing) #=================================================================== self.endProcessingSignals=[] for station in self.busyStations: self.endProcessingSignals.append(station.endedLastProcessing) station.isWorkingOnTheLast=True # FIX this will fail as the first machine sends the signal (router.waitingSingnal-> False) self.waitingSignal=True #=================================================================== # # XXX wait till all the stations have finished their current WIP #=================================================================== # TODO: fix that, add flags, reset the signals receivedEvent=yield self.env.all_of(self.endProcessingSignals) for station in self.busyStations: if station.endedLastProcessing in receivedEvent: station.endedLastProcessing=self.env.event() #=================================================================== # # XXX if the resources are still assigned then un-assign them from the machines they are currently assigned # # the same for all the objects exits #=================================================================== for operator in [x for x in G.OperatorsList if x.isAssignedTo()]: operator.unAssign() for object in [x for x in G.ObjList if x.exitIsAssignedTo()]: object.unAssignExit() #=================================================================== # # XXX un-assign all the PBs from their operatorPools #=================================================================== for station in G.MachineList: station.operatorPool.operators=[] #=================================================================== # # XXX calculate the WIP of each station #=================================================================== for station in self.availableStations: # station.wip=0 station.wip=1+(len(station.getActiveObjectQueue())/station.capacity) for predecessor in station.previous: # predecessor.remainingWip=0 # if len(predecessor.next)>1: # nextNo=len(predecessor.next) # for obj in predecessor.next: # if not obj in self.availableStations: # nextNo-=1 try: station.wip+=float(len(predecessor.getActiveObjectQueue())/predecessor.capacity) except: # XXX what happens in the case of sources or infinite-capacity-queues pass # predecessor.remainingWip=len(predecessor.getActiveObjectQueue()) % nextNo # for buffer in G.QueueList: # if buffer.remainingWip: # nextObj=next(x for x in buffer.next if x in self.availableStations) # pick the first of the list available # nextObj.wip+=buffer.remainingWip # buffer.remainingWip=0 #=================================================================== # # stations of the line and their corresponding WIP # TODO: the WIP of the stations must be normalised to the max WIP possible on that station #=================================================================== self.availableStationsDict={} for station in self.availableStations: self.availableStationsDict[str(station.id)]={'stationID':str(station.id),'WIP':station.wip} #=================================================================== # # operators and their skills set #=================================================================== self.operators={} for operator in G.OperatorsList: self.operators[str(operator.id)]=operator.skillsList #=================================================================== # # available operators #=================================================================== self.availableOperatorList=[] for operator in G.OperatorsList: if operator.available: self.availableOperatorList.append(operator.id) #=================================================================== # # XXX run the LP assignment algorithm # # should return a list of correspondences # # XXX signal the stations that the assignment is complete # TODO: a constant integer must be added to all WIP before provided to the opAss_LP # as it doesn't support zero WIP levels #=================================================================== solution=opAss_LP(self.availableStationsDict, self.availableOperatorList, self.operators) # XXX assign the operators to operatorPools # pendingStations/ available stations not yet given operator self.pendingStations=[] from Globals import findObjectById for operator in solution.keys(): for resource in G.OperatorsList: if resource.id==operator: station=findObjectById(solution[operator]) station.operatorPool.operators=[resource] resource.assignTo(station) self.toBeSignalled.append(station) i=0 for op in self.availableOperatorList: if op==resource.id: self.availableOperatorList.pop(i) break i+=1 break if len(solution)!=len(self.availableStations): from Globals import findObjectById for station in self.availableStations: if not station.id in solution.keys(): for i in range(len(self.availableOperatorList)): for resource in G.OperatorsList: if resource.id==self.availableOperatorList[i]: candidate=resource if station.id in candidate.skillsList: operatorID=self.availableOperatorList.pop(i) break #operator=findObjectById(operatorID) for resource in G.OperatorsList: if resource.id==operatorID: operator=resource station.operatorPool.operators=[operator] operator.assignTo(station) self.toBeSignalled.append(station) #=================================================================== # # XXX signal the stations that the assignment is complete #=================================================================== for station in self.toBeSignalled: if station.broker.waitForOperator: # signal this station's broker that the resource is available self.printTrace('router', 'signalling broker of'+' '*50+station.id) station.broker.resourceAvailable.succeed(self.env.now) else: # signal the queue proceeding the station if station.canAccept()\ and any(type=='Load' for type in station.multOperationTypeList): self.printTrace('router', 'signalling'+' '*50+station.id) station.loadOperatorAvailable.succeed(self.env.now) #=================================================================== # 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() # 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() # signal the stations that ought to be signalled self.signalOperatedStations() self.printTrace('', 'router exiting') self.printTrace('','=-'*20) self.exit()
def run(self): while 1: # wait until the router is called self.expectedSignals['isCalled'] = 1 yield self.isCalled transmitter, eventTime = self.isCalled.value self.isCalled = self.env.event() self.printTrace('', '=-' * 15) self.printTrace('', 'router received event') # wait till there are no more events, the machines must be blocked while 1: if self.env.now == self.env.peek(): self.printTrace('', 'there are MORE events for now') yield self.env.timeout(0) else: self.printTrace('', 'there are NO more events for now') break self.printTrace('', '=-' * 15) from Globals import G if self.allocation: #=================================================================== # # XXX wait for the interval time to finish (10 minutes between reassignments #=================================================================== '''not implemented yet''' #=================================================================== # # find stations that are in position to process #=================================================================== self.availableStations = [] for station in G.MachineList: if station.checkIfActive(): self.availableStations.append(station) if self.waitEndProcess: #=================================================================== # # XXX wait till all the stations have finished their current WIP # # XXX find all the machines that are currently busy #=================================================================== self.busyStations = [] for station in self.availableStations: if station.getActiveObjectQueue( ) and not station.waitToDispose: self.busyStations.append(station) #=================================================================== # # XXX create a list of all the events (endLastProcessing) #=================================================================== self.endProcessingSignals = [] for station in self.busyStations: self.endProcessingSignals.append( station.endedLastProcessing) station.isWorkingOnTheLast = True # FIX this will fail as the first machine sends the signal (router.waitingSingnal-> False) self.waitingSignal = True #=================================================================== # # XXX wait till all the stations have finished their current WIP #=================================================================== # TODO: fix that, add flags, reset the signals self.expectedSignals['endedLastProcessing'] = 1 receivedEvent = yield self.env.all_of( self.endProcessingSignals) for station in self.busyStations: if station.endedLastProcessing in receivedEvent: transmitter, eventTime = station.endedLastProcessing.value station.endedLastProcessing = self.env.event() #=================================================================== # # XXX if the resources are still assigned then un-assign them from the machines they are currently assigned # # the same for all the objects exits #=================================================================== for operator in [ x for x in G.OperatorsList if x.isAssignedTo() ]: operator.unAssign() for object in [x for x in G.ObjList if x.exitIsAssignedTo()]: object.unAssignExit() #=================================================================== # # XXX un-assign all the PBs from their operatorPools #=================================================================== for station in G.MachineList: station.operatorPool.operators = [] #=================================================================== # # XXX calculate the WIP of each station #=================================================================== for station in self.availableStations: station.wip = 1 + (len(station.getActiveObjectQueue()) / station.capacity) for predecessor in station.previous: try: station.wip += float( len(predecessor.getActiveObjectQueue()) / float(predecessor.capacity)) except: # XXX what happens in the case of sources or infinite-capacity-queues pass #=================================================================== # # stations of the line and their corresponding WIP # TODO: the WIP of the stations must be normalised to the max WIP possible on that station #=================================================================== self.availableStationsDict = {} for station in self.availableStations: self.availableStationsDict[str(station.id)] = { 'stationID': str(station.id), 'WIP': station.wip, 'lastAssignment': self.env.now } #=================================================================== # # operators and their skills set #=================================================================== self.operators = {} for operator in G.OperatorsList: self.operators[str(operator.id)] = operator.skillsList #=================================================================== # # available operators #=================================================================== self.availableOperatorList = [] for operator in G.OperatorsList: if operator.available: self.availableOperatorList.append(operator.id) #=================================================================== # # XXX run the LP assignment algorithm # # should return a list of correspondences # # XXX signal the stations that the assignment is complete # TODO: a constant integer must be added to all WIP before provided to the opAss_LP # as it doesn't support zero WIP levels #=================================================================== solution = opAss_LP(self.availableStationsDict, self.availableOperatorList, self.operators, previousAssignment=self.previousSolution) # print '-------' # print self.env.now, solution # XXX assign the operators to operatorPools # pendingStations/ available stations not yet given operator self.pendingStations = [] from Globals import findObjectById # apply the solution # loop through the entries in the solution dictionary for operatorID in solution.keys(): # obtain the operator and the station operator = findObjectById(operatorID) station = findObjectById(solution[operatorID]) if operatorID in self.previousSolution: # if the solution returned the operator that is already in the station # then no signal is needed if not self.previousSolution[operatorID] == solution[ operatorID]: self.toBeSignalled.append(station) else: self.toBeSignalled.append(station) # update the operatorPool of the station station.operatorPool.operators = [operator] # assign the operator to the station operator.assignTo(station) # set that the operator is dedicated to the station operator.operatorDedicatedTo = station # set in every station the operator that it is to get station.operatorToGet = operator # remove the operator id from availableOperatorList self.availableOperatorList.remove(operatorID) #=================================================================== # # XXX signal the stations that the assignment is complete #=================================================================== # if the operator is free the station can be signalled right away stationsProcessingLast = [] toBeSignalled = list(self.toBeSignalled) for station in toBeSignalled: # check if the operator that the station waits for is free operator = station.operatorToGet if operator.workingStation: if operator.workingStation.isProcessing: stationsProcessingLast.append( operator.workingStation) continue # signal the station so that it gets the operator self.signalStation(station, operator) # else wait for signals that operator became available and signal the stations self.expectedFinishSignalsDict = {} self.expectedFinishSignals = [] for station in stationsProcessingLast: signal = self.env.event() self.expectedFinishSignalsDict[station.id] = signal self.expectedFinishSignals.append(signal) while self.expectedFinishSignals: receivedEvent = yield self.env.any_of( self.expectedFinishSignals) for signal in self.expectedFinishSignals: if signal in receivedEvent: transmitter, eventTime = signal.value assert eventTime == self.env.now, 'the station finished signal must be received on the time of request' self.expectedFinishSignals.remove(signal) del self.expectedFinishSignalsDict[station.id] for id in solution.keys(): operator = findObjectById(id) station = findObjectById(solution[id]) if station in self.toBeSignalled: # signal the station so that it gets the operator self.signalStation(station, operator) #=================================================================== # default behaviour #=================================================================== else: # entry actions self.entryActions() # 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.previousSolution = solution self.printTrace('', 'router exiting') self.printTrace('', '=-' * 20) self.exitActions()