Полярный метод Марсальи
Марсальи . Полярный метод [1] — это метод выборки псевдослучайных чисел для генерации пары независимых стандартных нормальных случайных величин . [2]
Стандартные нормальные случайные величины часто используются в информатике , вычислительной статистике и, в частности, в приложениях метода Монте-Карло .
Полярный метод работает путем выбора случайных точек ( x , y ) в квадрате −1 < x < 1, −1 < y < 1 до тех пор, пока
а затем возвращая требуемую пару нормальных случайных величин как
или, что то же самое,
где и представляют косинус и синус угла, который вектор ( x , y ) образует с x осью .
Теоретическая основа
[ редактировать ]Основополагающую теорию можно резюмировать следующим образом:
Если u равномерно распределено в интервале 0 ≤ u < 1, то точка (cos(2π u ), sin(2π u )) равномерно распределен по единичной окружности х 2 + и 2 = 1, и умножив эту точку на независимую случайная величина ρ, распределение которой равно
поставит точку
координаты которых совместно распределены как два независимых стандарта обычные случайные величины.
История
[ редактировать ]Эта идея восходит к Лапласу , которому Гаусс приписывает открытие вышеизложенного.
извлекая квадратный корень из
Преобразование в полярные координаты показывает, что θ есть равномерно распределены (постоянная плотность) от 0 до 2π, и что радиальное расстояние r имеет плотность
( р 2 имеет соответствующее распределение хи-квадрат .)
Этот метод создания пары независимых стандартных нормальных переменных путем радиального проецирования случайной точки на единичную окружность на расстояние, определяемое квадратным корнем из переменной хи-квадрат-2, называется полярным методом генерации пары нормальных случайных величин. ,
Практические соображения
[ редактировать ]Прямое применение этой идеи
называется преобразованием Бокса-Мюллера , в котором переменная хи обычно равна генерируется как
но для этого преобразования требуются функции логарифма, квадратного корня, синуса и косинуса. На некоторых процессорах косинус и синус одного и того же аргумента можно вычислить параллельно с помощью одной инструкции. [3] В частности, для машин на базе процессоров Intel можно использовать инструкцию ассемблера fsincos или инструкцию expi (доступную, например, в D), для вычисления сложных
и просто разделите действительную и мнимую части.
Примечание: Чтобы явно вычислить комплексно-полярную форму, используйте следующие замены в общей форме:
Позволять и Затем
Напротив, полярный метод здесь избавляет от необходимости вычислять косинус и синус. Вместо этого, найдя точку на единичном круге, эти две функции можно заменить координатами x и y, нормализованными к радиус. В частности, случайная точка ( x , y ) внутри единичного круга проецируется на единичную окружность, установив и формируем точку
это более быстрая процедура, чем вычисление косинуса и синуса. Некоторые исследователи утверждают, что условная инструкция if (для отклонения точки за пределами единичного круга) может замедлить работу программ на современных процессорах, оснащенных конвейерной обработкой и прогнозированием ветвей. [4] Кроме того, эта процедура требует примерно на 27% больше вычислений базового генератора случайных чисел (только сгенерированных точек лежат внутри единичного круга).
Затем эта случайная точка на окружности проецируется радиально на необходимое случайное расстояние с помощью
используя одно и то же s , поскольку оно не зависит от случайной точки на окружности и само по себе равномерно распределено от 0 до 1.
Выполнение
[ редактировать ]Ява
[ редактировать ]Простая реализация на Java с использованием среднего и стандартного отклонения:
private static double spare;
private static boolean hasSpare = false;
public static synchronized double generateGaussian(double mean, double stdDev) {
if (hasSpare) {
hasSpare = false;
return spare * stdDev + mean;
} else {
double u, v, s;
do {
u = Math.random() * 2 - 1;
v = Math.random() * 2 - 1;
s = u * u + v * v;
} while (s >= 1 || s == 0);
s = Math.sqrt(-2.0 * Math.log(s) / s);
spare = v * s;
hasSpare = true;
return mean + stdDev * u * s;
}
}
С++
[ редактировать ]Непотокобезопасная с реализация на C++ использованием среднего и стандартного отклонения:
double generateGaussian(double mean, double stdDev) {
static double spare;
static bool hasSpare = false;
if (hasSpare) {
hasSpare = false;
return spare * stdDev + mean;
} else {
double u, v, s;
do {
u = (rand() / ((double)RAND_MAX)) * 2.0 - 1.0;
v = (rand() / ((double)RAND_MAX)) * 2.0 - 1.0;
s = u * u + v * v;
} while (s >= 1.0 || s == 0.0);
s = sqrt(-2.0 * log(s) / s);
spare = v * s;
hasSpare = true;
return mean + stdDev * u * s;
}
}
в C++11 в GNU GCC libstdc++ Реализация std::normal_distribution использует полярный метод Марсальи, как указано здесь .
Юлия
[ редактировать ]Простая реализация Джулии :
"""
marsagliasample(N)
Generate `2N` samples from the standard normal distribution using the Marsaglia method.
"""
function marsagliasample(N)
z = Array{Float64}(undef,N,2);
for i in axes(z,1)
s = Inf;
while s > 1
z[i,:] .= 2rand(2) .- 1;
s = sum(abs2.(z[i,:]))
end
z[i,:] .*= sqrt(-2log(s)/s);
end
vec(z)
end
"""
marsagliasample(n,μ,σ)
Generate `n` samples from the normal distribution with mean `μ` and standard deviation `σ` using the Marsaglia method.
"""
function marsagliasample(n,μ,σ)
μ .+ σ*marsagliasample(cld(n,2))[1:n];
end
Цикл for можно распараллелить с помощью Threads.@threads
макрос.
Ссылки
[ редактировать ]- ^ Марсалья, Г.; Брей, Т. А. (1964). «Удобный метод генерации нормальных переменных». Обзор СИАМ . 6 (3): 260–264. Бибкод : 1964SIAMR...6..260M . дои : 10.1137/1006063 . JSTOR 2027592 .
- ^ Питер Э. Клоден Экхард Платен Анри Шурц, Численное решение СДУ посредством компьютерных экспериментов, Springer, 1994.
- ^ Кантер, Дэвид. «Графическая архитектура Intel Ivy Bridge» . Реальные мировые технологии . Проверено 8 апреля 2013 г.
- ^ Этот эффект может быть усилен, если графический процессор параллельно генерирует множество вариантов, где отказ на одном процессоре может замедлить работу многих других процессоров. См. раздел 7 Томас, Дэвид Б.; Хоуз, Ли В.; Люк, Уэйн (2009), «Сравнение процессоров, графических процессоров, FPGA и массивов процессоров с массовым параллелизмом для генерации случайных чисел», Чоу, Пол; Чунг, Питер Ю.К. (ред.), Труды 17-го Международного симпозиума ACM/SIGDA по программируемым вентильным матрицам, FPGA 2009, Монтерей, Калифорния, США, 22–24 февраля 2009 г. , Ассоциация вычислительной техники , стр. 63–72 , CiteSeerX 10.1.1.149.6066 , doi : 10.1145/1508128.1508139 , ISBN 9781605584102 , S2CID 465785 .