-
-
Save Sinabon2004/aa53389863b9e4038017b8ba3ee540dc 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 state_space(c: int, g: int): | |
| """Множество состояний X: {(n1, n2): 0 <= n1 <= g, 0 <= n2, n1 + n2 <= C}.""" | |
| states = [] | |
| for n1 in range(0, g + 1): | |
| for n2 in range(0, c + 1): | |
| if n1 + n2 <= c: | |
| states.append((n1, n2)) | |
| return states | |
| def stationary_distribution(c: int, g: int, lam_1: float, lam_2: float, mu_1: float, mu_2: float): | |
| """Стационарное распределение вероятностей p(n1, n2).""" | |
| ro_1 = lam_1 / mu_1 if mu_1 != 0 else 0.0 | |
| ro_2 = lam_2 / mu_2 if mu_2 != 0 else 0.0 | |
| X = state_space(c, g) | |
| # Нормирующий знаменатель | |
| Z = 0.0 | |
| for n1, n2 in X: | |
| Z += (ro_1 ** n1) / math.factorial(n1) * (ro_2 ** n2) / math.factorial(n2) | |
| if Z == 0: | |
| return {(0, 0): 1.0} | |
| p00 = 1.0 / Z | |
| p = {} | |
| for n1, n2 in X: | |
| p[(n1, n2)] = p00 * (ro_1 ** n1) / math.factorial(n1) * (ro_2 ** n2) / math.factorial(n2) | |
| return p | |
| def blocking_probabilities(p: dict, c: int, g: int): | |
| """Вероятности блокировки по времени для заявок 1-го и 2-го типа.""" | |
| B1 = 0.0 | |
| B2 = 0.0 | |
| for (n1, n2), prob in p.items(): | |
| # Блокировка 1-го типа: n1 = g или n1 + n2 = C | |
| if (n1 == g) or (n1 + n2 == c): | |
| B1 += prob | |
| # Блокировка 2-го типа: n1 + n2 = C | |
| if (n1 + n2 == c): | |
| B2 += prob | |
| return B1, B2 | |
| def average_number(p: dict): | |
| """Среднее число заявок в системе: N = sum (n1 + n2) * p(n1, n2).""" | |
| N = 0.0 | |
| for (n1, n2), prob in p.items(): | |
| N += (n1 + n2) * prob | |
| return N | |
| def metrics(c: int, lam_1: float, lam_2: float, mu_1: float, mu_2: float, g: int): | |
| """Вычисление всех основных метрик.""" | |
| p = stationary_distribution(c, g, lam_1, lam_2, mu_1, mu_2) | |
| B1, B2 = blocking_probabilities(p, c, g) | |
| av_num = average_number(p) | |
| return { | |
| "pn": p, | |
| "B1": B1, | |
| "B2": B2, | |
| "average_number": av_num, | |
| "blocking_calls": (B1, B2), | |
| "blocking_load": (B1, B2), | |
| } | |
| # ========================== | |
| # РИСУЕМ ГРАФИКИ | |
| # ========================== | |
| def plot_blocking_two_types_vs_lambda(c, g, lam_2, mu_1, mu_2, lam_1_range): | |
| """График зависимости вероятностей блокировки от λ1.""" | |
| B1_range = [] | |
| B2_range = [] | |
| for lam_1 in lam_1_range: | |
| p = stationary_distribution(c, g, lam_1, lam_2, mu_1, mu_2) | |
| B1, B2 = blocking_probabilities(p, c, g) | |
| B1_range.append(B1) | |
| B2_range.append(B2) | |
| plt.figure(figsize=(10, 6)) | |
| plt.plot(lam_1_range, B1_range, label="B1(λ1) — блокировка 1-го типа", | |
| color="crimson", linewidth=2) | |
| plt.plot(lam_1_range, B2_range, label="B2(λ1) — блокировка 2-го типа", | |
| color="navy", linewidth=2) | |
| plt.title("Вероятность блокировки по времени в зависимости от λ1", fontsize=14) | |
| plt.xlabel("Интенсивность λ1", fontsize=12) | |
| plt.ylabel("Вероятность блокировки", fontsize=12) | |
| plt.grid(True, linestyle="--", alpha=0.7) | |
| plt.legend(fontsize=10) | |
| plt.tight_layout() | |
| plt.show() | |
| def plot_average_number_vs_lambda(c, g, lam_2, mu_1, mu_2, lam_1_range): | |
| """График зависимости среднего числа заявок от λ1.""" | |
| N_range = [] | |
| for lam_1 in lam_1_range: | |
| p = stationary_distribution(c, g, lam_1, lam_2, mu_1, mu_2) | |
| N = average_number(p) | |
| N_range.append(N) | |
| plt.figure(figsize=(10, 6)) | |
| plt.plot(lam_1_range, N_range, label="N(λ1)", color="darkgreen", linewidth=2) | |
| plt.title("Среднее число заявок в системе в зависимости от λ1", fontsize=14) | |
| plt.xlabel("Интенсивность λ1", fontsize=12) | |
| plt.ylabel("Среднее число заявок N", fontsize=12) | |
| plt.grid(True, linestyle="--", alpha=0.7) | |
| plt.legend(fontsize=10) | |
| plt.tight_layout() | |
| plt.show() | |
| # ========================== | |
| # ЗАПУСКАЕМ!!! | |
| # ========================== | |
| if __name__ == "__main__": | |
| # Параметры модели | |
| C = 4 | |
| G = 3 | |
| MU_1 = 2.0 | |
| MU_2 = 1.0 | |
| LAMBDA_1 = 1.0 | |
| LAMBDA_2 = 1.0 | |
| result = metrics(C, LAMBDA_1, LAMBDA_2, MU_1, MU_2, G) | |
| print("\n--- Результаты ---") | |
| for (n1, n2) in sorted(result["pn"].keys()): | |
| print(f"P(n1={n1}, n2={n2}) = {result['pn'][(n1, n2)]:.5f}") | |
| print(f"Сумма вероятностей = {sum(result['pn'].values()):.5f}") | |
| print(f"Вероятность блокировки по времени для 1-го типа (B1) = {result['B1']:.5f}") | |
| print(f"Вероятность блокировки по времени для 2-го типа (B2) = {result['B2']:.5f}") | |
| print(f"Среднее число заявок = {result['average_number']:.5f}") | |
| print( | |
| f"Вероятность блокировки по вызовам: " | |
| f"B1 = {result['blocking_calls'][0]:.5f}, " | |
| f"B2 = {result['blocking_calls'][1]:.5f}" | |
| ) | |
| print( | |
| f"Вероятность блокировки по нагрузке: " | |
| f"C1 = {result['blocking_load'][0]:.5f}, " | |
| f"C2 = {result['blocking_load'][1]:.5f}" | |
| ) | |
| # Диапазон λ1 для графиков | |
| lam_1_range = np.arange(0.1, 50, 0.5) | |
| # Построение графиков | |
| plot_blocking_two_types_vs_lambda(C, G, LAMBDA_2, MU_1, MU_2, lam_1_range) | |
| plot_average_number_vs_lambda(C, G, LAMBDA_2, MU_1, MU_2, lam_1_range) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment