Est-ce que deux millions de points par seconde suffiront?
La distribution est symétrique: il suffit de calculer la distribution pour un huitième du cercle complet, puis de la copier autour des autres octants. En coordonnées polaires , la distribution cumulée de l'angle Θ pour l'emplacement aléatoire( r , θ )Θ à la valeur θ est donnée par l'aire entre le triangle ( 0 , 0 ) , ( 1 , 0 ) , ( 1 , tan θ ) et l'arc de cercle s'étendant de (( X, Y)θ( 0 , 0 ) , ( 1 , 0 ) , ( 1 , bronzageθ) à ( cos θ , sin θ ) . Il est ainsi proportionnel à(1,0)(cosθ,sinθ)
FΘ( θ ) = Pr ( Θ ≤ θ ) ∝ 12bronzer( θ ) - θ2,
d'où sa densité
FΘ( θ ) = dréθFΘ( θ ) ∝ tan2( θ ) .
Nous pouvons échantillonner à partir de cette densité en utilisant, par exemple, une méthode de rejet (qui a une efficacité de ).8 / π- 2 ≈ 54,6479 %
La densité conditionnelle de la coordonnée radiale est proportionnelle à r d r entre r = 1 et r = sec θ . Cela peut être échantillonné avec une inversion facile du CDF.Rr drr = 1r = secθ
Si nous générons des échantillons indépendants , la conversion en coordonnées cartésiennes ( x i , y i ) échantillonne cet octant. Du fait que les échantillons sont indépendants, un échange aléatoire des coordonnées produit un échantillon aléatoire indépendant du premier quadrant, comme souhaité. (Les échanges aléatoires nécessitent de générer une seule variable binomiale pour déterminer le nombre de réalisations à échanger.)( rje, θje)( xje, yje)
Chacune de ces réalisations de nécessite, en moyenne, une variable uniforme (pour R ) plus 1 / ( 8 π( X, Y)R fois deux variables uniformes (pour Θ ) et une petite quantité de calcul (rapide). C'est 4 / ( π - 4 ) ≈ 4,66 varie par point (qui, bien sûr, a deux coordonnées). Tous les détails sont dans l'exemple de code ci-dessous. Ce chiffre représente 10 000 des plus d'un demi-million de points générés.1 / ( 8 π- 2 )Θ4/(π−4)≈4.66
Voici le R
code qui a produit cette simulation et l'a chronométré.
n.sim <- 1e6
x.time <- system.time({
# Generate trial angles `theta`
theta <- sqrt(runif(n.sim)) * pi/4
# Rejection step.
theta <- theta[runif(n.sim) * 4 * theta <= pi * tan(theta)^2]
# Generate radial coordinates `r`.
n <- length(theta)
r <- sqrt(1 + runif(n) * tan(theta)^2)
# Convert to Cartesian coordinates.
# (The products will generate a full circle)
x <- r * cos(theta) #* c(1,1,-1,-1)
y <- r * sin(theta) #* c(1,-1,1,-1)
# Swap approximately half the coordinates.
k <- rbinom(1, n, 1/2)
if (k > 0) {
z <- y[1:k]
y[1:k] <- x[1:k]
x[1:k] <- z
}
})
message(signif(x.time[3] * 1e6/n, 2), " seconds per million points.")
#
# Plot the result to confirm.
#
plot(c(0,1), c(0,1), type="n", bty="n", asp=1, xlab="x", ylab="y")
rect(-1, -1, 1, 1, col="White", border="#00000040")
m <- sample.int(n, min(n, 1e4))
points(x[m],y[m], pch=19, cex=1/2, col="#0000e010")