Генерация Пуассона Прибытие на Яву - PullRequest
2 голосов
/ 23 марта 2012

Я хотел бы создать функцию на Java, которая генерирует прибытия Пуассона, учитывая среднюю скорость прибытия (лямбда) и среднюю скорость обслуживания (мю).

В моем примере у меня есть: 2,2 запроса /день, другими словами 2,2 прибытия / день и среднее время обслуживания 108 часов.Учитывая, что моя программа начинается с t = 0 минут, я хотел бы создать функцию, которая возвращает Arrivals [], которая будет содержать t1, t2 и возможный t3.T1, t2 и t3 - моменты (в минутах) в течение дня, когда происходят эти прибытия.У меня есть следующие ограничения:

t1 < t2 < t3 < 1440 minutes (24 hours*60 minutes/hour)

t2-t1 > 108 minutes

t3-t2 > 108 minutes

t3+ 108 minutes < 1440 minutes

Может кто-топожалуйста, помогите мне?

Спасибо,

Ана

Ответы [ 4 ]

5 голосов
/ 23 марта 2012

Вы можете использовать этот алгоритм, предложенный Д. Кнутом :

private static int getPoissonRandom(double mean) {
    Random r = new Random();
    double L = Math.exp(-mean);
    int k = 0;
    double p = 1.0;
    do {
        p = p * r.nextDouble();
        k++;
    } while (p > L);
    return k - 1;
}

Чтобы понять, как это работает, обратите внимание, что после k итераций условие цикла становится

p 1 * p 2 * ... * p k > L

что эквивалентно

-ln (p 1 ) / среднее -ln (p 2 ) / среднее ... -ln (p k ) / среднее> 1

Обратите внимание, что если p равномерно распределено, то -ln (p) / среднее значение имеет экспоненциальное распределение с заданным средним значением. Случайная переменная с пуассоновским распределением равна числу случаев, когда данное событие происходит в фиксированном интервале, когда длины интервалов между событиями являются независимыми случайными величинами с экспоненциальным распределением. Поскольку мы используем среднее значение распределения Пуассона в качестве среднего экспоненциального распределения для интервалов между событиями, фиксированное внутреннее число, в котором мы считаем события, является единицей длины. Таким образом, условие цикла суммирует длины интервалов между событиями и проверяет, вышли ли мы за единичный интервал. Если при подсчете k-го события мы превысили единичный интервал, то в этом интервале произошли k-1 события, поэтому мы возвращаем k-1.

2 голосов
/ 01 ноября 2012

Я нашел это решение, используя выборку с обратным преобразованием:

http://preshing.com/20111007/how-to-generate-random-timings-for-a-poisson-process

Он не использует подход выборки с отбраковкой, эффективен и точен.

Этоиспользует тот факт, что распределение времени между событиями является экспоненциальным распределением с параметром lambda, который является скоростью поступления.Экспоненциальное распределение - лямбда-эксп (-lambda x).Чтобы выбрать значения из этого распределения и избежать выборки отклонения, проще использовать функцию накопительного распределения (CDF): 1 - exp (-lambda x).CDF - это функция, которая начинается с 0,0 и увеличивается до 1,0 с параметрами larget.Интуитивно понятно, что вероятность того, что вы получите событие, увеличивается с течением времени.

Чтобы произвести выборку CDF и снова избежать выборки отклонения, проще выбрать равномерное случайное число U между [0,1] и довставьте это значение в обратную функцию CDF, которая дает: nextEvent = - Ln (U) / lambda.Поскольку Ln (0) не определено, и большинство генераторов случайных чисел включают 0.0 и исключают 1.0, безопаснее использовать: nextEvent = -Ln (1.0-U) / lambda.Если ваш код использует миллисекундную функцию времени / сна, вы можете использовать:

double rate = 20.0 / 1000.0;// в среднем 20 в секунду

sleep (floor (-1.0 * log (1.0 - rand () * 1.0 / RAND_MAX) / rate));

0 голосов
/ 17 мая 2019

Вы можете добавить это в build.gradle

implementation 'org.kie.modules:org-apache-commons-math:6.5.0.Final'

и используйте класс PoissonDistribution подробнее

0 голосов
/ 23 марта 2012

Вот некоторый упрощенный код для генерации номера Пуассона с заданным средним значением:

private static int poisson(double mean) {
    int r = 0;
    double a = random.nextDouble();
    double p = Math.exp(-mean);

    while (a > p) {
        r++;
        a = a - p;
        p = p * mean / r;
    }
    return r;
}

Вы должны иметь возможность использовать это или что-то подобное для генерации номеров вашего прибытия для каждого периода времени: ввод должен бытьсреднее число поступлений, которое вы ожидаете в течение периода.

Обратите внимание, что если ваше среднее значение очень велико (скажем, 500+), вы захотите вместо этого приблизить число поступлений с нормальным распределением.Это более эффективно, плюс это позволяет избежать проблем с переполнением чисел, присущих приведенному выше коду (в какой-то момент Math.exp (-mean) округляется до нуля ...... ooops!)

...