import numpy as np
import random
import matplotlib.pyplot as plt

def simulate_tdma(M, lambd, p, total_slots=20_000, warm_up=2_000):
    queues = [[] for _ in range(M)]
    lambda_i = lambd / M

    for t in range(warm_up):
        for i in range(M):
            if random.random() < lambda_i:
                queues[i].append(t)
        current_subscriber = t % M
        if queues[current_subscriber]:
            if random.random() > p:
                queues[current_subscriber].pop(0)

    total_delay = 0.0
    transmitted_count = 0
    sum_queue_sizes = 0.0

    for t in range(warm_up, warm_up + total_slots):
        for i in range(M):
            if random.random() < lambda_i:
                queues[i].append(t)
        current_subscriber = t % M
        if queues[current_subscriber]:
            if random.random() > p:
                arrival_time = queues[current_subscriber].pop(0)
                total_delay += (t - arrival_time)
                transmitted_count += 1
        sum_queue_sizes += sum(len(q) for q in queues)

    avg_delay = float('inf') if transmitted_count == 0 else total_delay / transmitted_count
    throughput = transmitted_count / total_slots
    avg_queue_size = sum_queue_sizes / total_slots

    return throughput, avg_delay, avg_queue_size


def simulate_polling(M, lambd, p, tau=1.0, cycles=3_000, warm_up=1_000):
    queues = [[] for _ in range(M)]
    lambda_i = lambd / M
    current_time = 0.0

    for _ in range(warm_up):
        for i in range(M):
            for ab in range(M):
                if random.random() < (lambda_i * tau):
                    queues[ab].append(current_time)
            current_time += tau
            if queues[i]:
                if random.random() > p:
                    queues[i].pop(0)
                current_time += 1

    total_delay = 0.0
    transmitted_count = 0
    sum_queue_sizes = 0.0
    sum_time_intervals = 0.0

    start_time = current_time

    for _ in range(cycles):
        for i in range(M):
            for ab in range(M):
                if random.random() < (lambda_i * tau):
                    queues[ab].append(current_time)
            total_messages = sum(len(q) for q in queues)
            sum_queue_sizes += total_messages * tau
            sum_time_intervals += tau
            current_time += tau
            if queues[i]:
                if random.random() > p:
                    arrival_time = queues[i].pop(0)
                    total_delay += (current_time - arrival_time)
                    transmitted_count += 1
                total_messages = sum(len(q) for q in queues)
                sum_queue_sizes += total_messages * 1
                sum_time_intervals += 1
                current_time += 1

    end_time = current_time
    total_time = max(end_time - start_time, 1e-9)

    avg_delay = float('inf') if transmitted_count == 0 else total_delay / transmitted_count
    throughput = transmitted_count / total_time
    avg_queue_size = sum_queue_sizes / sum_time_intervals if sum_time_intervals > 0 else 0

    return throughput, avg_delay, avg_queue_size


def main():
    M = 5
    tau = 1
    fixed_lambda_for_p = 0.5
    p_values = np.linspace(0, 1, 6)
    tdma_delays_p = []
    polling_delays_p = []
    theoretical_tdma = (M + 2) / 2
    theoretical_polling = (tau * (M + 2) + 2) / 2
    for p_ in p_values:
        _, d_tdma, _ = simulate_tdma(M, lambd=fixed_lambda_for_p, p=p_, total_slots=20_000, warm_up=2_000)
        tdma_delays_p.append(d_tdma)
        _, d_poll, _ = simulate_polling(M, lambd=fixed_lambda_for_p, p=p_, tau=tau, cycles=3_000, warm_up=1_000)
        polling_delays_p.append(d_poll)
    print("\n--- Средняя задержка от вероятности ошибки ---")
    print("Разделение времени (p=0) теоретическое =", theoretical_tdma, "; практическое =", tdma_delays_p[0])
    print("Достпу по запросу (p=0) теоретическое=", theoretical_polling, "; практическое =", polling_delays_p[0])
    for i, p_ in enumerate(p_values):
        print(f"p = {p_:.1f} => Задержка РВ = {tdma_delays_p[i]:.3f}, Задержка ДЗ = {polling_delays_p[i]:.3f}")

    plt.figure(figsize=(6,4))
    plt.plot(p_values, tdma_delays_p, label='Доступ с разделением времени')
    plt.plot(p_values, polling_delays_p, label='Доступ по запросу')
    plt.axhline(y=theoretical_tdma, color='blue', linestyle='--', label='РВ теоретическое)')
    plt.axhline(y=theoretical_polling, color='orange', linestyle='--', label='ДЗ теоретическое')
    plt.xlabel('Вероятность ошибки, p')
    plt.ylabel('Средняя задержка, d0')
    plt.title(f'Средняя задержка в зависимости от вероятности ошибки при (λ={fixed_lambda_for_p})')
    plt.legend()
    plt.grid(True)
    plt.tight_layout()
    plt.show()

    p_list = [0.0, 0.2, 0.5, 0.8]
    lambda_values = np.linspace(0.1, 0.9, 9)
    fig, axs = plt.subplots(4, 3, figsize=(12, 10))
    fig.suptitle("Графики для Разделения по времени и доступа по запросу для разных значений p", fontsize=14)
    for row_idx, p_ in enumerate(p_list):
        tdma_delay_list = []
        tdma_thpt_list = []
        tdma_queue_list = []
        poll_delay_list = []
        poll_thpt_list = []
        poll_queue_list = []
        for lambd in lambda_values:
            thpt_tdma, delay_tdma, qsize_tdma = simulate_tdma(M, lambd=lambd, p=p_, total_slots=20_000, warm_up=2_000)
            tdma_delay_list.append(delay_tdma)
            tdma_thpt_list.append(thpt_tdma)
            tdma_queue_list.append(qsize_tdma)
            thpt_poll, delay_poll, qsize_poll = simulate_polling(M, lambd=lambd, p=p_, tau=tau, cycles=3_000, warm_up=1_000)
            poll_delay_list.append(delay_poll)
            poll_thpt_list.append(thpt_poll)
            poll_queue_list.append(qsize_poll)
        ax_delay = axs[row_idx, 0]
        ax_delay.plot(lambda_values, tdma_delay_list, label='РВ')
        ax_delay.plot(lambda_values, poll_delay_list, label='ДЗ')
        ax_delay.set_title(f"p={p_}, Средняя задержка")
        ax_delay.set_xlabel("λ")
        ax_delay.set_ylabel("Средняя задержка")
        ax_delay.grid(True)
        ax_thr = axs[row_idx, 1]
        ax_thr.plot(lambda_values, tdma_thpt_list, label='РВ')
        ax_thr.plot(lambda_values, poll_thpt_list, label='ДЗ')
        ax_thr.set_title(f"p={p_}, Выходная интенсивность")
        ax_thr.set_xlabel("λ")
        ax_thr.set_ylabel("Выходная интенсивность")
        ax_thr.grid(True)
        ax_queue = axs[row_idx, 2]
        ax_queue.plot(lambda_values, tdma_queue_list, label='РВ')
        ax_queue.plot(lambda_values, poll_queue_list, label='ДЗ')
        ax_queue.set_title(f"p={p_}, Среднее число заявок")
        ax_queue.set_xlabel("λ")
        ax_queue.set_ylabel("Среднее число заявок")
        ax_queue.grid(True)
        if row_idx == 0:
            ax_delay.legend()
            ax_thr.legend()
            ax_queue.legend()
    plt.tight_layout(rect=[0, 0, 1, 0.96])
    plt.show()

if __name__ == "__main__":
    main()



напиши коментарии подрробные в коде