Pregunta

He estado mirando a su alrededor, pero no estoy seguro de cómo hacerlo.

He encontrado esta página que, en el último párrafo, dice:

Se obtiene un generador simple para números aleatorios tomados de una distribución de Poisson utilizando esta receta simple: si x1, X2, ... es una secuencia de números aleatorios con distribución uniforme entre cero y uno, k es el primer entero para el que el producto X1 · X2 · ... · XK+1 <e

He encontrado otra página Describiendo cómo generar números binomiales, pero creo que está usando una aproximación de la generación de Poisson, lo que no me ayuda.

Por ejemplo, considere números aleatorios binomiales. Un número aleatorio binomial es el número de cabezas en n lanzamientos de una moneda con probabilidad P de una cabezal en cualquier lanzamiento. Si genera n números aleatorios uniformes en el intervalo (0,1) y cuenta el número menor que P, entonces el recuento es un número aleatorio binomial con los parámetros n y p.

Sé que hay bibliotecas para hacerlo, pero no puedo usarlas, solo los generadores uniformes estándar proporcionados por el lenguaje (Java, en este caso).

¿Fue útil?

Solución

distribución de veneno

Aquí es Cómo Wikipedia dice que Knuth dice que lo haga:

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.

En Java, eso sería:

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

Distribución binomial

Pasando por el Capítulo 10 de Generación variada aleatoria no uniforme (PDF) por Luc Devroye (que encontré vinculado el artículo de Wikipedia) da esto:

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

tenga en cuenta

Ninguno de estos algoritmos es óptimo. El primero es o (λ), el segundo es o (n). Dependiendo de cuán grandes sean típicamente estos valores y con qué frecuencia necesite llamar a los generadores, es posible que necesite un mejor algoritmo. El documento al que vinculé anteriormente tiene algoritmos más complicados que se ejecutan en un tiempo constante, pero dejaré esas implementaciones como un ejercicio para el lector. :)

Otros consejos

Para este y otros problemas numéricos, la Biblia es el libro de recetas numéricas.

Hay una versión gratuita para C aquí: http://www.nrbook.com/a/bookcpdf.php (Requerido el complemento)

O puedes verlo en Google Books: http://books.google.co.uk/books?id=4t-sybvuoqoc&lpg=pp1&ots=5ihminlhho&dq=numerical%20recipes%20in%20C&pg=pp1#v=onepage&q=&f=false

El código C debería ser muy fácil de transferir a Java.

Este libro vale su peso en oro para muchos problemas numéricos. En el sitio anterior también puede comprar la última versión del libro.

Aunque la respuesta publicada por KIP es perfectamente válida para generar RV de Poisson con una pequeña tasa de llegadas (Lambda), el segundo algoritmo publicado en Wikipedia Generando variables aleatorias de Poisson es mejor para una mayor tasa de llegadas debido a la estabilidad numérica.

Me enfrenté a los problemas durante la implementación de uno de los proyectos que requieren la generación de Poisson RV con Lambda muy alta debido a esto. Entonces sugiero lo contrario.

Hay varias implementaciones de CERN en la siguiente biblioteca (código Java):

http://acs.lbl.gov/~hoschek/colt/

Con respecto a los números aleatorios binomiales, se basa en el documento de 1988 "generación variada binomial aleatoria", que le recomiendo, ya que usan un algoritmo optimizado.

Saludos

Puedes agregar esto a Build.gradle

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

y usar clase Distribución de veneno Más detalles para la clase PoisDistribution

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top