Reichen zwei Millionen Punkte pro Sekunde aus?
Die Verteilung ist symmetrisch: Wir müssen die Verteilung nur für ein Achtel des vollen Kreises berechnen und dann um die anderen Oktanten kopieren. In Polarkoordinaten ist die kumulative Verteilung des Winkels Θ für den zufälligen Ort ( X , Y ) beim Wert θ durch die Fläche zwischen den Dreiecken ( 0 , 0 ) , ( 1 , 0 ) , ( 1 , tan θ ) und der Kreisbogen von (( r , θ )Θ( X, Y)θ(0,0),(1,0),(1,tanθ) bis ( cos θ , sin θ ) . Es ist dabei proportional zu(1,0)(cosθ,sinθ)
FΘ(θ)=Pr(Θ≤θ)∝12tan(θ)−θ2,
woher seine Dichte ist
fΘ(θ)=ddθFΘ(θ)∝tan2(θ).
Wir können aus dieser Dichte beispielsweise eine Rückweisungsmethode (mit einem Wirkungsgrad von ) entnehmen .8/π−2≈54.6479%
Die bedingte Dichte der Radialkoordinate ist proportional zu r d r zwischen r = 1 und r = sec θ . Das kann mit einer einfachen Inversion der CDF abgetastet werden.Rrdrr=1r=secθ
Wenn wir unabhängige Abtastwerte erzeugen , tastet die Umwandlung in kartesische Koordinaten ( x i , y i ) diesen Oktanten ab. Da die Abtastwerte unabhängig sind, wird durch zufälliges Vertauschen der Koordinaten je nach Wunsch ein unabhängiger Zufallsabtastwert aus dem ersten Quadranten erzeugt. (Für die zufälligen Auslagerungen muss nur eine einzige Binomialvariable generiert werden, um zu bestimmen, wie viele Realisierungen ausgetauscht werden müssen.)(ri,θi)(xi,yi)
Jede solche Realisierung von erforderlich ist , im Durchschnitt einer einheitlichen Veränderlichen (für R ) sowie 1 / ( 8 π - 2 ) mal zwei einheitliches variates (für Θ ) und eine geringe Menge (schnell) Berechnung. Das sind 4 / ( π - 4 ) ≈ 4,66 Variationen pro Punkt (der natürlich zwei Koordinaten hat). Vollständige Details finden Sie im folgenden Codebeispiel. Diese Zahl zeigt 10.000 von mehr als einer halben Million generierten Punkten.(X,Y)R1 / ( 8 π- 2 )Θ4 / ( π- 4 ) ≈ 4.66
Hier ist der R
Code, der diese Simulation erstellt und zeitgesteuert hat.
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")