Created
October 4, 2025 14:18
-
-
Save Sinabon2004/1bdcec6e7dbcb2e1c86378a1ce3870a9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import math | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| # ========================== | |
| # СЧИТАЕМ МЕТРИКИ | |
| # ========================== | |
| def stationary_distribution(c, g, ro_1, ro_2): | |
| values = [] | |
| # n ≤ g | |
| sigma1 = sum(((ro_1 + ro_2) ** n) / math.factorial(n) for n in range(0, g+1)) | |
| # n > g | |
| sigma2 = ((ro_1 + ro_2) ** g) / math.factorial(g) * sum((ro_1 ** k) / math.factorial(k) for k in range(1, c-g+1)) | |
| p0 = 1 / (sigma1 + sigma2) | |
| for n in range(0, c+1): | |
| if n <= g: | |
| pn = ((ro_1 + ro_2) ** n) / math.factorial(n) * p0 | |
| else: | |
| pn = ((ro_1 + ro_2) ** g) / math.factorial(g) * (ro_1 ** (n-g)) / math.factorial(n-g) * p0 | |
| values.append(pn) | |
| return values | |
| def time_blocking(pn: list): | |
| """Вероятность блокировки по времени (последнее состояние).""" | |
| return pn[-1] | |
| def average_number(pn: list): | |
| """Среднее число обслуживаемых заявок.""" | |
| return sum(n * pn[n] for n in range(len(pn))) | |
| def metrics(c: int, lam_1: float, lam_2: float, mu: float, g: int): | |
| """Вычисление всех основных метрик.""" | |
| ro_1 = lam_1 / mu | |
| ro_2 = lam_2 / mu | |
| pn = stationary_distribution(c, g, ro_1, ro_2) | |
| E1 = pn[c] | |
| E2 = sum(pn[n] for n in range(g, c+1)) | |
| t_b = time_blocking(pn) | |
| av_num = average_number(pn) | |
| blocking_on_calls_1 = (lam_1 / (lam_1 + lam_2)) * t_b if lam_1 + lam_2 > 0 else 0 | |
| blocking_on_calls_2 = (lam_2 / (lam_1 + lam_2)) * t_b if lam_1 + lam_2 > 0 else 0 | |
| return { | |
| "pn": pn, | |
| "time_block": t_b, | |
| "average_number": av_num, | |
| "blocking_calls": (blocking_on_calls_1, blocking_on_calls_2), | |
| "blocking_load": (t_b, t_b), | |
| "E1": E1, | |
| "E2": E2, | |
| } | |
| # ========================== | |
| # СЧИТАЕМ РАЗМЕТКУ И РИСУЕМ ГРАФИКИ | |
| # ========================== | |
| def plot_blocking_two_types_vs_lambda(c, g, lam_2, mu, lam_range): | |
| B1_range = [] | |
| B2_range = [] | |
| for lam_1 in lam_range: | |
| pn = stationary_distribution(c, g, lam_1 / mu, lam_2 / mu) | |
| t_b = time_blocking(pn) | |
| total_lambda = lam_1 + lam_2 | |
| if total_lambda > 0: | |
| B1 = (lam_1 / total_lambda) * t_b | |
| B2 = (lam_2 / total_lambda) * t_b | |
| else: | |
| B1, B2 = 0, 0 | |
| B1_range.append(B1) | |
| B2_range.append(B2) | |
| plt.figure(figsize=(10,6)) | |
| plt.plot(lam_range, B1_range, label="Блокировка заявок 1-го типа", color="crimson", linewidth=2) | |
| plt.plot(lam_range, B2_range, label="Блокировка заявок 2-го типа", color="navy", linewidth=2) | |
| plt.title("Вероятность блокировки по типам заявок", fontsize=16) | |
| plt.xlabel("Интенсивность запросов λ1", fontsize=14) | |
| plt.ylabel("Вероятность блокировки", fontsize=14) | |
| plt.grid(True, linestyle="--", alpha=0.7) | |
| plt.legend(fontsize=12) | |
| plt.tight_layout() | |
| plt.show() | |
| def plot_average_number_vs_lambda(c, g, lam_2, mu, lam_range): | |
| av_num_range = [ | |
| average_number(stationary_distribution(c, g, lam / mu, lam_2 / mu)) for lam in lam_range | |
| ] | |
| plt.figure(figsize=(10, 6)) | |
| plt.plot(lam_range, av_num_range, label="Среднее число обслуживаемых заявок", linewidth=2, color="navy") | |
| plt.title("Среднее число обслуживаемых заявок от интенсивности запросов", fontsize=16) | |
| plt.xlabel("Интенсивность запросов (λ1)", fontsize=14) | |
| plt.ylabel("Среднее число заявок", fontsize=14) | |
| plt.grid(True, linestyle="--", alpha=0.7) | |
| plt.legend(fontsize=12) | |
| plt.tight_layout() | |
| plt.show() | |
| # ========================== | |
| # ЗАПУСКАЕМ!!! | |
| # ========================== | |
| if __name__ == "__main__": | |
| # АРГУМЕНТЫ ИЗ ПРИМЕРА ВЫПОЛНЕНИЯ | |
| g = 56 | |
| C = 121 | |
| MU = 0.5 | |
| LAMBDA_1 = 50 | |
| LAMBDA_2 = 40 | |
| result = metrics(C, LAMBDA_1, LAMBDA_2, MU, g) | |
| print("\n--- Результаты --- 📊✨") | |
| for n, p in enumerate(result["pn"]): | |
| print(f"P(n={n}) = {p:.5f} 🎲") | |
| print(f"Сумма вероятностей = {sum(result['pn']):.5f} ➕") | |
| print(f"Вероятность блокировки (по времени) = {result['time_block']:.5f} ⏳🚫") | |
| print(f"Среднее число заявок = {result['average_number']:.5f} 👥") | |
| print(f"Вероятность блокировки по вызовам: B1 = {result['blocking_calls'][0]:.5f} 📞🚫, B2 = {result['blocking_calls'][1]:.5f} 📞🚫") | |
| print(f"Вероятность блокировки по нагрузке: C1 = {result['blocking_load'][0]:.5f} 📦🚫, C2 = {result['blocking_load'][1]:.5f} 📦🚫") | |
| print(f"Вероятность блокировки для заявок 1-го типа (E1) = {result['E1']:.5f}") | |
| print(f"Вероятность блокировки для заявок 2-го типа (E2) = {result['E2']:.5f}") | |
| # Диапазон для графиков | |
| lam_1_range = np.arange(0.1, C, 0.5) | |
| # Построение графиков | |
| plot_blocking_two_types_vs_lambda(C, g, LAMBDA_2, MU, lam_1_range) | |
| plot_average_number_vs_lambda(C, g, LAMBDA_2, MU, lam_1_range) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment