Сгенерируйте случайное число в пределах диапазона, используя распределение Пуассона

Мне нужно распределение Пуассона.

В настоящее время у меня есть следующий код:

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;
}

Мне было интересно, как я могу изменить его так, чтобы я мог генерировать x значений в пределах определенного диапазона, то есть, если a = 5, b = 10 и lambda = 6, все сгенерированные значения будут находиться в диапазоне от 5 до 10 .

Примечание. Я мог бы перегрузить метод и, таким образом, принять параметры диапазона и вызвать метод getPossion внутри цикла; отбрасывая все, что не соответствует этому диапазону. Однако я хотел бы проверить, существуют ли математически определенные средства для достижения этого и/или подходит ли этот подход.

РЕДАКТИРОВАТЬ: средства, с помощью которых я отбрасываю значения «вне границ»:

public static int getPoisson(final double min, final double max, final double lambda) {
    int k = 0;
    do {
        k = getPoisson(lambda);
    } while (k < min || k > max);
    return k;
}

person Dan    schedule 09.02.2019    source источник


Ответы (1)


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

Какой-то псевдокод:

public class BoundedSampler {
  private final int min;
  private final double[] table;

  public BoundedSampler(int min, int max, double lambda) {
    this.min = min;
    this.table = new double[max - min + 1];

    double cumulative = 0;
    for(int x = min; x <= max; ++x) {
      double prob = probability(x, lambda);
      table[x - min] = cumulative + prob;
      cumulative += prob;
    }

    for(int i = 0; i < table.length; ++i) {
      table[i] /= cumulative;
    }
  }

  public int sample() {
    double r = Math.random();
    for(int i = 0; i < table.length; ++i) {
      if(table[i] <= r) {
        return i + min;
      }
    }
    return -1; // impossible: last table value == 1
  }
}

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

person Nikolay    schedule 09.02.2019
comment
Что это за алгоритм? - person Dan; 10.02.2019
comment
Заглушка кода для выборки псевдослучайных чисел из конечного дискретного распределения с помощью линейного поиска. - person Nikolay; 10.02.2019
comment
К сожалению, это должен быть алгоритмом Пуассона. Я опубликую текущую реализацию, которую я качаю, чтобы вы могли ее проверить. - person Dan; 10.02.2019
comment
Если должно быть пуассоновское распределение (и min, max, lambda фиксированы на некоторое время), функция probability может быть реализована как PDF для пуассона. Основная идея состоит в том, чтобы заменить бесконечное распределение пуассонов конечным ограниченным пуассонов. Я могу предоставить несколько полезных ссылок: mathworld.wolfram.com/PoissonDistribution.html -- формулы в формате PDF. github.com/apache/commons-rng/blob/master/commons-rng-sampling/ -- реализация для очень больших средств. Если это должен быть алгоритм - ваш код хорош. - person Nikolay; 11.02.2019
comment
Итак, чтобы сгенерировать значение из распределения Пуассона, я должен реализовать ограниченный алгоритм PDF? Если да, то есть ли какие-либо источники для достижения этого, или я должен реализовать формулы вручную? - person Dan; 12.02.2019