Скачиваний:
1
Добавлен:
05.01.2024
Размер:
9.37 Кб
Скачать
import numpy as np
import pandas as pd
import warnings
import matplotlib.pyplot as plt
from scipy.integrate import quad
from scipy.stats import uniform

warnings.filterwarnings('ignore')

def unif(min, max, N: int = ...):
    """Функция преобразования случайной выборки

    Параметры:
    -------
    min (int, float): 
        Нижняя граница распределения
    max (int, float): 
        Верхняя граница распределения
    N (int): 
        Количество числе, которые необходимо сгенерировать

    Возвращаемое значение:
    -------
    Массив случайных величин, распределённых равномерно между (min, max)
    """
    uni_nums = np.random.uniform(size=N)
    return uni_nums*(max-min) + min

def plot_modulated(a, b, fig):
    """Функция построения модулируемого закона. Работает только с равномерным
    распределением

    Параметры:
    ----------
    a (int, float): 
        Нижняя граница распределения
    b (int, float): 
        Верхняя граница
    fig (int):
        Номер фигуры при рисовании
    """
    x = np.arange(a-0.1, b+0.1, 0.01)
    plt.figure(fig)
    plt.plot(x, uniform.pdf(x, loc=a, scale=b-a))
    plt.title('Функция распределения моделируемого закона')

def plot_compare(first, second, fig: int, first_label: str = ..., second_label: str = ...):
    """Функция для сравнения двух выборок между собой

    Параметры:
    ----------
    first (array of float):
        Выборка случайной величины №1
    second (array of float): 
        Выборка случайной величины №2
    first_label (str):
        Описание выборки случайной величины №1. Необходим для построения графика
    second_label (str):
        Описание выборки случайной величины №2. Необходим для построения графика
    fig (int):
        Номер фигуры при рисовании
    """
    plt.figure(fig)
    plt.title('Сравнение выборок')
    plt.hist(first, bins=10, label=first_label)
    plt.hist(second, bins=10, label=second_label, alpha=0.5)
    plt.legend()

def plot_hist(x, y, delta, samples, fig: int):
    """Функция построения гистограммы

    Параметры:
    ----------
    x (arr of float):
        Массив середин интервалов 
    y (arr of float):
        Массив высот столбцов интервала
    delta (float):
        Длина одного интервала
    samples (arr of float):
        Выборка случайной величины
    fig (int):
        Номер фигуры при рисовании
    """
    global a
    global b
    x_axis = np.linspace(min(samples), max(samples), 100)
    plt.figure(fig)
    plt.bar(x, y, width=delta)
    plt.plot(x_axis, uniform.pdf(x_axis, loc=a, scale=b-a), color='red')
    plt.title('Гистограмма нормального распределения')

def plot_dependence(arr, depend: str, fig: int):
    """Функция построения графиков зависимостей (матожидания и дисперсии)

    Параметры:
    ----------
    arr (arr of float): 
        Массив оценок значений матожидания/дисперсии
    depend (str): 
        Текстовое описание (для графика)
    fig (int):
        Номер фигуры при рисовании
        
    """
    sizes = [i for i in range(1, len(arr)+1)]
    global a
    global b
    if depend == "Мат. ожидания":
        num = (a+b)/2
    elif depend == "Дисперсии":
        num = ((b-a)**2)/12
    plt.figure(fig)
    plt.title(f'График зависимости {depend} от количества')
    plt.plot(sizes, arr, label='Эксперимент')
    plt.plot(sizes, [num]*len(sizes), label='Истина')
    plt.legend()

def engine(data_for_hist: bool = False, data_for_means_and_vars: bool = False, get_samples_and_dist: bool = False):
    """Основная функция для создания экспериментальной гистограммы

    Параметры:
    ----------
        data_for_hist (bool):
            По умолчанию True. Возвращает все данные, необходимые для построения гистограммы в формате:
                [x, y, delta, samples], где:
                    x - середина отрезка; 
                    y - высота отрезка;
                    delta - размеры отрезка;
                    samples - исходная выборка.

        data_for_means_and_vars (bool):
            По умолчанию False. Возвращает все данные, необходимые для построения графиков
            матожидания и дисперсии в формате:
                [mean, var], где:
                    mean - массив матожиданий от размеров выборки;
                    var - массив дисперсий от размеров выборки.

        get_samples_and_dist (bool):
            По умолчанию False. Возвращает созданную выборку и распределение чисел по интервалам
                [samples, N_i], где:
                    samples - исходная выборка;
                    N_i - распределение чисел по интервалам

    Возвращает
    -------
        Массив returns, наполнение которого зависит от выбранных параметров
    """
    global a
    global b
    samples, returns = [], []
    s_min, s_max, delta, N, amount_of_parts = 0, 0, 0, 0, 10
    borders, N_i = np.array([]), [0] * amount_of_parts
    if data_for_means_and_vars:
        mean, var = [], []
    
    while min(N_i) <= 100:
        # Создание случайного число и добавление его к выборке:
        alpha = unif(a, b, 1)
        samples.append(alpha[0])
        N = len(samples)

        # Распределение чисел:
        if alpha > s_min and delta != 0 and alpha < s_max:
            k = int(np.floor((alpha - s_min)/delta))
            N_i[k] += 1
        
        # Вероятность ошибки:
        p = (N - np.sum(N_i))/N

        # Изменение размеров:
        if p >= 0.01:
            s_min, s_max = min(samples), max(samples)
            delta = (s_max - s_min)/(amount_of_parts)
            borders = np.linspace(s_min, s_max, amount_of_parts, True)
            ids = np.searchsorted(borders, samples)
            N_i = [0] * amount_of_parts
            for id in ids:
                N_i[id] += 1

        # Расчет мат ожидания и дисперсии выборки:
        if data_for_means_and_vars:
            mean.append(np.mean(samples))
            var.append(np.var(samples))
    
    # Формирование вектора Y
    x, y = [], [n/(N*delta) for n in N_i]
    x.append(s_min + delta/2)
    for i in range(amount_of_parts-1):
        x.append(x[i] + delta)

    if get_samples_and_dist:
        returns.append([samples, N_i])
    if data_for_means_and_vars:
        returns.append([mean, var])
    if data_for_hist:
        returns.append([x, y, delta, samples])
    
    return returns


if __name__ == '__main__':
    a, b = 2, 3
    # График модулируемого закона
    N = 100
    plot_modulated(a, b, fig=1)

    # Преобразование чисел
    random_uniform = unif(a, b, N)
    test = np.random.uniform(a, b, N)
    plot_compare(first=random_uniform, second=test, first_label='Ручная', second_label='Встроенная', fig=2)

    # Табличное представление результатов моделирования
    print('\nТабличное представление результатов моделирования:')
    data = engine(get_samples_and_dist=True)[0]
    df = pd.DataFrame(data[1])
    print(df.T)

    # Гистограмма выборки
    data = engine(data_for_hist=True)[0]
    plot_hist(*data, fig=3)

    # Графики зависимости величин от количества
    data = engine(data_for_means_and_vars=True)[0]
    plot_dependence(data[0], depend="Мат. ожидания", fig=4)
    plot_dependence(data[1], depend="Дисперсии", fig=5)

    plt.show()
Соседние файлы в папке Лаба 2