Ceci est une généralisation du fameux problème d'anniversaire : étant donné n=100 individus qui ont des "anniversaires" aléatoires et uniformément répartis parmi un ensemble de d=6 possibilités, quelle est la probabilité qu'aucun anniversaire ne soit partagé par plus de m=20 individus?
Un calcul exact donne la réponse (à double précision). Je vais esquisser la théorie et fournir le code général n , m , d . La synchronisation asymptotique du code est O ( n 2 log ( d ) ), ce qui le rend approprié pour un très grand nombre d'anniversaires d et fournit des performances raisonnables jusqu'à ce que n soit des milliers. À ce stade, l'approximation de Poisson discutée lors de l'extension du paradoxe d'anniversaire à plus de 2 personnesdevrait bien fonctionner dans la plupart des cas.0.267747907805267n,m,d.O(n2log(d))dn
Explication de la solution
La fonction de génération de probabilité (PGF) pour les résultats des bobines indépendantes de d à flancs Diend
d−nfn(x1,x2,…,xd)=d−n(x1+x2+⋯+xd)n.
Le coefficient de dans l'expansion de ce multinomial donne le nombre de façons dont la face i peut apparaître exactement e i fois, i = 1 , 2 , … , d .xe11xe22⋯xeddieii=1,2,…,d.
Limiter notre intérêt à pas plus de apparitions par n'importe quel visage revient à évaluer f n modulo l'idéal I généré par x m + 1 1 , x m + 1 2 , … , x m + 1 d . Pour effectuer cette évaluation, utilisez le théorème binomial récursivement pour obtenirmfnIxm+11,xm+12,…,xm+1d.
Fn( x1, … , Xré)= ( ( x1+ ⋯ + xr) + ( xr + 1+ xr + 2+ ⋯ + x2 r) )n= ∑k = 0n( nk) (x1+ ⋯ + xr)k( xr + 1+ ⋯ + x2 r)n - k= ∑k = 0n( nk) fk( x1, … , Xr) fn - k( xr + 1, … , X2 r)
lorsque est pair. En écrivant f ( d ) n = f n ( 1 , 1 , … , 1 ) ( d termes), on aré= 2 rF( d)n= fn( 1 , 1 , … , 1 )ré
F( 2 r )n= ∑k = 0n( nk) f( r )kF( r )n - k.(une)
Lorsque est impair, utilisez une décomposition analogued=2r+1
fn(x1,…,xd)=((x1+⋯+x2r)+x2r+1)n=∑k=0n(nk)fk(x1,…,x2r)fn−k(x2r+1),
donnant
f(2r+1)n=∑k=0n(nk)f(2r)kf(1)n−k.(b)
Dans les deux cas, nous pouvons également réduire tout qui est modulo I , ce qui est facile à réaliser en commençant parI
fn(xj)≅{xn0n≤mn>mmodI,
fournir les valeurs de départ pour la récursivité,
f(1)n={10n≤mn>m
Ce qui rend cela efficace, c'est qu'en divisant les variables en deux groupes de variables r de taille égale chacune et en définissant toutes les valeurs des variables à 1 , nous n'avons qu'à tout évaluer une fois pour un groupe, puis à combiner les résultats. Cela nécessite de calculer jusqu'à n + 1 termes, chacun d'eux nécessitant un calcul O ( n ) pour la combinaison. Nous n'avons même pas besoin d'un tableau 2D pour stocker le f ( r ) n , car lors du calcul de f ( d ) n , seulement fdr1 ,n + 1O ( n )F( r )nF( d)n, etf ( 1 ) n sont requis.F( r )nF( 1 )n
Le nombre total d'étapes est inférieur de un au nombre de chiffres de l'expansion binaire de (qui compte les divisions en groupes égaux dans la formule ( a ) ) plus le nombre de celles de l'expansion (qui compte toutes les fois une impaire est rencontrée, nécessitant l'application de la formule ( b ) ). Ce n'est encore que des étapes O ( log ( d ) ) .ré( A )( B )O ( log( d) )
Sur R
un poste de travail vieux de dix ans, le travail a été effectué en 0,007 secondes. Le code est répertorié à la fin de cet article. Il utilise des logarithmes des probabilités, plutôt que les probabilités elles-mêmes, pour éviter d'éventuels débordements ou accumuler trop de débordements. Cela permet de supprimer le facteur dans la solution afin que nous puissions calculer les comptes qui sous-tendent les probabilités.ré- n
Notez que cette procédure aboutit au calcul de la séquence entière des probabilités à la fois, ce qui nous permet facilement d'étudier comment les chances changent avec n .F0, f1, … , Fnn
Applications
La distribution dans le problème d'anniversaire généralisé est calculée par la fonction tmultinom.full
. Le seul défi consiste à trouver une limite supérieure pour le nombre de personnes qui doivent être présentes avant que les chances d'une collision ne deviennent trop grandes. Le code suivant le fait par force brute, en commençant par un petit n et en le doublant jusqu'à ce qu'il soit suffisamment grand. L'ensemble du calcul prend donc O ( n 2 log ( n ) log ( d ) ) temps où n est la solution. La distribution entière des probabilités pour le nombre de personnes jusqu'à n est calculée.m + 1nO ( n2Journal( n ) journal( d) )nn
#
# The birthday problem: find the number of people where the chance of
# a collision of `m+1` birthdays first exceeds `alpha`.
#
birthday <- function(m=1, d=365, alpha=0.50) {
n <- 8
while((p <- tmultinom.full(n, m, d))[n] > alpha) n <- n * 2
return(p)
}
À titre d'exemple, le nombre minimum de personnes nécessaires dans une foule pour qu'il soit plus probable qu'improbable qu'au moins huit d'entre elles partagent un anniversaire est de , comme le révèle le calcul . Cela ne prend que quelques secondes. Voici un tracé d'une partie de la sortie:798birthday(7)
Une version spéciale de ce problème est abordée dans Etendre le paradoxe de l'anniversaire à plus de 2 personnes , ce qui concerne le cas d'un dé faces qui est lancé un très grand nombre de fois.365
Code
# Compute the chance that in `n` independent rolls of a `d`-sided die,
# no side appears more than `m` times.
#
tmultinom <- function(n, m, d, count=FALSE) tmultinom.full(n, m, d, count)[n+1]
#
# Compute the chances that in 0, 1, 2, ..., `n` independent rolls of a
# `d`-sided die, no side appears more than `m` times.
#
tmultinom.full <- function(n, m, d, count=FALSE) {
if (n < 0) return(numeric(0))
one <- rep(1.0, n+1); names(one) <- 0:n
if (d <= 0 || m >= n) return(one)
if(count) log.p <- 0 else log.p <- -log(d)
f <- function(n, m, d) { # The recursive solution
if (d==1) return(one) # Base case
r <- floor(d/2)
x <- double(f(n, m, r), m) # Combine two equal values
if (2*r < d) x <- combine(x, one, m) # Treat odd `d`
return(x)
}
one <- c(log.p*(0:m), rep(-Inf, n-m)) # Reduction modulo x^(m+1)
double <- function(x, m) combine(x, x, m)
combine <- function(x, y, m) { # The Binomial Theorem
z <- sapply(1:length(x), function(n) { # Need all powers 0..n
z <- x[1:n] + lchoose(n-1, 1:n-1) + y[n:1]
z.max <- max(z)
log(sum(exp(z - z.max), na.rm=TRUE)) + z.max
})
return(z)
}
x <- exp(f(n, m, d)); names(x) <- 0:n
return(x)
}
La réponse est obtenue avec
print(tmultinom(100,20,6), digits=15)
0,267747907805267