Добавил:
egrpleh
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:ЛР3 / MSRR_LR3
.pyimport numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from config import const_var
def get_corrected_distance(distance, base_station_height, sub_station_height):
'''Возвращает дистанцию от БС до АБ с учетом высот и расстояния между ними'''
return (distance**2 + abs(base_station_height - sub_station_height)**2)**.5
def subs_generator(subs_cnt):
'''Генерация пропускных способностей для всех абанентов в каждом моделируемом слоте'''
slot_cnt = const_var.get("slot_cnt") # Кол-во моделируемых слотов
R = const_var.get("R") # Радиус действия базовой станции
f0 = const_var.get("f0") # Частота БС
Ptx = const_var.get("Ptx") # Мощность излучения БС
DF = const_var.get("DF") # Полоса пропускания канала связи
Pn = const_var.get("Pn") # Мощность теплового шума
T_rb = const_var.get("T_rb") # Длительность слота
h_bs = const_var.get("h_bs") # Высота базовой станции
h_rx = const_var.get("h_rx") # Высота точки приема
S = const_var.get("S") # small city (S = 0) / large city (S = 3)
# Таблицы с пропускными способностями абонентов для каждого слота
subs = pd.DataFrame(columns=range(slot_cnt))
# Список растояний до АБ в км
sub_distans = [get_corrected_distance(dist, h_bs, h_rx) / 1000 for dist in np.sqrt(np.random.uniform(0, R ** 2, subs_cnt))]
# print(sub_distans)
# Список случайных затуханий сигнала по модели Indoor Propagation Model (ITU)
# L_list = 10 ** ((20 * np.log10(f0) + 29 * np.log10(sub_distans) + 0 - 28) / 10)
# Список случайных затуханий сигнала по модели Окамура-Хаты
a = (1.1 * np.log10(f0) - 0.7) * h_rx - (1.56 * np.log10(f0) - 0.8)
L_list = 10**((46.3 + 33.9 * np.log10(f0) - 13.82 * np.log10(h_bs) - a + (44.9 - 6.55 * np.log10(h_rx)) * np.log10(sub_distans) + S) / 10)
# Цикл по пользователям
for sub_idx, L in enumerate(L_list):
# Расчеты для slot_cnt слотов
Prx = Ptx / (L + np.random.normal(0, 1, slot_cnt)) # Расчёт мощности
SNR = Prx / Pn # Сигнал/шум
CC = DF * np.log2(1 + SNR) # Макс пропускная способность канала связи
# Запись расчитанных объемов сообщения которое
# может быть переданно из буфера на АБ для каждого слота
subs.loc['sub_' + str(sub_idx)] = CC * T_rb
return subs
def get_R_mean(slot_resource_blocks, subs, sub_idx, slot_idx):
'''Возвращает среднюю скорость с которой АБ скачивал данные'''
cd_slot_cnt = const_var.get("cooldown_slot_count") # Кол-во слотов перерасчета, средней скорости
Nrb = const_var.get("Nrb") # Кол-во ресурсных блоков
# Объём данных, который передан абоненту sub_idx
packs_sum = 0
# Цикл по слотам
for slot_idx in range(max(0, slot_idx - 1 - cd_slot_cnt), slot_idx):
# Кол-во ресурсных блоков в слоте slot_idx, которые пренадлежат АБ с индексом sub_idx
sub_slot_res_block_cnt = 0
# Цикл по ресурсным блокам
for res_sub_idx in slot_resource_blocks[slot_idx]:
# Проверка принадлежности ресурсного блока в слоте АБ sub_idx
if res_sub_idx == sub_idx:
sub_slot_res_block_cnt += 1
# Находим объём данных, который передан абоненту sub_idx в ресурсных блоках в слоте slot_idx
packs_sum += subs[slot_idx][sub_idx] * sub_slot_res_block_cnt
return packs_sum / cd_slot_cnt
def get_R_mean_smoothing_filter(slot_resource_blocks, subs, sub_idx, slot_idx, sub_R_mean_list):
'''Возвращает среднюю скорость с которой АБ скачивал данные методом сглаживающего фильтра'''
cd_slot_cnt = const_var.get("cooldown_slot_count") # Кол-во слотов перерасчета, средней скорости
T_rb = const_var.get("T_rb") # Длительность слота
betta = 1 / cd_slot_cnt # Параметр сглаживающего фильтра
return (1 - betta) * sub_R_mean_list[sub_idx] + betta * sum([subs[slot_idx][sub_idx] for res_sub_idx in slot_resource_blocks[-1] if res_sub_idx == sub_idx]) / T_rb
def get_sub_index_by_equa_blind(sub_R_mean_list, sub_with_full_buffer):
'''
Возвращает индекс АБ для алгоритма Proportional fair, который
обеспечивает равные скорости между всеми абонентами
'''
# Расчет приоритетов и возвращение максимального
subs_priority = [1 / sub_R_mean if sub_R_mean > 0 else 1 for sub_R_mean in sub_R_mean_list]
# Получаем список отсортированных индексов АБ по приоритету
subs_priority_idx = np.argsort(subs_priority)
# Возвращаем список тех у кого не пустой буфер
return [sub_idx for sub_idx in subs_priority_idx if sub_idx in sub_with_full_buffer]
def get_sub_index_by_maximum_throughput(subs_slot_CC, sub_with_full_buffer):
'''
Возвращает индекс АБ для алгоритма Maximum Throughput,
который максимизирует суммарную скорость передачи базовой станцией
'''
# Получаем список отсортированных индексов АБ по приоритету
subs_priority_idx = np.argsort(subs_slot_CC)
# Возвращаем список тех у кого не пустой буфер
return [sub_idx for sub_idx in subs_priority_idx if sub_idx in sub_with_full_buffer]
def get_sub_index_by_proportional_fair(subs_slot_CC, sub_R_mean_list, sub_with_full_buffer):
'''
Возвращает индекс АБ для алгоритма Proportional fair, который
выделяет равные доли ресурсов всем абонентам
'''
# Расчет приоритетов и возвращение максимального
subs_priority = [sub_slot_CC / (sub_R_mean if sub_R_mean > 0 else 1) for sub_slot_CC, sub_R_mean in zip(subs_slot_CC, sub_R_mean_list)]
# Получаем список отсортированных индексов АБ по приоритету
subs_priority_idx = np.argsort(subs_priority)
# Возвращаем список тех у кого не пустой буфер
return [sub_idx for sub_idx in subs_priority_idx if sub_idx in 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 get_sub_index_by_equa_blind(sub_R_mean_list, sub_with_full_buffer)
case 'Maximum Throughput':
return get_sub_index_by_maximum_throughput(subs_slot_CC, sub_with_full_buffer)
case 'Proportional fair':
return get_sub_index_by_proportional_fair(subs_slot_CC, sub_R_mean_list, sub_with_full_buffer)
return 0
def get_mean_buffer_score(subs, p, algorithm = 'Maximum Throughput'):
'''Возвращает оценку среднего объема буффера'''
V = const_var.get("V") # Объем передоваемого сообщения
Nrb = const_var.get("Nrb") # Кол-во ресурсных блоков
slot_cnt = const_var.get("slot_cnt") # Кол-во слотов
subs_cnt = len(subs.index) # Кол-во пользователей
# Список генерация пакетов входящего потока
packs = pd.DataFrame(columns=subs.columns, data=[(np.random.geometric(p, size = slot_cnt) - 1) * V for _ in range(subs_cnt)])
# packs = pd.DataFrame(columns=subs.columns, data=[np.random.exponential(1/lambd) * V for _ in range(subs_cnt)])
# print('packs', packs) # ОТЛАДОЧНАЯ ПЕЧАТЬ
# Записываем пакеты пришедшие в первом слоте в буффер
buffer = [packs[0].tolist()]
# Список для ресурсных блоков слотов
slot_resource_blocks = [[]]
# Список средних скоростей
sub_R_mean_list = [[get_R_mean(slot_resource_blocks, subs, sub_idx, 0) for sub_idx in range(subs_cnt)]]
cur_sub_idx = 0
# Цикл по слотам
for slot_idx in range(1, slot_cnt):
# print(slot_resource_blocks[-1])
# Расчитываем среднюю скорость только для алгоритмаов EB и PF
if algorithm in ['Equal Blind', 'Proportional fair']:
# sub_R_mean_list.append(
# [get_R_mean(slot_resource_blocks, subs, sub_idx, slot_idx) for sub_idx in range(subs_cnt)]
# )
sub_R_mean_list.append(
[get_R_mean_smoothing_filter(slot_resource_blocks, subs, sub_idx, slot_idx, sub_R_mean_list[-1]) for sub_idx 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[slot_idx].to_list(), algorithm, sub_with_full_buffer, sub_R_mean_list[-1])
new_slot_res_block = []
for sub_idx in subs_priority_idx:
# Кол-во ресурсных блоков необходимых АБ
sub_res_block_cnt = int(np.ceil(buffer[-1][sub_idx] / subs[slot_idx][sub_idx]))
# Добавляем необходимое кол-во ресурсных блоков
new_slot_res_block.extend([sub_idx for _ in range(sub_res_block_cnt)])
# Проверка на превышеняе кол-ва ресурсных блоков в слоте
if len(new_slot_res_block) >= Nrb: break
# Записываем респределенные ресурсные блоки слота в список
slot_resource_blocks.append(new_slot_res_block[:Nrb])
# Цикл по абанентам, которым выделены ресурсные блоки в текущем слоте
for sub_idx in [sub_idx for sub_idx in slot_resource_blocks[-1] if sub_idx != -1]:
# Уменьшаем буфер на объем передоваемого АБ сообщения
buffer[-1][sub_idx] = max(0, buffer[-1][sub_idx] - subs[slot_idx][sub_idx])
else:
slot_resource_blocks.append([])
# Увеличение буфера на обем пакетов генерируемых входным потоком
buffer[-1] = [sub_buf + sub_pac for sub_buf, sub_pac in zip(buffer[-1], packs[slot_idx])]
# print(packs.sum(axis = 1))
# plt.plot([sum(slot_buffer) for slot_buffer in buffer])
# plt.show()
# Рассчет среднего суммарного буффера слотов
return np.mean([sum(slot_buffer) for slot_buffer in buffer])
# return sum([sum(slot_buffer) for slot_buffer in buffer]) / slot_cnt
def start_model():
'''Функция моделирования работы системы'''
lambd_start = const_var.get("lambd_start") # Начальное значение интенсивности
lambd_end = const_var.get("lambd_end") # Конечное значение интенсивности
lambd_step = const_var.get("lambd_step") # Шаг изменения
T_rb = const_var.get("T_rb") # Длительность слота
# Интенсивность входного потока (Пакетов/сек)
lambd_list = np.arange(lambd_start, lambd_end, lambd_step)
# Параметр p геометрического распределения
p_list = 1 / (lambd_list * T_rb + 1)
# Цикл по кол-ву АБ
for subs_cnt in const_var.get("subs_list"):
# Генерация расположения АБ
subs = subs_generator(subs_cnt)
# print('subs', subs) # ОТЛАДОЧНАЯ ПЕЧАТЬ
# Цикл по алгоритмам
for alg in const_var.get("algoritm_list"):
buffer_score = []
for p, lambd in zip(p_list, lambd_list):
buffer_score.append(get_mean_buffer_score(subs, p, alg) / 8192)
print('subs_cnt = ', subs_cnt, ', lambd = ', lambd, ', alg = ', alg, ', buffer_score = ', buffer_score[-1], sep='')
# Добавляем линию на график
plt.plot(lambd_list, buffer_score, marker='o', label = str(subs_cnt) + ' ' + alg)
# Построение графика
plt.title('Моделирование для ' + str(const_var.get('slot_cnt')) + ' слотов')
plt.xlabel('Интенсивность входного потока (пакетов/сек)')
plt.ylabel('Средн. суммарный объём данных в буфере (Кбайт)')
plt.legend()
plt.grid()
plt.show()
return 0
if __name__ == "__main__":
start_model()
Соседние файлы в папке ЛР3