Интегрирование методом Монте-Карло#
Общий подход#
Давайте теперь рассмотрим, как можно обобщить этот метод. Пусть нам необходимо вычислить какой-то многомерный интеграл по какой-то области \(\Omega \subset \mathbb{R}^D\) следующего вида:
Сразу напрашивается тривиальное обобщение: давайте просто случайным образом выбирать точку из области \(\boldsymbol{r}_i \in \Omega\) (предположим, у нас имеется такой алгоритм); тогда мы могли бы записать:
(где \(V_{\Omega}-\) объём области \(\Omega\), который, как мы предполагаем, мы тоже умеем вычислять).
По сути, это обобщение той самой предыдущей формулы для вычисления числа \(\pi\) при \(V_{\Omega}-\) квадрат, \(f(\boldsymbol{r})\) - индикаторная функция единичного круга.
Какие в этом метода есть подводные камни?
Проблема некомпактного носителя#
Первый подводный камень заключается в том, что будет если функция \(f(\boldsymbol{r})\) отлична от нуля во всём пространстве? Формально , это соответствует \(\Omega=\mathbb{R}^D\) и \(V_{\Omega}=\infty\).
Первый «наивный» подход - обрезка функции.
Вместо области \(\Omega\) посчитаем интеграл на некоторой меньшую компактную область \(\Omega^{\prime} \subset \Omega\), где функция существенно отлична от нуля. Некомпактный остаток на \(\Omega \backslash \Omega^{\prime}\) оценим аналитически.
У этого подхода есть много проблем:
Сложность аналитической оценки остатка
Увеличение области \(\Omega\) повышает погрешность метода Монте-Карло, т.к. \(\sigma_I^2 \propto V_{\Omega}^2\)
В случае непрямоугольной \(\Omega^{\prime}\) (например, какая-нибудь кривая), то выбирать случайным образом из неё точки тоже является сложной задачей
Второй «крутой» подход - выбор функции распределения.
Вообще говоря, нам необязательно выбирать точку из равномерного распределения. Давайте модифицируем наш интеграл следуюшим образом:
Если функция \(P(\boldsymbol{r}) \geq 0\) и \(\int d^D \boldsymbol{r} P(\boldsymbol{r})=1\), то эту формулу можно интерпретировать следующим образом:
где \(\boldsymbol{r}_i\) выбираются из известного распределения \(P(\boldsymbol{r})\).
Наша задача заключается в выборе из этого набора распределения \(P(\boldsymbol{r})\), который максимально похож на функцию \(f(\boldsymbol{r})\) - тем самым мы минимизируем дисперсию \(\left\langle\left\langle(f(\boldsymbol{r}) / P(\boldsymbol{r}))^2\right\rangle\right\rangle\).
Возникает вопрос, а как нам генерировать \(\boldsymbol{r}_i\) из определенного распределения \(P(\boldsymbol{r})\)? Конечно, в python уже встроены алгоритмы генерации многих распределений и для многих простых случаев они подойдут, но в случае практических задач придётся научиться генерировать точки из нужного нам распределения.
Пример#
Давайте разберём тривиальный пример. Пусть мы хотим сосчитать такой интеграл:
(тут \(\Gamma(x)\) - так называемая Гамма-функция Эйлера). Пусть мы хотим вычислить интеграл с точностью \(\epsilon=10^{-3}\). Действовать будем «на глаз».
Уменьшение области интегрирования#
Построим подынтегральную функцию, и пристально на неё посмотрим. Судя по графику, кажется, что существенно отлична от нуля примерно на отрезке \((-2,2)\). Это будет нашей отправной точкой.
Сама функция на краях этого отрезка уже достаточно мала: \(e^{-8} \approx 3 \cdot 10^{-4}\), это даёт нам наивную оценку сверху для погрешности от такого приближения (точная оценка даёт \(2 \int_2^{\infty} \exp \left(-x^3\right) d x \approx 5 \cdot 10^{-5}\), но чтобы её получить, нужно уметь этот интеграл считать…). Такая погрешность нас вполне удовлетворяет, поэтому мы реализуем следующий алгоритм:
Выбираем \(N\) случайных точек \(x_i\) из отрезка \((-2,2)\)
Вычисляем \(I_N=4 \frac{1}{N} \sum_{i=1}^N f\left(x_i\right)\).
Погрешность этого алгоритма будет равна
Выбор функции распределения#
А давайте теперь вместо этого попробуем приблизить эту функцию при помощи нормального распределения \(P(x)=e^{-x^2 / 2 \sigma^2} / \sqrt{2 \pi \sigma^2}\).
Дисперсию этого распределения \(\sigma\) мы опять выберем «на глаз», чтобы функция распределения была максимально похожей на подынтегральное выражение. Автору хорошим приближением показалось значение \(\sigma=0.5\). Так и поступим:
Выбираем \(N\) случайных точек \(x_i\) из нормального распределения с нулевым средним и дисперсией \(\sigma=0.5\) ( распределение \(P(x)\) ).
Вычисляем \(I_N=\frac{1}{N} \sum_{i=1}^N \frac{f\left(x_i\right)}{P\left(x_i\right)}\).
Погрешность этого алгоритма будет равна
Ключевой вывод, который мы можем сделать из этого примера: выбирая правильным образом распределение \(P(\boldsymbol{r})\), можно заметным образом (в нашем случае - почти в шесть раз!) ускорить алгоритм.
Лирика: когда имеет смысл использовать Монте-Карло алгоритмы?#
Если мы вспомним прошлые семинары, то в том же методе прямоугольников количество шагов для достижении нужной точности меньше:
Тогда как в методе Монте-Карло:
А ведь метод прямоугольников был худшим из всех, что мы рассматривали, в плане скорости сходимости. Зачем же нужен Монте-Карло?
Метод Монте-Карло нужен, когда интегрирование происходит в многомерном пространстве достаточно большой размерности \(D\).
Ведь если мы хотим использовать квадратуру, то нам будет необходимо дискретизовать вдоль каждой пространственной размерности; и если мы апроксимируем интеграл, используя \(N\) точек, то каждое пространственное измерение мы будем вынуждены дискретизовать, вводя гораздо меньше - порядка \(N^{1 / D}\) - точек.
Как следствие, общая погрешность квадратурного метода будет вести себя уже как \(\delta I / I \propto \frac{1}{N^{m / D}}\), и при достаточно больших \(D>2 m\) Монте-Карло метод будет более эффективным (на него \(D\) не влияет никак в ассимптотике)
Поэтому ключевой вывод, который отсюда стоит вынести: метод Монте-Карло эффективен при интегрировании в пространстве достаточно большой размерности. И как раз основное применение методов Монте-Карло - случай, когда размерность пространства оказывается астрономически большой (например, фазовое пространство системы большого количество частиц).