Основы численных методов курсовая работа

Автор работы: Пользователь скрыл имя, 08 Апреля 2013 в 23:07, курсовая работа

Описание работы

Методами Монте-Карло называется семейство методов решения численных задач, основанных на моделирование различных случайных величин. Главная идея методов Монте-Карло заключается в следующем: пусть поставлена некая задача и скалярная величина является ее решением (это может быть решение СЛАУ или же значение интеграла , и т.д.). Постараемся придумать такую случайную величину , чтобы . Если это удастся сделать, то естественно ожидать, что решение поставленной задачи можно получить как при достаточно большом .

Содержание работы

Введение 3
§1. Моделирование случайных величин 4
1.1. Генерация стандартной случайной величины 4
1.2. Статистическая проверка генератора 5
Длина апериодичности 5
Критерий Пирсона 6
Частотный тест 7
Тест серий 8
§2. Применение метода Монте-Карло для вычисления интегралов 9
2.1. Общий метод 9
Оценка математического ожидания 9
Погрешность метода 9
2.2. Простейший метод Монте-Карло 10
Одномерный определенный интеграл 11
2.3. Простейший метод с повышенной скоростью сходимости 12
Двумерный определенный интеграл 17
Выводы 20
Список литературы 21
Приложения и листинги 22
Приложение 1. Листинг генератора Д.Лемера 22
Приложение 2. Листинг статистических функций 24
Приложение 3. Листинг основной части программы 27

Файлы: 1 файл

Курсач.docx

— 717.97 Кб (Скачать файл)

 

Замечание: не смотря на свою простоту, простейший метод требует слишком большие мощности выборки , что с одной стороны одновременно создает необходимость иметь генератор случайных чисел с большим отрезком апериодичности, а также требует внушительных временных затрат на построение оценки . Картину дополняет вероятностный характер оценки точности: существует не нулевая вероятность, что заданная рассчетная точность не будет достигнута даже на самых качественных случайных числах и нужном объеме выборки .

2.3. Простейший метод с повышенной скоростью сходимости

Как было показано ранее, простейший метод в своей наивной реализации совершенно не пригоден для решения  численных задач. Напомним, что это  было связано с неравенством

,

имеющем место с вероятностью . Однако, как уже отмечалось, точность зависит от двух критериев величин; увеличение хоть и увеличило точность решения, но сделало расчет чрезвычайно долгим. Постараемся, теперь, уменьшить дисперсию .

Как и ранее, будем полагать, что  - равномерно распределенная в случайная величина. Ее дисперсия , откуда легко видно, что при . На этом простом факте основан метод существенной выборки. Опишем его в общем случае.

 

Вновь рассмотрим задачу приближенного  вычисления интеграла

,

Разобьем произвольно множество  ; далее, пусть

 и 

Очевидно, что  и . В каждой из областей будем рассматривать случайную точку с плотностью . Для оценки воспользуемся простейшим методом Монте-Карло: так как

,

то, выбрав независимых реализаций точки можем запистаь оценку:

 

 

 

Складывая такие оценки, получим  новую оценку для отыскиваемого  интеграла:

Для построения которой необходимо использовать количество случайных чисел.

 

Численный пример 2

Пересчитаем численный пример 1 с  использованием ускоренного метода

График подынтегральной функции

 

При и имеем

При и имеем

При и имеем


 

 

 

 

 

 

 

 

 

 

Численный пример 3

Пусть требуется взять интеграл

 

При и имеем


 

Численный пример 4

Пусть требуется взять интеграл

 

При и имеем

При и имеем

При и имеем


 

 

 

Численный пример 5

Пусть требуется взять интеграл

 

При и имеем

При и имеем

При и имеем


 

Численный пример 6

Пусть требуется взять интеграл

 

При и имеем

При и имеем

При и имеем


 

Замечание: как видно из примеров выше, метод существенной выборки заметно ускоряет сходимость простейшего метода Монте-Карло для вычисления одномерных определенных интегралов и позволяет уменьшить размеры выборки случайных чисел. Такая экономизация делает ускоренный метод крайне привлекательным для использования.

Двумерный определенный интеграл

Построим  расчетную схему ускоренного метода Монте-Карло с использованием равномерно распределенных случайных величин для приближенного вычисления интеграла

Для этого, прямоугольную область  разобьем на частей по с шагом , и на частей по с шагом . Возьмем случайных величин , равномерно распределенных на отрезке ( ), а также случайных величин , равномерно распределенных на ( ). Случайная величина же будет иметь математическое ожидание:

при

 

 

 

 

 

 

 

 

Численный пример 7

Пусть требуется взять интеграл

 

При и имеем

При и имеем


 

Численный пример 8

Пусть требуется взять интеграл

 

При и имеем


 

 

 

 

 

Численный пример 9

Пусть требуется взять интеграл

 

При и имеем


 

Замечание: Ускоренный метод Монте-Карло замечательно сходится даже на двумерных интегралах!

 

Выводы

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

Был рассмотрен метод Монте-Карло  в приложении к вычислению одномерных и двумерных интегралов. Построен общий ход решения методов  Монте-Карло, сделана вероятностная  оценка погрешности методов.

Построен и непосредственно  апробован на одномерном интеграле  простейший метод Монте-Карло, после  чего была выяснена его несостоятельность. Простейший метод был ускорен  с помощью метода существенной выборки, что дало приемлемые вычислительные затраты и хорошую точность на тестовых примерах вычисления одномерных и двумерных интегралов.

 

Список литературы

  1. Численные методы Монте-Карло, И.М. Соболь. Главная редакция физико-математической литературы изд-ва «Наука», 1973
  2. Дональд Кнут Искусство программирования, том 2. Получисленные методы = The Art of Computer Programming, vol.2. Seminumerical Algorithms. — 3-е изд. — М.: «Вильямс», 2007. — С. 832. — ISBN 0-201-89684-2
  3. Кобзарь А.И. Прикладная математическая статистика. Для инженеров и научных работников. – М.: ФИЗМАТЛИТ, 2006. – 816 с. – ISBN 5-9221-0707-0

 

 

Приложения и  листинги

Приложение 1. Листинг генератора Д.Лемера

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace MonteCarlo

{

    /* Генератор реализации базовой случайной величины

     * (равномерно  распределенной в [0, 1])

     * на  базе алгоритма Д.Лемера

     */

    class LehmerGenerator

    {

        /* Конструктор генератора

         * (m0, M, g) - параметры генератора

         * capacity - объем генератора

         */

        public LehmerGenerator(ulong m0, ulong M, ulong g, ulong capacity)

        {

            m_m0 = m_m = m0;

            m_M = M;

            m_g = g;

 

            m_totalCapacity = m_capacity = capacity;

        }

 

        /* Установка генератора в начальное состояние

         */

        public void SetInitialState()

        {

            m_m = m_m0;

            m_capacity = m_totalCapacity;

        }

 

 

        /* Взятие очередной реализации базовой случайной величины

         */

        public double GetValue()

        {

            m_capacity--;

            if (m_capacity < 0)

            {

                throw new CapacityOverException();

            }

 

            m_m = (m_m * m_g) % m_M;

 

            return ((double)m_m) / ((double)m_M);

        }

 

        /* Получение оставшегося запаса генератора

         */

        public ulong GetCapacity()

        {

            return m_capacity;

        }

 

        /* Исключени: генератор исчерпан

         */

        public class CapacityOverException

            : Exception

        {

        };

 

        /* Текущее значение параметра m тройки (m, M, g)

         */

        private ulong m_m;

 

        /* Оставшийся объем генератора

         */

        private ulong m_capacity;

 

        /* Начальное значение параметра m0

         */

        private ulong m_m0;

 

        /* Параметр M тройки (m, M, g)

         */

        private ulong m_M;

 

        /* Параметр g тройки (m, M, g)

         */

        private ulong m_g;

 

        /* Начальный объем генератора

         */

        private ulong m_totalCapacity;

    }

}


 

 

 

Приложение 2. Листинг статистических функций

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace MonteCarlo

{

    /* Класс-обертка статистических функций

     */

    static class Statistics

    {

        /* Распределение Пирсона

         * (аппроксимация Голдштейна квантилей хи-квадрат)

         * n - количество степеней свободы

         * alpha - коэффиицент значимости из [0.001, 0.999]

         */

        static public double PearsonDistribution(int n, double alpha)

        {

            double[] a = {1.0000886, 0.4713941, 0.0001348028, -0.008553069, 0.00312558, -0.0008426812, 0.00009780499};

            double[] b = {-0.2237368, 0.02607083, 0.01128186, -0.01156761, 0.005169654, 0.00253001, -0.001450117};

            double[] c = {-0.01513904, -0.008986007, 0.02277679, -0.01323293, -0.006950356, 0.001060438, 0.001565326};

           

            double d = 0;

            if (0.001 <= alpha && alpha < 0.5)

            {

                d = -2.0637 * Math.Pow(Math.Log(1 / alpha) - 0.16, 0.4274) + 1.5774;

            }

            else if (0.5 <= alpha && alpha <= 0.999)

            {

                d = 2.0637 * Math.Pow(Math.Log(1 / (1 - alpha)) - 0.16, 0.4274) - 1.5774;

            }

 

            double Chi = 0;

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

            {

                Chi += Math.Pow(n, -i / 2.0) * Math.Pow(d, (double)i) *

                    (a[i] + b[i] / n + c[i] / Math.Pow((double)n, 2.0));

            }

            Chi = n * Math.Pow(Chi, 3.0);

 

            return Chi;

        }

 

        /* Частотный тест генератора Лемера:

         * проверка частот и проверка  частот пар

         * generator - генератор Лемера

         * alpha - коэффициент значимости

         */

        static public bool FrequencyTest(LehmerGenerator generator, double alpha)

        {

            generator.SetInitialState();

 

            // мощность генератора

            ulong N = generator.GetCapacity();

 

            // полная табличка частот

            ulong[,] V = new ulong[10, 10];

            for (ulong i = 0; i < N / 2; i++)

            {

                V[(ulong)(generator.GetValue() * 10), (ulong)(generator.GetValue() * 10)]++;

            }

 

            // вектора частот пар

            ulong[] a = new ulong[10];

            ulong[] b = new ulong[10];

            ulong[] c = new ulong[10];

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

            {

                for (int j = 0; j < 10; j++)

                {

                    a[i] += V[i, j];

                    b[i] += V[j, i];

                }

                c[i] = a[i] + b[i];

            }

 

            // проверка пар

            double empiricalChi1 = 0;

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

            {

                empiricalChi1 += Math.Pow(c[i] - 0.1 * N, 2);

            }

            empiricalChi1 *= 10.0 / (double)N;

 

            // проверка частот

            double empiricalChi2 = 0;

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

            {

                for (int j = 0; j < 10; j++)

                {

                    empiricalChi2 += Math.Pow(V[i, j] - 0.005 * N, 2.0);

                }

            }

            empiricalChi2 *= 50.0 / (double)N;

 

            generator.SetInitialState();

 

            // вывод ответа

            if (empiricalChi1 < PearsonDistribution(9, alpha) && empiricalChi2 < PearsonDistribution(99, alpha))

            {

                return true;

            }

            else

            {

                return false;

            }

        }

 

        /* Тест серий генератора Лемера

         * generator - генератор Лемера

         * m - количество степеней свободы

         * alpha - коэффициент значимости

         */

        static public bool RunTest(LehmerGenerator generator, int m, double alpha)

        {

            generator.SetInitialState();

 

            // полная матрица частот

            ulong[] V = new ulong[m + 1];

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

            {

                V[i] = 0;

            }

 

            ulong l = 1;

            int currentValue = 0,

                previousValue = (int)(generator.GetValue() * 10);

            bool endFlag = false;

            while (endFlag == false)

            {

                if (generator.GetCapacity() > 0)

                {

                    currentValue = (int)(generator.GetValue() * 10);

                }

                else

                {

                    endFlag = true;

                }

 

                if (currentValue == previousValue && endFlag == false)

                {

                    l++;

                }

                else

                {

                    if (l > (ulong)m)

                    {

                        V[m]++;

                        l = 1;

                    }

                    else

                    {

                        V[l - 1]++;

                        l = 1;

                    }

                    previousValue = currentValue;

                }

            }

 

            // общее количество серий

            ulong n = 0;

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

            {

                n += V[i];

            }

 

            // проверка серий

            double empiricalChi = 0;

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

            {

                double p = 9 * Math.Pow(10.0, -(double)(i + 1));

                empiricalChi += Math.Pow(V[i] - n * p, 2.0) / (n * p);

            }

            empiricalChi += Math.Pow(V[m] - n * Math.Pow(10.0, (double)(-m)), 2.0) /

                (n * Math.Pow(10.0, (double)(-m)));

 

            generator.SetInitialState();

 

            // вывод ответа

            if (empiricalChi < PearsonDistribution(m, alpha))

            {

                return true;

            }

            else

            {

                return false;

            }

        }

    }

}


 

 

Приложение 3. Листинг основной части программы

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.IO;

 

namespace MonteCarlo

{

    class Program

    {

        /* Делегаты одномерной и двумерной функций

         */

        public delegate double Function1(double x);

        public delegate double Function2(double x, double y);

 

        /* Метод простейшего интегрирования по методу Монте-Карло

         * f - одномерная функция, интегрируемая на отрезке [a, b]

         * generator - генератор Д.Лемера, источник стандартных случайных чисел

         * n - мощность выборки

         */

        public static double SimpleIntegrate(Function1 f, double a, double b, LehmerGenerator generator, ulong n)

        {

            // случайная величина, равномерно распределенная в [a, b]

            UniformVariates Q = new UniformVariates(generator, a, b);

 

            // вычисление интеграла

            double I = 0;

            for (ulong i = 0; i < n; i++)

            {

                I += f(Q.GetValue());

            }

            I *= (b - a) / n;

 

            return I;

        }

 

        /* Метод простейшего интегрирования по методу Монте-Карло

         * для одномерной функции

         * (ускоренный методом существенной выборки)

         * f - одномерная функция, интегрируемая на отрезке [a, b]

         * generator - генератор Д.Лемера, источник стандартных случайных чисел

         * m - мощность разбиения

         * n - мощность выборки

         */

        public static double AcceleratedIntegrate1(Function1 f, double a, double b, LehmerGenerator generator, int m, ulong n)

        {

            // шаг разбиения

            double h = (b - a) / m;

 

            // вычисление интеграла

            double I = 0;

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

            {

                // случайная величина, равномерно распределенная в m-ом отрезке

                double alpha = a + i * h,

                       beta = a + (i + 1) * h;

                UniformVariates Q = new UniformVariates(generator, alpha, beta);

 

                // вычисление частичного интеграла

                double S = 0;

                for (ulong j = 0; j < n; j++)

                {

                    S += f(Q.GetValue());

                }

                S *= (beta - alpha) / n;

                I += S;

            }

 

            return I;

        }

 

        /* Метод простейшего интегрирования по методу Монте-Карло

         * для двумерной функции

         * (ускоренный методом существенной выборки)

         * f - двумерная функция, интегрируемая на отрезке [a, b]

         * generator - генератор Д.Лемера, источник стандартных случайных чисел

         * m - мощность разбиения

         * n - мощность выборки

         */

        public static double AcceleratedIntegrate2(Function2 f, double a, double b,

            double c, double d, LehmerGenerator generator, int mx, int my, ulong n)

        {

            // шаг разбиения

            double hx = (b - a) / mx,

                   hy = (d - c) / my;

 

            // вычисление интеграла

            double I = 0;

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

            {

                for (int j = 0; j < my; j++)

                {

                    // случайная величина, равномерно распределенная в m-ом квадратике

                    double alpha = a + i * hx,

                           beta = a + (i + 1) * hx,

                           gamma = c + j * hy,

                           delta = c + (j + 1) * hy;

 

                    UniformVariates Qx = new UniformVariates(generator, alpha, beta);

                    UniformVariates Qy = new UniformVariates(generator, gamma, delta);

 

                    // вычисление частичного интеграла

                    double S = 0;

                    for (ulong k = 0; k < n; k++)

                    {

                        S += f(Qx.GetValue(), Qy.GetValue());

                    }

                    S *= (hx * hy) / n;

                    I += S;

                }

            }

 

            return I;

        }

 

        /* Интегрируемые функции одной переменной

         */

        public static double I1(double x)

        {

            return Math.Pow(x, 3) * Math.Sin(x + 1);

        }

 

        public static double I2(double x)

        {

            return Math.Cos(x) / Math.Pow(x, 2) + Math.Pow(x, 3) * Math.Sin(x);

        }

 

        public static double I3(double x)

        {

            return 8 * Math.Pow(x, 5) - 10 * Math.Pow(x, 4) + 5 * Math.Pow(x, 3) + x - 18;

        }

 

        public static double I4(double x)

        {

            return x / Math.Sqrt(x + 1);

        }

 

        public static double I5(double x)

        {

            return Math.Exp(x) * Math.Sin(10 * x);

        }

 

        /* Интегрируемые функции двух переменных

         */

        public static double J1(double x, double y)

        {

            return Math.Pow(x, 2) + Math.Pow(y, 2) * Math.Sin(x);

        }

 

        public static double J2(double x, double y)

        {

            return Math.Pow(x, 2) - Math.Pow(y, 2) - Math.Cos(3 * x) + y * Math.Sin(4 * x);

        }

 

        public static double J3(double x, double y)

        {

            return Math.Pow(x, 3) - y + Math.Cos(x) * Math.Exp(y) + Math.Sqrt(x * y);

        }

 

        static void Main(string[] args)

        {

            ulong m = 1,

                  M = (ulong)Math.Pow(2, 26),

                  g = (ulong)Math.Pow(5, 17),

                  L = (ulong)Math.Pow(2, 24);

 

 

            LehmerGenerator G = new LehmerGenerator(m, M, g, L);

 

            Console.WriteLine(AcceleratedIntegrate2(J3, 0, 7, 0, 7, G, 120, 120, 5000));

        }   

    }

}

Информация о работе Основы численных методов курсовая работа