Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лабораторная работа 3

.docx
Скачиваний:
12
Добавлен:
17.06.2021
Размер:
95.62 Кб
Скачать

Министерство образования и науки РФ

Федеральное государственное бюджетное образовательное учреждение высшего образования

«Омский государственный технический университет»

Кафедра «Комплексная защита информации»

Отчёт по лабораторной работе № 3

по дисциплине

«Математические модели в информационных системах»

Выполнил

Студент гр. ИВТм-192

Козлитин Ю.В. ______________

(подп., дата)

Проверил

Профессор каф. КЗИ

Магазев А.А ______________

(подп., дата)

Омск 2019

Ход работы

Задание. Необходимо реализовать 3 генератора псевдослучайных чисел:

  1. Равномерно распределенной случайной величины на участке [0; 1].

  2. Нормально распределенной случайной величины с мат. ожиданием 0 и стандартным отклонением 1.

  3. Экспоненциально распределенной с параметром λ = 1.

Для генерации равномерно распределенной величины на участке [0; 1] достаточно использовать ЛКГ (линейные конгруэнтный генератор) из лабораторной работы №1, преобразуя результаты делением на модуль генератора. В общем случае, для каждого , сгенерированного ЛКГ, будет применена формула (1):

(1)

где – псевдослучайный элемент последовательности; –элемент, сгенерированный при помощи ЛКГ; N – модуль генератора.

После генерации 259200 элементов, было произведено разбиение участка на 100 интервалов, график распределения псевдослучайных элементов последовательности пример вид, представленный на рисунке 1.

Рисунок 1 – Распределение элементов псевдослучайной последовательности, сгенерированных при помощи генератора равномерно распределенной случайной величины

Для генерации псевдослучайной последовательности, распределённой по нормальному закону, был использован следующий алгоритм:

  1. Сгенерировать числа , равномерно распределенные на отрезке [0; 1].

  2. Рассчитать значения и по формулам (2, 3).

(2)

(3)

  1. Рассчитать S по формуле (4).

(4)

  1. Если S > 1, перейти к п.1 иначе п.5.

  2. Рассчитать и по формулам (5, 6).

(5)

(6)

Полученные в п. 5 и будут являться элементами псевдослучайной последовательности. График нормального распределения для 518 400 сгенерированных случайных величин представлен на рисунке 2.

Рисунок 2 - Распределение элементов псевдослучайной последовательности, сгенерированных при помощи генератора равномерно распределенной случайной величины

Генерация экспоненциально распределенной псевдослучайной величины с параметром λ происходит с использованием формулы (7).

(8)

где U – это элемент нормально распределенной последовательности.

График распределения элементов последовательности с экспоненциальным законом представлен на рисунке 3.

Рисунок 3 - Распределение элементов псевдослучайной последовательности, сгенерированных при помощи генератора экспоненциально распределенной случайной величины

Заключение

Генерирование псевдослучайных величин необходимо для моделирования процессов, где количество влияющих факторов слишком велико, чтобы учитывать каждый из них. В таких случаях подходит псевдослучайный генератор, который «возьмет» на себя поведение влияющих на процесс факторов. При этом, для каждого отдельного случая необходим свой закон распределения чисел, так как характер влияющих факторов различен.

В рамках данной работы был изучен процесс создания генератора псевдослучайной величины из ЛКГ с заданным законом распределения.

Приложение А Исходный код программы

public class EvenDistributionGenerator

{

public EvenDistributionGenerator(int a = 421, int b = 54773, int generatorModule = 259200)

{

generator = new LinearCongruationGenerator.Generator(421, 54773, generatorModule);

this.a = a;

this.b = b;

this.generatorModule = generatorModule;

}

public void generate(string filename)

{

using (FileStream stream = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite))

{

StreamWriter writer = new StreamWriter(stream);

for (int i = 0; i < generatorModule; i++)

{

double next = generateNext();

writer.WriteLine(next);

}

}

}

public double generateNext()

{

previousNumberForLCG = generator.getNextNumber(previousNumberForLCG);

return (double)previousNumberForLCG / generatorModule;

}

private LinearCongruationGenerator.Generator generator;

private int previousNumberForLCG = 1;

private int a, b, generatorModule;

}

public class ExpDistributionGenerator

{

public ExpDistributionGenerator(int a = 421, int b = 54773, int generatorModule = 259200, int lambda = 1, int avg = 0)

{

this.a = a;

this.b = b;

this.generatorModule = generatorModule;

this.lambda = lambda;

generator = new LinearCongruationGenerator.Generator(a, b, generatorModule);

}

public void generate(string filename)

{

using (FileStream stream = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite))

{

StreamWriter writer = new StreamWriter(stream);

for (int i = 0; i < generatorModule; i++)

{

double next = generateNext();

writer.WriteLine(next);

}

}

}

public double generateNext()

{

previousNumberForLCG = generator.getNextNumber(previousNumberForLCG);

return -1/lambda * Math.Log((double)previousNumberForLCG / generatorModule);

}

private int a, b, generatorModule, lambda;

private int previousNumberForLCG = 1;

private LinearCongruationGenerator.Generator generator;

}

public class NormalDistributionGenerator

{

public NormalDistributionGenerator(int a = 421, int b = 54773, int generatorModule = 259200)

{

this.a = a;

this.b = b;

this.generatorModule = generatorModule;

generator = new LinearCongruationGenerator.Generator(a, b, generatorModule);

}

public void generate(string filename)

{

using (FileStream stream = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite))

{

StreamWriter writer = new StreamWriter(stream);

for (int i = 0; i < generatorModule; i++)

{

foreach(double next in generateNextPair())

writer.WriteLine(next);

}

}

}

public IEnumerable<double> generateNextPair()

{

double u1, u2, V1, V2, S = -1;

do

{

previousNumberForLCG = generator.getNextNumber(previousNumberForLCG);

u1 = (double)previousNumberForLCG / generatorModule;

previousNumberForLCG = generator.getNextNumber(previousNumberForLCG);

u2 = (double)previousNumberForLCG / generatorModule;

V1 = 2 * u1 - 1;

V2 = 2 * u2 - 1;

S = Math.Pow(V1, 2.0) + Math.Pow(V2, 2.0);

} while (S > 1);

yield return V1 * Math.Sqrt(-2 * Math.Log(S) / S);

yield return V2 * Math.Sqrt(-2 * Math.Log(S) / S);

}

private LinearCongruationGenerator.Generator generator;

private int previousNumberForLCG = 1;

private int generatorModule, a, b;

}

public class DistributionChecker

{

public DistributionChecker(int a = 421, int b = 54773, int generatorModule = 259200, int intervalCount = 100)

{

this.a = a;

this.b = b;

this.generatorModule = generatorModule;

k = intervalCount;

}

public void check(string filename, string resultsFile)

{

List<double> numbers = getNumbers(filename);

double minValue = getMinValue(numbers);

double maxValue = getMaxValue(numbers);

double delta = maxValue - minValue;

Dictionary<int, int> amountOfNumberPerInterval = new Dictionary<int, int>();

FileStream fs = new FileStream(resultsFile, FileMode.Create, FileAccess.ReadWrite);

StreamWriter sw = new StreamWriter(fs);

double numberStep = delta / k;

for (int i = 0; i < k; i++)

{

amountOfNumberPerInterval.Add(i, 0);

}

for (int step = 0; step < k; step++)

{

foreach (double num in numbers)

{

if (num > minValue + step * numberStep && num < minValue + (step + 1) * numberStep)

amountOfNumberPerInterval[step]++;

}

}

double cumulativeSum = 0;

int count = 0;

foreach (var interval in amountOfNumberPerInterval)

{

Console.WriteLine($"For interval [{interval.Key * numberStep + minValue};{(interval.Key + 1) * numberStep + minValue - numberStep}] generated {interval.Value} numbers.");

sw.WriteLine($"{count};{interval.Key * numberStep + minValue};{(interval.Key + 1) * numberStep + minValue - numberStep}; {interval.Value}");

count++;

}

sw.Close();

fs.Close();

}

private List<double> getNumbers(string filename)

{

List<double> result = new List<double>();

foreach (string num in File.ReadAllText(filename).Split('\n'))

{

result.Add(double.Parse(num.Trim('\r')));

}

return result;

}

private double getMinValue(List<double> numbers)

{

double minValue = double.MaxValue;

foreach (double num in numbers)

{

if (num < minValue)

minValue = num;

}

return minValue;

}

private double getMaxValue(List<double> numbers)

{

double maxValue = double.MinValue;

foreach (double num in numbers)

{

if (double.IsFinite(num) && num > maxValue)

maxValue = num;

}

return maxValue;

}

private int a, b, generatorModule, k;

}

class Program

{

static void Main(string[] args)

{

NormalDistributionGenerator ndg = new NormalDistributionGenerator();

ndg.generate("normal-distribution.csv");

Console.WriteLine("Normal distribution generated");

EvenDistributionGenerator edg = new EvenDistributionGenerator();

edg.generate("even-distribution.csv");

Console.WriteLine("Even distribution generated");

ExpDistributionGenerator exdg = new ExpDistributionGenerator();

exdg.generate("exp-distribution.csv");

Console.WriteLine("Exp distribution generated");

DistributionChecker dc = new DistributionChecker();

Console.WriteLine("Checking normal distibution...\n\n");

dc.check("normal-distribution.csv", "normal-results.csv");

Console.WriteLine("Checking even distibution...\n\n");

dc.check("even-distribution.csv", "even-results.csv");

Console.WriteLine("Checking exp distibution...\n\n");

dc.check("exp-distribution.csv", "exp-results.csv");

Console.ReadKey();

}

}