Скачиваний:
0
Добавлен:
29.04.2025
Размер:
8.28 Кб
Скачать
import numpy as np
from matplotlib import pyplot as plt

# константы
R = 300 # радиус действия БС
Ptx = 0.1  #
f0 = 4000  # частота
df = 180 * 10**3  # частота пропускания канала
kn = 3  # коэффициент теплового шума
T = 300  # температура (К)
K = 1.380649 * 10 ** -23  # постоянная Больцмана
Pn = df * T * K * kn # мощность теплового шума
SLOTS = 10**3 # количество слотов
K_ITU = 29  # коэффициент типа помещения ?

subs_list = [2,4,8,16] # [8, 16, 64], # Список кол-ва АБ
algoritm_list =  ['Maximum Throughput', 'Equal Blind', 'Proportional fair'] # названия алгоритмов рр

T_rb = 0.5 * (10 ** -3) # длительность слота
y = 1 # последняя секунда
y_slot = round(y / T_rb) # кол-во слотов, на которых рассчитывается ср скорость

Nrb = 100 # кол-во ресурсных блоков
V = 2**13 # объем данных в пакете (1Кб)

lambd_list = np.arange(1, 10, 1)  # значения интенсивности входного потока

buffer_scores_by_alg = {}

def generate_ab(n, lam):
    # Генерация случайных расстояний пользователей до базовой станции
    dist = np.sqrt(np.random.uniform(0, R**2, n))
    L_list = 10 ** ((20 * np.log10(f0) + K_ITU * np.log10(dist) - 28) / 10)

    subs = []
    packs = []

    for L in L_list:
        # помеха
        fading_dB = np.random.normal(loc=0, scale=1, size=SLOTS)

        # Суммарное затухание в дБ
        total_loss_dB = 10 * np.log10(L) + fading_dB  # L уже в линейной шкале

        # Перевод в линейную шкалу: L_total = 10^(total_dB / 10)
        L_total = 10 ** (total_loss_dB / 10)

        # Мощность на приёме (в линейной шкале)
        Prx = Ptx / L_total
        SNR = Prx / Pn
        CC = df * np.log2(1 + SNR)
        subs.append(list(CC * T_rb))

        # Генерация количества пакетов
        user_packs = [(np.random.poisson(lam=lam)) * V for _ in range(SLOTS)]
        packs.append(user_packs)

    return subs, packs


def get_avg_R(slot_resource_blocks, subs, sub_idx, slot_idx):
    packs_sum = 0

    for i in range(max(0, slot_idx - 1 - y_slot), slot_idx):
        sub_slot_res_block_cnt = slot_resource_blocks[i].count(sub_idx)
        packs_sum += subs[sub_idx][i] * sub_slot_res_block_cnt

    return packs_sum / y_slot

def get_avg_R_smooth(slot_resource_blocks, subs, sub_idx, slot_idx, sub_R_mean_list):
    betta = 1 / y_slot

    return (1 - betta) * sub_R_mean_list[sub_idx] + betta * sum(
        [subs[sub_idx][slot_idx] for res_sub_idx in slot_resource_blocks[-1] if res_sub_idx == sub_idx]) / T_rb

# сортировка аб по приоритетам
def filter_and_sort(priorities, sub_with_full_buffer):
    sorted_indices = np.argsort(priorities)
    return [idx for idx in sorted_indices if idx in sub_with_full_buffer]

# Equal blind
def equal_blind(sub_R_mean_list, sub_with_full_buffer):
    priorities = [1 / r if r > 0 else 1 for r in sub_R_mean_list]
    return filter_and_sort(priorities, sub_with_full_buffer)

# Maximum throughput
def maximum_throughput(subs_slot_CC, sub_with_full_buffer):
    return filter_and_sort(subs_slot_CC, sub_with_full_buffer)

# Proportional fair
def proportional_fair(subs_slot_CC, sub_R_mean_list, sub_with_full_buffer):
    priorities = [cc / (rm if rm > 0 else 1) for cc, rm in zip(subs_slot_CC, sub_R_mean_list)]
    return filter_and_sort(priorities, sub_with_full_buffer)

# получаем индекс абонента, котором передаем данные в зависимости от алгоритма распределения
def get_sub_index(subs_slot_CC, algorithm, sub_with_full_buffer, sub_R_mean_list):
    match algorithm:
        case 'Equal Blind':
            return equal_blind(sub_R_mean_list, sub_with_full_buffer)
        case 'Maximum Throughput':
            return maximum_throughput(subs_slot_CC, sub_with_full_buffer)
        case 'Proportional fair':
            return proportional_fair(subs_slot_CC, sub_R_mean_list, sub_with_full_buffer)
    return 0


def get_avg_score(subs, packs, algorithm):
    subs_cnt = len(subs)

    buffer = [[packs[i][0] for i in range(subs_cnt)]] # начальное число пакетов в буфере
    slot_resource_blocks = [[]] # ресурсные блоки

    sub_R_mean_list = [[get_avg_R(slot_resource_blocks, subs, i, 0) for i in range(subs_cnt)]] # ср зн скорости передачи для первого слота
    cur_sub_idx = 0

    # перебор слотов
    for slot_idx in range(SLOTS):
        # распределение нагрузки
        if algorithm in ['Equal Blind', 'Proportional fair']:
            sub_R_mean_list.append([
                get_avg_R_smooth(slot_resource_blocks, subs, i, slot_idx, sub_R_mean_list[-1])
                for i in range(subs_cnt)])

        # Список абонентов, у которых буфер в текущем слоте не пустой
        sub_with_full_buffer = [i % subs_cnt for i in range(cur_sub_idx, cur_sub_idx + subs_cnt)
                                if buffer[-1][i % subs_cnt] != 0]
        # установление приоритета
        cur_sub_idx = (cur_sub_idx + 1) % subs_cnt
        # оставшиеся данные копируем в следующий слот
        buffer.append(buffer[-1].copy())

        # получение очереди аб, по приоритету
        if sub_with_full_buffer:
            subs_priority_idx = get_sub_index([subs[i][slot_idx] for i in range(subs_cnt)], algorithm,sub_with_full_buffer, sub_R_mean_list[-1])
            new_slot_res_block = []
            # print(f'Алг = {algorithm} Приоритет = {subs_priority_idx}')
            # перебор аб
            for sub_idx in subs_priority_idx:
                # выделение ресурсных блоков
                sub_res_block_cnt = int(np.ceil(buffer[-1][sub_idx] / subs[sub_idx][slot_idx]))
                new_slot_res_block.extend([sub_idx] * sub_res_block_cnt)
                if len(new_slot_res_block) >= Nrb: # ресурсные блоки кончились (всего 100)
                    break

            slot_resource_blocks.append(new_slot_res_block[:Nrb])

            # передача данных приоритетам
            for sub_idx in [i for i in slot_resource_blocks[-1] if i != -1]:
                buffer[-1][sub_idx] = max(0, buffer[-1][sub_idx] - subs[sub_idx][slot_idx])
        else:
            slot_resource_blocks.append([]) # нечего передавать

        buffer[-1] = [buf + packs[i][slot_idx] for i, buf in enumerate(buffer[-1])]

    return np.mean([sum(slot) for slot in buffer]) # средний суммарный объем

def modeling():
    plt.figure(figsize=(12, 6))

    for subs_cnt in subs_list:
        for lambd in lambd_list:
            subs, packs = generate_ab(subs_cnt, lambd)
            for alg in algoritm_list:
                score = get_avg_score(subs, packs, alg)
                key = f'{subs_cnt} {alg}'
                if lambd == lambd_list[0]:
                    buffer_scores_by_alg[key] = []
                buffer_scores_by_alg[key].append(score)
                print(f'lam : {lambd}, метод :{alg}, абонентов : {subs_cnt}, V : {score}')

    # Отрисовка графиков
    for key, buffer_scores in buffer_scores_by_alg.items():
        plt.plot(lambd_list, buffer_scores, marker='o', label=key)

    plt.title(f"Зависимость среднего объёма данных в буферах от интенсивности потока (SLOTS={SLOTS})")
    plt.xlabel("Интенсивность входного потока (λ)")
    plt.ylabel("Средний суммарный объём в буферах")
    plt.legend()
    plt.grid()
    plt.show()

modeling()
Соседние файлы в предмете Моделирование систем распределения ресурсов