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 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 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
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
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
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
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
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
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)
# 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(''))