5.3 Método de Alias
Se basa en representar la distribución de \(X\) como una mixtura (uniforme) de variables dicotómicas (Walker, 1977): \[Q^{(i)}=\left\{ \begin{array}{ll} x_{i} & \text{con prob. } q_{i} \\ x_{a_{i}} & \text{con prob. } 1-q_{i} \end{array} \ \right.\]
Hay varias formas de construir las tablas de probabilidades \(q_i\) y de alias \(a_i\). Se suele emplear el denominado algoritmo “Robin Hood” de inicialización (Kronmal y Peterson, 1979). La idea es “tomar prestada” parte de la probabilidad de los valores más probables (ricos) para asignársela a los valores menos probables (pobres), recordando el valor de donde procede (almacenando el índice en \(a_i\)).
Algoritmo 5.4 ("Robin Hood" de inicialización; Kronmal y Peterson, 1979)
Desde \(i=1\) hasta \(n\) hacer \(q_{i}=np_{i}\).
Establecer \(L=\left\{ l:q_{l}<1\right\}\) y \(H=\left\{ h:q_{h}\geq 1\right\}\).
Si \(L\) ó \(H\) vacios terminar.
Seleccionar \(l\in L\) y \(h\in H\).
Hacer \(a_{l}=h\).
Eliminar \(l\) de \(L\).
Hacer \(q_{h}=q_{h}-\left( 1-q_{l}\right)\).
Si \(q_{h}<1\) mover \(h\) de \(H\) a \(L\).
Ir al paso 3.
El algoritmo para generar las simulaciones es el estándar del método de composición:
Algoritmo 5.5 (método alias de simulación; Walker, 1977)
Generar \(U,V\sim \mathcal{U}\left( 0,1\right)\).
Hacer \(i=\left\lfloor nU\right\rfloor +1\).
Si \(V<q_{i}\) devolver \(X=x_{i}\).
En caso contrario devolver \(X=x_{a_{i}}\).
Este algoritmo es muy eficiente y es el empleado en la función sample()
de R18.
Este método también está implementado en la función simres::rpmf.alias()
(fichero rpmf.R), empleando código R menos eficiente:
rpmf.alias
## function(x, prob = 1/length(x), n = 1000, as.factor = FALSE) {
## # Inicializar tablas
## a <- numeric(length(x))
## q <- prob*length(x)
## low <- q < 1
## high <- which(!low)
## low <- which(low)
## while (length(high) && length(low)) {
## l <- low[1]
## h <- high[1]
## a[l] <- h
## q[h] <- q[h] - (1 - q[l])
## if (q[h] < 1) {
## high <- high[-1]
## low[1] <- h
## } else low <- low[-1]
## } # while
## # Generar valores
## V <- runif(n)
## i <- floor(runif(n)*length(x)) + 1
## X <- x[ ifelse( V < q[i], i, a[i]) ]
## if(as.factor) X <- factor(X, levels = x)
## return(X)
## }
## <bytecode: 0x00000000389e75f0>
## <environment: namespace:simres>
Ejemplo 5.4 (Simulación de una binomial mediante en método de Alias)
Repetimos la simulación del Ejemplo 5.1 anterior empleando esta rutina.
set.seed(1)
system.time( rx <- rpmf.alias(x, pmf, nsim) )
## user system elapsed
## 0.02 0.00 0.02
Análisis de los resultados:
<- table(rx)/nsim
res plot(res, ylab = "frecuencia relativa", xlab = "valores")
points(x, pmf, pch = 4, col = "blue") # Comparación teórica
R implementa este algoritmo en el fichero fuente random.c (para muestreo probabilístico con reemplazamiento, función C
walker_ProbSampleReplace()
), aunque el paso 2 del algoritmo de simulación empleado por defecto cambió ligeramente a partir de la versión 3.6.0 para evitar posibles problemas de redondeo (ver Sección 1.3.1).↩︎