Пример #1
0
    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()
Пример #2
0
    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()
Пример #3
0
    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()
Пример #4
0
    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()
Пример #5
0
    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()
Пример #6
0
    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()