Example #1
0
 def getEntity(self):
     activeObject = self.getActiveObject()
     activeEntity = Machine.getEntity(self)  #run the default code
     # read the processing time from the corresponding remainingRoute entry
     processingTime = activeEntity.remainingRoute[0].get(
         'processingTime', {})
     processingTime = self.getOperationTime(processingTime)
     self.rng = RandomNumberGenerator(self, processingTime)
     self.procTime = self.rng.generateNumber()
     # check if there is a need for manual processing
     self.checkForManualOperation(type='Processing', entity=activeEntity)
     # read the setup time from the corresponding remainingRoute entry
     setupTime = activeEntity.remainingRoute[0].get('setupTime', {})
     setupTime = self.getOperationTime(setupTime)
     self.stpRng = RandomNumberGenerator(self, setupTime)
     # check if there is a need for manual processing
     self.checkForManualOperation(type='Setup', entity=activeEntity)
     activeEntity.currentStep = activeEntity.remainingRoute.pop(
         0)  #remove data from the remaining route of the entity
     if activeEntity.currentStep:
         # update the task_id of the currentStep dict within the schedule
         try:
             activeEntity.schedule[-1][
                 "task_id"] = activeEntity.currentStep["task_id"]
             # if there is currentOperator then update the taskId of corresponding step of their schedule according to the task_id of the currentStep
             if self.currentOperator:
                 self.currentOperator.schedule[-1][
                     "task_id"] = activeEntity.currentStep["task_id"]
         except KeyError:
             pass
     return activeEntity
    def __init__(self, id, name, capacity=1, \
                 processingTime=None, repairman='None',\
                 scrapQuantity={},
                 operatorPool='None',operationType='None',\
                 setupTime=None, loadTime=None,
                 canDeliverOnInterruption=False,
                 **kw):
        if not processingTime:
            processingTime = {'distributionType': 'Fixed', 'mean': 1}
        # initialize using the default method of the object
        Machine.__init__(self,id=id,name=name,\
                                    capacity=capacity,\
                                    processingTime=processingTime,
                                    repairman=repairman,
                                    canDeliverOnInterruption=canDeliverOnInterruption,
                                    operatorPool=operatorPool,operationType=operationType,\
                                    setupTime=setupTime, loadTime=loadTime,
                                    )

        # set the attributes of the scrap quantity distribution
        if not scrapQuantity:
            scrapQuantity = {'Fixed': {'mean': 0}}

        self.scrapRng = RandomNumberGenerator(self, scrapQuantity)
        from Globals import G
        G.BatchScrapMachineList.append(self)
Example #3
0
    def __init__(self,
                 id,
                 name,
                 interArrivalTime=None,
                 entity='Dream.Part',
                 **kw):
        # Default values
        if not interArrivalTime:
            interArrivalTime = {'Fixed': {'mean': 1}}
        if 'Normal' in interArrivalTime.keys() and\
              interArrivalTime['Normal'].get('max', None) is None:
            interArrivalTime['Normal']['max'] = interArrivalTime['Normal'][
                'mean'] + 5 * interArrivalTime['Normal']['stdev']

        CoreObject.__init__(self, id, name)
        # properties used for statistics
        self.totalinterArrivalTime = 0  # the total interarrival time
        self.numberOfArrivals = 0  # the number of entities that were created

        self.type = "Source"  #String that shows the type of object
        self.rng = RandomNumberGenerator(self, interArrivalTime)

        self.item = Globals.getClassFromName(
            entity)  #the type of object that the Source will generate

        self.scheduledEntities = [
        ]  # list of creations that are scheduled. pattern is [timeOfCreation, EntityCounter]
        from Globals import G
        G.SourceList.append(self)
Example #4
0
 def __init__(self, id="", name="", victim=None, distribution=None, index=0, repairman=None, **kw):
     ObjectInterruption.__init__(self, id, name, victim=victim)
     self.rngTTF = RandomNumberGenerator(self, distribution.get("TTF", {"Fixed": {"mean": 100}}))
     self.rngTTR = RandomNumberGenerator(self, distribution.get("TTR", {"Fixed": {"mean": 10}}))
     self.name = "F" + str(index)
     self.repairman = repairman  # the resource that may be needed to fix the failure
     # if now resource is needed this will be "None"
     self.type = "PeriodicMaintenance"
Example #5
0
 def __init__(self, id='',name='',victim=None, distribution=None, index=0, repairman=None,**kw):
     ObjectInterruption.__init__(self,id,name,victim=victim)
     self.rngTTF=RandomNumberGenerator(self, distribution.get('TTF',{'Fixed':{'mean':100}}))
     self.rngTTR=RandomNumberGenerator(self, distribution.get('TTR',{'Fixed':{'mean':10}}))
     self.name="F"+str(index)
     self.repairman=repairman        # the resource that may be needed to fix the failure
                                     # if now resource is needed this will be "None" 
     self.type="PeriodicMaintenance"
Example #6
0
    def __init__(self, victim=None, distribution=None, index=0, repairman=None, offshift=False,
                 deteriorationType='constant',**kw):
        #Process.__init__(self)
        ObjectInterruption.__init__(self,victim)
        if distribution:
            self.distType=distribution.get('distributionType','No')              # the distribution that the failure duration follows
            self.MTTF=distribution.get('MTTF',60)                  # the MTTF
            self.MTTR=distribution.get('MTTR',5)                  # the MTTR  
            self.availability=distribution.get('availability',100)  # the availability      
        else:
            self.distType='No'
            self.MTTF=60
            self.MTTR=5
            self.availability=100
        self.name="F"+str(index)
        self.repairman=repairman        # the resource that may be needed to fix the failure
                                        # if now resource is needed this will be "None" 
        self.type="Failure"
        self.id=0

        # shows how the time to failure is measured
        # 'constant' means it counts not matter the state of the victim
        # 'onShift' counts only if the victim is onShift
        # 'working' counts only working time
        self.deteriorationType=deteriorationType
        
        if(self.distType=="Availability"):      
            
            # -------------------------------------------------------------- 
            #     the following are used if we have availability defined 
            #      (as in plant) the erlang is a special case of Gamma. 
            #        To model the Mu and sigma (that is given in plant) 
            #    as alpha and beta for gamma you should do the following:
            #                     beta=(sigma^2)/Mu    
            #                     alpha=Mu/beta
            # --------------------------------------------------------------    
            self.AvailabilityMTTF=self.MTTR*(float(availability)/100)/(1-(float(availability)/100))
            self.sigma=0.707106781185547*self.MTTR   
            self.theta=(pow(self.sigma,2))/float(self.MTTR)             
            self.beta=self.theta
            self.alpha=(float(self.MTTR)/self.theta)        
            self.rngTTF=RandomNumberGenerator(self, "Exp")
            self.rngTTF.avg=self.AvailabilityMTTF
            self.rngTTR=RandomNumberGenerator(self, "Erlang")
            self.rngTTR.alpha=self.alpha
            self.rngTTR.beta=self.beta       
        else:   
            # --------------------------------------------------------------
            #               if the distribution is fixed
            # --------------------------------------------------------------
            self.rngTTF=RandomNumberGenerator(self, self.distType)
            self.rngTTF.mean=self.MTTF
            self.rngTTR=RandomNumberGenerator(self, self.distType)
            self.rngTTR.mean=self.MTTR
        # flag used to identify if the time between failures should be counted while the victim is off-shift
        self.offshift=offshift
Example #7
0
 def __generate_instance(self, seed):
     RNG = RandomNumberGenerator(seed)
     task_queue = []
     for J in range(0, self.size):
         task_queue.append({'j': J + 1})
         for M in range(1, self.machines + 1):
             task_queue[J].update({f'p{M}': RNG.nextInt(1, MAX_VALUE)})
             task_queue[J].update({f'S{M}': 0})
             task_queue[J].update({f'C{M}': 0})
     return task_queue
Example #8
0
 def calculateProcessingTime(self):
     # this is only for processing of the initial wip
     if self.isProcessingInitialWIP:
         activeEntity=self.getActiveObjectQueue()[0]
         if activeEntity.remainingProcessingTime:
             remainingProcessingTime=activeEntity.remainingProcessingTime
             from RandomNumberGenerator import RandomNumberGenerator
             initialWIPrng=RandomNumberGenerator(self, remainingProcessingTime)
             return initialWIPrng.generateNumber()
     return self.rng.generateNumber()           # this is if we have a default processing time for all the entities
Example #9
0
 def __init__(self, id='',name='',victim=None, distribution={},
              endUnfinished=True,offShiftAnticipation=0,**kw):
     ObjectInterruption.__init__(self,id,name,victim=victim)
     self.rngTTB=RandomNumberGenerator(self, distribution.get('TTB',{'Fixed':{'mean':100}}))
     self.rngTTR=RandomNumberGenerator(self, distribution.get('TTR',{'Fixed':{'mean':10}}))
     self.type="Break"
     # end current wip before going to break
     self.endUnfinished=endUnfinished
     # if the break is close to end of shift below a limit it will be suspended
     self.offShiftAnticipation=offShiftAnticipation
Example #10
0
 def calculateProcessingTime(self):
     # this is only for processing of the initial wip
     if self.isProcessingInitialWIP:
         activeEntity=self.getActiveObjectQueue()[0]
         if activeEntity.remainingProcessingTime:
             remainingProcessingTime=activeEntity.remainingProcessingTime
             from RandomNumberGenerator import RandomNumberGenerator
             initialWIPrng=RandomNumberGenerator(self, remainingProcessingTime)
             return initialWIPrng.generateNumber()
     return self.rng.generateNumber()           # this is if we have a default processing time for all the entities
Example #11
0
def instanceGenerator(Z, size):
    generator = RandomNumberGenerator(Z)
    d = [[0 for i in range(size)] for j in range(size)]

    for i in range(size):
        for j in range(size):
            if (i > j):
                d[i][j] = generator.nextInt(1, 50)
                d[j][i] = generator.nextInt(1, 50)

    return d
Example #12
0
    def __init__(self,
                 id,
                 name,
                 numberOfSubBatches=1,
                 processingTime=None,
                 operator='None',
                 outputResults=False,
                 **kw):
        CoreObject.__init__(self, id, name)
        self.type = "BatchRassembly"  #String that shows the type of object
        if not processingTime:
            processingTime = {'Fixed': {'mean': 0}}
        if 'Normal' in processingTime.keys() and\
                processingTime['Normal'].get('max', None) is None:
            processingTime['Normal']['max'] = float(
                processingTime['Normal']['mean']) + 5 * float(
                    processingTime['Normal']['stdev'])

        # holds the capacity of the object
        self.numberOfSubBatches = numberOfSubBatches
        # sets the operator resource of the Machine
        self.operator = operator
        # Sets the attributes of the processing (and failure) time(s)
        self.rng = RandomNumberGenerator(self, processingTime)
        from Globals import G
        G.BatchReassemblyList.append(self)
        # flag to show if the objects outputs results
        self.outputResults = bool(int(outputResults))
    def __init__(self,
                 id,
                 name,
                 processingTime=None,
                 numberOfSubBatches=1,
                 operator='None',
                 **kw):
        CoreObject.__init__(self, id, name)
        self.type = "BatchDecomposition"  #String that shows the type of object

        if not processingTime:
            processingTime = {'Fixed': {'mean': 0}}
        if 'Normal' in processingTime.keys() and\
                processingTime['Normal'].get('max', None) is None:
            processingTime['Normal']['max'] = float(
                processingTime['Normal']['mean']) + 5 * float(
                    processingTime['Normal']['stdev'])

        # holds the capacity of the object
        self.numberOfSubBatches = int(numberOfSubBatches)
        # sets the operator resource of the Machine
        self.operator = operator
        # Sets the attributes of the processing (and failure) time(s)
        self.rng = RandomNumberGenerator(self, processingTime)
        from Globals import G
        G.BatchDecompositionList.append(self)
Example #14
0
 def calculateInitialOperationTimes(self):
     # read the setup/processing time from the first entry of the full route
     activeEntity = self.getActiveObjectQueue()[0]
     #if the entity has its route defined in the BOM then remainingProcessing/SetupTime is provided
     # XX consider moving setupUPtime update to checkForManualOperationTypes as Setup is performed before Processing
     if activeEntity.routeInBOM:
         processingTime = self.getOperationTime(
             activeEntity.remainingProcessingTime)
         setupTime = self.getOperationTime(activeEntity.remainingSetupTime)
     else:  # other wise these should be read from the route
         processingTime = activeEntity.route[0].get('processingTime', {})
         processingTime = self.getOperationTime(processingTime)
         setupTime = activeEntity.route[0].get('setupTime', {})
         setupTime = self.getOperationTime(setupTime)
     self.rng = RandomNumberGenerator(self, processingTime)
     self.stpRng = RandomNumberGenerator(self, setupTime)
Example #15
0
 def getEntity(self):
     activeObject=self.getActiveObject()
     activeEntity=Machine.getEntity(self)     #run the default code
     # read the processing time from the corresponding remainingRoute entry
     processingTime=activeEntity.remainingRoute[0].get('processingTime',{})
     processingTime=self.getOperationTime(processingTime)
     self.rng=RandomNumberGenerator(self, processingTime)
     self.procTime=self.rng.generateNumber()
     # check if there is a need for manual processing
     self.checkForManualOperation(type='Processing',entity=activeEntity)
     # read the setup time from the corresponding remainingRoute entry
     setupTime=activeEntity.remainingRoute[0].get('setupTime',{})
     setupTime=self.getOperationTime(setupTime)
     self.stpRng=RandomNumberGenerator(self, setupTime)
     # check if there is a need for manual processing
     self.checkForManualOperation(type='Setup',entity=activeEntity)
     activeEntity.currentStep = activeEntity.remainingRoute.pop(0)      #remove data from the remaining route of the entity
     if activeEntity.currentStep:
         # update the task_id of the currentStep dict within the schedule
         try:
             activeEntity.schedule[-1]["task_id"] = activeEntity.currentStep["task_id"]
             # if there is currentOperator then update the taskId of corresponding step of their schedule according to the task_id of the currentStep
             if self.currentOperator:
                 self.currentOperator.schedule[-1]["task_id"] = activeEntity.currentStep["task_id"]
         except KeyError:
             pass
     return activeEntity
Example #16
0
    def __init__(self, id, name, capacity=1, \
                 processingTime=None, repairman='None',\
                 scrapQuantity={},
                 operatorPool='None',operationType='None',\
                 setupTime=None, loadTime=None,
                 canDeliverOnInterruption=False, 
                 technology=None,
                 **kw):
        if not processingTime:
          processingTime = {'distributionType': 'Fixed',
                            'mean': 1}
        # initialize using the default method of the object 
        Machine.__init__(self,id=id,name=name,\
                                    capacity=capacity,\
                                    processingTime=processingTime,
                                    repairman=repairman,
                                    canDeliverOnInterruption=canDeliverOnInterruption,
                                    operatorPool=operatorPool,operationType=operationType,\
                                    setupTime=setupTime, loadTime=loadTime,     
                                    technology=technology              
                                    )

        # set the attributes of the scrap quantity distribution
        if not scrapQuantity:
            scrapQuantity = {'Fixed':{'mean': 0}}
            
        self.scrapRng=RandomNumberGenerator(self, scrapQuantity)
        from Globals import G
        G.BatchScrapMachineList.append(self)
class Main:
    generator = RandomNumberGenerator()
    observer1 = DigitObserver()
    observer2 = GraphObserver()
    generator.addObserver(observer1)
    generator.addObserver(observer2)
    generator.execute()
Example #18
0
    def __init__(self, victim=None, distribution=None, index=0, repairman=None):
        #Process.__init__(self)
        ObjectInterruption.__init__(self,victim)
        if distribution:
            self.distType=distribution.get('distributionType','No')              # the distribution that the failure duration follows
            self.MTTF=distribution.get('MTTF',60)                  # the MTTF
            self.MTTR=distribution.get('MTTR',5)                  # the MTTR  
            self.availability=distribution.get('availability',100)  # the availability      
        else:
            self.distType='No'
            self.MTTF=60
            self.MTTR=5
            self.availability=100
        self.name="F"+str(index)
        self.repairman=repairman        # the resource that may be needed to fix the failure
                                        # if now resource is needed this will be "None" 
        self.type="Failure"
        self.id=0

        if(self.distType=="Availability"):      
            
            # -------------------------------------------------------------- 
            #     the following are used if we have availability defined 
            #      (as in plant) the erlang is a special case of Gamma. 
            #        To model the Mu and sigma (that is given in plant) 
            #    as alpha and beta for gamma you should do the following:
            #                     beta=(sigma^2)/Mu    
            #                     alpha=Mu/beta
            # --------------------------------------------------------------    
            self.AvailabilityMTTF=self.MTTR*(float(availability)/100)/(1-(float(availability)/100))
            self.sigma=0.707106781185547*self.MTTR   
            self.theta=(pow(self.sigma,2))/float(self.MTTR)             
            self.beta=self.theta
            self.alpha=(float(self.MTTR)/self.theta)        
            self.rngTTF=RandomNumberGenerator(self, "Exp")
            self.rngTTF.avg=self.AvailabilityMTTF
            self.rngTTR=RandomNumberGenerator(self, "Erlang")
            self.rngTTR.alpha=self.alpha
            self.rngTTR.beta=self.beta       
        else:   
            # --------------------------------------------------------------
            #               if the distribution is fixed
            # --------------------------------------------------------------
            self.rngTTF=RandomNumberGenerator(self, self.distType)
            self.rngTTF.mean=self.MTTF
            self.rngTTR=RandomNumberGenerator(self, self.distType)
            self.rngTTR.mean=self.MTTR
Example #19
0
 def getEntity(self):
     activeObject=self.getActiveObject()
     activeEntity=Machine.getEntity(self)     #run the default code
     # read the processing time from the corresponding remainingRoute entry
     processingTime=activeEntity.remainingRoute[0].get('processingTime',{})
     processingTime=self.getOperationTime(processingTime)
     self.rng=RandomNumberGenerator(self, processingTime)
     self.procTime=self.rng.generateNumber()
     # check if there is a need for manual processing
     self.checkForManualOperation(type='Processing',entity=activeEntity)
     # read the setup time from the corresponding remainingRoute entry
     setupTime=activeEntity.remainingRoute[0].get('setupTime',{})
     setupTime=self.getOperationTime(setupTime)
     self.stpRng=RandomNumberGenerator(self, setupTime)
     # check if there is a need for manual processing
     self.checkForManualOperation(type='Setup',entity=activeEntity)
     removedStep = activeEntity.remainingRoute.pop(0)      #remove data from the remaining route of the entity
     return activeEntity
Example #20
0
 def readLoadTime(self,callerObject=None):
     assert callerObject!=None, 'the caller of readLoadTime cannot be None'
     thecaller=callerObject
     thecaller.sortEntities()
     activeEntity=thecaller.Res.users[0]
     # read the load time from the corresponding remainingRoute entry
     loadTime=activeEntity.remainingRoute[0].get('loadTime',{})
     loadTime=self.getOperationTime(loadTime)
     self.loadRng=RandomNumberGenerator(self, loadTime)
Example #21
0
def main():
    seed = int(input("Wprowadź Z: "))
    generator = RandomNumberGenerator(seed)
    taskNumber = int(input("Wprowadź rozmiar problemu: "))
    tasks = range(1, taskNumber + 1)
    nr = []
    pj = []  #czas wykonania
    wj = []  #waga/współczynnik kary
    dj = []  #żądany termin zakończenia

    for task in tasks:
        nr.append(task)
        pj.append(generator.nextInt(1, 29))

    A = 0
    for number in pj:
        A += number

    for task in tasks:
        wj.append(generator.nextInt(1, 9))
    X = 29
    #X=A
    for task in tasks:
        dj.append(generator.nextInt(1, X))

    print("\nnr:", nr)
    print("pj: ", pj)
    print("wj ", wj)
    print("dj", dj)

    witi_start = target_fun(pj, wj, dj, taskNumber)
    print(f'\nWiTi dla początkowego = {witi_start[0]}')
    print(f'C: {witi_start[2]}')
    print(f'T: {witi_start[1]}')

    witi_greedy = greedy(pj, wj, dj, taskNumber)
    print(f'\nWiTi dla Greedy algorithm = {witi_greedy[0]}')
    print(f'C: {witi_greedy[2]}')
    print(f'T: {witi_greedy[1]}')

    witi_brute_force = brute_force(pj, wj, dj, taskNumber)
    print(f'\nWiTi dla Brute Force = {witi_brute_force[0]}')
    print(f'C: {witi_brute_force[2]}')
    print(f'T: {witi_brute_force[1]}')
def main():
    seed = int(input("Wprowadź Z: "))
    generator = RandomNumberGenerator(seed)
    taskNumber = int(input("Wprowadź liczbę zadań: "))
    tasks = range(1, taskNumber + 1)
    machineNumber = int(input("Wprowadź liczbę maszyn: "))
    machines = range(1, machineNumber + 1)

    #lista wszystkich zadan na konkretnych maszynach
    p_ij = []
    # permutacja zadan
    pi = []
    # wyswietlenie rozwiazania po wykonaniu algorytmu optymalizacji
    solution = []
    #lista zadan przydzielonych do jednej maszyny
    pj = []

    for task in tasks:
        for machine in machines:
            pj.append(generator.nextInt(1, 29))
        p_ij.append(pj.copy())
        pj.clear()
        pi.append(task)

    print(p_ij)
    print("Permutacj naturalna: ")
    print("pi: ", pi)
    Cj, Cmax = calculate(p_ij, taskNumber, machineNumber)
    print("C:", Cj)
    print("Cmax:", Cmax)

    for task in tasks:
        solution.append([pi[task - 1], p_ij[task - 1]])

    pi = Johnson(tasks, p_ij.copy())
    print("Johnson: ")
    print("pi: ", pi)

    sort = {x: i for i, x in enumerate(pi)}
    solution.sort(key=lambda x: sort[x[0]])
    Cj, Cmax = calculate([row[1] for row in solution], taskNumber,
                         machineNumber)
    print("C", Cj)
    print("Cmax:", Cmax)
Example #23
0
class BatchScrapMachine(Machine):
    
    # =======================================================================
    # constructor run every time a new instance is created
    # calls the Machine constructor, but also reads attributes for 
    # scraping distribution
    # ======================================================================= 
    def __init__(self, id, name, capacity=1, \
                 processingTime=None, repairman='None',\
                 scrapQuantity={}, **kw):
        if not processingTime:
          processingTime = {'distributionType': 'Fixed',
                            'mean': 1}
        # initialize using the default method of the object 
        Machine.__init__(self,id=id,name=name,\
                                    capacity=capacity,\
                                    processingTime=processingTime,
                                    repairman=repairman)

        # set the attributes of the scrap quantity distribution
        if not scrapQuantity:
            scrapQuantity = {'distributionType': 'Fixed',
                            'mean': 0}
            
        self.scrapRng=RandomNumberGenerator(self, **scrapQuantity)
        from Globals import G
        G.BatchScrapMachineList.append(self)

    # =======================================================================
    # removes an Entity from the Object the Entity to be removed is passed
    # as argument by getEntity of the receiver
    # extends the default behaviour so that
    # it can scrap a number of units before disposing the Batch/SubBatch
    # =======================================================================
    def removeEntity(self, entity=None):
        activeEntity = Machine.removeEntity(self, entity)
        scrapQuantity=self.scrapRng.generateNumber()  
        activeEntity.numberOfUnits-=int(scrapQuantity)  # the scrapQuantity should be integer at whatever case
        if activeEntity.numberOfUnits<0:
            activeEntity.numberOfUnits==0
        return activeEntity


    # =======================================================================
    # calculates the processing time
    # extends the default behaviour so that 
    # the per-unit processing time is multiplied with the number of units
    # =======================================================================                                                                                
    def calculateProcessingTime(self):
        activeEntity = self.getActiveObjectQueue()[0]
        # this is only for processing of the initial wip
        if self.isProcessingInitialWIP:
            if activeEntity.unitsToProcess:
                return self.rng.generateNumber()*activeEntity.unitsToProcess 
        return self.rng.generateNumber()*activeEntity.numberOfUnits        
Example #24
0
 def __init__(self, id='',name='',victim=None, distribution={}, index=0, repairman=None, offshift=False,
              deteriorationType='constant',
              waitOnTie=False,**kw):
     ObjectInterruption.__init__(self,id,name,victim=victim)
     self.rngTTF=RandomNumberGenerator(self, distribution.get('TTF',{'Fixed':{'mean':100}}))
     self.rngTTR=RandomNumberGenerator(self, distribution.get('TTR',{'Fixed':{'mean':10}}))
     self.name="F"+str(index)
     self.repairman=repairman        # the resource that may be needed to fix the failure
                                     # if now resource is needed this will be "None" 
     self.type="Failure"
     
     # shows how the time to failure is measured
     # 'constant' means it counts not matter the state of the victim
     # 'onShift' counts only if the victim is onShift
     # 'working' counts only working time
     self.deteriorationType=deteriorationType
     # flag used to identify if the time between failures should be counted while the victim is off-shift
     self.offshift=offshift
     # flag to show if the failure will wait on tie with other events before interrupting the victim
     self.waitOnTie=waitOnTie
Example #25
0
def defineScrapQuantities():
    process = G.CMSDData.getElementsByTagName('Process')

    #loop through the processes
    for proc in process:
        try:
            #read the scrap quantity
            Property = proc.getElementsByTagName('Property')
            for prop in Property:
                name = prop.getElementsByTagName('Name')
                name = name[0].toxml().replace('<Name>',
                                               '').replace('</Name>', '')
                if name == 'ScrapQuantity':
                    scrap = Property[0].getElementsByTagName('Distribution')
                    scrapName = scrap[0].getElementsByTagName('Name')
                    scrapName = scrapName[0].toxml().replace('<Name>',
                                                             '').replace(
                                                                 '</Name>', '')

                    distrParA = scrap[0].getElementsByTagName(
                        'DistributionParameterA')
                    parAName = distrParA[0].getElementsByTagName('Name')
                    parAName = parAName[0].toxml().replace('<Name>',
                                                           '').replace(
                                                               '</Name>', '')
                    parAValue = distrParA[0].getElementsByTagName('Value')
                    parAValue = parAValue[0].toxml().replace(
                        '<Value>', '').replace('</Value>', '')

                else:
                    continue

                #read the id of the station resource
                ResourcesRequired = proc.getElementsByTagName(
                    'ResourcesRequired')
                for res in ResourcesRequired:
                    Resource = res.getElementsByTagName('Resource')
                    ResourceIdentifier = Resource[0].getElementsByTagName(
                        'ResourceIdentifier')
                    ResourceIdentifier = ResourceIdentifier[0].toxml().replace(
                        '<ResourceIdentifier>',
                        '').replace('</ResourceIdentifier>', '')

                    #loop through the stations and for the one with the id set the scrap
                    distributionDict = {
                        str(scrapName): {
                            str(parAName): parAValue
                        }
                    }
                for obj in G.ObjList:
                    if obj.id == ResourceIdentifier:
                        obj.rng = RandomNumberGenerator(obj, distributionDict)
        except IndexError:
            continue
Example #26
0
    def __init__(self, size, seed):
        self.size = size
        self.last_permutation = []
        RNG = RandomNumberGenerator(seed)
        p_list = []
        w_list = []
        d_list = []
        p_sum = 0
        self.queue = []
        for J in range(0, self.size):
            p_list.append(RNG.nextInt(1, MAX_VALUE))
            p_sum += p_list[-1]

        for J in range(0, self.size):
            w_list.append(RNG.nextInt(1, 9))

        for J in range(0, self.size):
            d_list.append(RNG.nextInt(1, MAX_D))

        for J in range(0, self.size):
            self.queue.append(task(J + 1, p_list[J], w_list[J], d_list[J]))
            self.last_permutation.append(J + 1)
Example #27
0
 def __init__(self,
              id='',
              name='',
              victim=None,
              distribution={},
              endUnfinished=True,
              offShiftAnticipation=0,
              **kw):
     ObjectInterruption.__init__(self, id, name, victim=victim)
     self.rngTTB = RandomNumberGenerator(
         self, distribution.get('TTB', {'Fixed': {
             'mean': 100
         }}))
     self.rngTTR = RandomNumberGenerator(
         self, distribution.get('TTR', {'Fixed': {
             'mean': 10
         }}))
     self.type = "Break"
     # end current wip before going to break
     self.endUnfinished = endUnfinished
     # if the break is close to end of shift below a limit it will be suspended
     self.offShiftAnticipation = offShiftAnticipation
Example #28
0
def defineProcessingTimes():
    process = G.CMSDData.getElementsByTagName('Process')

    #loop through the processes
    for proc in process:
        try:
            #read the mean processing time a the unit
            OperationTime = proc.getElementsByTagName('OperationTime')
            distr = OperationTime[0].getElementsByTagName('Distribution')
            distrName = distr[0].getElementsByTagName('Name')
            distrName = distrName[0].toxml().replace('<Name>', '').replace(
                '</Name>', '')

            distrParA = distr[0].getElementsByTagName('DistributionParameterA')
            parAName = distrParA[0].getElementsByTagName('Name')
            parAName = parAName[0].toxml().replace('<Name>',
                                                   '').replace('</Name>', '')
            parAValue = distrParA[0].getElementsByTagName('Value')
            parAValue = parAValue[0].toxml().replace('<Value>', '').replace(
                '</Value>', '')

            distrParB = distr[0].getElementsByTagName('DistributionParameterB')
            parBName = distrParB[0].getElementsByTagName('Name')
            parBName = parBName[0].toxml().replace('<Name>',
                                                   '').replace('</Name>', '')
            parBValue = distrParB[0].getElementsByTagName('Value')
            parBValue = parBValue[0].toxml().replace('<Value>', '').replace(
                '</Value>', '')

            #read the id of the station resource
            ResourcesRequired = proc.getElementsByTagName('ResourcesRequired')
            for res in ResourcesRequired:
                Resource = res.getElementsByTagName('Resource')
                ResourceIdentifier = Resource[0].getElementsByTagName(
                    'ResourceIdentifier')
                ResourceIdentifier = ResourceIdentifier[0].toxml().replace(
                    '<ResourceIdentifier>',
                    '').replace('</ResourceIdentifier>', '')

                #loop through the stations and for the one with the id set the processing time
                distributionDict = {
                    str(distrName): {
                        str(parAName): parAValue,
                        str(parBName): parBValue
                    }
                }
                for obj in G.ObjList:
                    if obj.id == ResourceIdentifier:
                        obj.rng = RandomNumberGenerator(obj, distributionDict)
        except IndexError:
            continue
Example #29
0
 def calculateProcessingTime(self):
     # this is only for processing of the initial wip
     if self.isProcessingInitialWIP:
         # read the processing/setup/load times from the first entry of the full route
         activeEntity=self.getActiveObjectQueue()[0]
         processingTime=activeEntity.route[0].get('processingTime',{})
         processingTime=self.getProcessingTime(processingTime)
         self.rng=RandomNumberGenerator(self, **processingTime)
         self.procTime=self.rng.generateNumber()
         
         setupTime=activeEntity.route[0].get('setupTime',{})
         setupTime=self.getSetupTime(setupTime)
         self.stpRng=RandomNumberGenerator(self, **setupTime)
     return self.procTime    #this is the processing time for this unique entity 
Example #30
0
def simulatedAnnealing(tasks):
    RNG = RandomNumberGenerator(123)
    t = copy.deepcopy(tasks)
    T = 1550.0  #temperatura zarzenia na bialo rozgrzanej stali :)
    Tend = 1E-10  # cokolwiek większe od zera
    it = 0
    L = 10
    pi = []
    pi_new = []
    pi_best = []

    #natural perm
    for perm in range(1, t.size + 1):
        pi.append(perm)
        pi_best.append(perm)

    while T > Tend:
        for k in range(L):
            i = RNG.nextInt(0, t.size) - 1
            j = RNG.nextInt(0, t.size) - 1
            pi_new = copy.deepcopy(pi)
            swap_value = pi_new[i]
            pi_new[i] = pi_new[j]
            pi_new[j] = swap_value
            cmax_new = t.calculate_Cmax(pi_new)
            cmax_old = t.calculate_Cmax(pi)
            if cmax_new > cmax_old:
                r = RNG.nextFloat(0, 1)
                dCmax = cmax_old - cmax_new
                if r >= math.exp(dCmax / T):
                    pi_new = copy.deepcopy(pi)
            pi = copy.deepcopy(pi_new)
            if t.calculate_Cmax(pi_best) > t.calculate_Cmax(pi):
                pi_best = copy.deepcopy(pi)
        it += 1
        T = T / math.log(it + 1)  #ln(it+1)
    return pi_best
Example #31
0
 def calculateInitialOperationTimes(self):
     # read the setup/processing time from the first entry of the full route
     activeEntity=self.getActiveObjectQueue()[0]
     #if the entity has its route defined in the BOM then remainingProcessing/SetupTime is provided
     # XX consider moving setupUPtime update to checkForManualOperationTypes as Setup is performed before Processing
     if activeEntity.routeInBOM:
         processingTime=self.getOperationTime(activeEntity.remainingProcessingTime)
         setupTime=self.getOperationTime(activeEntity.remainingSetupTime)
     else:   # other wise these should be read from the route
         processingTime=activeEntity.route[0].get('processingTime',{})
         processingTime=self.getOperationTime(processingTime)
         setupTime=activeEntity.route[0].get('setupTime',{})
         setupTime=self.getOperationTime(setupTime)
     self.rng=RandomNumberGenerator(self, processingTime)
     self.stpRng=RandomNumberGenerator(self, setupTime)
Example #32
0
 def getEntity(self):
     activeObject=self.getActiveObject()
     activeEntity=Machine.getEntity(self)     #run the default code
     
     # read the processing/setup/load times from the corresponding remainingRoute entry
     processingTime=activeEntity.remainingRoute[0].get('processingTime',{})
     processingTime=self.getProcessingTime(processingTime)
     self.rng=RandomNumberGenerator(self, **processingTime)
     self.procTime=self.rng.generateNumber()
     
     setupTime=activeEntity.remainingRoute[0].get('setupTime',{})
     setupTime=self.getSetupTime(setupTime)
     self.stpRng=RandomNumberGenerator(self, **setupTime)
     
     removedStep = activeEntity.remainingRoute.pop(0)      #remove data from the remaining route of the entity
     return activeEntity
Example #33
0
    def __init__(self, id, name, capacity=1, \
                 processingTime=None, repairman='None',\
                 scrapQuantity={}, **kw):
        if not processingTime:
          processingTime = {'distributionType': 'Fixed',
                            'mean': 1}
        # initialize using the default method of the object 
        Machine.__init__(self,id=id,name=name,\
                                    capacity=capacity,\
                                    processingTime=processingTime,
                                    repairman=repairman)

        # set the attributes of the scrap quantity distribution
        if not scrapQuantity:
            scrapQuantity = {'distributionType': 'Fixed',
                            'mean': 0}
            
        self.scrapRng=RandomNumberGenerator(self, **scrapQuantity)
        from Globals import G
        G.BatchScrapMachineList.append(self)
Example #34
0
    def __init__(self, id, name, interArrivalTime=None, entity='Dream.Part',**kw):
        # Default values
        if not interArrivalTime:
          interArrivalTime = {'Fixed': {'mean': 1}}
        if 'Normal' in interArrivalTime.keys() and\
              interArrivalTime['Normal'].get('max', None) is None:
          interArrivalTime['Normal']['max'] = interArrivalTime['Normal']['mean'] + 5 * interArrivalTime['Normal']['stdev']

        CoreObject.__init__(self, id, name)
        # properties used for statistics
        self.totalinterArrivalTime = 0                  # the total interarrival time 
        self.numberOfArrivals = 0                       # the number of entities that were created

        self.type="Source"                              #String that shows the type of object
        self.rng = RandomNumberGenerator(self, interArrivalTime)

        self.item=Globals.getClassFromName(entity)      #the type of object that the Source will generate
               
        self.scheduledEntities=[]       # list of creations that are scheduled. pattern is [timeOfCreation, EntityCounter]     
        from Globals import G
        G.SourceList.append(self)  
Example #35
0
    def __init__(self,
                 id='',
                 name='',
                 processingTime=None,
                 inputsDict=None,
                 **kw):
        self.type = "Assembly"  #String that shows the type of object
        self.next = []  #list with the next objects in the flow
        self.previous = []  #list with the previous objects in the flow
        self.previousPart = []  #list with the previous objects that send parts
        self.previousFrame = [
        ]  #list with the previous objects that send frames
        self.nextIds = []  #list with the ids of the next objects in the flow
        self.previousIds = [
        ]  #list with the ids of the previous objects in the flow

        #lists to hold statistics of multiple runs
        self.Waiting = []
        self.Working = []
        self.Blockage = []

        if not processingTime:
            processingTime = {'Fixed': {'mean': 0}}
        if 'Normal' in processingTime.keys() and\
                processingTime['Normal'].get('max', None) is None:
            processingTime['Normal']['max'] = float(
                processingTime['Normal']['mean']) + 5 * float(
                    processingTime['Normal']['stdev'])

        CoreObject.__init__(self, id, name)
        self.rng = RandomNumberGenerator(self, processingTime)

        # ============================== variable that is used for the loading of machines =============
        self.exitAssignedToReceiver = False  # by default the objects are not blocked
        # when the entities have to be loaded to operatedMachines
        # then the giverObjects have to be blocked for the time
        # that the machine is being loaded
        from Globals import G
        G.AssemblyList.append(self)
Example #36
0
    def __init__(self, id, name, interarrivalTime=None, entity='Dream.Part'):
        # Default values
        if not interarrivalTime:
          interarrivalTime = {'distributionType': 'Fixed', 'mean': 1}
        if interarrivalTime['distributionType'] == 'Normal' and\
              interarrivalTime.get('max', None) is None:
          interarrivalTime['max'] = interarrivalTime['mean'] + 5 * interarrivalTime['stdev']

        CoreObject.__init__(self, id, name)
        # properties used for statistics
        self.totalInterArrivalTime = 0                    # the total interarrival time 
        self.numberOfArrivals = 0                         # the number of entities that were created
#         # list containing objects that follow in the routing 
#         self.next=[]                                    # list with the next objects in the flow
#         self.nextIds=[]                                 # list with the ids of the next objects in the flow
#         self.previousIds=[]                             # list with the ids of the previous objects in the flow. 
#                                                         # For the source it is always empty!
        self.type="Source"                              #String that shows the type of object
        
        self.rng = RandomNumberGenerator(self, **interarrivalTime)

        self.item=Globals.getClassFromName(entity)       #the type of object that the Source will generate
Example #37
0
    def parseInputs(self, inputsDict):
        CoreObject.parseInputs(self, inputsDict)
        processingTime = inputsDict.get('processingTime', {})
        if not processingTime:
            processingTime = {
                'distributionType': 'Fixed',
                'mean': 0,
                'stdev': 0,
                'min': 0,
            }
        if processingTime['distributionType'] == 'Normal' and\
              processingTime.get('max', None) is None:
            processingTime['max'] = float(
                processingTime['mean']) + 5 * float(processingTime['stdev'])

        self.rng = RandomNumberGenerator(self, **processingTime)

        # ============================== variable that is used for the loading of machines =============
        self.exitAssignedToReceiver = False  # by default the objects are not blocked
        # when the entities have to be loaded to operatedMachines
        # then the giverObjects have to be blocked for the time
        # that the machine is being loaded
        from Globals import G
        G.AssemblyList.append(self)
Example #38
0
class Break(ObjectInterruption):
    def __init__(self,
                 id='',
                 name='',
                 victim=None,
                 distribution={},
                 endUnfinished=True,
                 offShiftAnticipation=0,
                 **kw):
        ObjectInterruption.__init__(self, id, name, victim=victim)
        self.rngTTB = RandomNumberGenerator(
            self, distribution.get('TTB', {'Fixed': {
                'mean': 100
            }}))
        self.rngTTR = RandomNumberGenerator(
            self, distribution.get('TTR', {'Fixed': {
                'mean': 10
            }}))
        self.type = "Break"
        # end current wip before going to break
        self.endUnfinished = endUnfinished
        # if the break is close to end of shift below a limit it will be suspended
        self.offShiftAnticipation = offShiftAnticipation

    def initialize(self):
        ObjectInterruption.initialize(self)
        self.victimStartsProcess = self.env.event()
        self.victimEndsProcess = self.env.event()

    # =======================================================================
    #    The run method for the break which has to served by a repairman
    # =======================================================================
    def run(self):
        from CoreObject import CoreObject
        from ObjectResource import ObjectResource

        while 1:
            # if the victim is off-shift wait for the victim to become on-shift
            if not self.victim.onShift:
                self.isWaitingForVictimOnShift = True
                self.expectedSignals['victimOnShift'] = 1
                yield self.victimOnShift
                self.victimOnShift = self.env.event()

            timeToBreak = self.rngTTB.generateNumber()
            remainingTimeToBreak = timeToBreak

            self.expectedSignals['victimOffShift'] = 1
            self.isWaitingForVictimOffShift = True

            # wait for the break or the end off shift of the victim
            receivedEvent = yield self.env.any_of(
                [self.env.timeout(remainingTimeToBreak), self.victimOffShift])

            # if the victim became off shift the loop should start again (to wait on-shift etc)
            if self.victimOffShift in receivedEvent:
                transmitter, eventTime = self.victimOffShift.value
                assert eventTime == self.env.now, 'victimOffShift was triggered earlier, not now'
                # reset the signalparam of the victimOffShift event
                self.victimOffShift = self.env.event()
                continue

            # check if we are close to the end of the shift. If yes then the break may be suspended
            # (depending on offShiftAnticipation)
            timeToNextOfShift = None
            for oi in self.victim.objectInterruptions:
                if oi.type == 'ShiftScheduler':
                    if oi.remainingShiftPattern:
                        timeToNextOfShift = oi.remainingShiftPattern[0][1]
            if timeToNextOfShift:
                if self.offShiftAnticipation >= timeToNextOfShift - self.env.now:
                    continue

            # interrupt the victim
            # if the victim is station
            if issubclass(self.victim.__class__, CoreObject):
                # if the mode is to end current work before going to break and there is current work,
                # wait for victimEndedLastProcessing or victimFailed
                # signal before going into break
                if self.endUnfinished and self.victim.isProcessing:
                    self.victim.isWorkingOnTheLast = True
                    self.waitingSignal = True
                    self.expectedSignals['endedLastProcessing'] = 1
                    self.expectedSignals['victimFailed'] = 1
                    receivedEvent = yield self.env.any_of(
                        [self.victim.endedLastProcessing, self.victimFailed])
                    if self.victim.endedLastProcessing in receivedEvent:
                        transmitter, eventTime = self.victim.endedLastProcessing.value
                        self.victim.endedLastProcessing = self.env.event()
                    elif self.victimFailed in receivedEvent:
                        transmitter, eventTime = self.victimFailed.value
                        self.victimFailed = self.env.event()
                self.interruptVictim()
            # if the victim is operator
            elif issubclass(self.victim.__class__, ObjectResource):
                # if the operator is working in a station and the mode is
                # to stop current work in the end of shift
                # signal to the station that the operator has to leave
                station = self.victim.workingStation
                if station:
                    if not self.endUnfinished and station.expectedSignals[
                            'processOperatorUnavailable']:
                        self.sendSignal(
                            receiver=station,
                            signal=station.processOperatorUnavailable)
                if self.victim.schedule:
                    if not self.victim.schedule[-1].get("exitTime", None):
                        self.victim.schedule[-1]["exitTime"] = self.env.now
                self.victim.schedule.append({
                    "station": {
                        'id': 'on-break'
                    },
                    "entranceTime": self.env.now
                })
                self.requestAllocation()

            self.victim.timeLastBreakStarted = self.env.now
            self.victim.onBreak = True  # get the victim on break
            self.outputTrace(self.victim.name, "starts break")
            # update the break time
            breakTime = self.env.now

            self.expectedSignals['victimOffShift'] = 1
            self.isWaitingForVictimOffShift = True

            # wait for the break or the end off shift of the victim
            receivedEvent = yield self.env.any_of([
                self.env.timeout(self.rngTTR.generateNumber()),
                self.victimOffShift
            ])

            # if the victim became off shift the break is considered over and
            # the loop should start again (to wait on-shift etc)
            if self.victimOffShift in receivedEvent:
                transmitter, eventTime = self.victimOffShift.value
                assert eventTime == self.env.now, 'victimOffShift was triggered earlier, not now'
                # reset the signalparam of the victimOffShift event
                self.victimOffShift = self.env.event()
                self.outputTrace(self.victim.name,
                                 "went off-shift so not on break anymore")
            else:
                self.outputTrace(self.victim.name, "returns from break")

            if issubclass(self.victim.__class__, CoreObject):
                self.reactivateVictim(
                )  # re-activate the victim in case it was interrupted
            else:
                if self.victim.schedule:
                    if not self.victim.schedule[-1].get("exitTime", None):
                        self.victim.schedule[-1]["exitTime"] = self.env.now
                self.requestAllocation()

            self.victim.timeLastBreakEnded = self.env.now
            self.victim.totalBreakTime += self.env.now - breakTime
            self.victim.onBreak = False  # get the victim on break
Example #39
0
class PeriodicMaintenance(ObjectInterruption):
    def __init__(self, id="", name="", victim=None, distribution=None, index=0, repairman=None, **kw):
        ObjectInterruption.__init__(self, id, name, victim=victim)
        self.rngTTF = RandomNumberGenerator(self, distribution.get("TTF", {"Fixed": {"mean": 100}}))
        self.rngTTR = RandomNumberGenerator(self, distribution.get("TTR", {"Fixed": {"mean": 10}}))
        self.name = "F" + str(index)
        self.repairman = repairman  # the resource that may be needed to fix the failure
        # if now resource is needed this will be "None"
        self.type = "PeriodicMaintenance"

    def initialize(self):
        ObjectInterruption.initialize(self)
        self.victimStartsProcess = self.env.event()
        self.victimEndsProcess = self.env.event()

    # =======================================================================
    #    The run method for the failure which has to served by a repairman
    # =======================================================================
    def run(self):
        while 1:
            # if the time that the victim is off-shift should not be counted
            timeToFailure = self.rngTTF.generateNumber()
            remainingTimeToFailure = timeToFailure
            failureNotTriggered = True

            yield self.env.timeout(remainingTimeToFailure)

            if self.victim.isProcessing:
                self.victim.isWorkingOnTheLast = True
                self.waitingSignal = True
                self.expectedSignals["endedLastProcessing"] = 1
                self.expectedSignals["victimFailed"] = 1
                receivedEvent = yield self.env.any_of([self.victim.endedLastProcessing, self.victimFailed])
                if self.victim.endedLastProcessing in receivedEvent:
                    transmitter, eventTime = self.victim.endedLastProcessing.value
                    self.victim.endedLastProcessing = self.env.event()
                elif self.victimFailed in receivedEvent:
                    transmitter, eventTime = self.victimFailed.value
                    self.victimFailed = self.env.event()

            # interrupt the victim
            self.interruptVictim()  # interrupt the victim

            # check in the ObjectInterruptions of the victim. If there is a one that is waiting for victimFailed send it
            for oi in self.victim.objectInterruptions:
                if oi.expectedSignals["victimFailed"]:
                    self.sendSignal(receiver=oi, signal=oi.victimFailed)
            self.victim.Up = False
            self.victim.timeLastFailure = self.env.now
            self.outputTrace(self.victim.name, "is down")
            # update the failure time
            failTime = self.env.now
            if self.repairman and self.repairman != "None":  # if the failure needs a resource to be fixed,
                # the machine waits until the
                # resource is available

                with self.repairman.getResource().request() as request:
                    yield request
                    # update the time that the repair started
                    timeOperationStarted = self.env.now
                    self.repairman.timeLastOperationStarted = self.env.now

                    yield self.env.timeout(self.rngTTR.generateNumber())  # wait until the repairing process is over
                    self.victim.totalFailureTime += self.env.now - failTime
                    self.reactivateVictim()  # since repairing is over, the Machine is reactivated
                    self.victim.Up = True
                    self.outputTrace(self.victim.name, "is up")

                    self.repairman.totalWorkingTime += self.env.now - timeOperationStarted
                continue

            yield self.env.timeout(self.rngTTR.generateNumber())  # wait until the repairing process is over

            # add the failure
            # if victim is off shift add only the fail time before the shift ended
            if not self.victim.onShift and failTime < self.victim.timeLastShiftEnded:
                self.victim.totalFailureTime += self.victim.timeLastShiftEnded - failTime
            # if the victim was off shift since the start of the failure add nothing
            elif not self.victim.onShift and failTime >= self.victim.timeLastShiftEnded:
                pass
            # if victim was off shift in the start of the fail time, add on
            elif self.victim.onShift and failTime < self.victim.timeLastShiftStarted:
                self.victim.totalFailureTime += self.env.now - self.victim.timeLastShiftStarted
                # this can happen only if deteriorationType is constant
                assert (
                    self.deteriorationType == "constant"
                ), "object got failure while off-shift and deterioration type not constant"
            else:
                self.victim.totalFailureTime += self.env.now - failTime
            self.reactivateVictim()  # since repairing is over, the Machine is reactivated
            self.victim.Up = True
            self.outputTrace(self.victim.name, "is up")
Example #40
0
class Source(CoreObject):
    def __init__(self, id, name, interarrivalTime=None, entity='Dream.Part'):
        # Default values
        if not interarrivalTime:
          interarrivalTime = {'distributionType': 'Fixed', 'mean': 1}
        if interarrivalTime['distributionType'] == 'Normal' and\
              interarrivalTime.get('max', None) is None:
          interarrivalTime['max'] = interarrivalTime['mean'] + 5 * interarrivalTime['stdev']

        CoreObject.__init__(self, id, name)
        # properties used for statistics
        self.totalInterArrivalTime = 0                    # the total interarrival time 
        self.numberOfArrivals = 0                         # the number of entities that were created
#         # list containing objects that follow in the routing 
#         self.next=[]                                    # list with the next objects in the flow
#         self.nextIds=[]                                 # list with the ids of the next objects in the flow
#         self.previousIds=[]                             # list with the ids of the previous objects in the flow. 
#                                                         # For the source it is always empty!
        self.type="Source"                              #String that shows the type of object
        
        self.rng = RandomNumberGenerator(self, **interarrivalTime)

        self.item=Globals.getClassFromName(entity)       #the type of object that the Source will generate
        
    def initialize(self):
        # using the Process __init__ and not the CoreObject __init__
        CoreObject.initialize(self)
         
        # initialize the internal Queue (type Resource) of the Source 
        self.Res=Resource(capacity=infinity)
        self.Res.activeQ=[]                                 
        self.Res.waitQ=[]                                   
        
    def run(self):
        # get active object and its queue
        activeObject=self.getActiveObject()
        activeObjectQueue=self.getActiveObjectQueue()
        
        while 1:
            entity=self.createEntity()                            # create the Entity object and assign its name 
            entity.creationTime=now()                             # assign the current simulation time as the Entity's creation time 
            entity.startTime=now()                                # assign the current simulation time as the Entity's start time 
            entity.currentStation=self                            # update the current station of the Entity
            G.EntityList.append(entity)
            self.outputTrace(entity.name, "generated")          # output the trace
            activeObjectQueue.append(entity)                      # append the entity to the resource 
            self.numberOfArrivals+=1                              # we have one new arrival
            G.numberOfEntities+=1       
            yield hold,self,self.calculateInterarrivalTime()      # wait until the next arrival
    #============================================================================
    #            sets the routing out element for the Source
    #============================================================================
    def defineRouting(self, successorList=[]):
        self.next=successorList                                   # only successors allowed for the source
    #============================================================================        
    #                          creates an Entity
    #============================================================================
    def createEntity(self):
        return self.item(id = self.item.type+str(G.numberOfEntities), name = self.item.type+str(self.numberOfArrivals)) #return the newly created Entity
    #============================================================================
    #                    calculates the processing time
    #============================================================================
    def calculateInterarrivalTime(self):
        return self.rng.generateNumber()    #this is if we have a default interarrival  time for all the entities
Example #41
0
from implement_observers import DigitObserver, GraphObserver
from RandomNumberGenerator import RandomNumberGenerator


if __name__ == "__main__":
    generator = RandomNumberGenerator()

    observer1 = DigitObserver()
    observer2 = GraphObserver()

    generator.add_observer(observer1)
    generator.add_observer(observer2)

    generator.execute()
Example #42
0
class PeriodicMaintenance(ObjectInterruption):
    
    def __init__(self, id='',name='',victim=None, distribution=None, index=0, repairman=None,**kw):
        ObjectInterruption.__init__(self,id,name,victim=victim)
        self.rngTTF=RandomNumberGenerator(self, distribution.get('TTF',{'Fixed':{'mean':100}}))
        self.rngTTR=RandomNumberGenerator(self, distribution.get('TTR',{'Fixed':{'mean':10}}))
        self.name="F"+str(index)
        self.repairman=repairman        # the resource that may be needed to fix the failure
                                        # if now resource is needed this will be "None" 
        self.type="PeriodicMaintenance"
        

    def initialize(self):
        ObjectInterruption.initialize(self)
        self.victimStartsProcess=self.env.event()
        self.victimEndsProcess=self.env.event()       
        
    # =======================================================================
    #    The run method for the failure which has to served by a repairman
    # =======================================================================
    def run(self):     
        while 1:
            # if the time that the victim is off-shift should not be counted
            timeToFailure=self.rngTTF.generateNumber()
            remainingTimeToFailure=timeToFailure
            failureNotTriggered=True
            
            yield self.env.timeout(remainingTimeToFailure)
 
            if self.victim.isProcessing:
                self.victim.isWorkingOnTheLast=True
                self.waitingSignal=True
                self.expectedSignals['endedLastProcessing']=1
                self.expectedSignals['victimFailed']=1
                receivedEvent=yield self.env.any_of([self.victim.endedLastProcessing , self.victimFailed])
                if self.victim.endedLastProcessing in receivedEvent:
                    transmitter, eventTime=self.victim.endedLastProcessing.value
                    self.victim.endedLastProcessing=self.env.event()
                elif self.victimFailed in receivedEvent:
                    transmitter, eventTime=self.victimFailed.value
                    self.victimFailed=self.env.event()
           
            # interrupt the victim
            self.interruptVictim()                      # interrupt the victim
            
            # check in the ObjectInterruptions of the victim. If there is a one that is waiting for victimFailed send it
            for oi in self.victim.objectInterruptions:
                if oi.expectedSignals['victimFailed']:
                    self.sendSignal(receiver=oi, signal=oi.victimFailed)
            self.victim.Up=False
            self.victim.timeLastFailure=self.env.now           
            self.outputTrace(self.victim.name,"is down")
            # update the failure time
            failTime=self.env.now    
            if(self.repairman and self.repairman!="None"):     # if the failure needs a resource to be fixed, 
                                                               # the machine waits until the 
                                                               # resource is available
                
                with self.repairman.getResource().request() as request:
                    yield request
                    # update the time that the repair started
                    timeOperationStarted=self.env.now
                    self.repairman.timeLastOperationStarted=self.env.now
                    
                    yield self.env.timeout(self.rngTTR.generateNumber())    # wait until the repairing process is over
                    self.victim.totalFailureTime+=self.env.now-failTime    
                    self.reactivateVictim()                     # since repairing is over, the Machine is reactivated
                    self.victim.Up=True              
                    self.outputTrace(self.victim.name,"is up")
                    
                    self.repairman.totalWorkingTime+=self.env.now-timeOperationStarted   
                continue
                
                
                                
            yield self.env.timeout(self.rngTTR.generateNumber())    # wait until the repairing process is over
            
            # add the failure
            # if victim is off shift add only the fail time before the shift ended
            if not self.victim.onShift and failTime < self.victim.timeLastShiftEnded:
                self.victim.totalFailureTime+=self.victim.timeLastShiftEnded-failTime
            # if the victim was off shift since the start of the failure add nothing
            elif not self.victim.onShift and failTime >= self.victim.timeLastShiftEnded:
                pass
            # if victim was off shift in the start of the fail time, add on
            elif self.victim.onShift and failTime < self.victim.timeLastShiftStarted:
                self.victim.totalFailureTime+=self.env.now-self.victim.timeLastShiftStarted
                # this can happen only if deteriorationType is constant
                assert self.deteriorationType=='constant', 'object got failure while off-shift and deterioration type not constant' 
            else:
                self.victim.totalFailureTime+=self.env.now-failTime   
            self.reactivateVictim()                     # since repairing is over, the Machine is reactivated
            self.victim.Up=True              
            self.outputTrace(self.victim.name,"is up")
Example #43
0
class MouldAssembly(MachineJobShop):

    # =======================================================================
    # parses inputs if they are given in a dictionary
    # =======================================================================
    def parseInputs(self, **kw):
        from Globals import G
        G.MouldAssemblyList.append(self)

    # =======================================================================
    # the initialize method
    # =======================================================================
    def initialize(self):
        self.mouldParent = None  # the mould's to be assembled parent order
        self.mouldToBeCreated = None  # the mould to be assembled
        MachineJobShop.initialize(self)  # run default behaviour

    # =======================================================================
    # getEntity method that gets the entity from the giver
    # it should run in a loop till it get's all the entities from the same order
    # (with the flag componentsReadyForAssembly set)
    # it is run only once, and receives all the entities to be assembled inside a while loop
    # =======================================================================
    def getEntity(self):
        activeObject = self.getActiveObject()
        giverObject = activeObject.getGiverObject()
        # get the first entity from the predecessor
        # TODO: each MachineJobShop.getEntity is invoked,
        #     the self.procTime is updated. Have to decide where to assign
        #     the processing time of the assembler
        activeEntity = MachineJobShop.getEntity(self)
        # this is kept so that in the next loop it will not try to re-get this Entity
        firstObtained = activeEntity
        # check weather the activeEntity is of type Mould
        if activeEntity.type == 'Mould':
            # and return the mould received
            return activeEntity
        # otherwise, collect all the entities to be assembled

        # read the number of basic and secondary components of the moulds
        capacity = len(activeEntity.order.getAssemblyComponents())
        # clear the active object queue
        del activeObject.getActiveObjectQueue()[:]
        # and set the capacity of the internal queue of the assembler
        activeObject.updateCapacity(capacity)
        # append the activeEntity to the activeObjectQueue
        activeObjectQueue = activeObject.getActiveObjectQueue()
        activeObjectQueue.append(activeEntity)
        # loop through the basic/secondary components of the order that is currently obtained
        # all the components are received at the same time
        for entity in activeEntity.order.getAssemblyComponents():
            # continue for the one that is already  obtained before
            if entity is firstObtained:
                continue

            self.entityToGet = entity
            # get the next component
            activeEntity = MachineJobShop.getEntity(self)
            # check whether the activeEntity is of type Mould
            try:
                if activeEntity.type == 'Mould':
                    # and return the mould received
                    raise AssembleMouldError(
                        'Having already received an orderComponent the assembler\
                                                is not supposed to receive an object of type Mould'
                    )
            # check if the last component received has the same parent order as the previous one
                elif not (activeEntity.order is activeObjectQueue[1].order):
                    raise AssembleMouldError(
                        'The orderComponents received by the assembler must have the\
                                                same parent order')
            except AssembleMouldError as mouldError:
                print 'Mould Assembly Error: {0}'.format(mouldError)
                return False
        # perform the assembly-action and return the assembled mould
        activeEntity = activeObject.assemble()
        return activeEntity

    # =======================================================================
    # method that updates the capacity according to the componentsList of the
    # activeEntity's parent order
    # =======================================================================
    def updateCapacity(self, capacity):
        activeObject = self.getActiveObject()
        self.capacity = capacity
        self.Res = simpy.Resource(self.env, self.capacity)

    # =======================================================================
    #     assemble method that assembles the components together to a mould (order
    # and returns the product of the assembly. Furthermore, it resets the capacity
    # of the internal queue to 1
    # =======================================================================
    def assemble(self):
        activeObject = self.getActiveObject()
        # get the internal queue of the active core object
        activeObjectQueue = activeObject.getActiveObjectQueue()
        # assert that all the components are of the same parent order
        for entity in activeObjectQueue:
            assert entity.order==activeObjectQueue[0].order,\
                'The components residing in the MouldAssembly internal queue\
                are not of the same parent order!'

        # if we have to create a new Entity (mould) this should be modified
        # we need the new entity's route, priority, isCritical flag, etc.
        self.mouldParent = activeObjectQueue[0].order
        # assert that there is a parent order
        assert self.mouldParent.type == 'Order', 'the type of the assembled to be mould\' s parent is not correct'
        # delete the contents of the internal queue
        temp_activeObjectQueue = list(activeObjectQueue)
        for element in temp_activeObjectQueue:
            # update their schedule
            element.schedule[-1]["exitTime"] = self.env.now
            # remove the elements from the activeObjectQueue and reset the current station of the entity
            activeObjectQueue.remove(element)
            element.currentStation = None
        del temp_activeObjectQueue[:]
        # after assembling reset the capacity
        activeObject.updateCapacity(1)
        #if there is a mould to be assembled
        try:
            if self.mouldParent:
                # find the component which is of type Mould
                # there must be only one mould component
                for entity in self.mouldParent.componentsList:
                    entityClass = entity.get('_class', None)
                    if entityClass == 'Dream.Mould':
                        self.mouldToBeCreated = entity
                        break
                # create the mould
                self.createMould(self.mouldToBeCreated)
                # check if there is a need for manual processing
                self.checkForManualOperation(type='Processing',
                                             entity=self.mouldToBeCreated)
                # check if there is a need for manual processing
                self.checkForManualOperation(type='Setup',
                                             entity=self.mouldToBeCreated)
                # set the created mould as WIP
                import Globals
                Globals.setWIP([self.mouldToBeCreated])
                # read the activeObjectQueue again as it has been updated by the setWIP()
                activeObjectQueue = activeObject.getActiveObjectQueue()
                # reset attributes
                self.mouldParent = None
                self.mouldToBeCreated = None
                # return the assembled mould
                return activeObjectQueue[0]
            else:
                raise AssembleMouldError('There is no mould to be assembled')
        except AssembleMouldError as mouldError:
            print 'Mould Assembly Error: {0}'.format(mouldError)

    # =======================================================================
    # creates the mould
    # =======================================================================
    def createMould(self, component):
        #read attributes from the json or from the orderToBeDecomposed
        id = component.get('id', 'not found')
        name = component.get('name', 'not found')
        try:
            # dummy variable that holds the routes of the jobs the route from the JSON file is a sequence of dictionaries
            JSONRoute = component.get('route', [])
            # variable that holds the argument used in the Job initiation hold None for each entry in the 'route' list
            route = [x for x in JSONRoute]  #    copy JSONRoute
            # assert that the assembler is in the moulds route and update the initial step of the mould's route
            firstStep = route.pop(0)
            assert (self.id in firstStep.get('stationIdsList',[])),\
                         'the assembler must be in the mould-to-be-created route\' initial step'
            # normal processing operation
            processingTime = firstStep['processingTime']
            processingTime = self.getOperationTime(processingTime)
            self.rng = RandomNumberGenerator(self, processingTime)
            self.procTime = self.rng.generateNumber()
            # update the activeObject's processing time according to the readings in the mould's route
            processDistType = processingTime.keys()[0]
            procTime = float(processingTime[processDistType].get('mean', 0))
            processOpType = firstStep.get('operationType', {}).get(
                'Processing', 'not found')  # can be manual/automatic
            # task_id
            task_id = firstStep.get('task_id', None)
            # sequence
            sequence = firstStep.get('sequence', None)
            # operator
            operator = firstStep.get('operator', {})
            # technology
            technology = firstStep.get('technology', None)
            # quantity
            quantity = firstStep.get('quantity', None)
            # setup operation
            setupTime = firstStep.get('setupTime', None)
            if setupTime:
                setupTime = self.getOperationTime(setupTime)
                self.stpRng = RandomNumberGenerator(self, setupTime)
                # update the activeObject's processing time according to the readings in the mould's route
                setupDistType = setupTime.keys()[0]
                setTime = float(setupTime[setupDistType].get('mean', 0))
                setupOpType = firstStep.get('operationType', {}).get(
                    'Setup', 'not found')  # can be manual/automatic
                # update the first step of the route with the activeObjects id as sole element of the stationIdsList
                route.insert(0, {'stationIdsList':[str(self.id)],
                                 'processingTime':{str(processDistType):{'mean':str(procTime)}},\
                                 'setupTime':{str(setupDistType):{'mean':str(setupTime)}},
                                 'operationType':{'Processing':processOpType,'Setup':setupOpType}})
            else:
                # update the first step of the route with the activeObjects id as sole element of the stationIdsList
                route.insert(
                    0, {
                        'stationIdsList': [str(self.id)],
                        'processingTime': {
                            str(processDistType): {
                                'mean': str(procTime)
                            }
                        },
                        'operationType': {
                            'Processing': processOpType
                        }
                    })
            # if there is task_id then add it to the route
            if task_id:
                route[0]["task_id"] = task_id
            # if there is sequence then add it to the route
            if sequence:
                route[0]["sequence"] = sequence
            # if there is operator then add it to the route
            if operator:
                route[0]["operator"] = operator
            # if there is technology then add it to the route
            if technology:
                route[0]["technology"] = technology
            # if there is quantity then add it to the route
            if quantity != None:
                route[0]["quantity"] = quantity
            #Below it is to assign an exit if it was not assigned in JSON
            #have to talk about it with NEX
            exitAssigned = False
            for element in route:
                elementIds = element.get('stationIdsList', [])
                for obj in G.ObjList:
                    for elementId in elementIds:
                        if obj.id == elementId and obj.type == 'Exit':
                            exitAssigned = True
            # assign an exit to the route of the mould
            if not exitAssigned:
                exitId = None
                for obj in G.ObjList:
                    if obj.type == 'Exit':
                        exitId = obj.id
                        break
                if exitId:
                    route.append({
                        'stationIdsList': [str(exitId)],
                        'processingTime': {}
                    })
            # keep a reference of all extra properties passed to the job
            extraPropertyDict = {}
            for key, value in component.items():
                if key not in ('_class', 'id'):
                    extraPropertyDict[key] = value
            # create and initiate the OrderComponent
            from Mould import Mould
            M=Mould(id, name, route, \
                              priority=self.mouldParent.priority, \
                              order=self.mouldParent,\
                              dueDate=self.mouldParent.dueDate, \
                              orderDate=self.mouldParent.orderDate, \
                              extraPropertyDict=extraPropertyDict,\
                              isCritical=self.mouldParent.isCritical)
            # update the mouldToBeCreated
            self.mouldToBeCreated = M
            G.JobList.append(M)
            G.WipList.append(M)
            G.EntityList.append(M)
            G.MouldList.append(M)
            #initialize the component
            M.initialize()
        except:
            # added for testing
            print 'the mould to be created', component.get(
                'name', 'not found'), 'cannot be created', 'time', self.env.now
            raise
Example #44
0
class MachineJobShop(Machine):    
    # =======================================================================
    # set all the objects in previous and next
    # =======================================================================
    def initialize(self):
        from Globals import G
        self.previous=G.ObjList
        self.next=[]
        Machine.initialize(self)    #run default behaviour
    
    # =======================================================================
    # gets an entity from the predecessor that the predecessor index points to
    # =======================================================================     
    def getEntity(self):
        activeObject=self.getActiveObject()
        activeEntity=Machine.getEntity(self)     #run the default code
        # read the processing time from the corresponding remainingRoute entry
        processingTime=activeEntity.remainingRoute[0].get('processingTime',{})
        processingTime=self.getOperationTime(processingTime)
        self.rng=RandomNumberGenerator(self, processingTime)
        self.procTime=self.rng.generateNumber()
        # check if there is a need for manual processing
        self.checkForManualOperation(type='Processing',entity=activeEntity)
        # read the setup time from the corresponding remainingRoute entry
        setupTime=activeEntity.remainingRoute[0].get('setupTime',{})
        setupTime=self.getOperationTime(setupTime)
        self.stpRng=RandomNumberGenerator(self, setupTime)
        # check if there is a need for manual processing
        self.checkForManualOperation(type='Setup',entity=activeEntity)
        activeEntity.currentStep = activeEntity.remainingRoute.pop(0)      #remove data from the remaining route of the entity
        if activeEntity.currentStep:
            # update the task_id of the currentStep dict within the schedule
            try:
                activeEntity.schedule[-1]["task_id"] = activeEntity.currentStep["task_id"]
                # if there is currentOperator then update the taskId of corresponding step of their schedule according to the task_id of the currentStep
                if self.currentOperator:
                    self.currentOperator.schedule[-1]["task_id"] = activeEntity.currentStep["task_id"]
            except KeyError:
                pass
        return activeEntity
    
    #===========================================================================
    # update the next list of the object based on the activeEentity
    #===========================================================================
    def updateNext(self,entity=None):
        activeObject = self.getActiveObject()
        activeEntity=entity
        # read the possible receivers - update the next list
        import Globals
        # XXX: in the case of MouldAssembler there is no next defined in the route of the entities that are received
        # the position activeEntity.remainingRoute[1] is out of bound. the next should be updated by the remaining route of the entity to be assembled
        if len(activeEntity.remainingRoute)>1:
            nextObjectIds=activeEntity.remainingRoute[1].get('stationIdsList',[])
            nextObjects = []
            for nextObjectId in nextObjectIds:
                nextObject = Globals.findObjectById(nextObjectId)
                nextObjects.append(nextObject)
            # update the next list of the object
            for nextObject in nextObjects:
                # append only if not already in the list
                if nextObject not in activeObject.next:
                    activeObject.next.append(nextObject)
                                                                             
    # =======================================================================  
    # calculates the processing time
    # =======================================================================
    def calculateProcessingTime(self):
        # this is only for processing of the initial wip
        if self.isProcessingInitialWIP:
            self.procTime = self.rng.generateNumber()
        return self.procTime    #this is the processing time for this unique entity  
    
    #===========================================================================
    # get the initial operation times (setup/processing); 
    # XXX initialy only setup time is calculated here
    #===========================================================================
    def calculateInitialOperationTimes(self):
        # read the setup/processing time from the first entry of the full route
        activeEntity=self.getActiveObjectQueue()[0]
        #if the entity has its route defined in the BOM then remainingProcessing/SetupTime is provided
        # XX consider moving setupUPtime update to checkForManualOperationTypes as Setup is performed before Processing
        if activeEntity.routeInBOM:
            processingTime=self.getOperationTime(activeEntity.remainingProcessingTime)
            setupTime=self.getOperationTime(activeEntity.remainingSetupTime)
        else:   # other wise these should be read from the route
            processingTime=activeEntity.route[0].get('processingTime',{})
            processingTime=self.getOperationTime(processingTime)
            setupTime=activeEntity.route[0].get('setupTime',{})
            setupTime=self.getOperationTime(setupTime)
        self.rng=RandomNumberGenerator(self, processingTime)
        self.stpRng=RandomNumberGenerator(self, setupTime)
                
    
    # =======================================================================
    # checks if the Queue can accept an entity       
    # it checks also the next station of the Entity 
    # and returns true only if the active object is the next station
    # ======================================================================= 
    def canAccept(self, callerObject=None):
        activeObjectQueue=self.Res.users
        thecaller=callerObject
        #return according to the state of the Queue
        # also check if (if the machine is to be operated) there are available operators
        if (self.operatorPool!='None' and (any(type=='Load' for type in self.multOperationTypeList))):
            return self.operatorPool.checkIfResourceIsAvailable()\
                    and len(activeObjectQueue)<self.capacity\
                    and self.checkIfMachineIsUp()\
                    and self.isInRouteOf(thecaller)\
                    and not self.entryIsAssignedTo()
        else:
            return len(activeObjectQueue)<self.capacity\
                    and self.checkIfMachineIsUp()\
                    and self.isInRouteOf(thecaller)\
                    and not self.entryIsAssignedTo()
                        
    #===========================================================================
    # method used to check whether the station is in the entity-to-be-received route
    #===========================================================================
    def isInRouteOf(self, callerObject=None):
        activeObjectQueue=self.Res.users
        thecaller=callerObject
        # if the caller is not defined then return True. We are only interested in checking whether 
        # the station can accept whatever entity from whichever giver
        if not thecaller:
            return True
        #check it the caller object holds an Entity that requests for current object
        if len(thecaller.Res.users)>0:
            # TODO: make sure that the first entity of the callerObject is to be disposed
            activeEntity=thecaller.Res.users[0]
            # if the machine's Id is in the list of the entity's next stations
            if self.id in activeEntity.remainingRoute[0].get('stationIdsList',[]):
                return True
        return False
    
    # =======================================================================   
    # checks if the Machine can dispose an entity. 
    # Returns True only to the potential receiver
    # =======================================================================     
    def haveToDispose(self, callerObject=None):
        activeObjectQueue=self.Res.users
        thecaller=callerObject
        #if we have only one successor just check if machine waits to dispose and also is up
        # this is done to achieve better (cpu) processing time
        if(callerObject==None):
            return len(activeObjectQueue)>0\
                 and self.waitToDispose\
                 and self.checkIfActive()\
        #return True if the Machine in the state of disposing and the caller is the receiver
        return len(activeObjectQueue)>0\
             and self.waitToDispose\
             and self.checkIfActive()\
             and thecaller.isInRouteOf(self)

    # =======================================================================
    # method to execute preemption
    # =======================================================================    
    def preempt(self):
#         self.printTrace(self.id,preempted='')
        activeEntity=self.Res.users[0] #get the active Entity
        #calculate the remaining processing time
        #if it is reset then set it as the original processing time
        if self.resetOnPreemption:
            remainingProcessingTime=self.procTime
        #else subtract the time that passed since the entity entered
        #(may need also failure time if there was. TO BE MELIORATED)
        else:
            remainingProcessingTime=self.procTime-(self.env.now-self.timeLastEntityEntered)
        #update the remaining route of activeEntity
        activeEntity.remainingRoute.insert(0, {'stationIdsList':[str(self.id)],\
                                               'processingTime':\
                                                    {'Fixed':{'mean':str(remainingProcessingTime)}}})
        activeEntity.remainingRoute.insert(0, {'stationIdsList':[str(self.lastGiver.id)],\
                                               'processingTime':{'Fixed':{'mean':'0'}}})   
        #set the receiver  as the object where the active entity was preempted from 
        self.receiver=self.lastGiver
        self.next=[self.receiver]
        self.waitToDispose=True                     #set that I have to dispose
        self.receiver.timeLastEntityEnded=self.env.now     #required to count blockage correctly in the preemptied station
        # TODO: use a signal and wait for it, reactivation is not recognised as interruption
#         reactivate(self)
        if self.expectedSignals['preemptQueue']:
            self.sendSignal(receiver=self, signal=self.preemptQueue)
        # TODO: consider the case when a failure has the Station down. The event preempt will not be received now()
        #     but at a later simulation time. 
            
    #===========================================================================
    # extend the default behaviour to check if whether the station 
    #     is in the route of the entity to be received
    #===========================================================================
    def canAcceptAndIsRequested(self,callerObject):
        giverObject=callerObject
        assert giverObject, 'there must be a caller for canAcceptAndIsRequested'
        if self.isInRouteOf(giverObject):
            if Machine.canAcceptAndIsRequested(self,giverObject):
                self.readLoadTime(giverObject)
                return True
        return False

    #===========================================================================
    # to be called by canAcceptAndIsRequested if it is to return True.
    # the load time of the Entity must be read
    #===========================================================================
    def readLoadTime(self,callerObject=None):
        assert callerObject!=None, 'the caller of readLoadTime cannot be None'
        thecaller=callerObject
        thecaller.sortEntities()
        activeEntity=thecaller.Res.users[0]
        # read the load time from the corresponding remainingRoute entry
        loadTime=activeEntity.remainingRoute[0].get('loadTime',{})
        loadTime=self.getOperationTime(loadTime)
        self.loadRng=RandomNumberGenerator(self, loadTime)
    
    #===========================================================================
    # get the initial operationTypes (Setup/Processing) : manual or automatic
    #===========================================================================
    def checkInitialOperationTypes(self):
        # check if manual Setup is required
        self.checkForManualOperation(type='Setup')
        # check if manual Processing is required
        self.checkForManualOperation(type='Processing')
    
    #===========================================================================
    # check if the operation defined as an argument requires manual operation
    #===========================================================================
    def checkForManualOperation(self,type,entity=None):
        typeDict={'Setup':'setupTime', 'Processing':'processingTime'}
        assert type!=None, 'a type must be defined for the checkForManualOperation method'
        if not entity:
            activeEntity=self.getActiveObjectQueue()[0]
        else:
            activeEntity=entity
        # read the definition of the time from the remainingRoute dict
        if not self.isProcessingInitialWIP:
            operationTypeDict=activeEntity.remainingRoute[0].get('operationType',{})
            operationType=operationTypeDict.get(str(type),'not defined')
        else: # if the active entity is initialWIP at the start of simulation
            operationType=activeEntity.initialOperationTypes.get(str(type),'not defined')
        # if the operationType is not 'not defined'
        if operationType!='not defined':
            # if the operationType key has value 1 (manual operation)
            if operationType:
                # add setup to the multOpeartionTypeList
                if not type in self.multOperationTypeList:
                    self.multOperationTypeList.append(str(type))
            else:   # otherwise remove it from the multOperationTypeList
                if type in self.multOperationTypeList:
                    self.multOperationTypeList.remove(str(type))
        
    # =======================================================================
    # removes an entity from the Machine
    # extension to remove possible receivers accordingly
    # =======================================================================
    def removeEntity(self, entity=None):
        receiverObject=self.receiver  
        activeEntity=Machine.removeEntity(self, entity)         #run the default method  
        removeReceiver=True 
        # search in the internalQ. If an entity has the same receiver do not remove
        for ent in self.Res.users:
            nextObjectIds=ent.remainingRoute[0].get('stationIdsList',[])
            if receiverObject.id in nextObjectIds:
                removeReceiver=False      
        # if not entity had the same receiver then the receiver will be removed    
        if removeReceiver:
            self.next.remove(receiverObject)
        return activeEntity
Example #45
0
class Break(ObjectInterruption):
    
    def __init__(self, id='',name='',victim=None, distribution={},
                 endUnfinished=True,offShiftAnticipation=0,**kw):
        ObjectInterruption.__init__(self,id,name,victim=victim)
        self.rngTTB=RandomNumberGenerator(self, distribution.get('TTB',{'Fixed':{'mean':100}}))
        self.rngTTR=RandomNumberGenerator(self, distribution.get('TTR',{'Fixed':{'mean':10}}))
        self.type="Break"
        # end current wip before going to break
        self.endUnfinished=endUnfinished
        # if the break is close to end of shift below a limit it will be suspended
        self.offShiftAnticipation=offShiftAnticipation

    def initialize(self):
        ObjectInterruption.initialize(self)
        self.victimStartsProcess=self.env.event()
        self.victimEndsProcess=self.env.event()       
        
    # =======================================================================
    #    The run method for the break which has to served by a repairman
    # =======================================================================
    def run(self):     
        from CoreObject import CoreObject
        from ObjectResource import ObjectResource
        
        while 1:
            # if the victim is off-shift wait for the victim to become on-shift
            if not self.victim.onShift:
                self.isWaitingForVictimOnShift=True
                self.expectedSignals['victimOnShift']=1
                yield self.victimOnShift
                self.victimOnShift=self.env.event()                
                
            timeToBreak=self.rngTTB.generateNumber()
            remainingTimeToBreak=timeToBreak
            
            self.expectedSignals['victimOffShift']=1
            self.isWaitingForVictimOffShift=True
            
            # wait for the break or the end off shift of the victim
            receivedEvent = yield self.env.any_of([self.env.timeout(remainingTimeToBreak),self.victimOffShift])
            
            # if the victim became off shift the loop should start again (to wait on-shift etc)
            if self.victimOffShift in receivedEvent:
                transmitter, eventTime=self.victimOffShift.value
                assert eventTime==self.env.now, 'victimOffShift was triggered earlier, not now'
                # reset the signalparam of the victimOffShift event
                self.victimOffShift=self.env.event()
                continue
            
            # check if we are close to the end of the shift. If yes then the break may be suspended 
            # (depending on offShiftAnticipation)
            timeToNextOfShift=None
            for oi in self.victim.objectInterruptions:
                if oi.type=='ShiftScheduler':
                    if oi.remainingShiftPattern:
                        timeToNextOfShift=oi.remainingShiftPattern[0][1]
            if timeToNextOfShift:
                if self.offShiftAnticipation>=timeToNextOfShift-self.env.now:
                    continue
          
            # interrupt the victim
            # if the victim is station
            if issubclass(self.victim.__class__, CoreObject):
                # if the mode is to end current work before going to break and there is current work, 
                # wait for victimEndedLastProcessing or victimFailed
                # signal before going into break
                if self.endUnfinished and self.victim.isProcessing:
                    self.victim.isWorkingOnTheLast=True
                    self.waitingSignal=True
                    self.expectedSignals['endedLastProcessing']=1
                    self.expectedSignals['victimFailed']=1
                    receivedEvent=yield self.env.any_of([self.victim.endedLastProcessing , self.victimFailed])
                    if self.victim.endedLastProcessing in receivedEvent:
                        transmitter, eventTime=self.victim.endedLastProcessing.value
                        self.victim.endedLastProcessing=self.env.event()
                    elif self.victimFailed in receivedEvent:
                        transmitter, eventTime=self.victimFailed.value
                        self.victimFailed=self.env.event()
                self.interruptVictim()
            # if the victim is operator
            elif issubclass(self.victim.__class__, ObjectResource):
                # if the operator is working in a station and the mode is 
                # to stop current work in the end of shift
                # signal to the station that the operator has to leave
                station=self.victim.workingStation
                if station:
                    if not self.endUnfinished and station.expectedSignals['processOperatorUnavailable']:
                        self.sendSignal(receiver=station, signal=station.processOperatorUnavailable)
                if self.victim.schedule:
                    if not self.victim.schedule[-1].get("exitTime", None):
                        self.victim.schedule[-1]["exitTime"] = self.env.now
                self.victim.schedule.append({"station": {'id':'on-break'},
                                             "entranceTime": self.env.now})
                self.requestAllocation()
            
            self.victim.timeLastBreakStarted=self.env.now     
            self.victim.onBreak=True                        # get the victim on break     
            self.outputTrace(self.victim.name,"starts break")
            # update the break time
            breakTime=self.env.now                

            self.expectedSignals['victimOffShift']=1
            self.isWaitingForVictimOffShift=True
            
            # wait for the break or the end off shift of the victim
            receivedEvent = yield self.env.any_of([self.env.timeout(self.rngTTR.generateNumber()),self.victimOffShift])

            # if the victim became off shift the break is considered over and 
            # the loop should start again (to wait on-shift etc)
            if self.victimOffShift in receivedEvent:
                transmitter, eventTime=self.victimOffShift.value
                assert eventTime==self.env.now, 'victimOffShift was triggered earlier, not now'
                # reset the signalparam of the victimOffShift event
                self.victimOffShift=self.env.event()
                self.outputTrace(self.victim.name,"went off-shift so not on break anymore") 
            else:
                self.outputTrace(self.victim.name,"returns from break")    

            if issubclass(self.victim.__class__, CoreObject): 
                self.reactivateVictim()                 # re-activate the victim in case it was interrupted
            else:
                if self.victim.schedule:
                    if not self.victim.schedule[-1].get("exitTime", None):
                        self.victim.schedule[-1]["exitTime"] = self.env.now
                self.requestAllocation()
            
            self.victim.timeLastBreakEnded=self.env.now     
            self.victim.totalBreakTime+=self.env.now-breakTime  
            self.victim.onBreak=False                        # get the victim on break     
Example #46
0
class MachineJobShop(Machine):    
    # =======================================================================
    # set all the objects in previous and next
    # =======================================================================
    def initialize(self):
        from Globals import G
        self.previous=G.ObjList
        self.next=[]
        Machine.initialize(self)    #run default behaviour
    
    # =======================================================================
    # gets an entity from the predecessor that the predecessor index points to
    # =======================================================================     
    def getEntity(self):
        activeObject=self.getActiveObject()
        activeEntity=Machine.getEntity(self)     #run the default code
        # read the processing time from the corresponding remainingRoute entry
        processingTime=activeEntity.remainingRoute[0].get('processingTime',{})
        processingTime=self.getOperationTime(processingTime)
        self.rng=RandomNumberGenerator(self, processingTime)
        self.procTime=self.rng.generateNumber()
        # check if there is a need for manual processing
        self.checkForManualOperation(type='Processing',entity=activeEntity)
        # read the setup time from the corresponding remainingRoute entry
        setupTime=activeEntity.remainingRoute[0].get('setupTime',{})
        setupTime=self.getOperationTime(setupTime)
        self.stpRng=RandomNumberGenerator(self, setupTime)
        # check if there is a need for manual processing
        self.checkForManualOperation(type='Setup',entity=activeEntity)
        removedStep = activeEntity.remainingRoute.pop(0)      #remove data from the remaining route of the entity
        return activeEntity
    
    #===========================================================================
    # update the next list of the object based on the activeEentity
    #===========================================================================
    def updateNext(self,entity=None):
        activeObject = self.getActiveObject()
        activeEntity=entity
        # read the possible receivers - update the next list
        import Globals
        # XXX: in the case of MouldAssembler there is no next defined in the route of the entities that are received
        # the position activeEntity.remainingRoute[1] is out of bound. the next should be updated by the remaining route of the entity to be assembled
        if len(activeEntity.remainingRoute)>1:
            nextObjectIds=activeEntity.remainingRoute[1].get('stationIdsList',[])
            nextObjects = []
            for nextObjectId in nextObjectIds:
                nextObject = Globals.findObjectById(nextObjectId)
                nextObjects.append(nextObject)
            # update the next list of the object
            for nextObject in nextObjects:
                # append only if not already in the list
                if nextObject not in activeObject.next:
                    activeObject.next.append(nextObject)
                                                                             
    # =======================================================================  
    # calculates the processing time
    # =======================================================================
    def calculateProcessingTime(self):
        # this is only for processing of the initial wip
        if self.isProcessingInitialWIP:
            # read the setup/processing time from the first entry of the full route
            activeEntity=self.getActiveObjectQueue()[0]
            #if the entity has its route defined in the BOM then remainingProcessing/SetupTime is provided
            # XX consider moving setupUPtime update to checkForManualOperationTypes as Setup is performed before Processing
            if activeEntity.routeInBOM:
                processingTime=self.getOperationTime(activeEntity.remainingProcessingTime)
                setupTime=self.getOperationTime(activeEntity.remainingSetupTime)
            else:   # other wise these should be read from the route
                processingTime=activeEntity.route[0].get('processingTime',{})
                processingTime=self.getOperationTime(processingTime)
                setupTime=activeEntity.route[0].get('setupTime',{})
                setupTime=self.getOperationTime(setupTime)
            self.rng=RandomNumberGenerator(self, processingTime)
            self.procTime=self.rng.generateNumber()
            self.stpRng=RandomNumberGenerator(self, setupTime)
        return self.procTime    #this is the processing time for this unique entity 
    
    # =======================================================================
    # checks if the Queue can accept an entity       
    # it checks also the next station of the Entity 
    # and returns true only if the active object is the next station
    # ======================================================================= 
    def canAccept(self, callerObject=None):
        activeObjectQueue=self.Res.users
        thecaller=callerObject
        #return according to the state of the Queue
        # also check if (if the machine is to be operated) there are available operators
        if (self.operatorPool!='None' and (any(type=='Load' for type in self.multOperationTypeList))):
            return self.operatorPool.checkIfResourceIsAvailable()\
                    and len(activeObjectQueue)<self.capacity\
                    and self.checkIfMachineIsUp()\
                    and self.isInRouteOf(thecaller)\
                    and not self.entryIsAssignedTo()
        else:
            return len(activeObjectQueue)<self.capacity\
                    and self.checkIfMachineIsUp()\
                    and self.isInRouteOf(thecaller)\
                    and not self.entryIsAssignedTo()
                        
    #===========================================================================
    # method used to check whether the station is in the entity-to-be-received route
    #===========================================================================
    def isInRouteOf(self, callerObject=None):
        activeObjectQueue=self.Res.users
        thecaller=callerObject
        # if the caller is not defined then return True. We are only interested in checking whether 
        # the station can accept whatever entity from whichever giver
        if not thecaller:
            return True
        #check it the caller object holds an Entity that requests for current object
        if len(thecaller.Res.users)>0:
            # TODO: make sure that the first entity of the callerObject is to be disposed
            activeEntity=thecaller.Res.users[0]
            # if the machine's Id is in the list of the entity's next stations
            if self.id in activeEntity.remainingRoute[0].get('stationIdsList',[]):
                return True
        return False
    
    # =======================================================================   
    # checks if the Machine can dispose an entity. 
    # Returns True only to the potential receiver
    # =======================================================================     
    def haveToDispose(self, callerObject=None):
        activeObjectQueue=self.Res.users
        thecaller=callerObject
        #if we have only one successor just check if machine waits to dispose and also is up
        # this is done to achieve better (cpu) processing time
        if(callerObject==None):
            return len(activeObjectQueue)>0\
                 and self.waitToDispose\
                 and self.checkIfActive()\
        #return True if the Machine in the state of disposing and the caller is the receiver
        return len(activeObjectQueue)>0\
             and self.waitToDispose\
             and self.checkIfActive()\
             and thecaller.isInRouteOf(self)

    # =======================================================================
    # method to execute preemption
    # =======================================================================    
    def preempt(self):
#         self.printTrace(self.id,preempted='')
        activeEntity=self.Res.users[0] #get the active Entity
        #calculate the remaining processing time
        #if it is reset then set it as the original processing time
        if self.resetOnPreemption:
            remainingProcessingTime=self.procTime
        #else subtract the time that passed since the entity entered
        #(may need also failure time if there was. TO BE MELIORATED)
        else:
            remainingProcessingTime=self.procTime-(self.env.now-self.timeLastEntityEntered)
        #update the remaining route of activeEntity
        activeEntity.remainingRoute.insert(0, {'stationIdsList':[str(self.id)],\
                                               'processingTime':\
                                                    {'Fixed':{'mean':str(remainingProcessingTime)}}})
        activeEntity.remainingRoute.insert(0, {'stationIdsList':[str(self.lastGiver.id)],\
                                               'processingTime':{'Fixed':{'mean':'0'}}})   
        #set the receiver  as the object where the active entity was preempted from 
        self.receiver=self.lastGiver
        self.next=[self.receiver]
        self.waitToDispose=True                     #set that I have to dispose
        self.receiver.timeLastEntityEnded=self.env.now     #required to count blockage correctly in the preemptied station
        # TODO: use a signal and wait for it, reactivation is not recognised as interruption
#         reactivate(self)
        if self.expectedSignals['preemptQueue']:
            self.sendSignal(receiver=self, signal=self.preemptQueue)
        # TODO: consider the case when a failure has the Station down. The event preempt will not be received now()
        #     but at a later simulation time. 
            
    #===========================================================================
    # extend the default behaviour to check if whether the station 
    #     is in the route of the entity to be received
    #===========================================================================
    def canAcceptAndIsRequested(self,callerObject):
        giverObject=callerObject
        assert giverObject, 'there must be a caller for canAcceptAndIsRequested'
        if self.isInRouteOf(giverObject):
            if Machine.canAcceptAndIsRequested(self,giverObject):
                self.readLoadTime(giverObject)
                return True
        return False

    #===========================================================================
    # to be called by canAcceptAndIsRequested if it is to return True.
    # the load time of the Entity must be read
    #===========================================================================
    def readLoadTime(self,callerObject=None):
        assert callerObject!=None, 'the caller of readLoadTime cannot be None'
        thecaller=callerObject
        thecaller.sortEntities()
        activeEntity=thecaller.Res.users[0]
        # read the load time from the corresponding remainingRoute entry
        loadTime=activeEntity.remainingRoute[0].get('loadTime',{})
        loadTime=self.getOperationTime(loadTime)
        self.loadRng=RandomNumberGenerator(self, loadTime)
    
    #===========================================================================
    # get the initial operationTypes (Setup/Processing) : manual or automatic
    #===========================================================================
    def checkInitialOperationTypes(self):
        # check if manual Setup is required
        self.checkForManualOperation(type='Setup')
        # check if manual Processing is required
        self.checkForManualOperation(type='Processing')
    
    #===========================================================================
    # check if the operation defined as an argument requires manual operation
    #===========================================================================
    def checkForManualOperation(self,type,entity=None):
        typeDict={'Setup':'setupTime', 'Processing':'processingTime'}
        assert type!=None, 'a type must be defined for the checkForManualOperation method'
        if not entity:
            activeEntity=self.getActiveObjectQueue()[0]
        else:
            activeEntity=entity
        # read the definition of the time from the remainingRoute dict
        if not self.isProcessingInitialWIP:
            operationTypeDict=activeEntity.remainingRoute[0].get('operationType',{})
            operationType=operationTypeDict.get(str(type),'not defined')
        else: # if the active entity is initialWIP at the start of simulation
            operationType=activeEntity.initialOperationTypes.get(str(type),'not defined')
        # if the operationType is not 'not defined'
        if operationType!='not defined':
            # if the operationType key has value 1 (manual operation)
            if operationType:
                # add setup to the multOpeartionTypeList
                if not type in self.multOperationTypeList:
                    self.multOperationTypeList.append(str(type))
            else:   # otherwise remove it from the multOperationTypeList
                if type in self.multOperationTypeList:
                    self.multOperationTypeList.remove(str(type))
        
    # =======================================================================
    # removes an entity from the Machine
    # extension to remove possible receivers accordingly
    # =======================================================================
    def removeEntity(self, entity=None):
        receiverObject=self.receiver  
        activeEntity=Machine.removeEntity(self, entity)         #run the default method  
        removeReceiver=True 
        # search in the internalQ. If an entity has the same receiver do not remove
        for ent in self.Res.users:
            nextObjectIds=ent.remainingRoute[0].get('stationIdsList',[])
            if receiverObject.id in nextObjectIds:
                removeReceiver=False      
        # if not entity had the same receiver then the receiver will be removed    
        if removeReceiver:
            self.next.remove(receiverObject)
        return activeEntity
Example #47
0
class Failure(ObjectInterruption):
    
    def __init__(self, id='',name='',victim=None, distribution={}, index=0, repairman=None, offshift=False,
                 deteriorationType='constant',
                 waitOnTie=False,**kw):
        ObjectInterruption.__init__(self,id,name,victim=victim)
        self.rngTTF=RandomNumberGenerator(self, distribution.get('TTF',{'Fixed':{'mean':100}}))
        self.rngTTR=RandomNumberGenerator(self, distribution.get('TTR',{'Fixed':{'mean':10}}))
        self.name="F"+str(index)
        self.repairman=repairman        # the resource that may be needed to fix the failure
                                        # if now resource is needed this will be "None" 
        self.type="Failure"
        
        # shows how the time to failure is measured
        # 'constant' means it counts not matter the state of the victim
        # 'onShift' counts only if the victim is onShift
        # 'working' counts only working time
        self.deteriorationType=deteriorationType
        # flag used to identify if the time between failures should be counted while the victim is off-shift
        self.offshift=offshift
        # flag to show if the failure will wait on tie with other events before interrupting the victim
        self.waitOnTie=waitOnTie

    def initialize(self):
        ObjectInterruption.initialize(self)
        self.victimStartsProcess=self.env.event()
        self.victimEndsProcess=self.env.event()       
        
    # =======================================================================
    #    The run method for the failure which has to served by a repairman
    # =======================================================================
    def run(self):     
        while 1:
            # if the time that the victim is off-shift should not be counted
            timeToFailure=self.rngTTF.generateNumber()
            remainingTimeToFailure=timeToFailure
            failureNotTriggered=True
            
            # if time to failure counts not matter the state of the victim
            if self.deteriorationType=='constant':
                yield self.env.timeout(remainingTimeToFailure)
            # if time to failure counts only in onShift time
            elif self.deteriorationType=='onShift':
                while failureNotTriggered:
                    timeRestartedCounting=self.env.now
                    self.isWaitingForVictimOffShift=True
                    
                    self.expectedSignals['victimOffShift']=1
                    
                    receivedEvent=yield self.env.timeout(remainingTimeToFailure) | self.victimOffShift 
                    # the failure should receive a signal if there is a shift-off triggered
                    if self.victimOffShift in receivedEvent:
                        assert self.victim.onShift==False, 'shiftFailure cannot recalculate TTF if the victim is onShift'
                        self.victimOffShift=self.env.event()
                        remainingTimeToFailure=remainingTimeToFailure-(self.env.now-timeRestartedCounting)   
                        # wait for the shift to start again
                        self.isWaitingForVictimOnShift=True
                        
                        self.expectedSignals['victimOnShift']=1
                        
                        yield self.victimOnShift

                        self.isWaitingForVictimOnShift=False
                        self.victimOnShift=self.env.event()
                        assert self.victim.onShift==True, 'the victim of shiftFailure must be onShift to continue counting the TTF'
                    else:
                        self.isWaitingForVictimOffShift=False
                        failureNotTriggered=False

            # if time to failure counts only in working time
            elif self.deteriorationType=='working':
                # wait for victim to start process
                
                self.expectedSignals['victimStartsProcess']=1
                
                yield self.victimStartsProcess

                self.victimStartsProcess=self.env.event()
                while failureNotTriggered:
                    timeRestartedCounting=self.env.now
                    
                    self.expectedSignals['victimEndsProcess']=1
                    
                    # wait either for the failure or end of process
                    receivedEvent=yield self.env.timeout(remainingTimeToFailure) | self.victimEndsProcess 
                    if self.victimEndsProcess in receivedEvent:
                        self.victimEndsProcess=self.env.event()
                        remainingTimeToFailure=remainingTimeToFailure-(self.env.now-timeRestartedCounting)
                        
                        self.expectedSignals['victimStartsProcess']=1
                        
                        yield self.victimStartsProcess

                        # wait for victim to start again processing
                        self.victimStartsProcess=self.env.event()
                    else:
                        failureNotTriggered=False
            
            # if the mode is to wait on tie before interruption add a dummy hold for 0
            # this is done so that if processing finishes exactly at the time of interruption
            # the processing will finish first (if this mode is selected)
            if self.waitOnTie:
                if hasattr(self.victim, 'timeToEndCurrentOperation'):
                    if float(self.victim.timeToEndCurrentOperation)==float(self.env.now):
                        yield self.env.timeout(0)
                
            # interrupt the victim
            self.interruptVictim()                      # interrupt the victim
            
            # check in the ObjectInterruptions of the victim. If there is a one that is waiting for victimFailed send it
            for oi in self.victim.objectInterruptions:
                if oi.expectedSignals['victimFailed']:
                    self.sendSignal(receiver=oi, signal=oi.victimFailed)
            self.victim.Up=False
            self.victim.timeLastFailure=self.env.now           
            self.outputTrace(self.victim.name,"is down")
            # update the failure time
            failTime=self.env.now    
            if(self.repairman and self.repairman!="None"):     # if the failure needs a resource to be fixed, 
                                                               # the machine waits until the 
                                                               # resource is available
                
                with self.repairman.getResource().request() as request:
                    yield request
                    # update the time that the repair started
                    timeOperationStarted=self.env.now
                    self.repairman.timeLastOperationStarted=self.env.now
                    
                    yield self.env.timeout(self.rngTTR.generateNumber())    # wait until the repairing process is over
                    self.victim.totalFailureTime+=self.env.now-failTime    
                    self.reactivateVictim()                     # since repairing is over, the Machine is reactivated
                    self.victim.Up=True              
                    self.outputTrace(self.victim.name,"is up")
                    
                    self.repairman.totalWorkingTime+=self.env.now-timeOperationStarted   
                continue
                
                
                                
            yield self.env.timeout(self.rngTTR.generateNumber())    # wait until the repairing process is over
            
            # add the failure
            # if victim is off shift add only the fail time before the shift ended
            if not self.victim.onShift and failTime < self.victim.timeLastShiftEnded:
                self.victim.totalFailureTime+=self.victim.timeLastShiftEnded-failTime
            # if the victim was off shift since the start of the failure add nothing
            elif not self.victim.onShift and failTime >= self.victim.timeLastShiftEnded:
                pass
            # if victim was off shift in the start of the fail time, add on
            elif self.victim.onShift and failTime < self.victim.timeLastShiftStarted:
                self.victim.totalFailureTime+=self.env.now-self.victim.timeLastShiftStarted
                # this can happen only if deteriorationType is constant
                assert self.deteriorationType=='constant', 'object got failure while off-shift and deterioration type not constant' 
            else:
                self.victim.totalFailureTime+=self.env.now-failTime   
            self.reactivateVictim()                     # since repairing is over, the Machine is reactivated
            self.victim.Up=True              
            self.outputTrace(self.victim.name,"is up")
Example #48
0
class Source(CoreObject):
    #===========================================================================
    # the __init__method of the Source class
    #===========================================================================
    def __init__(self, id, name, interArrivalTime=None, entity='Dream.Part',**kw):
        # Default values
        if not interArrivalTime:
          interArrivalTime = {'Fixed': {'mean': 1}}
        if 'Normal' in interArrivalTime.keys() and\
              interArrivalTime['Normal'].get('max', None) is None:
          interArrivalTime['Normal']['max'] = interArrivalTime['Normal']['mean'] + 5 * interArrivalTime['Normal']['stdev']

        CoreObject.__init__(self, id, name)
        # properties used for statistics
        self.totalinterArrivalTime = 0                  # the total interarrival time 
        self.numberOfArrivals = 0                       # the number of entities that were created

        self.type="Source"                              #String that shows the type of object
        self.rng = RandomNumberGenerator(self, interArrivalTime)

        self.item=Globals.getClassFromName(entity)      #the type of object that the Source will generate
               
        self.scheduledEntities=[]       # list of creations that are scheduled. pattern is [timeOfCreation, EntityCounter]     
        from Globals import G
        G.SourceList.append(self)  
    
    #===========================================================================
    # The initialize method of the Source class
    #===========================================================================
    def initialize(self):
        # using the Process __init__ and not the CoreObject __init__
        CoreObject.initialize(self)
        
        # initialize the internal Queue (type Resource) of the Source 
        # self.Res=Resource(capacity=infinity)
        self.Res=simpy.Resource(self.env, capacity=float('inf'))
        self.Res.users=[]                                 
        self.entityGenerator=EntityGenerator(victim=self)     # the EntityGenerator of the Source

        self.numberOfArrivals = 0 
#         self.entityGenerator.initialize()
        # activate(self.entityGenerator,self.entityGenerator.run())
        self.env.process(self.entityGenerator.run())
        # self.entityCreated=SimEvent('an entity is created')
        self.entityCreated=self.env.event()
        # event used by router
        # self.loadOperatorAvailable=SimEvent('loadOperatorAvailable')
        self.loadOperatorAvailable=self.env.event()
        self.scheduledEntities=[]       # list of creations that are scheduled
        
        self.expectedSignals['entityCreated']=1
        self.expectedSignals['loadOperatorAvailable']=1
        self.expectedSignals['canDispose']=1
    
    #===========================================================================
    # the generator of the Source class 
    #===========================================================================
    def run(self):
        # get active object and its queue
        activeObject=self.getActiveObject()
        activeObjectQueue=self.getActiveObjectQueue()
        while 1:
            # wait for any event (entity creation or request for disposal of entity)
            self.expectedSignals['canDispose']=1
            self.expectedSignals['entityCreated']=1
            self.expectedSignals['loadOperatorAvailable']=1
            receivedEvent=yield self.env.any_of([self.entityCreated, self.canDispose, self.loadOperatorAvailable])
            self.printTrace(self.id, received='')
            # if an entity is created try to signal the receiver and continue
            if self.entityCreated in receivedEvent:
                transmitter, eventTime=self.entityCreated.value
                self.entityCreated=self.env.event()
            # otherwise, if the receiver requests availability then try to signal him if there is anything to dispose of
            if self.canDispose in receivedEvent:
                transmitter, eventTime=self.canDispose.value
                self.canDispose=self.env.event()
            if self.loadOperatorAvailable in receivedEvent:
                transmitter, eventTime=self.loadOperatorAvailable.value
                self.loadOperatorAvailable=self.env.event()
            if self.haveToDispose():
                if self.signalReceiver():
                    continue
        
    #===========================================================================
    # add newly created entity to pendingEntities
    #===========================================================================
    def appendEntity(self, entity):
        from Globals import G
        assert entity, 'cannot append None entity'
        activeEntity=entity
        if G.RouterList:
            # at the newly created entity to the pendingEntities
            G.pendingEntities.append(activeEntity)

    #============================================================================
    #            sets the routing out element for the Source
    #============================================================================
    def defineRouting(self, successorList=[]):
        self.next=successorList                                   # only successors allowed for the source
    #============================================================================        
    #                          creates an Entity
    #============================================================================
    def createEntity(self):
        self.printTrace(self.id, create='')
        return self.item(id = self.item.type+str(G.numberOfEntities), name = self.item.type+str(self.numberOfArrivals)) #return the newly created Entity
    #============================================================================
    #                    calculates the processing time
    #============================================================================
    def calculateInterArrivalTime(self):
        return self.rng.generateNumber()    #this is if we have a default interarrival  time for all the entities
    
    # =======================================================================
    # removes an entity from the Source
    # =======================================================================
    def removeEntity(self, entity=None):
        if len(self.getActiveObjectQueue())==1 and len(self.scheduledEntities):
            newEntity=self.createEntity()                       # create the Entity object and assign its name
            newEntity.creationTime=self.scheduledEntities.pop(0)                      # assign the current simulation time as the Entity's creation time 
            newEntity.startTime=newEntity.creationTime                                # assign the current simulation time as the Entity's start time
            #print self.env.now, 'getting from the list. StartTime=',newEntity.startTime
            newEntity.currentStation=self                            # update the current station of the Entity
            G.EntityList.append(newEntity)
            self.getActiveObjectQueue().append(newEntity)            # append the entity to the resource 
            self.numberOfArrivals+=1                              # we have one new arrival
            G.numberOfEntities+=1
            self.appendEntity(newEntity)  
        activeEntity=CoreObject.removeEntity(self, entity)          # run the default method  
        if len(self.getActiveObjectQueue())==1:
            if self.expectedSignals['entityCreated']:
                self.sendSignal(receiver=self, signal=self.entityCreated)
        return activeEntity
class BatchScrapMachine(Machine):

    # =======================================================================
    # constructor run every time a new instance is created
    # calls the Machine constructor, but also reads attributes for
    # scraping distribution
    # =======================================================================
    def __init__(self, id, name, capacity=1, \
                 processingTime=None, repairman='None',\
                 scrapQuantity={},
                 operatorPool='None',operationType='None',\
                 setupTime=None, loadTime=None,
                 canDeliverOnInterruption=False,
                 **kw):
        if not processingTime:
            processingTime = {'distributionType': 'Fixed', 'mean': 1}
        # initialize using the default method of the object
        Machine.__init__(self,id=id,name=name,\
                                    capacity=capacity,\
                                    processingTime=processingTime,
                                    repairman=repairman,
                                    canDeliverOnInterruption=canDeliverOnInterruption,
                                    operatorPool=operatorPool,operationType=operationType,\
                                    setupTime=setupTime, loadTime=loadTime,
                                    )

        # set the attributes of the scrap quantity distribution
        if not scrapQuantity:
            scrapQuantity = {'Fixed': {'mean': 0}}

        self.scrapRng = RandomNumberGenerator(self, scrapQuantity)
        from Globals import G
        G.BatchScrapMachineList.append(self)

    # =======================================================================
    # removes an Entity from the Object the Entity to be removed is passed
    # as argument by getEntity of the receiver
    # extends the default behaviour so that
    # it can scrap a number of units before disposing the Batch/SubBatch
    # =======================================================================
    def removeEntity(self, entity=None):
        activeEntity = Machine.removeEntity(self, entity)
        scrapQuantity = self.scrapRng.generateNumber()
        activeEntity.numberOfUnits -= int(
            scrapQuantity
        )  # the scrapQuantity should be integer at whatever case
        if activeEntity.numberOfUnits < 0:
            activeEntity.numberOfUnits == 0
        return activeEntity

    # =======================================================================
    # calculates the processing time
    # extends the default behaviour so that
    # the per-unit processing time is multiplied with the number of units
    # =======================================================================
    def calculateProcessingTime(self):
        activeEntity = self.getActiveObjectQueue()[0]
        # this is only for processing of the initial wip
        if self.isProcessingInitialWIP:
            if activeEntity.unitsToProcess:
                return self.rng.generateNumber() * activeEntity.unitsToProcess
        return self.rng.generateNumber() * activeEntity.numberOfUnits
Example #50
0
class MouldAssembly(MachineJobShop):
    
    # =======================================================================
    # parses inputs if they are given in a dictionary
    # =======================================================================       
    def parseInputs(self, **kw):
        from Globals import G
        G.MouldAssemblyList.append(self)

    # =======================================================================
    # the initialize method
    # =======================================================================
    def initialize(self):
        self.mouldParent = None                 # the mould's to be assembled parent order
        self.mouldToBeCreated = None            # the mould to be assembled
        MachineJobShop.initialize(self)      # run default behaviour
        
    # =======================================================================
    # getEntity method that gets the entity from the giver
    # it should run in a loop till it get's all the entities from the same order
    # (with the flag componentsReadyForAssembly set)
    # it is run only once, and receives all the entities to be assembled inside a while loop
    # =======================================================================
    def getEntity(self):
        activeObject = self.getActiveObject()
        giverObject = activeObject.getGiverObject()
        # get the first entity from the predecessor
        # TODO: each MachineJobShop.getEntity is invoked, 
        #     the self.procTime is updated. Have to decide where to assign 
        #     the processing time of the assembler
        activeEntity=MachineJobShop.getEntity(self)
        # this is kept so that in the next loop it will not try to re-get this Entity
        firstObtained=activeEntity  
        # check weather the activeEntity is of type Mould
        if activeEntity.type=='Mould':
            # and return the mould received
            return activeEntity
        # otherwise, collect all the entities to be assembled
        
        # read the number of basic and secondary components of the moulds
        capacity = len(activeEntity.order.getAssemblyComponents())
        # clear the active object queue
        del activeObject.getActiveObjectQueue()[:]
        # and set the capacity of the internal queue of the assembler
        activeObject.updateCapacity(capacity)
        # append the activeEntity to the activeObjectQueue
        activeObjectQueue = activeObject.getActiveObjectQueue()
        activeObjectQueue.append(activeEntity)
        # loop through the basic/secondary components of the order that is currently obtained
        # all the components are received at the same time
        for entity in activeEntity.order.getAssemblyComponents():
            # continue for the one that is already  obtained before
            if entity is firstObtained:
                continue

            self.entityToGet=entity
            # get the next component
            activeEntity=MachineJobShop.getEntity(self)
            # check whether the activeEntity is of type Mould
            try:
                if activeEntity.type=='Mould':
            # and return the mould received
                    raise AssembleMouldError('Having already received an orderComponent the assembler\
                                                is not supposed to receive an object of type Mould')
            # check if the last component received has the same parent order as the previous one
                elif not (activeEntity.order is activeObjectQueue[1].order):
                    raise AssembleMouldError('The orderComponents received by the assembler must have the\
                                                same parent order')
            except AssembleMouldError as mouldError:
                print 'Mould Assembly Error: {0}'.format(mouldError)
                return False
        # perform the assembly-action and return the assembled mould
        activeEntity = activeObject.assemble()
        return activeEntity
    
    # =======================================================================
    # method that updates the capacity according to the componentsList of the 
    # activeEntity's parent order
    # =======================================================================
    def updateCapacity(self,capacity):
        activeObject = self.getActiveObject()
        self.capacity = capacity
        self.Res=simpy.Resource(self.env, self.capacity)
    
    # =======================================================================
    #     assemble method that assembles the components together to a mould (order
    # and returns the product of the assembly. Furthermore, it resets the capacity
    # of the internal queue to 1
    # =======================================================================
    def assemble(self):
        activeObject = self.getActiveObject()
        # get the internal queue of the active core object
        activeObjectQueue=activeObject.getActiveObjectQueue()
        # assert that all the components are of the same parent order
        for entity in activeObjectQueue:
            assert entity.order==activeObjectQueue[0].order,\
                'The components residing in the MouldAssembly internal queue\
                are not of the same parent order!'
        # if we have to create a new Entity (mould) this should be modified
        # we need the new entity's route, priority, isCritical flag, etc. 
        self.mouldParent = activeObjectQueue[0].order
        # assert that there is a parent order
        assert self.mouldParent.type=='Order', 'the type of the assembled to be mould\' s parent is not correct'
        # delete the contents of the internal queue
        temp_activeObjectQueue=list(activeObjectQueue)
        for element in temp_activeObjectQueue:
            # update their schedule
            element.schedule[-1]["exitTime"] = self.env.now
            # remove the elements from the activeObjectQueue and reset the current station of the entity
            activeObjectQueue.remove(element)
            element.currentStation=None
        del temp_activeObjectQueue[:]
        # after assembling reset the capacity
        activeObject.updateCapacity(1)
        #if there is a mould to be assembled
        try:
            if self.mouldParent:
                # find the component which is of type Mould
                # there must be only one mould component
                for entity in self.mouldParent.componentsList:
                    entityClass=entity.get('_class', None)
                    if entityClass=='Dream.Mould':
                        self.mouldToBeCreated=entity
                        break
                # create the mould
                self.createMould(self.mouldToBeCreated)
                # check if there is a need for manual processing
                self.checkForManualOperation(type='Processing',entity=self.mouldToBeCreated)
                # check if there is a need for manual processing
                self.checkForManualOperation(type='Setup',entity=self.mouldToBeCreated)
                # set the created mould as WIP
                import Globals
                Globals.setWIP([self.mouldToBeCreated])
                # read the activeObjectQueue again as it has been updated by the setWIP()
                activeObjectQueue=activeObject.getActiveObjectQueue()
                # reset attributes
                self.mouldParent = None
                self.mouldToBeCreated = None
                # return the assembled mould
                return activeObjectQueue[0]
            else:
                raise AssembleMouldError('There is no mould to be assembled')
        except AssembleMouldError as mouldError:
            print 'Mould Assembly Error: {0}'.format(mouldError)
            
    # =======================================================================
    # creates the mould
    # =======================================================================
    def createMould(self, component):
        #read attributes from the json or from the orderToBeDecomposed
        id=component.get('id', 'not found')
        name=component.get('name', 'not found')
        try:
            # dummy variable that holds the routes of the jobs the route from the JSON file is a sequence of dictionaries
            JSONRoute=component.get('route', [])
            # variable that holds the argument used in the Job initiation hold None for each entry in the 'route' list
            route = [x for x in JSONRoute]       #    copy JSONRoute
            # assert that the assembler is in the moulds route and update the initial step of the mould's route
            firstStep = route.pop(0)
            assert (self.id in firstStep.get('stationIdsList',[])),\
                         'the assembler must be in the mould-to-be-created route\' initial step'
            # normal processing operation
            processingTime=firstStep['processingTime']
            processingTime=self.getOperationTime(processingTime)
            self.rng=RandomNumberGenerator(self, processingTime)
            self.procTime=self.rng.generateNumber()
            # update the activeObject's processing time according to the readings in the mould's route
            processDistType=processingTime.keys()[0]
            procTime=float(processingTime[processDistType].get('mean', 0))
            processOpType=firstStep.get('operationType',{}).get('Processing','not found') # can be manual/automatic
            # task_id
            task_id = firstStep.get('task_id', None)
            # sequence
            sequence = firstStep.get('sequence', None)
            # operator
            operator = firstStep.get('operator', {})
            # technology
            technology = firstStep.get('technology', None)
            # quantity
            quantity = firstStep.get('quantity', None)
            # setup operation
            setupTime=firstStep.get('setupTime',None)
            if setupTime:
                setupTime=self.getOperationTime(setupTime)
                self.stpRng=RandomNumberGenerator(self, setupTime)
                # update the activeObject's processing time according to the readings in the mould's route
                setupDistType=setupTime.keys()[0]
                setTime=float(setupTime[setupDistType].get('mean', 0))
                setupOpType=firstStep.get('operationType',{}).get('Setup','not found') # can be manual/automatic
                # update the first step of the route with the activeObjects id as sole element of the stationIdsList
                route.insert(0, {'stationIdsList':[str(self.id)],
                                 'processingTime':{str(processDistType):{'mean':str(procTime)}},\
                                 'setupTime':{str(setupDistType):{'mean':str(setupTime)}},
                                 'operationType':{'Processing':processOpType,'Setup':setupOpType}})
            else:
                # update the first step of the route with the activeObjects id as sole element of the stationIdsList
                route.insert(0, {'stationIdsList':[str(self.id)],
                                 'processingTime':{str(processDistType):{'mean':str(procTime)}},
                                 'operationType':{'Processing':processOpType}})
            # if there is task_id then add it to the route
            if task_id:
                route[0]["task_id"] = task_id
            # if there is sequence then add it to the route
            if sequence:
                route[0]["sequence"] = sequence
            # if there is operator then add it to the route
            if operator:
                route[0]["operator"] = operator
            # if there is technology then add it to the route
            if technology:
                route[0]["technology"] = technology
            # if there is quantity then add it to the route
            if quantity!=None:
                route[0]["quantity"] = quantity
            #Below it is to assign an exit if it was not assigned in JSON
            #have to talk about it with NEX
            exitAssigned=False
            for element in route:
                elementIds = element.get('stationIdsList',[])
                for obj in G.ObjList:
                    for elementId in elementIds:
                        if obj.id==elementId and obj.type=='Exit':
                            exitAssigned=True 
            # assign an exit to the route of the mould 
            if not exitAssigned:
                exitId=None
                for obj in G.ObjList:
                    if obj.type=='Exit':
                        exitId=obj.id
                        break
                if exitId:
                    route.append({'stationIdsList':[str(exitId)],'processingTime':{}})
            # keep a reference of all extra properties passed to the job
            extraPropertyDict = {}
            for key, value in component.items():
                if key not in ('_class', 'id'):
                    extraPropertyDict[key] = value
            # create and initiate the OrderComponent
            from Mould import Mould
            M=Mould(id, name, route, \
                              priority=self.mouldParent.priority, \
                              order=self.mouldParent,\
                              dueDate=self.mouldParent.dueDate, \
                              orderDate=self.mouldParent.orderDate, \
                              extraPropertyDict=extraPropertyDict,\
                              isCritical=self.mouldParent.isCritical)
            # update the mouldToBeCreated
            self.mouldToBeCreated=M
            G.JobList.append(M)
            G.WipList.append(M)
            G.EntityList.append(M)
            G.MouldList.append(M)
            #initialize the component
            M.initialize()
        except:
            # added for testing
            print 'the mould to be created', component.get('name', 'not found'), 'cannot be created', 'time', self.env.now
            raise
Example #51
0
class Failure(ObjectInterruption):
    
    def __init__(self, id='',name='',victim=None, distribution=None, index=0, repairman=None, offshift=False,
                 deteriorationType='constant',**kw):
        ObjectInterruption.__init__(self,id,name,victim=victim)
        if distribution:
            self.distType=distribution.get('distributionType','No')              # the distribution that the failure duration follows
            self.MTTF=distribution.get('MTTF',60)                  # the MTTF
            self.MTTR=distribution.get('MTTR',5)                  # the MTTR  
            self.availability=distribution.get('availability',100)  # the availability      
        else:
            self.distType='No'
            self.MTTF=60
            self.MTTR=5
            self.availability=100
        self.name="F"+str(index)
        self.repairman=repairman        # the resource that may be needed to fix the failure
                                        # if now resource is needed this will be "None" 
        self.type="Failure"
        # shows how the time to failure is measured
        # 'constant' means it counts not matter the state of the victim
        # 'onShift' counts only if the victim is onShift
        # 'working' counts only working time
        self.deteriorationType=deteriorationType
        
        if(self.distType=="Availability"):      
            
            # -------------------------------------------------------------- 
            #     the following are used if we have availability defined 
            #      (as in plant) the erlang is a special case of Gamma. 
            #        To model the Mu and sigma (that is given in plant) 
            #    as alpha and beta for gamma you should do the following:
            #                     beta=(sigma^2)/Mu    
            #                     alpha=Mu/beta
            # --------------------------------------------------------------    
            self.AvailabilityMTTF=self.MTTR*(float(availability)/100)/(1-(float(availability)/100))
            self.sigma=0.707106781185547*self.MTTR   
            self.theta=(pow(self.sigma,2))/float(self.MTTR)             
            self.beta=self.theta
            self.alpha=(float(self.MTTR)/self.theta)        
            self.rngTTF=RandomNumberGenerator(self, "Exp")
            self.rngTTF.avg=self.AvailabilityMTTF
            self.rngTTR=RandomNumberGenerator(self, "Erlang")
            self.rngTTR.alpha=self.alpha
            self.rngTTR.beta=self.beta       
        else:   
            # --------------------------------------------------------------
            #               if the distribution is fixed
            # --------------------------------------------------------------
            self.rngTTF=RandomNumberGenerator(self, self.distType)
            self.rngTTF.mean=self.MTTF
            self.rngTTR=RandomNumberGenerator(self, self.distType)
            self.rngTTR.mean=self.MTTR
        # flag used to identify if the time between failures should be counted while the victim is off-shift
        self.offshift=offshift

    def initialize(self):
        ObjectInterruption.initialize(self)
        self.victimStartsProcess=self.env.event()
        self.victimEndsProcess=self.env.event()       
        
    # =======================================================================
    #    The run method for the failure which has to served by a repairman
    # =======================================================================
    def run(self):     
        while 1:
            # if the time that the victim is off-shift should not be counted
            timeToFailure=self.rngTTF.generateNumber()
            remainingTimeToFailure=timeToFailure
            failureNotTriggered=True
            
            # if time to failure counts not matter the state of the victim
            if self.deteriorationType=='constant':
                yield self.env.timeout(remainingTimeToFailure)
            # if time to failure counts only in onShift time
            elif self.deteriorationType=='onShift':
                while failureNotTriggered:
                    timeRestartedCounting=self.env.now
                    self.isWaitingForVictimOffShift=True
                    
                    self.expectedSignals['victimOffShift']=1
                    
                    receivedEvent=yield self.env.timeout(remainingTimeToFailure) | self.victimOffShift 
                    # the failure should receive a signal if there is a shift-off triggered
                    if self.victimOffShift in receivedEvent:
                        assert self.victim.onShift==False, 'shiftFailure cannot recalculate TTF if the victim is onShift'
                        self.victimOffShift=self.env.event()
                        remainingTimeToFailure=remainingTimeToFailure-(self.env.now-timeRestartedCounting)   
                        # wait for the shift to start again
                        self.isWaitingForVictimOnShift=True
                        
                        self.expectedSignals['victimOnShift']=1
                        
                        yield self.victimOnShift

                        self.isWaitingForVictimOnShift=False
                        self.victimOnShift=self.env.event()
                        assert self.victim.onShift==True, 'the victim of shiftFailure must be onShift to continue counting the TTF'
                    else:
                        self.isWaitingForVictimOffShift=False
                        failureNotTriggered=False

            # if time to failure counts only in working time
            elif self.deteriorationType=='working':
                # wait for victim to start process
                
                self.expectedSignals['victimStartsProcess']=1
                
                yield self.victimStartsProcess

                self.victimStartsProcess=self.env.event()
                while failureNotTriggered:
                    timeRestartedCounting=self.env.now
                    
                    self.expectedSignals['victimEndsProcess']=1
                    
                    # wait either for the failure or end of process
                    receivedEvent=yield self.env.timeout(remainingTimeToFailure) | self.victimEndsProcess 
                    if self.victimEndsProcess in receivedEvent:
                        self.victimEndsProcess=self.env.event()
                        remainingTimeToFailure=remainingTimeToFailure-(self.env.now-timeRestartedCounting)
                        
                        self.expectedSignals['victimStartsProcess']=1
                        
                        yield self.victimStartsProcess

                        # wait for victim to start again processing
                        self.victimStartsProcess=self.env.event()
                    else:
                        failureNotTriggered=False
           
            # interrupt the victim
            self.interruptVictim()                      # interrupt the victim

            self.victim.Up=False
            self.victim.timeLastFailure=self.env.now           
            self.outputTrace(self.victim.name,"is down")
            # update the failure time
            failTime=self.env.now    
            if(self.repairman and self.repairman!="None"):     # if the failure needs a resource to be fixed, 
                                                               # the machine waits until the 
                                                               # resource is available
                
                with self.repairman.getResource().request() as request:
                    yield request
                    # update the time that the repair started
                    timeOperationStarted=self.env.now
                    self.repairman.timeLastOperationStarted=self.env.now
                    
                    yield self.env.timeout(self.rngTTR.generateNumber())    # wait until the repairing process is over
                    self.victim.totalFailureTime+=self.env.now-failTime    
                    self.reactivateVictim()                     # since repairing is over, the Machine is reactivated
                    self.victim.Up=True              
                    self.outputTrace(self.victim.name,"is up")
                    
                    self.repairman.totalWorkingTime+=self.env.now-timeOperationStarted   
                continue
                
                
                                
            yield self.env.timeout(self.rngTTR.generateNumber())    # wait until the repairing process is over
            
            # add the failure
            # if victim is off shift add only the fail time before the shift ended
            if not self.victim.onShift and failTime < self.victim.timeLastShiftEnded:
                self.victim.totalFailureTime+=self.victim.timeLastShiftEnded-failTime
            # if the victim was off shift since the start of the failure add nothing
            elif not self.victim.onShift and failTime >= self.victim.timeLastShiftEnded:
                pass
            # if victim was off shift in the start of the fail time, add on
            elif self.victim.onShift and failTime < self.victim.timeLastShiftStarted:
                self.victim.totalFailureTime+=self.env.now-self.victim.timeLastShiftStarted
                # this can happen only if deteriorationType is constant
                assert self.deteriorationType=='constant', 'object got failure while off-shift and deterioration type not constant' 
            else:
                self.victim.totalFailureTime+=self.env.now-failTime   
            self.reactivateVictim()                     # since repairing is over, the Machine is reactivated
            self.victim.Up=True              
            self.outputTrace(self.victim.name,"is up")
def main():
    seed = int(input("Wprowadź Z: "))
    generator = RandomNumberGenerator(seed)
    taskNumber = int(input("Wprowadź liczbę zadań: "))
    tasks = range(1, taskNumber + 1)
    machineNumber = int(input("Wprowadź liczbę maszyn: "))
    machines = range(1, machineNumber + 1)

    Pi = []  #Permutacja po uszeregowaniu
    P = []  # Macierz czas wykonania
    Nr = []  # Lista zadań do wykonania
    P_Copy = []  #Macierz czasów wykonania
    Nr_Copy = []  # Lista zadań do wykonania
    C = []  # Macierz czasów zakończenia zadań
    S = []  # Macierz czasów trwania zadań

    for i in range(1, taskNumber + 1):
        Pi.append(i)

    for i in range(0, taskNumber):
        z = [None] * machineNumber
        C.append(z)

    for i in range(0, taskNumber):
        x = [None] * machineNumber
        S.append(x)

    for i in range(0, taskNumber):
        p = []
        for j in range(0, machineNumber):
            p.append(generator.nextInt(1, 29))
        P.append(p)
        P_Copy.append(p)

    for i in range(1, taskNumber + 1):
        Nr.append(i)
        Nr_Copy.append(i)

    print("\n")
    print("Tabu Calculate:")
    tabu_calculate(taskNumber, machineNumber, C, P, Pi, S)

    print(f"Pi: {Pi}")
    print(f"P: {P}")
    print(f"C: {C}")
    print(f"Cmax: {calculate_cmax(machineNumber,Pi,P)}")

    tabu_time_start = datetime.datetime.now()
    newPi = tabuSearch(taskNumber, machineNumber, P, Pi)
    tabu_time_end = datetime.datetime.now() - tabu_time_start

    newP = []

    for i in range(0, taskNumber):
        newP.append(P[newPi[i] - 1])

    tabu_calculate(taskNumber, machineNumber, C, newP, newPi, S)
    C, Cmax = calculate_neh(newP, taskNumber, machineNumber)
    print(f"Tabu search czas: {tabu_time_end}")
    print(f"Tabu search po sortowaniu: ")
    print(f"Pi: {newPi}")
    print(f"C: {C}")
    print(f"Cmax: {Cmax}")

    #lista wszystkich zadan na konkretnych maszynach
    p_ij_neh = P
    # permutacja zadan
    pi_neh = Nr
    p_kj = []

    print("\n")
    print("NEH:")
    print("p", p_ij_neh)
    print("Permutacj naturalna: ")
    print("pi: ", pi_neh)
    Cj, Cmax = calculate_neh(p_ij_neh, taskNumber, machineNumber)
    print("C:", Cj)
    print("Cmax:", Cmax)

    neh_time_start = datetime.datetime.now()
    p_kj = NEH(p_ij_neh.copy(), taskNumber, machineNumber)
    neh_time_end = datetime.datetime.now() - neh_time_start

    print(f"NEH czas: {neh_time_end}")
    print("NEH po sortowaniu: ")
    print("pkj: ", p_kj)
    Cj, Cmax = calculate_neh(p_kj, taskNumber, machineNumber)
    print("C:", Cj)
    print("Cmax:", Cmax)

    #lista wszystkich zadan na konkretnych maszynach
    p_ij_johnson = P
    # permutacja zadan
    pi_johnson = Nr
    # wyswietlenie rozwiazania po wykonaniu algorytmu optymalizacji
    solution = []

    print("\n")
    print("Johnson:")
    print(p_ij_johnson)
    print("Permutacj naturalna: ")
    print("pi: ", pi_johnson)
    Cj, Cmax = calculate_johnson(p_ij_johnson, taskNumber, machineNumber)
    print("C:", Cj)
    print("Cmax:", Cmax)

    for task in tasks:
        solution.append([pi_johnson[task - 1], p_ij_johnson[task - 1]])

    johson_time_start = datetime.datetime.now()
    pi = Johnson(tasks, p_ij_johnson.copy())
    johson_time_end = datetime.datetime.now() - johson_time_start
    print(f"Johson czas: {johson_time_end}")
    print("Johnson po sortowaniu: ")
    print("pi: ", pi)

    sort = {x: i for i, x in enumerate(pi)}
    solution.sort(key=lambda x: sort[x[0]])
    Cj, Cmax = calculate_johnson([row[1] for row in solution], taskNumber,
                                 machineNumber)
    print("C", Cj)
    print("Cmax:", Cmax)
Example #53
0
class MachineJobShop(Machine):
    @staticmethod
    def getProcessingTime(processingTime):
        '''returns the processingTime dictionary updated'''
        if not processingTime:
            processingTime = { 'distributionType': 'Fixed',
                               'mean': 0, }
        if processingTime['distributionType'] == 'Normal' and\
                processingTime.get('max', None) is None:
            processingTime['max'] = float(processingTime['mean']) + 5 * float(processingTime['stdev'])
        return processingTime
    @staticmethod
    def getSetupTime(setupTime):
        '''returns the setupTime dictionary updated'''
        if not setupTime:
            setupTime = { 'distributionType': 'Fixed',
                          'mean': 0, }
        if setupTime['distributionType'] == 'Normal' and\
                setupTime.get('max', None) is None:
            setupTime['max'] = float(setupTime['mean']) + 5 * float(setupTime['stdev'])
        return setupTime
    @staticmethod
    def getLoadTime(loadTime):
        '''returns the loadTime dictionary updated'''
        if not loadTime:
            loadTime = { 'distributionType': 'Fixed',
                         'mean': 0, }
        if loadTime['distributionType'] == 'Normal' and\
                loadTime.get('max', None) is None:
            loadTime['max'] = float(loadTime['mean']) + 5 * float(loadTime['stdev'])
        return loadTime
    
    # =======================================================================
    # set all the objects in previous and next
    # =======================================================================
    def initialize(self):
        from Globals import G
        self.previous=G.ObjList
        self.next=[]
        Machine.initialize(self)    #run default behaviour
    
#     # =======================================================================
#     # actions to be carried out when the processing of an Entity ends
#     # =======================================================================    
#     def endProcessingActions(self):
#         # set isProcessing to False
#         self.isProcessing=False
#         # add working time
#         self.totalWorkingTime+=self.env.now-self.timeLastProcessingStarted
# 
#         # blocking starts
#         self.isBlocked=True
#         self.timeLastBlockageStarted=self.env.now
# 
#         activeObject=self.getActiveObject()
#         activeObjectQueue=activeObject.Res.users
#         activeEntity=activeObjectQueue[0]
# #         self.printTrace(activeEntity.name,processEnd=activeObject.objName)
#         # reset the variables used to handle the interruptions timing 
#         # self.timeRestartingProcessing=0
#         self.breakTime=0
#         # output to trace that the processing in the Machine self.objName ended 
#         try:
#             activeObject.outputTrace(activeEntity.name,"ended processing in "+activeObject.objName)
#         except IndexError:
#             pass
#         
#         import Globals
#         from Globals import G
#         # the entity that just got processed is cold again it will get 
#         # hot again by the time it reaches the giver of the next machine
#         # TODO: Not only Machines require time to process entities
#         if activeEntity.family=='Job':
#             # read the list of next stations for the entity in just finished processing
#             nextObjectIds=activeEntity.remainingRoute[0].get('stationIdsList',[])
#             nextObjects = []
#             for nextObjectId in nextObjectIds:
#                 nextObject=Globals.findObjectById(nextObjectId)
#                 nextObjects.append(nextObject)
#             successorsAreMachines=True
#             for object in nextObjects:
#                 if not object in G.MachineList:
#                     successorsAreMachines=False
#                     break
#             if not successorsAreMachines:
#                 activeObjectQueue[0].hot = False
#         # the just processed entity is added to the list of entities 
#         # pending for the next processing
#         G.pendingEntities.append(activeObjectQueue[0])
#         # set the variable that flags an Entity is ready to be disposed 
#         activeObject.waitToDispose=True
#         #do this so that if it is overtime working it is not counted as off-shift time
#         if not activeObject.onShift:
#             activeObject.timeLastShiftEnded=self.env.now
#         # update the variables keeping track of Entity related attributes of the machine
#         activeObject.timeLastEntityEnded=self.env.now                              # this holds the time that the last entity ended processing in Machine 
#         activeObject.nameLastEntityEnded=activeObject.currentEntity.name    # this holds the name of the last entity that ended processing in Machine
#         activeObject.completedJobs+=1                                       # Machine completed one more Job
#         # reset flags
#         self.shouldPreempt=False 
#         self.isProcessingInitialWIP=False 
# 
#         # TODO: collapse that to Machine


    # =======================================================================
    # gets an entity from the predecessor that the predecessor index points to
    # =======================================================================     
    def getEntity(self):
        activeObject=self.getActiveObject()
        activeEntity=Machine.getEntity(self)     #run the default code
        
        # read the processing/setup/load times from the corresponding remainingRoute entry
        processingTime=activeEntity.remainingRoute[0].get('processingTime',{})
        processingTime=self.getProcessingTime(processingTime)
        self.rng=RandomNumberGenerator(self, **processingTime)
        self.procTime=self.rng.generateNumber()
        
        setupTime=activeEntity.remainingRoute[0].get('setupTime',{})
        setupTime=self.getSetupTime(setupTime)
        self.stpRng=RandomNumberGenerator(self, **setupTime)
        
        removedStep = activeEntity.remainingRoute.pop(0)      #remove data from the remaining route of the entity
        return activeEntity
    
    
    
    #===========================================================================
    # update the next list of the object based on the activeEentity
    #===========================================================================
    def updateNext(self,entity=None):
        activeObject = self.getActiveObject()
        activeEntity=entity
        # read the possible receivers - update the next list
        import Globals
        # XXX: in the case of MouldAssembler there is no next defined in the route of the entities that are received
        # the position activeEntity.remainingRoute[1] is out of bound. the next should be updated by the remaining route of the entity to be assembled
        if len(activeEntity.remainingRoute)>1:
            nextObjectIds=activeEntity.remainingRoute[1].get('stationIdsList',[])
            nextObjects = []
            for nextObjectId in nextObjectIds:
                nextObject = Globals.findObjectById(nextObjectId)
                nextObjects.append(nextObject)
            # update the next list of the object
            for nextObject in nextObjects:
                # append only if not already in the list
                if nextObject not in activeObject.next:
                    activeObject.next.append(nextObject)
                                                                             
    # =======================================================================  
    # calculates the processing time
    # =======================================================================
    def calculateProcessingTime(self):
        # this is only for processing of the initial wip
        if self.isProcessingInitialWIP:
            # read the processing/setup/load times from the first entry of the full route
            activeEntity=self.getActiveObjectQueue()[0]
            processingTime=activeEntity.route[0].get('processingTime',{})
            processingTime=self.getProcessingTime(processingTime)
            self.rng=RandomNumberGenerator(self, **processingTime)
            self.procTime=self.rng.generateNumber()
            
            setupTime=activeEntity.route[0].get('setupTime',{})
            setupTime=self.getSetupTime(setupTime)
            self.stpRng=RandomNumberGenerator(self, **setupTime)
        return self.procTime    #this is the processing time for this unique entity 
    
    # =======================================================================
    # checks if the Queue can accept an entity       
    # it checks also the next station of the Entity 
    # and returns true only if the active object is the next station
    # ======================================================================= 
    def canAccept(self, callerObject=None):
        activeObjectQueue=self.Res.users
        thecaller=callerObject
        #return according to the state of the Queue
        # also check if (if the machine is to be operated) there are available operators
        if (self.operatorPool!='None' and (any(type=='Load' for type in self.multOperationTypeList))):
            return self.operatorPool.checkIfResourceIsAvailable()\
                    and len(activeObjectQueue)<self.capacity\
                    and self.checkIfMachineIsUp()\
                    and self.isInRoute(thecaller)\
                    and not self.entryIsAssignedTo()
        else:
            return len(activeObjectQueue)<self.capacity\
                    and self.checkIfMachineIsUp()\
                    and self.isInRoute(thecaller)\
                    and not self.entryIsAssignedTo()
                        
    #===========================================================================
    # method used to check whether the station is in the entity-to-be-received route
    # TODO: consider giving the activeEntity as attribute
    # TODO: consider the case when no caller is defined, 
    #         postProcessing calls canAccept on next members with no arguments
    #===========================================================================
    def isInRoute(self, callerObject=None):
        activeObjectQueue=self.Res.users
        thecaller=callerObject
        # if the caller is not defined then return True. We are only interested in checking whether 
        # the station can accept whatever entity from whichever giver
        if not thecaller:
            return True
        #check it the caller object holds an Entity that requests for current object
        if len(thecaller.Res.users)>0:
            # TODO: make sure that the first entity of the callerObject is to be disposed
            activeEntity=thecaller.Res.users[0]
            # if the machine's Id is in the list of the entity's next stations
            if self.id in activeEntity.remainingRoute[0].get('stationIdsList',[]):
                return True
        return False
    
    # =======================================================================   
    # checks if the Machine can dispose an entity. 
    # Returns True only to the potential receiver
    # =======================================================================     
    def haveToDispose(self, callerObject=None):
        activeObjectQueue=self.Res.users
        thecaller=callerObject
        #if we have only one successor just check if machine waits to dispose and also is up
        # this is done to achieve better (cpu) processing time
        if(callerObject==None):
            return len(activeObjectQueue)>0\
                 and self.waitToDispose\
                 and self.checkIfActive()\
        #return True if the Machine in the state of disposing and the caller is the receiver
        return len(activeObjectQueue)>0\
             and self.waitToDispose\
             and self.checkIfActive()\
             and (thecaller in self.next)\
             and thecaller.isInRoute(self)

    # =======================================================================
    # method to execute preemption
    # =======================================================================    
    def preempt(self):
#         self.printTrace(self.id,preempted='')
        activeEntity=self.Res.users[0] #get the active Entity
        #calculate the remaining processing time
        #if it is reset then set it as the original processing time
        if self.resetOnPreemption:
            remainingProcessingTime=self.procTime
        #else subtract the time that passed since the entity entered
        #(may need also failure time if there was. TO BE MELIORATED)
        else:
            remainingProcessingTime=self.procTime-(self.env.now-self.timeLastEntityEntered)
        #update the remaining route of activeEntity
        activeEntity.remainingRoute.insert(0, {'stationIdsList':[str(self.id)],\
                                               'processingTime':\
                                                    {'distributionType':'Fixed',\
                                                     'mean':str(remainingProcessingTime)}})
        activeEntity.remainingRoute.insert(0, {'stationIdsList':[str(self.lastGiver.id)],\
                                               'processingTime':\
                                                    {'distributionType':'Fixed',\
                                                     'mean':'0'}})   
        #set the receiver  as the object where the active entity was preempted from 
        self.receiver=self.lastGiver
        self.next=[self.receiver]
        self.waitToDispose=True                     #set that I have to dispose
        self.receiver.timeLastEntityEnded=self.env.now     #required to count blockage correctly in the preemptied station
        # TODO: use a signal and wait for it, reactivation is not recognised as interruption
#         reactivate(self)
        if self.expectedSignals['preemptQueue']:
            self.sendSignal(receiver=self, signal=self.preemptQueue)
        # TODO: consider the case when a failure has the Station down. The event preempt will not be received now()
        #     but at a later simulation time. 
            
    #===========================================================================
    # extend the default behaviour to check if whether the station 
    #     is in the route of the entity to be received
    #===========================================================================
    def canAcceptAndIsRequested(self,callerObject):
        giverObject=callerObject
        assert giverObject, 'there must be a caller for canAcceptAndIsRequested'
        if self.isInRoute(giverObject):
            if Machine.canAcceptAndIsRequested(self,giverObject):
                self.readLoadTime(giverObject)
                return True
        return False

    #===========================================================================
    # to be called by canAcceptAndIsRequested if it is to return True.
    # the load timeof the Entity must be read
    #===========================================================================
    def readLoadTime(self,callerObject=None):
        assert callerObject!=None, 'the caller of readLoadTime cannot be None'
        thecaller=callerObject
        thecaller.sortEntities()
        activeEntity=thecaller.Res.users[0]
        loadTime=activeEntity.remainingRoute[0].get('loadTime',{})
        loadTime=self.getLoadTime(loadTime)
        self.loadRng=RandomNumberGenerator(self, **loadTime)
        
    # =======================================================================
    # removes an entity from the Machine
    # extension to remove possible receivers accordingly
    # =======================================================================
    def removeEntity(self, entity=None):
        receiverObject=self.receiver  
        activeEntity=Machine.removeEntity(self, entity)         #run the default method  
        removeReceiver=True 
        # search in the internalQ. If an entity has the same receiver do not remove
        for ent in self.Res.users:
            nextObjectIds=ent.remainingRoute[0].get('stationIdsList',[])
            if receiverObject.id in nextObjectIds:
                removeReceiver=False      
        # if not entity had the same receiver then the receiver will be removed    
        if removeReceiver:
            self.next.remove(receiverObject)
        return activeEntity
Example #54
0
 def createMould(self, component):
     #read attributes from the json or from the orderToBeDecomposed
     id = component.get('id', 'not found')
     name = component.get('name', 'not found')
     try:
         # dummy variable that holds the routes of the jobs the route from the JSON file is a sequence of dictionaries
         JSONRoute = component.get('route', [])
         # variable that holds the argument used in the Job initiation hold None for each entry in the 'route' list
         route = [x for x in JSONRoute]  #    copy JSONRoute
         # assert that the assembler is in the moulds route and update the initial step of the mould's route
         firstStep = route.pop(0)
         assert (self.id in firstStep.get('stationIdsList',[])),\
                      'the assembler must be in the mould-to-be-created route\' initial step'
         # normal processing operation
         processingTime = firstStep['processingTime']
         processingTime = self.getOperationTime(processingTime)
         self.rng = RandomNumberGenerator(self, processingTime)
         self.procTime = self.rng.generateNumber()
         # update the activeObject's processing time according to the readings in the mould's route
         processDistType = processingTime.keys()[0]
         procTime = float(processingTime[processDistType].get('mean', 0))
         processOpType = firstStep.get('operationType', {}).get(
             'Processing', 'not found')  # can be manual/automatic
         # task_id
         task_id = firstStep.get('task_id', None)
         # sequence
         sequence = firstStep.get('sequence', None)
         # operator
         operator = firstStep.get('operator', {})
         # technology
         technology = firstStep.get('technology', None)
         # quantity
         quantity = firstStep.get('quantity', None)
         # setup operation
         setupTime = firstStep.get('setupTime', None)
         if setupTime:
             setupTime = self.getOperationTime(setupTime)
             self.stpRng = RandomNumberGenerator(self, setupTime)
             # update the activeObject's processing time according to the readings in the mould's route
             setupDistType = setupTime.keys()[0]
             setTime = float(setupTime[setupDistType].get('mean', 0))
             setupOpType = firstStep.get('operationType', {}).get(
                 'Setup', 'not found')  # can be manual/automatic
             # update the first step of the route with the activeObjects id as sole element of the stationIdsList
             route.insert(0, {'stationIdsList':[str(self.id)],
                              'processingTime':{str(processDistType):{'mean':str(procTime)}},\
                              'setupTime':{str(setupDistType):{'mean':str(setupTime)}},
                              'operationType':{'Processing':processOpType,'Setup':setupOpType}})
         else:
             # update the first step of the route with the activeObjects id as sole element of the stationIdsList
             route.insert(
                 0, {
                     'stationIdsList': [str(self.id)],
                     'processingTime': {
                         str(processDistType): {
                             'mean': str(procTime)
                         }
                     },
                     'operationType': {
                         'Processing': processOpType
                     }
                 })
         # if there is task_id then add it to the route
         if task_id:
             route[0]["task_id"] = task_id
         # if there is sequence then add it to the route
         if sequence:
             route[0]["sequence"] = sequence
         # if there is operator then add it to the route
         if operator:
             route[0]["operator"] = operator
         # if there is technology then add it to the route
         if technology:
             route[0]["technology"] = technology
         # if there is quantity then add it to the route
         if quantity != None:
             route[0]["quantity"] = quantity
         #Below it is to assign an exit if it was not assigned in JSON
         #have to talk about it with NEX
         exitAssigned = False
         for element in route:
             elementIds = element.get('stationIdsList', [])
             for obj in G.ObjList:
                 for elementId in elementIds:
                     if obj.id == elementId and obj.type == 'Exit':
                         exitAssigned = True
         # assign an exit to the route of the mould
         if not exitAssigned:
             exitId = None
             for obj in G.ObjList:
                 if obj.type == 'Exit':
                     exitId = obj.id
                     break
             if exitId:
                 route.append({
                     'stationIdsList': [str(exitId)],
                     'processingTime': {}
                 })
         # keep a reference of all extra properties passed to the job
         extraPropertyDict = {}
         for key, value in component.items():
             if key not in ('_class', 'id'):
                 extraPropertyDict[key] = value
         # create and initiate the OrderComponent
         from Mould import Mould
         M=Mould(id, name, route, \
                           priority=self.mouldParent.priority, \
                           order=self.mouldParent,\
                           dueDate=self.mouldParent.dueDate, \
                           orderDate=self.mouldParent.orderDate, \
                           extraPropertyDict=extraPropertyDict,\
                           isCritical=self.mouldParent.isCritical)
         # update the mouldToBeCreated
         self.mouldToBeCreated = M
         G.JobList.append(M)
         G.WipList.append(M)
         G.EntityList.append(M)
         G.MouldList.append(M)
         #initialize the component
         M.initialize()
     except:
         # added for testing
         print 'the mould to be created', component.get(
             'name', 'not found'), 'cannot be created', 'time', self.env.now
         raise
Example #55
0
 def createMould(self, component):
     #read attributes from the json or from the orderToBeDecomposed
     id=component.get('id', 'not found')
     name=component.get('name', 'not found')
     try:
         # dummy variable that holds the routes of the jobs the route from the JSON file is a sequence of dictionaries
         JSONRoute=component.get('route', [])
         # variable that holds the argument used in the Job initiation hold None for each entry in the 'route' list
         route = [x for x in JSONRoute]       #    copy JSONRoute
         # assert that the assembler is in the moulds route and update the initial step of the mould's route
         firstStep = route.pop(0)
         assert (self.id in firstStep.get('stationIdsList',[])),\
                      'the assembler must be in the mould-to-be-created route\' initial step'
         # normal processing operation
         processingTime=firstStep['processingTime']
         processingTime=self.getOperationTime(processingTime)
         self.rng=RandomNumberGenerator(self, processingTime)
         self.procTime=self.rng.generateNumber()
         # update the activeObject's processing time according to the readings in the mould's route
         processDistType=processingTime.keys()[0]
         procTime=float(processingTime[processDistType].get('mean', 0))
         processOpType=firstStep.get('operationType',{}).get('Processing','not found') # can be manual/automatic
         # task_id
         task_id = firstStep.get('task_id', None)
         # sequence
         sequence = firstStep.get('sequence', None)
         # operator
         operator = firstStep.get('operator', {})
         # technology
         technology = firstStep.get('technology', None)
         # quantity
         quantity = firstStep.get('quantity', None)
         # setup operation
         setupTime=firstStep.get('setupTime',None)
         if setupTime:
             setupTime=self.getOperationTime(setupTime)
             self.stpRng=RandomNumberGenerator(self, setupTime)
             # update the activeObject's processing time according to the readings in the mould's route
             setupDistType=setupTime.keys()[0]
             setTime=float(setupTime[setupDistType].get('mean', 0))
             setupOpType=firstStep.get('operationType',{}).get('Setup','not found') # can be manual/automatic
             # update the first step of the route with the activeObjects id as sole element of the stationIdsList
             route.insert(0, {'stationIdsList':[str(self.id)],
                              'processingTime':{str(processDistType):{'mean':str(procTime)}},\
                              'setupTime':{str(setupDistType):{'mean':str(setupTime)}},
                              'operationType':{'Processing':processOpType,'Setup':setupOpType}})
         else:
             # update the first step of the route with the activeObjects id as sole element of the stationIdsList
             route.insert(0, {'stationIdsList':[str(self.id)],
                              'processingTime':{str(processDistType):{'mean':str(procTime)}},
                              'operationType':{'Processing':processOpType}})
         # if there is task_id then add it to the route
         if task_id:
             route[0]["task_id"] = task_id
         # if there is sequence then add it to the route
         if sequence:
             route[0]["sequence"] = sequence
         # if there is operator then add it to the route
         if operator:
             route[0]["operator"] = operator
         # if there is technology then add it to the route
         if technology:
             route[0]["technology"] = technology
         # if there is quantity then add it to the route
         if quantity!=None:
             route[0]["quantity"] = quantity
         #Below it is to assign an exit if it was not assigned in JSON
         #have to talk about it with NEX
         exitAssigned=False
         for element in route:
             elementIds = element.get('stationIdsList',[])
             for obj in G.ObjList:
                 for elementId in elementIds:
                     if obj.id==elementId and obj.type=='Exit':
                         exitAssigned=True 
         # assign an exit to the route of the mould 
         if not exitAssigned:
             exitId=None
             for obj in G.ObjList:
                 if obj.type=='Exit':
                     exitId=obj.id
                     break
             if exitId:
                 route.append({'stationIdsList':[str(exitId)],'processingTime':{}})
         # keep a reference of all extra properties passed to the job
         extraPropertyDict = {}
         for key, value in component.items():
             if key not in ('_class', 'id'):
                 extraPropertyDict[key] = value
         # create and initiate the OrderComponent
         from Mould import Mould
         M=Mould(id, name, route, \
                           priority=self.mouldParent.priority, \
                           order=self.mouldParent,\
                           dueDate=self.mouldParent.dueDate, \
                           orderDate=self.mouldParent.orderDate, \
                           extraPropertyDict=extraPropertyDict,\
                           isCritical=self.mouldParent.isCritical)
         # update the mouldToBeCreated
         self.mouldToBeCreated=M
         G.JobList.append(M)
         G.WipList.append(M)
         G.EntityList.append(M)
         G.MouldList.append(M)
         #initialize the component
         M.initialize()
     except:
         # added for testing
         print 'the mould to be created', component.get('name', 'not found'), 'cannot be created', 'time', self.env.now
         raise
Example #56
0
class Failure(ObjectInterruption):
    
    def __init__(self, victim=None, distribution=None, index=0, repairman=None):
        #Process.__init__(self)
        ObjectInterruption.__init__(self,victim)
        if distribution:
            self.distType=distribution.get('distributionType','No')              # the distribution that the failure duration follows
            self.MTTF=distribution.get('MTTF',60)                  # the MTTF
            self.MTTR=distribution.get('MTTR',5)                  # the MTTR  
            self.availability=distribution.get('availability',100)  # the availability      
        else:
            self.distType='No'
            self.MTTF=60
            self.MTTR=5
            self.availability=100
        self.name="F"+str(index)
        self.repairman=repairman        # the resource that may be needed to fix the failure
                                        # if now resource is needed this will be "None" 
        self.type="Failure"
        self.id=0

        if(self.distType=="Availability"):      
            
            # -------------------------------------------------------------- 
            #     the following are used if we have availability defined 
            #      (as in plant) the erlang is a special case of Gamma. 
            #        To model the Mu and sigma (that is given in plant) 
            #    as alpha and beta for gamma you should do the following:
            #                     beta=(sigma^2)/Mu    
            #                     alpha=Mu/beta
            # --------------------------------------------------------------    
            self.AvailabilityMTTF=self.MTTR*(float(availability)/100)/(1-(float(availability)/100))
            self.sigma=0.707106781185547*self.MTTR   
            self.theta=(pow(self.sigma,2))/float(self.MTTR)             
            self.beta=self.theta
            self.alpha=(float(self.MTTR)/self.theta)        
            self.rngTTF=RandomNumberGenerator(self, "Exp")
            self.rngTTF.avg=self.AvailabilityMTTF
            self.rngTTR=RandomNumberGenerator(self, "Erlang")
            self.rngTTR.alpha=self.alpha
            self.rngTTR.beta=self.beta       
        else:   
            # --------------------------------------------------------------
            #               if the distribution is fixed
            # --------------------------------------------------------------
            self.rngTTF=RandomNumberGenerator(self, self.distType)
            self.rngTTF.mean=self.MTTF
            self.rngTTR=RandomNumberGenerator(self, self.distType)
            self.rngTTR.mean=self.MTTR

    # =======================================================================
    #    The run method for the failure which has to served by a repairman
    # =======================================================================
    def run(self):           
        while 1:
            yield hold,self,self.rngTTF.generateNumber()    # wait until a failure happens                  
            if(len(self.getVictimQueue())>0):           # when a Machine gets failure
                self.interruptVictim()                  # while in process it is interrupted
            self.victim.Up=False
            self.victim.timeLastFailure=now()           
            self.outputTrace("is down")
            # update the failure time
            failTime=now()            
            if(self.repairman and self.repairman!="None"):     #if the failure needs a resource to be fixed, the machine waits until the 
                                            #resource is available
                yield request,self,self.repairman.getResource()
                # update the time that the repair started
                timeOperationStarted=now()
                self.repairman.timeLastOperationStarted=now()
                                
            yield hold,self,self.rngTTR.generateNumber()    # wait until the repairing process is over
            self.victim.totalFailureTime+=now()-failTime    
            
            if(len(self.getVictimQueue())>0):                
                self.reactivateVictim()                 # since repairing is over, the Machine is reactivated
            self.victim.Up=True              
            self.outputTrace("is up")              
            if(self.repairman and self.repairman!="None"): #if a resource was used, it is now released
                yield release,self,self.repairman.getResource() 
                self.repairman.totalWorkingTime+=now()-timeOperationStarted