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

np.random.seed(3) # Зерно рандома для воспроизводимости результатов

R = 20 # Радиус работы БС (м)
Ptx = 0.05 # Мощность излучаемого сигнала (Вт)
F0 = 1200 # Частота БС (МГц)
DF = 180 * 10**3 # Полоса пропускания канала связи (Гц)
KN = 4 # Коэф. шума приёмника

K = 1.38 * 10 ** (-23) # Постоянная Больцмана
T = 300 # Абсолютная температура

# Высота используется в модели Окамура-Хата
Hbs = 30 # Высота БС
Hrx = 1.5 # Высота Абонента

V = 8 * 1024 # Объем данных содержащихся в одном пакете равный 1 кбайт
t = 5*10**-4 # Длительность одного слота 0.5 мс


def random_user(N):
    # Генерация случайных велечин равномерно распределнных на радиусе
    distance = np.sqrt(np.random.uniform(0, R ** 2, N)) # Дальность до абонента
    return distance


# Рассчет пропускной способности канала связи
def kanal(distance):
    Pn = DF * T * K * KN # Мощность шума

    # ITU propagation model
    # L = 20*log10(f)+N*log10(d)+Pf(n) - 28
    '''
    L = the total path loss. Unit: decibel (dB).
    f = Frequency of transmission. Unit: megahertz(MHz).
    d = Distance. Unit: meter (m).
    N = The distance power loss coefficient.
    n = Number of floors between the transmitter and receiver.
    Pf(n) = the floor loss penetration factor.
    '''

    N = 32 # Коэффициент потери мощности от расстояния
    Pfn = 0 # Фактор потери из-за препятствий (этажей)
    Li = 20 * np.log10(F0) + N * np.log10(distance) + Pfn - 28 # Затухание сигнала по модели ITU

    xik = np.random.normal(0, 1, len(distance)) # Случайная нормальная величина с математическим ожиданием 0 и среднеквадратическим отклонением 1
    Lik = Li + xik # Затухание сигнала при распространении от БС до абонента (дБ)
    Lik = 10**(Lik/10) # Перевод в Разы
    Prx = Ptx / Lik  # Мощность принятого сигнала
    SNR = Prx / Pn  # Соотношение сигнал/шум
    C = DF * np.log2(1+SNR)  # Cik максимальная  пропускная способность
    return (C*t) # Vik объем данных, который может быть передан абоненту i в слоте с индексом k


# Обновление буфера после получения или отправки
# check=True загрузка в буферы на БС
# check=False отправка абоненту
def bufferReload(add, buffer, check=False, abonent_number=None):
    if check:
        return [buffer[i] + add[i] for i in range(len(buffer))]
    else:
        buffer[abonent_number] = buffer[abonent_number] - add
        if buffer[abonent_number] <= 0:
            buffer[abonent_number] = 0
        return buffer

# Загрузка пакетов в буферы на БС
def stationDownload(countAB, prop, buffer):
    dataSize = [(np.random.geometric(prop) - 1) * V for user in range(countAB)]
    buffer = bufferReload(dataSize, buffer, True)
    return buffer

# Отправка пакетов абоненту
def stationUpload(users, abonent_number, buffer):
    dataSize = kanal(users)
    buffer = bufferReload(dataSize[abonent_number], buffer, False, abonent_number)
    return buffer

def main():
    lambda_array=np.arange(1, 155, 2) # Массив со значениями лямбда (начало, конец, шаг)
    for countAB in [8, 16, 64]: # Цикл по количеству пользователей
        buffer_all = [0 for user in range(countAB)]  # Создание буфера для каждого абонента
        buffer = [0 for user in range(countAB)]  # Создание буфера для каждого абонента
        users = random_user(countAB)  # Генерация расстояний пользователй
        avgBuffers = []  # Массив со средними суммарными
        for lambd in lambda_array:  # Цикл по интенсивности входного потока
            buffer_list = []  # Массив с суммами
            lambda_slot=lambd*t
            prob = 1 / (lambda_slot + 1)  # Вер. успеха
            for slot in range(10 ** 3):  # Цикл по слотам
                if not slot:  # Если слот первый
                    buffer = stationDownload(countAB, prob, buffer)  # Загружаем первый поток данных на БС
                    buffer_list += [sum(buffer)]
                    continue
                buffer_all = buffer

                # slot%countAB определяет с каким абонентом в данном слоте ведется работа
                buffer_all = stationUpload(users, (slot % countAB), buffer_all)  # Отправка пакетов абоненту
                buffer = stationDownload(countAB, prob, buffer_all)  # Загружаем поток данных на БС

                # В конце слота складываем объем данных во всех буферах
                buffer_list += [sum(buffer)]

            # Когда прошли все слоты, находим средний объем суммы всех буферов на текущей лямбде
            avgBuffers += [np.mean(buffer_list)]

        # Когда собрали данные по каждой лямбде для текущего числа пользователей, строим график
        plt.plot(lambda_array, avgBuffers, label='N = {}'.format(countAB))

    plt.ylim(0, 10 ** 7)
    plt.xlabel('Интенсивность входного потока (пакетов/сек)')
    plt.ylabel('Средн. суммарный объём данных в буфере (бит)')
    plt.legend(loc='upper left')
    #plt.show()


def main_optimised():
    lambda_array=np.arange(1, 145, 2) # Массив со значениями лямбда (начало, конец, шаг)
    for countAB in [8, 16, 64]: # Цикл по количеству пользователей
        buffer_all = [0 for user in range(countAB)]  # Создание буфера для каждого абонента
        buffer = [0 for user in range(countAB)]  # Создание буфера для каждого абонента
        users = random_user(countAB)  # Генерация расстояний пользователй
        avgBuffers = []  # Массив со средними суммарными
        for lambd in lambda_array:  # Цикл по интенсивности входного потока
            buffer_list = []  # Массив с суммами
            lambda_slot = lambd * t
            prob = 1 / (lambda_slot + 1) # Вер. успеха
            reciever=0 # Принимающий абонент
            for slot in range(10 ** 3): # Цикл по слотам
                if not slot:  # Если слот первый
                    buffer = stationDownload(countAB, prob, buffer)  # Загружаем первый поток данных на БС
                    buffer_list += [sum(buffer)]
                    continue
                buffer_all = buffer

                # Проверяем есть ли данные для передачи а+боненту с индексом reciever
                if buffer_all[reciever] == 0:
                    next_receiver = (reciever + 1) % countAB  # Находим следующего абонента для передачи
                    while next_receiver != reciever:  # Пока не вернемся к начальному абоненту
                        if buffer_all[next_receiver] != 0:  # Если у абонента есть данные
                            break  # Прерываем цикл, нашли следующего абонента для передачи
                        next_receiver = (next_receiver + 1) % countAB  # Переходим к следующему абоненту
                    reciever = next_receiver  # Обновляем получателя на найденного абонента

                buffer_all = stationUpload(users, reciever, buffer_all)  # Отправка пакетов абоненту
                buffer = stationDownload(countAB, prob, buffer_all)  # Загружаем поток данных на БС

                reciever+=1 # Переход на следующего пользователя
                if reciever>countAB-1:
                  reciever=0 # Если мы вышли на N+1, то работаем с нулевым абонентом

                # В конце слота складываем объем данных во всех буферах
                buffer_list += [sum(buffer)]

           # Когда прошли все слоты, находим средний объем суммы всех буферов на текущей лямбде
            avgBuffers += [np.mean(buffer_list)]

        # Когда собрали данные по каждой лямбде для текущего числа пользователей, строим график
        plt.plot(lambda_array, avgBuffers, label='Оптимизированный N = {}'.format(countAB))

    plt.ylim(0, 10 ** 7)
    plt.grid()
    plt.legend(loc='upper left')
    plt.show()

main()
main_optimised()