मैं यहाँ परिभाषित नीले क्षेत्र से नमूने उत्पन्न करना चाहता हूँ:
भोली समाधान इकाई वर्ग में अस्वीकृति नमूने का उपयोग करना है, लेकिन यह केवल (~ 21.4%) दक्षता प्रदान करता है।
क्या कोई तरीका है जिससे मैं और अधिक कुशलता से नमूना ले सकता हूं?
मैं यहाँ परिभाषित नीले क्षेत्र से नमूने उत्पन्न करना चाहता हूँ:
भोली समाधान इकाई वर्ग में अस्वीकृति नमूने का उपयोग करना है, लेकिन यह केवल (~ 21.4%) दक्षता प्रदान करता है।
क्या कोई तरीका है जिससे मैं और अधिक कुशलता से नमूना ले सकता हूं?
जवाबों:
क्या प्रति सेकंड दो मिलियन अंक मिलेंगे?
वितरण सममित है: हमें केवल पूर्ण वृत्त के एक-आठवें भाग के लिए वितरण की आवश्यकता है और फिर इसे अन्य अष्टकों के आसपास कॉपी करें। ध्रुवीय निर्देशांक में , कोण की संचयी बंटन Θ यादृच्छिक स्थान के लिए ( एक्स , वाई ) मूल्य पर θ त्रिकोण के बीच के क्षेत्र द्वारा दिया जाता है ( 0 , 0 ) , ( 1 , 0 ) , ( 1 , तन θ ) और से विस्तार वृत्त के चाप ( के लिए ( क्योंकि θ , पाप θ ) । यह आनुपातिक है
जिसका घनत्व है
हम इस घनत्व से नमूनाकरण कर सकता है का उपयोग करते हुए, कहते हैं, एक अस्वीकृति विधि (जो दक्षता )।
रेडियल समन्वय की सशर्त घनत्व के लिए आनुपातिक है आर डी आर के बीच आर = 1 और आर = सेकंड θ । यह सीडीएफ के एक आसान उलटा के साथ नमूना लिया जा सकता है।
यदि हम स्वतंत्र नमूने उत्पन्न , रूपांतरण वापस कार्तीय निर्देशांक के लिए ( एक्स मैं , y मैं ) नमूने इस ओक्टांट। क्योंकि नमूने स्वतंत्र हैं, यादृच्छिक रूप से निर्देशांक की अदला-बदली करने से वांछित के रूप में पहले क्वाड्रंट से एक स्वतंत्र यादृच्छिक नमूना उत्पन्न होता है। (यादृच्छिक स्वैपों को स्वैप करने के लिए कितने बोधों को निर्धारित करने के लिए केवल एक द्विपद चर बनाने की आवश्यकता होती है।)
से प्रत्येक इस तरह के अहसास , की आवश्यकता है औसत, एक समान variate पर (के लिए आर ) प्लस 1 / ( 8 π - 2 ) बार दो वर्दी (के लिए variates Θ ) और (तेज) गणना की एक छोटी राशि। ऐसा इसलिए है 4 / ( π - 4 ) ≈ 4.66 बिंदु (जो, ज़ाहिर है, दो निर्देशांक) प्रति variates। पूर्ण विवरण नीचे दिए गए कोड उदाहरण में हैं। यह आंकड़ा उत्पन्न एक आधे मिलियन से अधिक अंकों में से 10,000 प्लॉट करता है।
यहाँ वह R
कोड है जिसने इस सिमुलेशन का निर्माण किया और इसे समयबद्ध किया।
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")
मैं निम्नलिखित समाधान प्रस्तावित करता हूं, जो अब तक @cardinal, @whuber और @ stephan-kolassa द्वारा अन्य soutions की तुलना में सरल, अधिक कुशल और / या कम्प्यूटेशनल रूप से सस्ता होना चाहिए।
इसमें निम्नलिखित सरल चरण शामिल हैं:
इस एल्गोरिथ्म के पीछे अंतर्ज्ञान चित्र में दिखाया गया है।
चरण 2a और 2b को एक ही चरण में मिलाया जा सकता है:
2) कतरनी परिवर्तन लागू करें और स्वैप करें
निम्न कोड ऊपर एल्गोरिथ्म को लागू करता है (और @ व्ह्यूसर कोड का उपयोग करके इसका परीक्षण करता है)।
n.sim <- 1e6
x.time <- system.time({
# Draw two standard uniform samples
u_1 <- runif(n.sim)
u_2 <- runif(n.sim)
# Apply shear transformation and swap
tmp <- 1 + sqrt(2)/2 * pmin(u_1, u_2)
x <- tmp - u_2
y <- tmp - u_1
# Reject if inside circle
accept <- x^2 + y^2 > 1
x <- x[accept]
y <- y[accept]
n <- length(x)
})
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")
कुछ त्वरित परीक्षण निम्नलिखित परिणाम देते हैं।
एल्गोरिथ्म /stats//a/258349 । 3 का सर्वश्रेष्ठ: 0.33 सेकंड प्रति मिलियन अंक।
यह एल्गोरिथ्म। 3 का सर्वश्रेष्ठ: 0.18 सेकंड प्रति मिलियन अंक।
खैर, अधिक कुशलता से किया जा सकता है, लेकिन मुझे यकीन है कि उम्मीद है कि आप तेजी से नहीं देख रहे हैं ।
वोल्फ्रम आपको एकीकृत करने में मदद करता है :
अगर आप कुछ सोच-समझकर निवेश करते हैं तो आप शायद CDF को थोड़ा बहुत उलटा कर सकते हैं। फिर सोचती है, दर्द होता है। मैं व्यक्तिगत रूप से अस्वीकृति नमूने के लिए जाऊंगा, जो तेज और बहुत कम त्रुटि वाला है, जब तक कि मेरे पास बहुत अच्छे कारण नहीं थे।
epsilon <- 1e-6
xx <- seq(0,1,by=epsilon)
x.cdf <- function(x) x-(x*sqrt(1-x^2)+asin(x))/2
xx.cdf <- x.cdf(xx)/x.cdf(1)
nn <- 1e4
rr <- matrix(nrow=nn,ncol=2)
set.seed(1)
pb <- winProgressBar(max=nn)
for ( ii in 1:nn ) {
setWinProgressBar(pb,ii,paste(ii,"of",nn))
x <- max(xx[xx.cdf<runif(1)])
y <- runif(1,sqrt(1-x^2),1)
rr[ii,] <- c(x,y)
}
close(pb)
plot(rr,pch=19,cex=.3,xlab="",ylab="")