¿Cómo genero números de acuerdo con una distribución de Soliton?

10

La distribución de Soliton es una distribución de probabilidad discreta sobre un conjunto con la función de masa de probabilidad{1,,N}

p(1)=1N,p(k)=1k(k1)for k{2,,N}

Me gustaría usarlo como parte de una implementación de un código LT , idealmente en Python, donde hay disponible un generador uniforme de números aleatorios.

Alex Chamberlain
fuente

Respuestas:

9

Si comenzamos en , el telescopio suma, dando para el CDF (modificado). Invertir esto y ocuparse del caso especial proporciona el siguiente algoritmo (codificado , me temo, pero puede tomarlo como pseudocódigo para una implementación de Python):1 - 1 / k k = 1k=211/kk=1R

rsoliton <- function(n.values, n=2) {
  x <- runif(n.values)         # Uniform values in [0,1)
  i <- ceiling(1/x)            # Modified soliton distribution
  i[i > n] <- 1                # Convert extreme values to 1
  i
}

Como ejemplo de su uso (y una prueba), dibujemos valores para : N = 10105N=10

n.trials <- 10^5
i <- rsoliton(n.trials, n=10)
freq <- table(i) / n.trials  # Tabulate frequencies
plot(freq, type="h", lwd=6)

Distribución de frecuencias

whuber
fuente
1
Para la distribución de solitones "robusta" relacionada, probablemente tenga que conformarse con una solución ligeramente menos eficiente (basada en una búsqueda binaria o su equivalente).
whuber
¿Cómo se te ocurrió eso tan rápido?
Alex Chamberlain
2
@Alex Chamberlain porque es bueno: D
gui11aume
7

Python (adaptado de la solución R de @ whuber )

from __future__ import print_function, division                                           
import random                                                                   
from math import ceil                                                           

def soliton(N, seed):                                                           
  prng = random.Random()                                                        
  prng.seed(seed)                                                                  
  while 1:                                                                         
    x = random.random() # Uniform values in [0, 1)                                 
    i = int(ceil(1/x))       # Modified soliton distribution                            
    yield i if i <= N else 1 # Correct extreme values to 1                         

if __name__ == '__main__':                                                         
  N = 10                                                                           
  T = 10 ** 5 # Number of trials                                                   
  s = soliton(N, s = soliton(N, random.randint(0, 2 ** 32 - 1)) # soliton generator                   
  f = [0]*N                       # frequency counter                              
  for j in range(T):                                                               
    i = next(s)                                                                    
    f[i-1] += 1                                                                    

  print("k\tFreq.\tExpected Prob\tObserved Prob\n");                               

  print("{:d}\t{:d}\t{:f}\t{:f}".format(1, f[0], 1/N, f[0]/T))                     
  for k in range(2, N+1):                                                          
    print("{:d}\t{:d}\t{:f}\t{:f}".format(k, f[k-1], 1/(k*(k-1)), f[k-1]/T))

Salida de muestra

k   Freq.   Expected Prob   Observed Prob

1   9965    0.100000    0.099650
2   49901   0.500000    0.499010
3   16709   0.166667    0.167090
4   8382    0.083333    0.083820
5   4971    0.050000    0.049710
6   3354    0.033333    0.033540
7   2462    0.023810    0.024620
8   1755    0.017857    0.017550
9   1363    0.013889    0.013630
10  1138    0.011111    0.011380

Requisitos

El código debería funcionar en Python 2 o 3.

Alex Chamberlain
fuente
+1 Gracias por compartir la traducción de Python. ¡Bienvenido a nuestro sitio!
whuber
Sin preocupaciones. Si obtengo códigos LT funcionando, estarán en GitHub.
Alex Chamberlain
1
Implementación de @whuber LT ahora en GitHub . No es perfecto, pero es un comienzo.
Alex Chamberlain