Consideremos una generalización de este problema. Existenm=4 latas de pintura de m=4 colores distintos y n(0)=100pelotas. latai puede aguantar hasta a(0)i=(100,100,50,75)pelotas. Desea generar configuraciones de bolas en las latas que tienen al menosbi=(0,50,0,25) bolas en lata i para cada i, cada configuración con igual probabilidad.
Dichas configuraciones están en correspondencia uno a uno con las configuraciones obtenidas después de eliminar bi bolas de lata i, limitando el n=n(0)−∑ibi=100−(0+50+0+25)=25 bolas restantes a lo sumo ai=a(0)i−bi=(100,50,50,50)por lata. Por lo tanto, solo generaré estos y te dejaré ajustarlos después (poniendobi bolas de vuelta en lata i para cada i)
Para contar estas configuraciones, arregle todos menos dos de los índices, digamos i y j. Supongamos que haysk bolas ya en lata k para cada k diferente de i y j. Eso dejasi+sjpelotas. Condicional a donde el otron−(si+sj)las bolas son, estas se distribuyen uniformemente dentro de latasi y j. Las configuraciones posibles son1+min(ai+aj−si−sj,si+sj) en número (ver los comentarios), que van desde colocar tantas bolas en la lata i como sea posible a través de la colocación de tantas bolas en la lata j como sea posible.
Si lo desea, puede contar el número total de configuraciones aplicando este argumento de forma recursiva al resto m−2latas Sin embargo, para obtener muestras ni siquiera necesitamos saber este recuento. Todo lo que necesitamos hacer es visitar repetidamente todos los pares desordenados posibles{i,j}de latas y al azar (y de manera uniforme) cambian la distribución de las bolas dentro de esas dos latas. Esta es una cadena de Markov con una distribución de probabilidad limitante que es uniforme en todos los estados posibles (como se muestra fácilmente usando métodos estándar). Por lo tanto, es suficiente comenzar en cualquier estado, ejecutar la cadena el tiempo suficiente para alcanzar la distribución limitante y luego realizar un seguimiento de los estados visitados por este procedimiento. Como de costumbre, para evitar la correlación en serie, esta secuencia de estados debe "diluirse" saltando a través de ellos (o revisada al azar). El adelgazamiento por un factor de aproximadamente la mitad del número de latas tiende a funcionar bien, porque después de eso, en promedio, muchos pasos se han visto afectados, produciendo una configuración realmente nueva.
Este algoritmo cuesta O(m)esfuerzo para generar cada configuración aleatoria en promedio. Aunque otroO(m) existen algoritmos, este tiene la ventaja de no necesitar hacer cálculos combinatorios de antemano.
Como ejemplo, resolvamos una situación más pequeña manualmente. Dejara=(4,3,2,1) y n=3, por ejemplo. Hay 15 configuraciones válidas, que pueden escribirse como cadenas de números de ocupación. Por ejemplo, 0201
coloca dos bolas en la segunda lata y una bola en la cuarta lata. Emulando el argumento, consideremos la ocupación total de las dos primeras latas. Cuando eso ess1+s2=3bolas, no quedan bolas para las dos últimas latas. Eso le da a los estados
30**, 21**, 12**, 03**
donde **
representa a todos los posibles números de ocupación para las dos últimas latas: a saber, 00
. Cuandos1+s2=2, los estados son
20**, 11**, 02**
donde ahora **
puede ser cualquiera 10
o 01
. Eso da3×2=6más estados Cuandos1+s2=1, los estados son
10**, 01**
donde ahora **
puede estar 20
, 11
pero no 02
(debido al límite de una bola en la última lata). Eso da2×2=4más estados Finalmente cuandos1+s2=0, todas las bolas están en las dos últimas latas, que deben estar llenas hasta el límite de 2 y 1. los4+6+4+1=15 estados igualmente probables por lo tanto son
3000, 2100, 1200, 0300; 2010, 2001, 1110, 1101, 0210, 0201; 1020, 1011, 0120, 0111; 0021.
Usando el siguiente código, una secuencia de 10,009 tales configuraciones fueron generadas y reducidas a cada tercio, creando 3337 configuraciones de la 15estados. Sus frecuencias fueron las siguientes:
State: 3000 2100 1200 0300 2010 1110 0210 1020 0120 2001 1101 0201 1011 0111 0021
Count: 202 227 232 218 216 208 238 227 237 209 239 222 243 211 208
UNA χ2 prueba de uniformidad da un χ2 valor de 11.2, p=0.67 (14 grados de libertad): es un hermoso acuerdo con la hipótesis de que este procedimiento produce estados igualmente probables.
Este R
código está configurado para manejar la situación en la pregunta. Cambiar a
y n
trabajar con otras situaciones. Establezca N
que sea lo suficientemente grande como para generar la cantidad de realizaciones que necesita después del adelgazamiento .
Este código engaña un poco al recorrer sistemáticamente todos (i,j)pares. Si quieres ser estrictos sobre la ejecución de la cadena de Markov, generar i
, j
y ij
al azar, como se da en el código comentado.
#
# Gibbs-like sampler.
#
# `a` is an array of maximum numbers of balls of each type. Its values should
# all be integers greater than zero.
# `n` is the total number of balls.
#------------------------------------------------------------------------------#
g <- function(j, state, a) {
#
# `state` contains the occupancy numbers.
# `a` is the array of maximum occupancy numbers.
# `j` is a pair of indexes into `a` to "rotate".
#
k <- sum(state[j]) # Total occupancy.
x <- floor(runif(1, max(0, k - a[j[2]]), min(k, a[j[1]]) + 1))
state[j] <- c(x, k-x)
return(state)
}
#
# Set up the problem.
#
a <- c(100, 50, 50, 50)
n <- 25
# a <- 4:1
# n <- 3
#
# Initialize the state.
#
state <- round(n * a / sum(a))
i <- 1
while (sum(state) < n) {
if (state[i] < a[i]) state[i] <- state[i] + 1
i <- i+1
}
while (sum(state) > n) {
i <- i-1
if (state[i] > 0) state[i] <- state[i] - 1
}
#
# Conduct a sequence of random changes.
#
set.seed(17)
N <- 1e5
sim <- matrix(state, ncol=1)
u <- ceiling(N / choose(length(state), 2) / 2)
i <- rep(rep(1:length(state), each=length(state)-1), u)
j <- rep(rep(length(state):1, length(state)-1), u)
ij <- rbind(i, j)
#
# Alternatively, generate `ij` randomly:
# i <- sample.int(length(state), N, replace=TRUE)
# j <- sample.int(length(state)-1, N, replace=TRUE)
# ij <- rbind(i, ((i+j-1) %% length(state))+1)
#
sim <- cbind(sim, apply(ij, 2, function(j) {state <<- g(j, state, a); state}))
rownames(sim) <- paste("Can", 1:nrow(sim))
#
# Thin them for use. Each column is a state.
#
thin <- function(x, stride=1, start=1) {
i <- round(seq(start, ncol(x), by=stride))
x[, i]
}
#
# Make a scatterplot of the results, to illustrate.
#
par(mfrow=c(1,1))
s <- thin(sim, stride=max(1, N/1e4))
pairs(t(s) + runif(length(s), -1/2, 1/2), cex=1/2, col="#00000005", pch=16)