Exemplo n.º 1
0
    def initializeEmptySystem(self):
        self.currentTime = 0

        self.queues = []
        self.cumQueueslen = []
        self.waitingTimes = []
        self.cycleTimes = []
        self.sojournTimes = []
        for i in range(self.n):
            self.queues.append(Queue())
            self.cumQueueslen.append(0)
            self.waitingTimes.append([])
            self.cycleTimes.append([])
            self.sojournTimes.append([])

        self.serverStatus = (0, 0)  #(idle, queue 1)
        self.cycleTimes[0].append(0)
        self.fes = FES()
Exemplo n.º 2
0
    def initializeEmptySystem(self): #initialize empty system
        self.currentTime = 0 #set time to 0
        self.k = 0 #initialize number of customers served in queue

        self.queues = []
        self.cumQueueslen = []
        self.waitingTimes = []
        self.cycleTimes = []
        self.sojournTimes = []
        for i in range(self.n): #create queues and performance measure variables
            self.queues.append(Queue())
            self.cumQueueslen.append(0)
            self.waitingTimes.append([])
            self.cycleTimes.append([])
            self.sojournTimes.append([])

        self.serverStatus = 0 #initialize server at queue 0
        self.cycleTimes[self.serverStatus].append(0) #first cycle time
        self.inactive = True #servers are inactive initially
        self.fes = FES() #create future event set
Exemplo n.º 3
0
    def initializeEmptySystem(self): #initialize empty system
        self.currentTime = 0 #set time to 0

        self.queues = []
        self.cumQueueslen = []
        self.waitingTimes = []
        self.cycleTimes = []
        self.sojournTimes = []
        for i in range(self.n): #create queues and performance measure variables
            self.queues.append(Queue())
            self.cumQueueslen.append(0)
            self.waitingTimes.append([])
            self.cycleTimes.append([])
            self.sojournTimes.append([])


        self.serverStatus = np.zeros(self.servers, dtype=int)
        for i in range(self.servers):
            self.serverStatus[i] = i #distribute servers over queues
            self.cycleTimes[i].append(0)  #initialize first cycle in queues with server

        self.inactive = True #servers are inactive initially
        self.fes = FES() #create future event set
Exemplo n.º 4
0
class RovingServerQueue:
    def __init__(self, inputfile, maxTime):
        self.maxTime = maxTime
        with open(inputfile) as f:
            #params = f.read()
            #params = params.replace('\n', ' ').replace('\t', ' ').split(' ')
            params = f.read().splitlines()

        paramlist = []
        for line in params:
            line = line.replace('\t', ' ').split(' ')
            line = list(map(float, line))
            paramlist.append(line)

        self.n = len(paramlist[0])  #number of queues
        self.lams = paramlist[0]  #lambdas
        self.muBs = paramlist[1]  #mean service times
        self.muRs = paramlist[2]  #mean switch times
        self.ks = paramlist[3]  #k's
        self.ps = []  #rejoin probabilities
        self.gated = 0
        self.k = 0

        for i in range(self.n):
            p = paramlist[4 + i] + [np.round(1 - sum(paramlist[4 + i]), 2)]
            self.ps.append(p)

        # self.lamOne = float(params[0])
        # self.lamTwo = float(params[1])
        # self.lamThree = float(params[2])
        # self.lamFour = float(params[3])
        # self.muBOne = float(params[4])
        # self.muBTwo = float(params[5])
        # self.muBThree = float(params[6])
        # self.muBFour = float(params[7])
        # self.muROne = float(params[8])
        # self.muRTwo = float(params[9])
        # self.muRThree = float(params[10])
        # self.muRFour = float(params[11])
        # self.kOne = float(params[12])
        # self.kTwo = float(params[13])
        # self.kThree = float(params[14])
        # self.kFour = float(params[15])
        # self.pOneOne = float(params[16])
        # self.pOneTwo = float(params[17])
        # self.pOneThree = float(params[18])
        # self.pOneFour = float(params[19])
        # self.pTwoOne = float(params[20])
        # self.pTwoTwo = float(params[21])
        # self.pTwoThree = float(params[22])
        # self.pTwoFour = float(params[23])
        # self.pThreeOne = float(params[24])
        # self.pThreeTwo = float(params[25])
        # self.pThreeThree = float(params[26])
        # self.pThreeFour = float(params[27])
        # self.pFourOne = float(params[28])
        # self.pFourTwo = float(params[29])
        # self.pFourThree = float(params[30])
        # self.pFourFour = float(params[31])
        #
        # self.pOneZero = 1 - (self.pOneOne + self.pOneTwo + self.pOneThree + self.pOneFour)
        # self.pTwoZero = 1 - (self.pTwoOne + self.pTwoTwo + self.pTwoThree + self.pTwoFour)
        # self.pThreeZero = 1 - (self.pThreeOne + self.pThreeTwo + self.pThreeThree + self.pThreeFour)
        # self.pFourZero = 1 - (self.pFourOne + self.pFourTwo + self.pFourThree + self.pFourFour)

        print('Initialize empty queue')
        self.initializeEmptySystem()
        print('schedule first arrivals')

        # self.scheduleArrivalEvent(1, self.lamOne)
        # self.scheduleArrivalEvent(1, self.lamTwo)
        # self.scheduleArrivalEvent(1, self.lamThree)
        # self.scheduleArrivalEvent(1, self.lamFour)

        for i in range(self.n):  #schedule arrival in every queue
            lam = self.lams[i]
            self.scheduleArrivalEvent(i, lam)

        # print(self.currentTime)
        # for i in range(self.n):
        #     print(self.queues[i])
        # print(self.fes)
        # print('')

        while self.currentTime < maxTime:

            #get event
            currentEvent = self.fes.next()
            self.oldTime = self.currentTime
            self.currentTime = currentEvent.time
            self.processResults(self.currentTime - self.oldTime)

            if currentEvent.typ == "ARRIVAL" or currentEvent.typ == "REJOIN":

                if currentEvent.typ == "REJOIN":
                    customer = self.rejoincustomer
                else:
                    customer = Customer(self.currentTime, self.currentTime,
                                        currentEvent.queue, currentEvent.queue)

                if self.serverStatus[0] == 0:  #check if server is inactive

                    serverqueue = self.serverStatus[1]
                    queue = currentEvent.queue
                    self.queues[queue].addCustomer(customer)
                    muR = self.muRs[queue]

                    if not self.fes.checkSwitch():
                        if self.queues[serverqueue].isempty(
                        ) or self.gated >= self.k:
                            self.scheduleSwitchEvent(serverqueue, muR)
                            self.serverStatus = (1, serverqueue)

                else:  #server active

                    queue = currentEvent.queue
                    self.queues[queue].addCustomer(customer)

                if currentEvent.typ == "ARRIVAL":

                    #schedule new arrival
                    queue = currentEvent.queue
                    lam = self.lams[queue]
                    self.scheduleArrivalEvent(queue, lam)

                    # if currentEvent.queue == 1:
                    #     self.scheduleArrivalEvent(1, self.lamOne)
                    #
                    # elif currentEvent.queue == 2:
                    #     self.scheduleArrivalEvent(2, self.lamTwo)
                    #
                    # elif currentEvent.queue == 3:
                    #     self.scheduleArrivalEvent(3, self.lamThree)
                    #
                    # elif currentEvent.queue == 4:
                    #     self.scheduleArrivalEvent(4, self.lamFour)

            elif currentEvent.typ == 'DEPARTURE':
                #remove customer from queue

                if self.serverStatus[
                        1] == currentEvent.queue:  # check if server is in same queue as event, wss onnodig

                    #serverqueue = self.serverStatus[1]
                    switch = range(0, (self.n + 1))
                    #switch = [1, 2, 3, 4, 0]

                    queue = currentEvent.queue
                    customer = self.queues[queue].queue[0]

                    muB = self.muBs[queue]
                    muR = self.muRs[queue]
                    probs = self.ps[queue]
                    new_arrival = np.random.choice(switch, 1, p=probs)[0]

                    if new_arrival == self.n:
                        self.processSojournTime(customer)
                    else:
                        self.scheduleRejoinEvent(new_arrival, customer)

                    self.queues[queue].pop(0)
                    self.k += 1

                    if not self.queues[queue].isempty(
                    ) and self.k < self.gated:
                        self.scheduleDepartureEvent(queue, muB)
                        self.processWaitingTime(customer)
                    else:
                        self.scheduleSwitchEvent(queue, muR)
                        self.serverStatus = (1, queue)

                    # if currentEvent.queue == 1:
                    #     self.queueOne.pop(0)
                    #     mu = self.muBOne
                    #     muR = self.muROne
                    #
                    #     probs = [self.pOneOne, self.pOneTwo, self.pOneThree, self.pOneFour, self.pOneZero]
                    #     new_arrival = np.random.choice(switch, 1, p = probs)[0]
                    #
                    #     if new_arrival == 0:
                    #         pass
                    #     else:
                    #         self.scheduleRejoinEvent(new_arrival)
                    #
                    #     if not self.queueOne.isempty():
                    #         #print(str(self.queueOne) + ' queue 1')
                    #         self.scheduleDepartureEvent(serverqueue, mu)
                    #     else:
                    #         self.scheduleSwitchEvent(serverqueue, muR)
                    #         self.serverStatus = (1, serverqueue)
                    #

                    # elif currentEvent.queue == 2:
                    #     self.queueTwo.pop(0)
                    #     mu = self.muBTwo
                    #     muR = self.muRTwo
                    #
                    #     probs = [self.pTwoOne, self.pTwoTwo, self.pTwoThree, self.pTwoFour, self.pTwoZero]
                    #     new_arrival = np.random.choice(switch, 1, p=probs)[0]
                    #
                    #     if new_arrival == 0:
                    #         pass
                    #     else:
                    #         self.scheduleRejoinEvent(new_arrival)
                    #
                    #     if not self.queueTwo.isempty():
                    #         #print(str(self.queueTwo) + ' queue 2')
                    #         self.scheduleDepartureEvent(serverqueue, mu)
                    #     else:
                    #         self.scheduleSwitchEvent(serverqueue, muR)
                    #         self.serverStatus = (1, serverqueue)
                    #
                    #
                    # elif currentEvent.queue == 3:
                    #     self.queueThree.pop(0)
                    #     mu = self.muBThree
                    #     muR = self.muRThree
                    #
                    #     probs = [self.pThreeOne, self.pThreeTwo, self.pThreeThree, self.pThreeFour, self.pThreeZero]
                    #     new_arrival = np.random.choice(switch, 1, p=probs)[0]
                    #
                    #     if new_arrival == 0:
                    #         pass
                    #     else:
                    #         self.scheduleRejoinEvent(new_arrival)
                    #
                    #     if not self.queueThree.isempty():
                    #         #print(str(self.queueThree) + ' queue 3')
                    #         self.scheduleDepartureEvent(serverqueue, mu)
                    #     else:
                    #         self.scheduleSwitchEvent(serverqueue, muR)
                    #         self.serverStatus = (1, serverqueue)
                    #
                    #
                    # elif currentEvent.queue == 4:
                    #     self.queueFour.pop(0)
                    #     mu = self.muBFour
                    #     muR = self.muRFour
                    #
                    #     probs = [self.pFourOne, self.pFourTwo, self.pFourThree, self.pFourFour, self.pFourZero]
                    #     new_arrival = np.random.choice(switch, 1, p=probs)[0]
                    #
                    #     if new_arrival == 0:
                    #         pass
                    #     else:
                    #         self.scheduleRejoinEvent(new_arrival)
                    #
                    #     if not self.queueFour.isempty():
                    #         #print(str(self.queueFour) + ' queue 4')
                    #         self.scheduleDepartureEvent(serverqueue, mu)
                    #     else:
                    #         self.scheduleSwitchEvent(serverqueue, muR)
                    #         self.serverStatus = (1, serverqueue)

                else:  #all initial customers in the queue are served
                    raise ValueError('fout')
                    pass

            elif currentEvent.typ == 'SWITCH':

                queue = currentEvent.queue
                muB = self.muBs[queue]
                self.processCycleTime(queue)
                self.gated = len(self.queues[queue].queue)
                self.k = 0

                if not self.queues[queue].isempty():
                    self.scheduleDepartureEvent(queue, muB)
                    customer = self.queues[queue].queue[0]
                    self.processWaitingTime(customer)
                    self.serverStatus = (1, queue)
                else:
                    self.serverStatus = (0, queue)

                # if queue == 1:
                #     if not self.queueOne.isempty():
                #         self.scheduleDepartureEvent(queue, mu)
                #         self.serverStatus = (1, queue)
                #     else:
                #         self.serverStatus = (0, queue)
                #
                # if queue == 2:
                #     if not self.queueTwo.isempty():
                #         self.scheduleDepartureEvent(queue, mu)
                #         self.serverStatus = (1, queue)
                #     else:
                #         self.serverStatus = (0, queue)
                #
                # if queue == 3:
                #     if not self.queueThree.isempty():
                #         self.scheduleDepartureEvent(queue, mu)
                #         self.serverStatus = (1, queue)
                #     else:
                #         self.serverStatus = (0, queue)
                #
                # if queue == 4:
                #     if not self.queueFour.isempty():
                #         self.scheduleDepartureEvent(queue, mu)
                #         self.serverStatus = (1, queue)
                #     else:
                #         self.serverStatus = (0, queue)

            # print(self.currentTime)
            # print(self.queueOne)
            # print(self.queueTwo)
            # print(self.queueThree)
            # print(self.queueFour)

            # print(self.currentTime)
            # for i in range(self.n):
            #     print(self.queues[i])

        # print(self.currentTime)
        # print(self.queueOne)
        # print(self.queueTwo)
        # print(self.queueThree)
        # print(self.queueFour)
        # print(self.fes)
        # print('')
        # print("Average queue length queue one: " + str(self.cumQueueOnelen / self.maxTime))
        # print("Average queue length queue two: " + str(self.cumQueueTwolen / self.maxTime))
        # print("Average queue length queue three: " + str(self.cumQueueThreelen / self.maxTime))
        # print("Average queue length queue four: " + str(self.cumQueueFourlen / self.maxTime))
        for i in range(self.n):
            print("Average queue length queue " + str(i) + ": " +
                  str(self.cumQueueslen[i] / self.maxTime))
            print("Average waiting time queue " + str(i) + ": " +
                  str(sum(self.waitingTimes[i]) / len(self.waitingTimes[i])))
            print("Average sojourn time queue " + str(i) + ": " +
                  str(sum(self.sojournTimes[i]) / len(self.sojournTimes[i])))
            cycles = len(self.cycleTimes[i]) - 1
            cycletime = self.cycleTimes[i][cycles] - self.cycleTimes[i][0]
            #print(self.cycleTimes[i], cycles, cycletime)
            print("Average cycle time queue " + str(i) + ": " +
                  str(cycletime / cycles))
            print('')

    def initializeEmptySystem(self):
        self.currentTime = 0

        self.queues = []
        self.cumQueueslen = []
        self.waitingTimes = []
        self.cycleTimes = []
        self.sojournTimes = []
        for i in range(self.n):
            self.queues.append(Queue())
            self.cumQueueslen.append(0)
            self.waitingTimes.append([])
            self.cycleTimes.append([])
            self.sojournTimes.append([])

        self.serverStatus = (0, 0)  #(idle, queue 1)
        self.cycleTimes[0].append(0)
        self.fes = FES()

    def scheduleArrivalEvent(self, queue, lam):
        # compute new arrival time
        if lam == 0:
            arrivalTime = 0
        else:
            arrivalTime = np.random.exponential(1 / lam)

        # schedule arrival at currentTime + arrivaltime
        event = Event("ARRIVAL", self.currentTime + arrivalTime, queue)
        self.fes.add(event)

    def processResults(self, t):
        for i in range(self.n):
            self.cumQueueslen[
                i] = self.cumQueueslen[i] + t * self.queues[i].size()
        # self.cumQueueOnelen = self.cumQueueOnelen + t * self.queueOne.size()
        # self.cumQueueTwolen = self.cumQueueTwolen + t * self.queueTwo.size()
        # self.cumQueueThreelen = self.cumQueueThreelen + t * self.queueThree.size()
        # self.cumQueueFourlen = self.cumQueueFourlen + t * self.queueFour.size()

    def processWaitingTime(self, customer):
        queue = customer.queue
        queueJoinTime = customer.queueJoinTime
        waitingTime = self.currentTime - queueJoinTime
        self.waitingTimes[queue].append(waitingTime)

    def processSojournTime(self, customer):
        queue = customer.queue
        arrivalTime = customer.arrivalTime
        sojournTime = self.currentTime - arrivalTime
        self.sojournTimes[queue].append(sojournTime)

    def processCycleTime(self, queue):
        self.cycleTimes[queue].append(self.currentTime)

    def scheduleDepartureEvent(self, queue, mu):
        # compute new departure time
        serviceTime = np.random.exponential(mu)
        # schedule arrival at currentTime + arrivaltime
        event = Event("DEPARTURE", self.currentTime + serviceTime, queue)
        self.fes.add(event)

    def scheduleSwitchEvent(self, queue, mu):
        switchTime = mu
        nextloc = queue + 1
        if nextloc > (self.n - 1):
            nextloc = 0

        # if queue == 4:
        #     nextloc = 1
        # else:
        #     nextloc = queue + 1

        event = Event("SWITCH", self.currentTime + switchTime, nextloc)
        self.fes.add(event)

    def scheduleRejoinEvent(self, queue, customer):
        event = Event("REJOIN", self.currentTime, queue)
        self.rejoincustomer = Customer(customer.arrivalTime, self.currentTime,
                                       queue, customer.arrivalQueue)
        self.fes.add(event)

    pass
Exemplo n.º 5
0
class Klimited:
    def __init__(self, inputfile, maxTime):
        self.maxTime = maxTime #max time specified
        with open(inputfile) as f:
            params = f.read().splitlines() #read input file of parameters

        paramlist = []
        for line in params: #process input file
            line = line.replace('\t', ' ').split(' ')
            line = list(map(float, line))
            paramlist.append(line)

        #define all parameters
        self.n = len(paramlist[0]) #number of queues
        self.lams = paramlist[0] #lambdas
        self.muBs = paramlist[1] #mean service times
        self.muRs = paramlist[2] #mean switch times
        self.ks = paramlist[3] #k's
        self.ps = [] #rejoin probabilities

        for i in range(self.n):
            p = paramlist[4+i] + [np.round(1 - sum(paramlist[4+i]), 2)]
            self.ps.append(p)

        self.switch = range(0, (self.n + 1)) #list of queue numbers used for scheduling rejoin event

        print('Initialize empty queue')
        self.initializeEmptySystem()
        print('schedule first arrivals')

        for i in range(self.n): #schedule arrival in every queue
            lam = self.lams[i]
            self.scheduleArrivalEvent(i, lam)

        while self.currentTime < maxTime: #loop until max time reached

            #get event
            currentEvent = self.fes.next()
            self.oldTime = self.currentTime #set old time
            self.currentTime = currentEvent.time #set current time
            self.processQueueLength(self.currentTime - self.oldTime) #add queue length

            if currentEvent.typ == "ARRIVAL" or currentEvent.typ == "REJOIN": #check if event type is arrival or rejoin

                if currentEvent.typ == "REJOIN": #if rejoin, keep old customer
                    customer = self.rejoincustomer
                else: #else make new customer
                    customer = Customer(self.currentTime, self.currentTime, currentEvent.queue, currentEvent.queue)

                if self.inactive:  #check if servers are inactive (first event)

                    self.inactive = False

                    if self.serverStatus == currentEvent.queue: #check if a server is in same queue as event

                        # select the right parameters according to the given queue
                        queue = currentEvent.queue
                        muB = self.muBs[queue]
                        self.queues[queue].addCustomer(customer) #add customer to queue

                        self.scheduleDepartureEvent(queue, muB) #schedule departure event
                        self.processWaitingTime(customer) #add waiting time

                    else: #servers inactive, wrong queue

                        queue = currentEvent.queue #get queue of event
                        serverqueue = self.serverStatus #get queue of server
                        self.queues[queue].addCustomer(customer) #add customer to queue
                        muR = self.muRs[serverqueue]

                        self.scheduleSwitchEvent(serverqueue, muR) #schedule switch event

                else: #server active

                    queue = currentEvent.queue
                    self.queues[queue].addCustomer(customer) #add customer to queue

                if currentEvent.typ == "ARRIVAL": #if event is arrival, schedule next arrival

                    #schedule new arrival
                    queue = currentEvent.queue
                    lam = self.lams[queue]
                    self.scheduleArrivalEvent(queue, lam)

            elif currentEvent.typ == "DEPARTURE": #if event type is departure

                queue = currentEvent.queue #get queue
                customer = self.queues[queue].queue[0] #get customer

                #get params
                muB = self.muBs[queue]
                muR = self.muRs[queue]
                probs = self.ps[queue]
                new_arrival = np.random.choice(self.switch, 1, p=probs)[0] #pick a queue to rejoin

                if new_arrival == self.n: #if customer leaves system
                    self.processSojournTime(customer) #add sojourn time
                else:
                    self.scheduleRejoinEvent(new_arrival, customer) #schedule rejoin

                self.queues[queue].pop(0) #remove customer from queue
                self.k += 1 #increment customers served in queue

                if ((not self.queues[queue].isempty()) or (new_arrival == queue)) and (self.k < self.ks[queue]):
                    #if queue is not empty or customer joins same queue and num of served customers less than k
                    self.scheduleDepartureEvent(queue, muB) #keep serving queue, schedule next departure
                    self.processWaitingTime(customer)
                else:
                    self.scheduleSwitchEvent(queue, muR) #schedule switch if queue is empty

            elif currentEvent.typ == "SWITCH": #if event type is switch

                #get params
                queue = currentEvent.queue #server switches to this queue
                self.serverStatus = queue
                muB = self.muBs[queue]
                muR = self.muRs[queue]
                self.k = 0 #reset number of customers served in current queue
                self.processCycleTime(queue) #save time for calculating cycle time

                if not self.queues[queue].isempty(): #if queue is not empty
                    self.scheduleDepartureEvent(queue, muB) #serve customer, schedule departure
                    customer = self.queues[queue].queue[0]
                    self.processWaitingTime(customer) #process customer waiting time
                else:
                    self.scheduleSwitchEvent(queue, muR) #schedule another switch event

            # print(self.currentTime)
            # for i in range(self.n):
            #     print(self.queues[i])
            # print(self.serverStatus)
            # print(self.k)
            # print(self.fes)
            # print('')


        fig1, axs1 = plt.subplots(2, 2)
        fig2, axs2 = plt.subplots(2, 2)
        axes = [[0,0], [0,1], [1,0], [1,1]]
        colors = ['tab:blue', 'tab:orange', 'tab:green', 'tab:red']

        for i in range(self.n): #print all interesting performance measures and create plots
            print("Average queue length queue " + str(i) + ": " + str(self.cumQueueslen[i] / self.maxTime))
            print("Average waiting time queue " + str(i) + ": " +str(sum(self.waitingTimes[i]) / len(self.waitingTimes[i]))
                  + ' ' + str(self.calculateCI(self.waitingTimes[i], 1.96)))
            print("Average sojourn time queue " + str(i) + ": " + str(sum(self.sojournTimes[i]) / len(self.sojournTimes[i]))
                  + ' ' + str(self.calculateCI(self.sojournTimes[i], 1.96)))

            # cycles = len(self.cycleTimes[i]) - 1
            # cycletime = self.cycleTimes[i][cycles] - self.cycleTimes[i][0]
            # print(self.cycleTimes[i], cycles, cycletime)
            # print("Average cycle time queue " + str(i) + ": " + str(cycletime / cycles))

            cycles = self.calculateCycleTime(i)
            print("Average cycle time queue " + str(i) + ": " + str(sum(cycles) / len(cycles))
                  + ' ' + str(self.calculateCI(cycles, 1.96)))
            print('')

            axs1[axes[i][0], axes[i][1]].plot(self.waitingTimes[i], color=colors[i])

            axs2[axes[i][0], axes[i][1]].hist(self.waitingTimes[i], bins=range(int(min(self.waitingTimes[i])), int(max(self.waitingTimes[i])) + 1, 1), color=colors[i])

        plt.show()


    def initializeEmptySystem(self): #initialize empty system
        self.currentTime = 0 #set time to 0
        self.k = 0 #initialize number of customers served in queue

        self.queues = []
        self.cumQueueslen = []
        self.waitingTimes = []
        self.cycleTimes = []
        self.sojournTimes = []
        for i in range(self.n): #create queues and performance measure variables
            self.queues.append(Queue())
            self.cumQueueslen.append(0)
            self.waitingTimes.append([])
            self.cycleTimes.append([])
            self.sojournTimes.append([])

        self.serverStatus = 0 #initialize server at queue 0
        self.cycleTimes[self.serverStatus].append(0) #first cycle time
        self.inactive = True #servers are inactive initially
        self.fes = FES() #create future event set

    def scheduleArrivalEvent(self, queue, lam):
        arrivalTime = np.random.exponential(1/lam) #take arrival time from distribution

        event = Event("ARRIVAL", self.currentTime + arrivalTime, queue) #schedule arrival event
        self.fes.add(event)

    def processQueueLength(self, t):
        for i in range(self.n): #add queue length to corresponding queue
            self.cumQueueslen[i] = self.cumQueueslen[i] + t * self.queues[i].size()

    def processWaitingTime(self, customer):
        queue = customer.queue #get queue
        queueJoinTime = customer.queueJoinTime #get time customer joined the queue
        waitingTime = self.currentTime - queueJoinTime #calculate waiting time
        self.waitingTimes[queue].append(waitingTime) #add waiting time

    def processSojournTime(self, customer):
        queue = customer.queue #get queue
        arrivalTime = customer.arrivalTime #get arrival time in system of customer
        sojournTime = self.currentTime - arrivalTime #calculate sojourn time
        self.sojournTimes[queue].append(sojournTime) #add sojourn time

    def processCycleTime(self, queue):
        self.cycleTimes[queue].append(self.currentTime) #add time of cycle completion

    def calculateCycleTime(self, queue):
        timestamps = self.cycleTimes[queue] #get times of finished cycles
        lenOfCycles = np.zeros(len(timestamps)-1) #intialize cycle times array
        for i in range(len(timestamps)-1): #calculate cycle times
            lenOfCycles[i] = timestamps[i+1] - timestamps[i]
        return lenOfCycles #return cycle times

    def scheduleDepartureEvent(self, queue, mu):
        # compute new departure time
        serviceTime = np.random.exponential(mu)
        # schedule arrival at currentTime + arrivaltime
        event = Event("DEPARTURE", self.currentTime + serviceTime, queue)
        self.fes.add(event) #add to future event set

    def scheduleSwitchEvent(self, queue, mu):
        switchTime = mu #switch time is discrete
        nextloc = queue + 1 #switch to next queue
        if nextloc > (self.n-1): #make sure queue exists
            nextloc = 0

        event = Event("SWITCH", self.currentTime + switchTime, nextloc) #schedule switch event
        self.fes.add(event) #add to future event set

    def scheduleRejoinEvent(self, queue, customer):
        event = Event("REJOIN", self.currentTime, queue) #schedule rejoin event
        self.rejoincustomer = Customer(customer.arrivalTime, self.currentTime, queue, customer.arrivalQueue) #save customer data
        self.fes.add(event) #add to future event set

    def calculateCI(self, data, z):
        avg = sum(data) / len(data) #get mean
        stdev = np.std(data) #get standard deviation
        halfWidth = z * stdev / np.sqrt(len(data)) #get halfwidth
        ci = (avg-halfWidth, avg+halfWidth) #get ci
        return ci #return ci
Exemplo n.º 6
0
    def simulate(self, T, verbose=False, immediate_departure=False):
        #start simulation untill time reaches T

        fes = FES()
        simres = SimulationResults(self.s, self.m, self.h, T)
        
        queue = deque()
        t = 0
        prev_gap_time = 0

        #schedule first arrival
        c0 = Car(self.sideArrDist.rvs())
        fes.add(Event(c0.arrTime, Event.ARRIVAL, car=c0))

        #schedule first gap
        fes.add( Event(self.mainArrDist.rvs(), Event.GAP))

        simres.registerQueue(t, len(queue))

        while t < T:
            if verbose:
                print(fes.getTypesList(), fes.events)
            
            #next event
            e = fes.next()
            
            if e.type == Event.GAP:
                t = e.time
                #register the transitionprobability if there is no immediate_departure
                if not immediate_departure:
                    simres.registerQueue(t, len(queue))
                
                #depart the right amount of cars from the queue
                duration = e.time - prev_gap_time
                prev_gap_time = e.time
                departures = int(duration // self.h)
                
                for _ in range(departures):
                    #a car leaves the queue, we save their waitingtime
                    if len(queue) != 0:
                        c = queue.popleft()       

                #register the transitionprobability if there is immediate_departure
                if immediate_departure:
                    simres.registerQueue(t, len(queue))             

                # schedule next gap
                fes.add( Event(t+self.mainArrDist.rvs(), Event.GAP) )

            if e.type == Event.ARRIVAL:
                #add car to the queue
                t = e.time
                queue.append(e.car)

                #schedule next car 
                c1 = Car(t + self.sideArrDist.rvs())
                fes.add(Event(c1.arrTime,Event.ARRIVAL, car=c1))

        simres.registerQueue(t, len(queue))
        return simres
Exemplo n.º 7
0
class RovingServerQueue:
    def __init__(self, inputfile, maxTime):
        self.maxTime = maxTime  #max time specified
        with open(inputfile) as f:
            params = f.read().splitlines()  #read input file of parameters

        paramlist = []
        for line in params:  #process input file
            line = line.replace('\t', ' ').split(' ')
            line = list(map(float, line))
            paramlist.append(line)

        #define all parameters
        self.n = len(paramlist[0])  #number of queues
        self.lams = paramlist[0]  #lambdas
        self.muBs = paramlist[1]  #mean service times
        self.muRs = paramlist[2]  #mean switch times
        self.ks = paramlist[3]  #k's
        self.ps = []  #rejoin probabilities
        for i in range(self.n):
            p = paramlist[4 + i] + [np.round(1 - sum(paramlist[4 + i]), 2)]
            self.ps.append(p)

        self.switch = range(
            0, (self.n +
                1))  #list of queue numbers used for scheduling rejoin event

        print('Initialize empty queue')
        self.initializeEmptySystem()
        print('schedule first arrivals')

        for i in range(self.n):  #schedule arrival in every queue
            lam = self.lams[i]
            self.scheduleArrivalEvent(i, lam)

        while self.currentTime < maxTime:  #loop until max time reached

            #get event
            currentEvent = self.fes.next()
            self.oldTime = self.currentTime  #set old time
            self.currentTime = currentEvent.time  #set current time
            self.processResults(self.currentTime -
                                self.oldTime)  #add queue length

            if currentEvent.typ == "ARRIVAL" or currentEvent.typ == "REJOIN":  #check if event type is arrival or rejoin

                if currentEvent.typ == "REJOIN":  #if rejoin, keep old customer
                    customer = self.rejoincustomer
                else:  #else make new customer
                    customer = Customer(self.currentTime, self.currentTime,
                                        currentEvent.queue, currentEvent.queue)

                if self.serverStatus[
                        0] == 0:  #check if server is inactive (first event)

                    if self.serverStatus[
                            1] == currentEvent.queue:  #check if server is in same queue as event

                        # select the right parameters according to the given queue
                        queue = currentEvent.queue
                        muB = self.muBs[queue]
                        self.queues[queue].addCustomer(
                            customer)  #add customer to queue

                        self.serverStatus = (1, queue
                                             )  #set server status to active
                        self.scheduleDepartureEvent(
                            queue, muB)  #schedule departure event
                        self.processWaitingTime(customer)  #add waiting time

                    else:  #server inactive, wrong queue

                        serverqueue = self.serverStatus[
                            1]  #get queue of server
                        queue = currentEvent.queue  #get queue of event
                        self.queues[queue].addCustomer(
                            customer)  #add customer to queue
                        muR = self.muRs[serverqueue]  #get switchtime

                        #if self.fes.checkSwitch(): #if no switch is scheduled yet, schedule switch
                        #raise ValueError('fout')
                        #niet nodig

                        if self.queues[serverqueue].isempty(
                        ):  #only schedule switch if queue of server is empty
                            self.scheduleSwitchEvent(serverqueue,
                                                     muR)  #schedule switch
                            self.serverStatus = (
                                1, serverqueue)  #set server status to active

                else:  #server active

                    queue = currentEvent.queue
                    self.queues[queue].addCustomer(
                        customer)  #add customer to queue

                if currentEvent.typ == "ARRIVAL":  #if event is arrival, schedule next arrival

                    #schedule new arrival
                    queue = currentEvent.queue
                    lam = self.lams[queue]
                    self.scheduleArrivalEvent(queue, lam)

            elif currentEvent.typ == "DEPARTURE":  #if event type is departure

                queue = currentEvent.queue  #get queue
                customer = self.queues[queue].queue[0]  #get customer

                #get params
                muB = self.muBs[queue]
                muR = self.muRs[queue]
                probs = self.ps[queue]
                new_arrival = np.random.choice(
                    self.switch, 1, p=probs)[0]  #pick a queue to rejoin

                if new_arrival == self.n:  #if customer leaves system
                    self.processSojournTime(customer)  #add sojourn time
                else:
                    self.scheduleRejoinEvent(new_arrival,
                                             customer)  #schedule rejoin

                self.queues[queue].pop(0)  #remove customer from queue

                if (not self.queues[queue].isempty()) or (
                        new_arrival == queue
                ):  #if queue is not empty or customer joins same queue
                    self.scheduleDepartureEvent(
                        queue,
                        muB)  #keep serving queue, schedule next departure
                    self.processWaitingTime(customer)
                else:
                    self.scheduleSwitchEvent(
                        queue, muR)  #schedule switch if queue is empty
                    #self.serverStatus = (1, queue) #set server to active
                    #niet nodig

            elif currentEvent.typ == "SWITCH":  #if event type is switch

                #get params
                queue = currentEvent.queue  #server switches to this queue
                muB = self.muBs[queue]
                muR = self.muRs[queue]
                self.processCycleTime(
                    queue)  #save time for calculating cycle time
                self.serverStatus = (1, queue)  #add server to next queue

                if not self.queues[queue].isempty():  #if queue is not empty
                    self.scheduleDepartureEvent(
                        queue, muB)  #serve customer, schedule departure
                    customer = self.queues[queue].queue[0]
                    self.processWaitingTime(
                        customer)  #process customer waiting time
                    #self.serverStatus = (1, queue) #set server to active
                else:
                    self.scheduleSwitchEvent(
                        queue, muR)  #schedule another switch event
                    #self.serverStatus = (1, queue) #set server to active
                    #should add switch event here

            print(self.currentTime)
            for i in range(self.n):
                print(self.queues[i])
            print(self.fes)
            print('')

        plt.figure()

        for i in range(self.n):
            print("Average queue length queue " + str(i) + ": " +
                  str(self.cumQueueslen[i] / self.maxTime))
            print("Average waiting time queue " + str(i) + ": " +
                  str(sum(self.waitingTimes[i]) / len(self.waitingTimes[i])) +
                  ' ' + str(self.calculateCI(self.waitingTimes[i], 1.96)))
            print("Average sojourn time queue " + str(i) + ": " +
                  str(sum(self.sojournTimes[i]) / len(self.sojournTimes[i])) +
                  ' ' + str(self.calculateCI(self.sojournTimes[i], 1.96)))

            # cycles = len(self.cycleTimes[i]) - 1
            # cycletime = self.cycleTimes[i][cycles] - self.cycleTimes[i][0]
            # print(self.cycleTimes[i], cycles, cycletime)
            # print("Average cycle time queue " + str(i) + ": " + str(cycletime / cycles))

            cycles = self.calculateCycleTime(i)
            print("Average cycle time queue " + str(i) + ": " +
                  str(sum(cycles) / len(cycles)) + ' ' +
                  str(self.calculateCI(cycles, 1.96)))
            print('')

            plt.plot(self.waitingTimes[i])
            plt.show()

            plt.hist(self.waitingTimes[i],
                     bins=range(int(min(self.waitingTimes[i])),
                                int(max(self.waitingTimes[i])) + 1, 1))
            plt.show()

    def initializeEmptySystem(self):
        self.currentTime = 0

        self.queues = []
        self.cumQueueslen = []
        self.waitingTimes = []
        self.cycleTimes = []
        self.sojournTimes = []
        for i in range(self.n):
            self.queues.append(Queue())
            self.cumQueueslen.append(0)
            self.waitingTimes.append([])
            self.cycleTimes.append([])
            self.sojournTimes.append([])

        self.serverStatus = (0, 0)  #(idle, queue 1)
        self.cycleTimes[0].append(0)
        self.fes = FES()

    def scheduleArrivalEvent(self, queue, lam):
        # compute new arrival time
        if lam == 0:
            arrivalTime = 0
        else:
            arrivalTime = np.random.exponential(1 / lam)

        # schedule arrival at currentTime + arrivaltime
        event = Event("ARRIVAL", self.currentTime + arrivalTime, queue)
        self.fes.add(event)

    def processResults(self, t):
        for i in range(self.n):
            self.cumQueueslen[
                i] = self.cumQueueslen[i] + t * self.queues[i].size()

    def processWaitingTime(self, customer):
        queue = customer.queue
        queueJoinTime = customer.queueJoinTime
        waitingTime = self.currentTime - queueJoinTime
        self.waitingTimes[queue].append(waitingTime)

    def processSojournTime(self, customer):
        queue = customer.queue
        arrivalTime = customer.arrivalTime
        sojournTime = self.currentTime - arrivalTime
        self.sojournTimes[queue].append(sojournTime)

    def processCycleTime(self, queue):
        self.cycleTimes[queue].append(self.currentTime)

    def calculateCycleTime(self, queue):
        timestamps = self.cycleTimes[queue]
        lenOfCycles = np.zeros(len(timestamps) - 1)
        for i in range(len(timestamps) - 1):
            lenOfCycles[i] = timestamps[i + 1] - timestamps[i]
        return lenOfCycles

    def scheduleDepartureEvent(self, queue, mu):
        # compute new departure time
        serviceTime = np.random.exponential(mu)
        # schedule arrival at currentTime + arrivaltime
        event = Event("DEPARTURE", self.currentTime + serviceTime, queue)
        self.fes.add(event)

    def scheduleSwitchEvent(self, queue, mu):
        switchTime = mu
        nextloc = queue + 1
        if nextloc > (self.n - 1):
            nextloc = 0

        event = Event("SWITCH", self.currentTime + switchTime, nextloc)
        self.fes.add(event)

    def scheduleRejoinEvent(self, queue, customer):
        event = Event("REJOIN", self.currentTime, queue)
        self.rejoincustomer = Customer(customer.arrivalTime, self.currentTime,
                                       queue, customer.arrivalQueue)
        self.fes.add(event)

    def calculateCI(self, data, z):
        avg = sum(data) / len(data)
        stdev = np.std(data)
        halfWidth = z * stdev / np.sqrt(len(data))
        ci = (avg - halfWidth, avg + halfWidth)
        return ci

    pass
Exemplo n.º 8
0
class Network:
    def __init__(self, nr_machines, policy, list_thresholds, list_lambdas,
                 list_alphas, list_betas, list_preventative_times,
                 list_corrective_times, list_preventative_costs,
                 list_corrective_costs, list_downtime_costs, list_travel_times,
                 dependency, warm_up_time):

        self.nr_machines = nr_machines
        self.policy = policy
        self.thresholds = list_thresholds

        # Both base lambdas and lambda's with dependency are created
        # If there is no dependency lambda's with dependency is equal to base lambdas and don't change during the simulation
        self.lambdas = list_lambdas.copy()
        self.dependency_lambdas = list_lambdas.copy()

        self.alphas = list_alphas
        self.betas = list_betas
        self.preventative_times = list_preventative_times
        self.corrective_times = list_corrective_times
        self.preventative_costs = list_preventative_costs
        self.corrective_costs = list_corrective_costs
        self.downtime_costs = list_downtime_costs
        self.travel_times = list_travel_times
        self.dependency = dependency

        self.machines = []

        # Initializing arrays/lists that will be used for calculating output variables

        # Stores total non-operational time for each machine during the whole simulation
        self.non_operational_times = np.zeros(nr_machines)

        # Stores response times for each machine during the whole simulation
        self.response_times = [[] for i in range(nr_machines)]

        # Stores total maintenance(preventive and corrective) costs for each machine during the whole simulation
        self.maintenance_costs = np.zeros(nr_machines)

        # Stores total downtime costs for each machine during the whole simulation
        self.total_downtime_costs = np.zeros(nr_machines)

        # Initializing time-stamped output variables that are going to be used in plotting
        self.maintenance_costs_stamped = [[] for i in range(nr_machines)]
        self.non_operational_times_stamped = [[] for i in range(nr_machines)]

        # Array to record most recent non operational starting time
        # (Either because of a failure or because of a start of the preventative maintenance)
        self.last_non_operational_times = np.zeros(nr_machines)

        # Initializing additional stats

        # Initializing a list that stores interarrival times of degradation events for each machine
        self.interarrivals = [[] for i in range(nr_machines)]

        # Stats to keep track of wasted or not wasted FSE travels
        self.correct_tour = []
        self.detour = []

        # Statistic to keep track of remaining degradation levels to failure at each decision point
        self.remaining_times = []

        # Statistic to keep track of remaining degradation levels to failure at each decision point
        self.number_of_repairs = np.zeros(nr_machines)

        # Statistic to keep track of jump sizes for each machine
        self.jump_sizes = [[] for i in range(nr_machines)]

        # Statistic to keep track of the last start of idle,travel,repair time for FSE
        self.last_idle_time = 0
        self.last_travel_time = 0
        self.last_repair_time = 0

        # Statistic to keep track of the total idle,travel,repair time for FSE
        self.total_idle_time = 0
        self.total_travel_time = 0
        self.total_repair_time = 0

        # Statistic to keep track of the total number of failed machines at each decision point
        self.failed_count = []

        # Statistic to keep track of the total number of skipped degradation events because of start of a repair on that machine
        self.removed_event_count = 0

        # Time statistics
        self.current_time = 0
        self.warm_up_time = warm_up_time  # Until the warm-up time is reached the output variables are not updated

        # Initializing the field service engineer
        self.fse = FSE()

        # Initializing FES to store all events
        self.fes = FES()

        for machine in range(nr_machines):

            # Adding the machines with their respective attributes to the list
            self.machines.append(
                Machine(machine, list_thresholds[machine],
                        list_lambdas[machine], list_alphas[machine],
                        list_betas[machine], list_preventative_times[machine],
                        list_corrective_times[machine],
                        list_preventative_costs[machine],
                        list_corrective_costs[machine],
                        list_downtime_costs[machine]))

            # Scheduling the first degradation for each machine
            self.schedule_degradation(machine)

    def schedule_arrival(self, initial_machine, target_machine):
        '''
        Function to schedule the arrival of field service engineer event from initial machine to target machine

        '''

        # Retrieve the travel time between initial machine and destination machine
        travel_time = self.travel_times[initial_machine][target_machine]

        # Schedule arrival event at current_time + travel_time
        event = Event("ARRIVAL", self.current_time + travel_time,
                      target_machine)

        # Add scheduled event to the FES
        self.fes.add(event)

    def schedule_degradation(self, machine_nr):
        '''
        Function to schedule degradation event for given machine

        '''
        # Compute the time between degradation events for given machine
        # Interarrival times of degradation events are always calculated with lambda's with dependency
        interarrival_time = np.random.exponential(
            1 / self.dependency_lambdas[machine_nr])

        # Updating the interarrivals statistic
        self.interarrivals[machine_nr].append(interarrival_time)

        # Schedule degradation event at current_time + interarrival_time
        event = Event("DEGRADATION", self.current_time + interarrival_time,
                      machine_nr)

        # Add scheduled event to the FES
        self.fes.add(event)

    def schedule_end_maintenance(self, machine_nr, repair_type):
        '''
        Function to schedule end of maintenance event for the field service engineer

        '''
        if repair_type == "CORRECTIVE":

            # Schedule end of maintenance event at current_time + corresponding corrective maintenance time
            event = Event(
                "END_MAINTENANCE",
                self.current_time + self.corrective_times[machine_nr],
                machine_nr)

            # Add scheduled event to the FES
            self.fes.add(event)

        elif repair_type == "PREVENTIVE":

            # Schedule end of maintenance event at current_time + corresponding preventative maintenance time
            event = Event(
                "END_MAINTENANCE",
                self.current_time + self.preventative_times[machine_nr],
                machine_nr)

            # Add scheduled event to the FES
            self.fes.add(event)

    def find_max_downtime(self):
        '''
        Function that finds the machine with the maximum downtime cost among failed machines
        (If there are multiple failed machines with the same downtime cost ties are resolved randomly)

        Returns selected machine and total number of failed machines at that decision point
        '''

        machine_number_and_cost = [(machine.machine_nr, machine.down_cost)
                                   for machine in self.machines
                                   if machine.state == "FAILED"]

        # If there are no failed machines at that decision point return -1 and 0(no failed machine)
        if len(machine_number_and_cost) == 0:

            return -1, 0

        # Calculating the maximum downtime cost among all failed machines
        max_downtime_penalty = max(machine_number_and_cost,
                                   key=lambda x: x[1])[1]

        # Selecting among all machines with the maximum downtime cost randomly
        selected_machine = np.random.choice([
            t[0] for t in machine_number_and_cost
            if t[1] == max_downtime_penalty
        ])

        # Return the selected machine and the total number of failed machines at that decision point
        return selected_machine, len(machine_number_and_cost)

    def find_biggest_degradation(self):
        '''
        Function that finds the machine with the biggest degradation among non-healthy machines

        Ties are first resolved by travel times and then further ties are resolved randomly)

        Returns selected machine and if that machine is FAILED or not at that decision point
        '''

        current_location = self.fse.location
        machine_number_degradation_traveltime = [
            (machine.machine_nr, machine.degradation,
             self.travel_times[current_location][machine.machine_nr])
            for machine in self.machines if machine.degradation != 0
        ]

        # If all the machines are healthy at that decision point return -1 and True(Functional Machine)
        if len(machine_number_degradation_traveltime) == 0:

            return -1, True

        # Sorting the list of tuples based on two criteria
        # (Degradation element is descending, travel time element is ascending)
        sorted_list = sorted(machine_number_degradation_traveltime,
                             key=operator.itemgetter(2))
        sorted_list = sorted(sorted_list,
                             key=operator.itemgetter(1),
                             reverse=True)

        # Getting the max_degradation of the machine with max_degradation
        max_degradation = sorted_list[0][1]

        # Getting the min_travel_time of the machine with max_degradation
        min_travel_time = sorted_list[0][2]

        # Selecting among these machines randomly
        selected_machine = np.random.choice([
            t[0] for t in machine_number_degradation_traveltime
            if t[1] == max_degradation and t[2] == min_travel_time
        ])

        # Returns selected machine and if that machine is FAILED or not at that decision point
        return selected_machine, self.machines[
            selected_machine].state == "FUNCTIONAL"

    def handle_fse_action_greedy(self, current_event):
        '''
        Function that handles all the required FSE actions for greedy policy at a decision point

        Takes current event as input parameter
        '''

        # Selecting the machine with the biggest degradation among non-healthy machines
        # and returning the condition of that machine
        selected_machine, functional_or_not = self.find_biggest_degradation()

        # If all the machines are healthy (have 0 degradation) FSE remains idle
        if selected_machine == -1:

            self.fse.state = "IDLE"

            # Update the last idle time
            self.last_idle_time = self.current_time

        # If that selected machine is the FSE's current location start one of the maintenance events
        elif selected_machine == self.fse.location:

            # If FSE starts maintenance at the same machine FSE set out to increase correct_tour statistic
            if current_event.typ == "ARRIVAL" and self.current_time > self.warm_up_time:

                # Update the correct_tour statistic if the simulation time is above warm-up time
                self.correct_tour.append(current_event.machine)

            # If the current state of fse is IDLE update the total_idle_time
            if self.fse.state == "IDLE" and self.current_time > self.warm_up_time:

                self.total_idle_time += self.current_time - self.last_idle_time

            # Set the field service engineer's state to "REPAIR" and update last repair time statistic
            self.fse.state = "REPAIR"
            self.last_repair_time = self.current_time

            # If the selected machine is still functional
            if functional_or_not is True:

                # Update the last non-operational time of the machine
                self.last_non_operational_times[
                    current_event.machine] = self.current_time

                if self.current_time > self.warm_up_time:

                    # Increasing the total maintenance cost for the machine
                    self.maintenance_costs[
                        current_event.machine] += self.preventative_costs[
                            current_event.machine]

                # Setting the degradation level to failure threshold to indicate non-operational machine
                self.machines[selected_machine].degradation = self.machines[
                    selected_machine].failure_threshold
                self.machines[selected_machine].state = "FAILED"

                # If there is dependency update all the arrival intensities
                if self.dependency is True:

                    self.handle_dependency(self.lambdas)

                # Schedule the end of repair event for preventative maintenance
                self.schedule_end_maintenance(current_event.machine,
                                              "PREVENTIVE")

            elif functional_or_not is False:

                if self.current_time > self.warm_up_time:

                    # Calculate the response time for the machine and update the response_times statistic
                    response_time = self.current_time - self.last_non_operational_times[
                        current_event.machine]
                    self.response_times[current_event.machine].append(
                        response_time)

                    # Increasing the total maintenance cost for the machine
                    self.maintenance_costs[
                        current_event.machine] += self.corrective_costs[
                            current_event.machine]

                    # Update time stamped maintenance cost statistic
                    self.maintenance_costs_stamped[
                        current_event.machine].append(
                            (self.maintenance_costs[current_event.machine] +
                             self.total_downtime_costs[current_event.machine],
                             self.current_time))

                # Schedule the end of repair event for corrective maintenance
                self.schedule_end_maintenance(current_event.machine,
                                              "CORRECTIVE")

        # If that selected machine is other than the current machine
        else:

            # If the current event is arrival it means FSE have set out to the current machine to fix it and then decided to
            # travel to some other machine when he arrives there, in this case detour statistic is updated
            if current_event.typ == "ARRIVAL" and self.current_time > self.warm_up_time:

                self.detour.append((self.fse.location, selected_machine))

            # If the current state of fse is IDLE update the total_idle_time
            if self.fse.state == "IDLE" and self.current_time > self.warm_up_time:

                # Updating the total idle time
                self.total_idle_time += self.current_time - self.last_idle_time

            # If that selected machine isn't the current machine start travelling
            self.fse.state = "TRAVEL"

            # Update the last travel time statistic
            self.last_travel_time = self.current_time

            # Schedule the arrival event for the field service engineer
            self.schedule_arrival(self.fse.location, selected_machine)

            # Updating the remaining_times statistic
            self.remaining_times.append(
                [10 - machine.degradation for machine in self.machines])

    def handle_fse_action_reactive(self, current_event):
        '''
        Function that handles all the required FSE actions for reactive policy at a decision point

        Takes current event as input parameter
        '''

        # Selecting the machine with the maximum downtime cost among failed machines
        selected_machine, failed_machines_count = self.find_max_downtime()

        # Update the failed_count statistic if the simulation time is above warm-up time
        if self.current_time > self.warm_up_time:

            # Update the failed machine count statistic
            self.failed_count.append(failed_machines_count)

        # If no machine is failed at the moment FSE remains idle
        if selected_machine == -1:

            self.fse.state = "IDLE"

            # Update the last idle time statistic
            self.last_idle_time = self.current_time

        # If that selected machine is the current machine start the corrective maintenance
        elif selected_machine == self.fse.location:

            # If FSE starts corrective maintenance at the same machine FSE set out to increase correct_tour statistic
            if current_event.typ == "ARRIVAL" and self.current_time > self.warm_up_time:

                # Update the correct_tour statistic if the simulation time is above warm-up time
                self.correct_tour.append(current_event.machine)

            # If the current state of fse is IDLE update the total_idle_time
            if self.fse.state == "IDLE" and self.current_time > self.warm_up_time:

                # Updating the total idle time
                self.total_idle_time += self.current_time - self.last_idle_time

            # Set the field service engineer's state to "REPAIR"
            self.fse.state = "REPAIR"
            self.last_repair_time = self.current_time

            # Update the performance measures if the simulation time is above warm-up time
            if self.current_time > self.warm_up_time:

                # Calculate the response time for the machine and update the response_times statistic
                response_time = self.current_time - self.last_non_operational_times[
                    current_event.machine]
                self.response_times[current_event.machine].append(
                    response_time)

                # Increasing the total maintenance cost for the machine
                self.maintenance_costs[
                    current_event.machine] += self.corrective_costs[
                        current_event.machine]

                # Update time stamped maintenance cost statistic
                self.maintenance_costs_stamped[current_event.machine].append(
                    (self.maintenance_costs[current_event.machine] +
                     self.total_downtime_costs[current_event.machine],
                     self.current_time))

            # Schedule the end of repair event
            self.schedule_end_maintenance(current_event.machine, "CORRECTIVE")

        # If that selected machine is other than the current machine
        else:

            # If the current event is arrival it means FSE have set out to the current machine to fix it and then decided to
            # travel to some other machine when he arrives there, in this case detour statistic is updated
            if current_event.typ == "ARRIVAL" and self.current_time > self.warm_up_time:

                self.detour.append((self.fse.location, selected_machine))

            # If the current state of fse is IDLE update the total_idle_time
            if self.fse.state == "IDLE" and self.current_time > self.warm_up_time:

                # Updating the total idle time
                self.total_idle_time += self.current_time - self.last_idle_time

            # Set the state of field service engineer to "TRAVEL"
            self.fse.state = "TRAVEL"
            self.last_travel_time = self.current_time

            # Schedule the arrival event for the field service engineer
            self.schedule_arrival(self.fse.location, selected_machine)

            # Updating the remaining_times statistic
            self.remaining_times.append(
                [10 - machine.degradation for machine in self.machines])

    def handle_degradation(self, current_event):
        '''
        Function that increases current event's machine's degradation level

        Takes current event as input parameter
        '''

        # Retrieving the alpha and beta parameters for the current machine
        alpha = self.alphas[current_event.machine]
        beta = self.betas[current_event.machine]

        # Finding the jump size(sampling from beta distribution)
        jump_size = np.random.beta(alpha, beta)

        # Updating the jump_sizes statistic
        self.jump_sizes[current_event.machine].append(jump_size)

        # Updating the degradation level for the current machine
        self.machines[current_event.machine].degradation += jump_size

    def handle_dependency(self, base_lambdas):
        '''
        Function that updates all the dependency lambdas for the network
        (When a machine fails or a preventive maintenance is started)

        Takes base_lambdas as input parameter
        '''

        # Find operational and non-operational machines in the network
        non_operational_machines = [
            machine.machine_nr for machine in self.machines
            if machine.degradation == machine.failure_threshold
        ]
        operational_machines = [
            machine.machine_nr for machine in self.machines
            if machine.degradation < machine.failure_threshold
        ]

        # For non operational machines set lambda to base lambda
        for non_operational_machine in non_operational_machines:

            self.dependency_lambdas[non_operational_machine] = 0

        # If there is no operational machine do nothing
        if len(operational_machines) == 0:

            pass

        # If there are operational machines add non_operational machines' load to them
        elif len(operational_machines) != 0:

            for operational_machine in operational_machines:

                # Calculating additional arrival intensity for each machine that is going to come from non operational machines

                additional_arrival_intensity = (1 / len(operational_machines)) * \
                    sum([base_lambdas[non_operational_machine] for non_operational_machine in non_operational_machines])

                # Adding calculated additional arrival intensity to each machines base lambda
                self.dependency_lambdas[operational_machine] = base_lambdas[
                    operational_machine] + additional_arrival_intensity
Exemplo n.º 9
0
    def __init__(self, nr_machines, policy, list_thresholds, list_lambdas,
                 list_alphas, list_betas, list_preventative_times,
                 list_corrective_times, list_preventative_costs,
                 list_corrective_costs, list_downtime_costs, list_travel_times,
                 dependency, warm_up_time):

        self.nr_machines = nr_machines
        self.policy = policy
        self.thresholds = list_thresholds

        # Both base lambdas and lambda's with dependency are created
        # If there is no dependency lambda's with dependency is equal to base lambdas and don't change during the simulation
        self.lambdas = list_lambdas.copy()
        self.dependency_lambdas = list_lambdas.copy()

        self.alphas = list_alphas
        self.betas = list_betas
        self.preventative_times = list_preventative_times
        self.corrective_times = list_corrective_times
        self.preventative_costs = list_preventative_costs
        self.corrective_costs = list_corrective_costs
        self.downtime_costs = list_downtime_costs
        self.travel_times = list_travel_times
        self.dependency = dependency

        self.machines = []

        # Initializing arrays/lists that will be used for calculating output variables

        # Stores total non-operational time for each machine during the whole simulation
        self.non_operational_times = np.zeros(nr_machines)

        # Stores response times for each machine during the whole simulation
        self.response_times = [[] for i in range(nr_machines)]

        # Stores total maintenance(preventive and corrective) costs for each machine during the whole simulation
        self.maintenance_costs = np.zeros(nr_machines)

        # Stores total downtime costs for each machine during the whole simulation
        self.total_downtime_costs = np.zeros(nr_machines)

        # Initializing time-stamped output variables that are going to be used in plotting
        self.maintenance_costs_stamped = [[] for i in range(nr_machines)]
        self.non_operational_times_stamped = [[] for i in range(nr_machines)]

        # Array to record most recent non operational starting time
        # (Either because of a failure or because of a start of the preventative maintenance)
        self.last_non_operational_times = np.zeros(nr_machines)

        # Initializing additional stats

        # Initializing a list that stores interarrival times of degradation events for each machine
        self.interarrivals = [[] for i in range(nr_machines)]

        # Stats to keep track of wasted or not wasted FSE travels
        self.correct_tour = []
        self.detour = []

        # Statistic to keep track of remaining degradation levels to failure at each decision point
        self.remaining_times = []

        # Statistic to keep track of remaining degradation levels to failure at each decision point
        self.number_of_repairs = np.zeros(nr_machines)

        # Statistic to keep track of jump sizes for each machine
        self.jump_sizes = [[] for i in range(nr_machines)]

        # Statistic to keep track of the last start of idle,travel,repair time for FSE
        self.last_idle_time = 0
        self.last_travel_time = 0
        self.last_repair_time = 0

        # Statistic to keep track of the total idle,travel,repair time for FSE
        self.total_idle_time = 0
        self.total_travel_time = 0
        self.total_repair_time = 0

        # Statistic to keep track of the total number of failed machines at each decision point
        self.failed_count = []

        # Statistic to keep track of the total number of skipped degradation events because of start of a repair on that machine
        self.removed_event_count = 0

        # Time statistics
        self.current_time = 0
        self.warm_up_time = warm_up_time  # Until the warm-up time is reached the output variables are not updated

        # Initializing the field service engineer
        self.fse = FSE()

        # Initializing FES to store all events
        self.fes = FES()

        for machine in range(nr_machines):

            # Adding the machines with their respective attributes to the list
            self.machines.append(
                Machine(machine, list_thresholds[machine],
                        list_lambdas[machine], list_alphas[machine],
                        list_betas[machine], list_preventative_times[machine],
                        list_corrective_times[machine],
                        list_preventative_costs[machine],
                        list_corrective_costs[machine],
                        list_downtime_costs[machine]))

            # Scheduling the first degradation for each machine
            self.schedule_degradation(machine)
Exemplo n.º 10
0
#         test['ds'] = test.index

#         evaluation_statistics.append([f":{train_end} | {test_start} - {test_end}",*FES.all(model(train, test), test['y'])])
#     evaluation_statistics = pd.DataFrame(evaluation_statistics, columns= ['period','ME', 'MSE', 'RMSE', 'MAE', 'MPE', 'MAPE', 'U1', 'U2'])
#     return evaluation_statistics

# # st.write(cross_validation(df))
# CV_evaluation = {}
# CV_evaluation['Prophet without regressors'] = cross_validation(df)
# CV_evaluation['Prophet with regressors'] = cross_validation(df, model = prophet_with_regressors)

# ma_vs_pr = pd.DataFrame(CV_evaluation['Prophet without regressors'].mean()).transpose()
# ma_vs_pr = ma_vs_pr.append(pd.DataFrame(CV_evaluation['Prophet with regressors'].mean()).transpose())

# ma_vs_pr['model'] = ['Prophet without regressors','Prophet with regressors']
# ma_vs_pr.set_index('model', inplace=True)
# st.write(ma_vs_pr)
# ma_vs_pr.to_html('cv.html')
evaluation_statistics = []
evaluation_statistics.append([
    f"Prophet without regressors",
    *FES.all(prophet_without_regressors(train, test), test['y'])
])
evaluation_statistics.append([
    f"Prophet with regressors",
    *FES.all(prophet_with_regressors(train, test), test['y'])
])
evaluation_statistics = pd.DataFrame(
    evaluation_statistics,
    columns=['', 'ME', 'MSE', 'RMSE', 'MAE', 'MPE', 'MAPE', 'U1', 'U2'])
st.write(evaluation_statistics.set_index(''))