Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy as np
- import matplotlib.pyplot as plt
- Q_LIMIT = int(input("Введите ограничение длины очереди: ")) # Ограничение длины очереди
- BUSY = 1 # Устройство занято
- IDLE = 0 # Устройство свободно
- class QueueSystem:
- def __init__(self, mean_interarrival, mean_service, time_end):
- self.mean_interarrival = mean_interarrival #среднее время между прибытиями требований
- self.mean_service = mean_service #среднее время обслуживания требования
- self.time_end = time_end #время завершения моделирования
- # переменные состояния
- self.sim_time = 0.0 #текущее время в симуляции.
- self.server_status = IDLE #статус устройства (занято или свободно).
- self.num_in_q = 0 #количество запросов в очереди.
- self.time_last_event = 0.0 #время последнего события.
- self.num_custs_delayed = 0 #количество обслуженных запросов.
- self.total_of_delays = 0.0 #общее время задержки запросов.
- self.area_num_in_q = 0.0 #для расчета средней длины очереди
- self.area_server_status = 0.0 # и коэффициента занятости устройства.
- self.time_arrival = [0.0] * (Q_LIMIT + 1) #массив. хранит времена поступления запросов.
- # инициализация списка времени для событий
- self.time_next_event = [1.0e+30, self.expon(self.mean_interarrival), 1.0e+30, self.time_end]
- # Для графика
- self.time_values = [] # массив времени моделирования
- self.queue_values = [] # массив количества требований в системе
- def expon(self, mean): #генерируем случайное время по экспоненциальному распределению
- return -mean * np.log(np.random.rand())
- def timing(self): #функция выбирает ближайшее событие, изменяет текущее время симуляции на время этого события и возвращает тип события (например, прибытие или уход).
- min_time_next_event = min(self.time_next_event)
- self.sim_time = min_time_next_event
- next_event_type = self.time_next_event.index(min_time_next_event)
- if next_event_type == 0:
- print(f"Список событий пуст в момент времени {self.sim_time}")
- exit(1)
- return next_event_type
- def update_time_avg_status(self):
- time_since_last_event = self.sim_time - self.time_last_event
- self.time_last_event = self.sim_time
- self.area_num_in_q += self.num_in_q * time_since_last_event #обновляем площадь под графиком количества запросов в очереди (это необходимо для расчета средней длины очереди)
- self.area_server_status += self.server_status * time_since_last_event #обновляем площадь занятости устройства (для расчета коэффициента занятости)
- # обновление значений для графика
- self.time_values.append(self.sim_time)
- self.queue_values.append(self.num_in_q)
- def arrive(self): #прибытие запроса
- self.time_next_event[1] = self.sim_time + self.expon(self.mean_interarrival) #рассчитывается следующее время прибытия запроса
- if self.server_status == BUSY: #помещается в очередь + проверка лимита
- self.num_in_q += 1
- if self.num_in_q > Q_LIMIT:
- print(f"Переполнение массива time_arrival в момент времени {self.sim_time}")
- exit(2)
- self.time_arrival[self.num_in_q] = self.sim_time
- else:
- delay = 0.0 #свободно. обслуживается немедленно
- self.total_of_delays += delay
- self.num_custs_delayed += 1
- self.server_status = BUSY
- self.time_next_event[2] = self.sim_time + self.expon(self.mean_service)
- def depart(self): #уход запроса
- if self.num_in_q == 0: #если нет запросов, свободное состояние
- self.server_status = IDLE
- self.time_next_event[2] = 1.0e+30
- else:
- self.num_in_q -= 1 #если не пуста обслуживаем первый запрос
- delay = self.sim_time - self.time_arrival[1]
- self.total_of_delays += delay
- self.num_custs_delayed += 1
- self.time_next_event[2] = self.sim_time + self.expon(self.mean_service)
- # сдвигаем массив прибытия требований
- for i in range(1, self.num_in_q + 1):
- self.time_arrival[i] = self.time_arrival[i + 1]
- def report(self):
- print(f"\nСредняя задержка в очереди: {self.total_of_delays / self.num_custs_delayed:.3f} мин")
- print(f"Среднее число требований в очереди: {self.area_num_in_q / self.sim_time:.3f}")
- print(f"Коэффициент занятости устройства: {self.area_server_status / self.sim_time:.3f}")
- print(f"Число завершенных задержек в очереди: {self.num_custs_delayed}\n")
- def plot(self):
- #построение графика Q(t)
- plt.figure(figsize=(10, 6))
- plt.step(self.time_values, self.queue_values, where='post', label="Q(t) — число требований в системе")
- plt.xlabel("Время, t")
- plt.ylabel("Число требований, Q(t)")
- plt.title("График количества требований в системе Q(t) от времени t")
- plt.grid(True)
- # на оси Y только целые числа
- max_queue = max(self.queue_values)
- plt.yticks(np.arange(1, max_queue + 1, step=1)) # Показываем только целые числа
- plt.legend()
- plt.show()
- def main():
- mean_interarrival = float(input("Введите среднее время между прибытиями требований, мин: "))
- mean_service = float(input("Введите среднее время обслуживания требования, мин: "))
- time_end = float(input("Введите время завершения моделирования, мин: "))
- queue_system = QueueSystem(mean_interarrival, mean_service, time_end)
- while queue_system.sim_time < time_end:
- next_event_type = queue_system.timing()
- queue_system.update_time_avg_status()
- if next_event_type == 1:
- queue_system.arrive()
- elif next_event_type == 2:
- queue_system.depart()
- queue_system.report() # отчет по результатам моделирования
- queue_system.plot() # построение графика по завершении моделирования
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement