Алгоритм для генерации случайных чисел Пуассона и биномиальных?
-
12-09-2019 - |
Вопрос
Я смотрел вокруг, но я не уверен, как это сделать.
я обнаружил эта страница Что в последнем абзаце говорит:
Простой генератор для случайных чисел, взятых из распределения Пуассона, получается с использованием этого простого рецепта: если x1, Икс2, ... - это последовательность случайных чисел с равномерным распределением между нулем и одним, k - первое целое число, для которого продукт x1 · Икс2 · ... · ИксK+1 <e-λ
я обнаружил другая страница Описывая, как генерировать биномиальные числа, но я думаю, что он использует приближение поколения Пуассона, что мне не помогает.
Например, рассмотрим биномиальные случайные числа. Биномиальное случайное число - это количество голов в n броска монеты с вероятностью p голов на любом броске. Если вы генерируете n равномерные случайные числа на интервале (0,1) и считаете число меньше P, то число является биномиальным случайным числом с параметрами n и p.
Я знаю, что есть библиотеки, чтобы сделать это, но я не могу их использовать, только стандартные унифицированные генераторы, предоставленные языком (Java, в данном случае).
Решение
распределение Пуассона
Вот Как Википедия говорит, что Кнут говорит, чтобы сделать это:
init:
Let L ← e^(−λ), k ← 0 and p ← 1.
do:
k ← k + 1.
Generate uniform random number u in [0,1] and let p ← p × u.
while p > L.
return k − 1.
На Java это будет:
public static int getPoisson(double lambda) {
double L = Math.exp(-lambda);
double p = 1.0;
int k = 0;
do {
k++;
p *= Math.random();
} while (p > L);
return k - 1;
}
Биномиальное распределение
Пройдя по главе 10 Неоднородное генерация случайного варианта (PDF) Люк Деврой (который я нашел связан Статья Википедии) дает это:
public static int getBinomial(int n, double p) {
int x = 0;
for(int i = 0; i < n; i++) {
if(Math.random() < p)
x++;
}
return x;
}
Пожалуйста, обрати внимание
Ни один из этих алгоритмов не является оптимальным. Первый - O (λ), второй - O (n). В зависимости от того, насколько велики эти значения, и как часто вам нужно вызывать генераторы, вам может понадобиться лучший алгоритм. В статье, на которую я ссылаюсь выше, есть более сложные алгоритмы, которые работают в постоянное время, но я оставлю эти реализации в качестве упражнения для читателя. :)
Другие советы
Для этого и других численных задач Библия является книгой численных рецептов.
Здесь есть бесплатная версия для C: http://www.nrbook.com/a/bookcpdf.php (плагин требуется)
Или вы можете увидеть это в книгах Google: http://books.google.co.uk/books?id=4t-sybvuoqoc&lpg=pp1&ots=5ihminlhho&dq=numeric%20recipes%20in%20c&pg=pp1#v=onepage&q=&f=false
Код C должен быть очень легко перевести на Java.
Эта книга стоит вес в золоте для множества численных проблем. На приведенном выше сайте вы также можете купить последнюю версию книги.
Хотя ответ, опубликованный KIP, совершенно действителен для создания RVS Poisson с небольшим количеством прибывающих (Lambda), второй алгоритм, размещенный в Википедии Генерирование случайных переменных Пуассона лучше для большей скорости прибытия из -за численной стабильности.
Я столкнулся с проблемами во время реализации одного из проектов, требующих поколения Пуассона RV с очень высокой Lambda из -за этого. Поэтому я предлагаю другой путь.
В следующей библиотеке есть несколько реализаций CERN (код Java):
http://acs.lbl.gov/~hoschek/colt/
Что касается биномиальных случайных чисел, он основан на статье от 1988 года «Биномиальное генерация случайного вариата», которую я рекомендую вам, поскольку они используют оптимизированный алгоритм.
С Уважением
Вы можете добавить это в build.gradle
implementation 'org.kie.modules:org-apache-commons-math:6.5.0.Final'
и использовать класс Распределение Пуассона Более подробная информация для класса -пусководов