James E. Gentle (2003) in Random Number Generation and Monte Carlo Methods describes the following algorithm for random generation from multivariate hypergeometric distribution:
To generate a multivariate hypergeometric random deviate, a simple way is to work with the marginals. The generation is done sequentially. Each succeeding conditional marginal is hypergeometric. To generate the deviate, combine all classes except the first in order to form just two classes. Next, generate a univariate hypergeometric deviate $x_1$. Then remove the first class and form two classes consisting of the second one and the third through the last combined, and generate a univariate hypergeometric deviate based on $N − x_1$ draws. This gives $x_2$, the number of the second class. Continue in this manner until the number remaining to be drawn is $0$ or until the classes are exhausted. For efficiency, the first marginal used would be the one with the largest probability.
This procedure however seems to give biased results for the class that is at the end of the queue, since it is possible to sample only from what is left from the previous draws, or am I mistaken? Is there any better way of sampling from this distribution?
Below I paste the naive implementation of the algorithm:
rng_mvhyper <- function(n, k) {
N <- sum(n)
m <- length(n)
n_otr <- N - n[1]
x <- rhyper(1, n[1], n_otr, k)
for (i in 2:m) {
n_otr <- n_otr - n[i]
k <- k - x[i-1]
x[i] <- rhyper(1, n[i], n_otr, k)
}
x
}
And the results of simulation:
> table(replicate(1e6, which.max(rng_mvhyper(c(2,2,2), 4))))
1 2 3
400246 333303 266451
While classes have the same size in the population, being in the beginning of the queue seems to make values of such class more common in the sample drawn.