एक सर्कल के भीतर एक यादृच्छिक बिंदु बनाएं (समान रूप से)


212

मुझे त्रिज्या आर के एक सर्कल के भीतर एक समान यादृच्छिक बिंदु उत्पन्न करने की आवश्यकता है ।

मुझे लगता है कि केवल अंतराल [0 ... 2,) में समान रूप से यादृच्छिक कोण उठाकर, और अंतराल में समान रूप से यादृच्छिक त्रिज्या (0 ... R ) मैं केंद्र की ओर अधिक बिंदुओं के साथ समाप्त होगा, क्योंकि दो दिए गए हैं त्रिज्या, छोटे त्रिज्या के बिंदु बड़े त्रिज्या के बिंदुओं की तुलना में एक दूसरे के करीब होंगे।

मुझे यहाँ पर इस पर एक ब्लॉग प्रविष्टि मिली लेकिन मुझे उसका तर्क समझ में नहीं आया। मुझे लगता है कि यह सही है, लेकिन मैं वास्तव में यह समझना चाहूंगा कि वह कहां से (2 / आर 2 ) × आर और कैसे वह अंतिम समाधान निकालता है।


अपडेट: इस सवाल को पोस्ट करने के 7 साल बाद भी मुझे स्क्वायर रूट एल्गोरिथ्म के पीछे के गणित के बारे में वास्तविक सवाल पर संतोषजनक जवाब नहीं मिला। इसलिए मैंने एक दिन स्वयं उत्तर लिखने में बिताया। मेरा उत्तर करने के लिए लिंक


18
क्या रिजेक्शन सैंपलिंग की खामी वाकई बहुत बड़ी बात है? आवश्यक कोशिशों की अपेक्षित संख्या 4 / π, 1.27 है, और आपको k कोशिशों से अधिक जिस संभावना की आवश्यकता है, वह है (1-(/ 4) ^ k। के लिए कश्मीर = 20 , इस ≈ .00000000000004 है और कश्मीर = 50 के लिए यह 10 ^ के आदेश पर है {- 34}। आप उन बाधाओं को किसी भी दिन ले सकते हैं; तुम ठीक करोगे
श्रीवत्सआर

3
दरअसल, अस्वीकृति नमूनाकरण समाप्ति के लिए गारंटी प्रदान करता है। ऑड्स असीम रूप से कम (सटीक, शून्य होने के लिए) हैं कि आपका एल्गोरिथ्म कभी समाप्त नहीं होगा।
जेरेड नील्सन

2
मेरी राय में, अस्वीकृति नमूने की खामी का महत्व नमूना पद्धति का उपयोग करने में आसानी के लिए आनुपातिक है जो अस्वीकृति से बचा जाता है। इस मामले में, खामी महत्वपूर्ण है क्योंकि अस्वीकृति के बिना नमूना सरल है।
spex

4
@spex व्यवहार में, अस्वीकृति तकनीक तेज होती है क्योंकि यह पारलौकिक कार्य मूल्यांकन की आवश्यकता से बचती है।
पीजे

2
(cont) अस्वीकृति: 0.52s सभी ने समान साधन और मानक विचलन (3 sig। अंजीर को) दिया। जैसा कि अपेक्षित था, अस्वीकृति का नमूना 27% समय (4 / pi-1) में विफल रहा, इसलिए इसे btilly की तुलना में 27% अधिक यादृच्छिक संख्याओं की आवश्यकता थी लेकिन सिगफ़ेप से 15% कम। यह पीजे और अन्य लोगों द्वारा की गई टिप्पणियों की पुष्टि करता है कि अस्वीकृति नमूनाकरण शायद सबसे अच्छा तरीका है, जब तक कि रैंडम उत्पन्न करने के लिए बहुत महंगा न हो।
पीटर डेविडसन

जवाबों:


189

आइए इस तरह से दृष्टिकोण करें जैसे आर्किमिडीज़ के पास होगा।

हम त्रिभुज ABC में समान रूप से एक बिंदु कैसे उत्पन्न कर सकते हैं, कहां | AB | = | BC | आइए एक समांतर चतुर्भुज ABCD तक विस्तार करके इसे आसान बनाते हैं। ABCD में समान रूप से अंक उत्पन्न करना आसान है। हम समान रूप से BC पर AB और Y पर एक यादृच्छिक बिंदु X चुनते हैं और Z को ऐसे चुनते हैं जैसे XBYZ एक समांतर चतुर्भुज है। मूल त्रिकोण में एक समान रूप से चुने गए बिंदु को प्राप्त करने के लिए, हम किसी भी बिंदु को जोड़ते हैं जो एडीसी में एसी के साथ एबीसी में वापस दिखाई देता है।

अब एक वृत्त पर विचार करें। सीमा में हम इसके बारे में सोच सकते हैं कि मूल रूप से बी के साथ कई आइसोक्लेस त्रिकोण एबीसी हैं और परिधि पर ए और सी एक दूसरे के करीब गायब हो जाते हैं। हम इन कोणों में से किसी एक को एक थीटा उठाकर चुन सकते हैं। इसलिए अब हमें स्लिवर ABC में एक बिंदु चुनकर केंद्र से दूरी बनाने की आवश्यकता है। फिर से, एबीसीडी तक विस्तार करें, जहां डी अब सर्कल सेंटर से दो बार त्रिज्या है।

उपरोक्त विधि का उपयोग करके एबीसीडी में एक यादृच्छिक बिंदु चुनना आसान है। AB पर एक यादृच्छिक बिंदु चुनें। समान रूप से बीसी पर एक यादृच्छिक बिंदु चुनें। अर्थात। केंद्र से दूरी देते हुए [0, R] पर समान रूप से x और y की एक जोड़ी चुनें। हमारा त्रिभुज एक पतला टुकड़ा है इसलिए AB और BC अनिवार्य रूप से समानांतर हैं। तो बिंदु Z मूल से बस x + y की दूरी पर है। यदि x + y> R हम वापस नीचे मोड़ते हैं।

यहाँ R = 1 के लिए पूरा एल्गोरिथ्म है। मुझे आशा है कि आप सहमत हैं कि यह बहुत आसान है। यह ट्रिगर का उपयोग करता है, लेकिन आप इस बात की गारंटी दे सकते हैं random()कि अस्वीकृति के नमूने के विपरीत, इसे कितने समय तक और कितनी कॉल की आवश्यकता होगी।

t = 2*pi*random()
u = random()+random()
r = if u>1 then 2-u else u
[r*cos(t), r*sin(t)]

यहां वह गणितज्ञों में है।

f[] := Block[{u, t, r},
  u = Random[] + Random[];
  t = Random[] 2 Pi;
  r = If[u > 1, 2 - u, u];
  {r Cos[t], r Sin[t]}
]

ListPlot[Table[f[], {10000}], AspectRatio -> Automatic]

यहां छवि विवरण दर्ज करें


6
@ केलारजारथ I एक अनंत पतले त्रिभुज की प्रतिरूपात्मक धारणा को पसंद करते हैं जो कि अभी भी एक छोर पर दूसरे की तुलना में व्यापक है :-) इसे सही उत्तर मिलता है।
सिगफैप

2
@hammar यकीन नहीं है कि यह n आयामों के लिए अच्छी तरह से सामान्यीकृत है। लेकिन 3 डी के लिए आप आर्किमिडीज द्वारा एक और परिणाम का उपयोग कर सकते हैं! सिलेंडर पर एक बिंदु (आसान!) उत्पन्न करने के लिए "हैट-बॉक्स" प्रमेय का उपयोग करें और फिर इसे गोले में वापस मैप करें। वह एक दिशा देता है। अब random()+random()+random()कुछ और जटिल फोल्डिंग का उपयोग करें (जैसे कि 6-गुना गुना एक असीम पतले पैरेल्लेपिपेड टू टेराहेड्रोन)। हालांकि यह एक अच्छा तरीका नहीं है।
सिगफैप

2
मैंने सोचा कि 1 मिनट यादृच्छिक () + यादृच्छिक () और 2 * यादृच्छिक () के बीच अंतर जानने के लिए ... मैं बहुत बेवकूफ हूं: /
JiminP

3
@Tharwen ध्यान दें कि कैसे वृत्त में त्रिज्या 0.9-1.0 की तुलना में त्रिज्या 0.0-0.1 पर अधिक अंक हैं। यादृच्छिक () + यादृच्छिक () रेडी 1.0 के आसपास होने की अधिक संभावना उत्पन्न करता है, लेकिन 0.0-2.0 की सीमा में है। जब मुड़े तो वे 1.0 के आसपास और हमेशा 0.0-1.0 के दायरे में रहने की संभावना रखते हैं। क्या अधिक है, यह इस टिप्पणी के पहले वाक्य में आवश्यक अनुपात है। बस आधा करने से 0.5 अंक के आसपास अधिक संख्या में उत्पादन होता है और यह गलत होगा।
२२:२२ पर सिगफेक

2
@Tharwen यादृच्छिक संख्या उत्पन्न करने और देखने के लिए दोनों योजनाओं का उपयोग करने का प्रयास करें। 2 * यादृच्छिक () 0 से 2. की सीमा में समान रूप से वितरित संख्याओं को देता है। यादृच्छिक () + यादृच्छिक () आपको 0 से 2 की सीमा में नंबर देता है, लेकिन वहाँ (आमतौर पर) 1.0 के पास 0.0 या 2.0 के मुकाबले अधिक संख्या होगी। यह ऐसा है कि कैसे दो पासा और समागम को रोल करना किसी अन्य संख्या की तुलना में 7 देने की अधिक संभावना है।
20

133

त्रिज्या R के एक वृत्त के भीतर एक यादृच्छिक बिंदु कैसे उत्पन्न करें :

r = R * sqrt(random())
theta = random() * 2 * PI

(मान लें random()कि 0 और 1 के बीच समान रूप से एक मान देता है)

यदि आप इसे कार्टेशियन निर्देशांक में बदलना चाहते हैं, तो आप कर सकते हैं

x = centerX + r * cos(theta)
y = centerY + r * sin(theta)


क्यों sqrt(random())?

आइए उस गणित को देखें जो आगे बढ़ता है sqrt(random())। सादगी के लिए मान लें कि हम यूनिट सर्कल यानी R = 1 के साथ काम कर रहे हैं ।

अंकों के बीच की औसत दूरी समान होनी चाहिए, भले ही हम केंद्र से कितनी दूर दिखते हों। उदाहरण के लिए, इसका मतलब है कि परिधि 2 के साथ एक वृत्त की परिधि को देखते हुए हमें परिधि 1 के साथ एक वृत्त की परिधि पर बिंदुओं की संख्या के दोगुने अंक प्राप्त करने चाहिए।


                

के बाद से एक चक्र (2π की परिधि आर ) के साथ रैखिक बढ़ता आर , यह इस प्रकार है कि यादृच्छिक अंकों की संख्या के साथ रैखिक बढ़ने चाहिए आर । दूसरे शब्दों में, वांछित संभावना घनत्व फ़ंक्शन (पीडीएफ) रैखिक रूप से बढ़ता है। चूंकि पीडीएफ में 1 के बराबर क्षेत्र और अधिकतम त्रिज्या 1 होना चाहिए, हमारे पास है


                

इसलिए हम जानते हैं कि हमारे यादृच्छिक मूल्यों का वांछित घनत्व कैसा दिखना चाहिए। अब: हम कैसे इस तरह के एक यादृच्छिक मूल्य उत्पन्न करते हैं जब हमारे पास 0 और 1 के बीच एक समान यादृच्छिक मूल्य होता है?

हम एक ट्रिक का उपयोग करते हैं जिसे उलटा ट्रांसफॉर्मिंग सैंपलिंग कहा जाता है

  1. PDF से, संचयी वितरण फ़ंक्शन (CDF) बनाएं
  2. इसे y = x के साथ मिरर करें
  3. परिणामी फ़ंक्शन को 0 और 1 के बीच एक समान मूल्य पर लागू करें।

जटिल लगता है? मुझे एक छोटी सी साइड ट्रैक के साथ एक ब्लॉकक्वाइन डालें जो अंतर्ज्ञान को व्यक्त करता है:

मान लें कि हम निम्नलिखित वितरण के साथ एक यादृच्छिक बिंदु उत्पन्न करना चाहते हैं:

                

अर्थात्

  • 1 और 2 के बीच समान रूप से 1/5 अंक, और
  • 2 और 3 के बीच समान रूप से 4/5 अंक।

सीडीएफ, जैसा कि नाम से पता चलता है, पीडीएफ का संचयी संस्करण है। Intuitively: पीडीएफ (जबकि एक्स ) यादृच्छिक मानों की संख्या का वर्णन करता है एक्स पर , CDF ( एक्स ) यादृच्छिक मानों की संख्या का वर्णन करता है एक्स की तुलना में कम

इस मामले में CDF ऐसा दिखेगा:

                

यह देखने के लिए कि यह कैसे उपयोगी है, कल्पना कीजिए कि हम समान रूप से वितरित ऊंचाइयों पर बाएं से दाएं गोलियां मारते हैं। जैसे ही गोलियां रेखा से टकराईं, वे नीचे जमीन पर गिर गईं:

                

देखें कि जमीन पर गोलियों का घनत्व हमारे वांछित वितरण के अनुरूप कैसे है! हम बस पहुँच गए!

समस्या यह है कि इस फ़ंक्शन के लिए, y अक्ष आउटपुट है और x अक्ष इनपुट है । हम केवल "जमीन से गोलियां सीधे गोली मार सकते हैं"! हमें उलटा फ़ंक्शन चाहिए!

यही कारण है कि हम पूरी बात को प्रतिबिंबित करते हैं; x बनता है y और y बनता है x :

                

हम इसे CDF -1 कहते हैं । वांछित वितरण के अनुसार मान प्राप्त करने के लिए, हम सीडीएफ -1 (यादृच्छिक ()) का उपयोग करते हैं।

… इसलिए, यादृच्छिक त्रिज्या मान उत्पन्न करने के लिए जहां हमारा पीडीएफ 2 x के बराबर है ।

चरण 1: सीडीएफ बनाएं:

चूंकि हम वास्तविक के साथ काम कर रहे हैं, सीडीएफ को पीडीएफ के अभिन्न अंग के रूप में व्यक्त किया गया है।

CDF ( x ) = = 2 x = x 2

चरण 2: CDF को y = x के साथ मिरर करें :

गणितीय इस अदला-बदली करने पर निर्भर करता है x और y और के लिए सुलझाने y :

CDF :      y = x 2
स्वैप:    x = y 2
हल:    y = F x
CDF -1 :   y = x x

चरण 3: परिणामी फ़ंक्शन को 0 और 1 के बीच एक समान मूल्य पर लागू करें

CDF -1 (यादृच्छिक ()) = (random ()

जिसे हमने :-) प्राप्त करने के लिए निर्धारित किया है


इस एल्गोरिदम का उपयोग रिंग पर कुशलता से अंक बनाने के लिए किया जा सकता है।
इवान कोवटन

रिंग पर? एक निश्चित दायरे के साथ की तरह? यकीन नहीं होता कि मैं आपके प्रश्न को समझ पा रहा हूं, लेकिन यदि आपके पास एक निश्चित त्रिज्या है, तो आपको बस कोण को यादृच्छिक बनाने की आवश्यकता है।
एरियोबे

2
मैंने अन्नुलस के बजाय सरल शब्द "रिंग" का उपयोग करने की कोशिश की - दो संकेंद्रित हलकों से घिरा क्षेत्र। इस मामले में अस्वीकृति एल्गोरिदम प्रभावी नहीं होता है और पहले शीर्ष एल्गोरिथ्म को सामान्य बनाना मुश्किल है। और एक त्रिज्या के साथ कोने का मामला भी आपके एल्गोरिथ्म के साथ कवर किया गया है। हम हमेशा त्रिज्या (रैंडम (min_radius ^ 2, max_radius ^ 2)) को min_radius == max_radius के रूप में भी उत्पन्न करते हैं।
इवान कोवटन

1
ओह अच्छा! स्पष्ट होने के लिए, जब आप कहते हैं random(min_radius², max_radius²), तो क्या आप का मतलब समान है random() * (max_radius² - min_radius²) + min_radius², जहां random()0 और 1 के बीच एक समान मूल्य देता है?
ऐयोबे

हां, इसका ठीक यही अर्थ है: त्रिज्या = sqrt (यादृच्छिक) (* (max_radius² - min_radius_) + min_radius²)।
इवान कोवटन

27

यहाँ एक तेज और सरल उपाय है।

श्रेणी (0, 1) में दो यादृच्छिक संख्याएँ चुनें, अर्थात् aऔर b। अगर b < a, उन्हें स्वैप करें। अपनी बात है (b*R*cos(2*pi*a/b), b*R*sin(2*pi*a/b))

आप इस समाधान के बारे में इस प्रकार सोच सकते हैं। यदि आपने सर्कल लिया है, तो इसे काटें, फिर इसे सीधा कर दें, आपको एक समकोण त्रिभुज मिलेगा। स्केल कि त्रिकोण नीचे, और आप से एक त्रिकोण होगा (0, 0)करने के लिए (1, 0)करने के लिए (1, 1)करने के लिए और फिर से वापस (0, 0)। ये सभी परिवर्तन घनत्व को समान रूप से बदलते हैं। आपने जो किया है, वह त्रिभुज में समान रूप से एक यादृच्छिक बिंदु उठाया है और सर्कल में एक बिंदु प्राप्त करने के लिए प्रक्रिया को उलट दिया है।


यह किसी कारण से, मुझे स्वीकृत उत्तर की तुलना में अधिक समान वितरण देता है, हालांकि मुझे त्रिज्या द्वारा समन्वय को विभाजित करने की आवश्यकता थी, अन्यथा यह आर ^ 2 के एक सर्कल के अंदर है
ग्रेग ज़ाल

3
धन्यवाद, यह जावा में आपका कोड है, शायद कोई इसे उपयोगी पाएगा: फ्लोट random1 = MathUtils.random (); फ्लोट random2 = MathUtils.random (); फ्लोट randomXPoint = random2 * त्रिज्या MathUtils.cos (MathUtils.PI2 * random1 / random2); फ्लोट randomYPoint = random2 * त्रिज्या MathUtils.sin (MathUtils.PI2 * random1 / random1);
टोनी सर्लावा

बहुत अच्छा! मुझे अंकों के केंद्रीकरण के लिए अधिक संभावना का विचार पसंद है, इसलिए यदि हम इसे प्राप्त नहीं कर पाते हैं तो हम स्वैप नहीं करते हैं b < a! उदाहरण के लिए javascript jsfiddle.net/b0sb5ogL/1
Guilherme

मुझे लगता है कि आपका समाधान बुरा है। यह समान रूप से परिणाम नहीं दे रहा है। इस स्क्रीनशॉट की जांच करें prntscr.com/fizxgc
bolec_kolec

4
क्या आप थोड़ा और समझा सकते हैं कि सर्कल को कैसे काटें और इसे सीधा करें?
kec

21

नोट आनुपातिक में बिंदु घनत्व त्रिज्या के वर्ग व्युत्क्रम, इसलिए बजाय उठा के rसे [0, r_max], से ले [0, r_max^2], तो के रूप में अपने निर्देशांक की गणना:

x = sqrt(r) * cos(angle)
y = sqrt(r) * sin(angle)

यह आपको डिस्क पर एक समान बिंदु वितरण देगा।

http://mathworld.wolfram.com/DiskPointPicking.html


12

इस तरह से इसके बारे में सोचो। यदि आपके पास एक आयत है जहां एक अक्ष त्रिज्या है और एक कोण है, और आप इस आयत के अंदर के बिंदुओं को लेते हैं जो कि त्रिज्या के पास हैं। 0. ये सभी मूल के बहुत करीब होंगे (जो कि वृत्त पर एक साथ करीब है।) हालांकि। त्रिज्या आर के पास के बिंदु, ये सभी चक्र के किनारे (यानी एक दूसरे से बहुत दूर) के पास गिरेंगे।

यह आपको कुछ विचार दे सकता है कि आपको यह व्यवहार क्यों मिल रहा है।

उस लिंक पर प्राप्त होने वाला कारक आपको बताता है कि सर्कल में मैप किए जाने के बाद आयत में संबंधित क्षेत्र को त्रिज्या पर निर्भर न होने के लिए समायोजित करने की आवश्यकता है।

संपादित करें: तो आपके द्वारा साझा किए गए लिंक में वह क्या लिखता है, "यह संचयी वितरण के व्युत्क्रम की गणना करने के लिए काफी आसान है, और हम आर के लिए प्राप्त करते हैं:"।

मूल आधार यहां है कि आप वांछित संभाव्यता घनत्व फ़ंक्शन के संचयी वितरण फ़ंक्शन के उलटा फ़ंक्शन द्वारा वर्दी को मैप करके एक समान वितरण से एक वांछित वितरण के साथ एक चर बना सकते हैं। क्यों? बस इसे अभी के लिए मान लें, लेकिन यह एक सच्चाई है।

यहाँ गणित के बारे में मेरी कुछ सहज व्याख्या है। R के संबंध में घनत्व फ़ंक्शन f (r) को स्वयं r के समानुपाती होना चाहिए। इस तथ्य को समझना किसी भी मूल कैलकुलस पुस्तकों का हिस्सा है। ध्रुवीय क्षेत्र तत्वों पर अनुभाग देखें। कुछ अन्य पोस्टरों ने इसका उल्लेख किया है।

तो हम इसे f (r) = C * r कहेंगे;

यह अधिकांश काम के लिए निकला। अब, चूँकि f (r) एक प्रायिकता घनत्व होना चाहिए, आप आसानी से देख सकते हैं कि अंतराल (0, R) पर f (r) को एकीकृत करके आप C = 2 / R ^ 2 प्राप्त करते हैं (यह पाठक के लिए एक अभ्यास है) ।)

इस प्रकार, एफ (आर) = 2 * आर / आर ^ 2

ठीक है, ताकि आप लिंक में सूत्र कैसे प्राप्त करें।

फिर, अंतिम भाग वर्दी यादृच्छिक चर u (0,1) से जा रहा है, आपको इस वांछित घनत्व f (r) से संचयी वितरण फ़ंक्शन के व्युत्क्रम फ़ंक्शन द्वारा मैप करना होगा। यह समझने के लिए कि यह ऐसा मामला है जिसे आपको शायद पापुलिस जैसा एक उन्नत संभावना पाठ खोजने की आवश्यकता है (या इसे स्वयं प्राप्त करें)।

एफ (आर) को एकीकृत करने से आपको एफ (आर) = आर ^ 2 / आर ^ 2 मिलता है

इसका उलटा कार्य खोजने के लिए आप u = r ^ 2 / R ^ 2 को सेट करें और फिर r को हल करें, जो आपको r = R * sqrt (u) देता है।

यह पूरी तरह से सहज ज्ञान युक्त भी बनाता है, यू = 0 को आर = 0. के लिए मैप करना चाहिए। इसके अलावा, आर = आर के लिए यू 1 शुडल मैप। इसके अलावा, यह स्क्वायर रूट फ़ंक्शन द्वारा जाता है, जो समझ में आता है और लिंक से मेल खाता है।


10

भोले समाधान काम नहीं करता है इसका कारण यह है कि यह सर्कल सेंटर के करीब बिंदुओं को एक उच्च संभावना घनत्व देता है। दूसरे शब्दों में जिस वृत्त में त्रिज्या r / 2 है, उसमें किसी बिंदु के चयनित होने की प्रायिकता r / 2 है, लेकिन इसका क्षेत्रफल (अंकों की संख्या) pi * r ^ 2/4 है।

इसलिए हम चाहते हैं कि एक त्रिज्या संभाव्यता घनत्व निम्नलिखित संपत्ति हो:

किसी त्रिज्या के छोटे या एक दिए गए आर के बराबर चुनने की संभावना त्रिज्या आर के साथ सर्कल के क्षेत्र के लिए आनुपातिक है। (क्योंकि हम बिंदुओं पर एक समान वितरण चाहते हैं और बड़े क्षेत्रों में अधिक अंक का मतलब है)

दूसरे शब्दों में, हम चाहते हैं कि [0, r] के बीच एक दायरा चुनने की संभावना सर्कल के समग्र क्षेत्र के अपने हिस्से के बराबर हो। कुल वृत्त क्षेत्र pi * R ^ 2 है, और त्रिज्या r के साथ वृत्त का क्षेत्रफल pi * r ^ 2 है। इस प्रकार हम [0, r] के बीच एक त्रिज्या चुनने की संभावना को पसंद करेंगे (pi * r ^ 2) / (pi * R ^ 2) = r ^ 2 / R ^ 2।

अब गणित आता है:

[0, r] के बीच एक त्रिज्या चुनने की संभावना 0 से r तक p (r) dr का अभिन्न अंग है (यह सिर्फ इसलिए है क्योंकि हम छोटे त्रिज्या की सभी संभावनाओं को जोड़ते हैं)। इस प्रकार हम अभिन्न (पी (आर) डॉ) = आर ^ 2 / आर ^ 2 चाहते हैं। हम स्पष्ट रूप से देख सकते हैं कि R ^ 2 एक स्थिर है, इसलिए हम सभी को यह पता लगाने की जरूरत है कि कौन सा p (r) है, जब एकीकृत हमें r ^ 2 जैसा कुछ देगा। उत्तर स्पष्ट रूप से आर * स्थिर है। अभिन्न (आर * निरंतर डॉ) = आर ^ 2/2 * निरंतर। यह r ^ 2 / R ^ 2 के बराबर होना है, इसलिए निरंतर = 2 / R ^ 2। इस प्रकार आपके पास संभावना वितरण p (r) = r * 2 / R ^ 2 है

नोट: समस्या के बारे में सोचने का एक और अधिक सहज तरीका यह कल्पना करना है कि आप परिधि के प्रत्येक वृत्त को उसके परिधि पर मौजूद अंकों के अनुपात के बराबर देने की कोशिश कर रहे हैं। इस प्रकार एक वृत्त जिसके त्रिज्या r है उसकी परिधि पर 2 * pi * r "अंक" होंगे। अंकों की कुल संख्या pi * R ^ 2 है। इस प्रकार आपको (2 * pi * r) / (pi * R ^ 2) = 2 * r / R ^ 2 के बराबर सर्कल ra प्रायिकता देनी चाहिए। यह समझना बहुत आसान है और अधिक सहज ज्ञान युक्त है, लेकिन यह गणितीय रूप से ध्वनि नहीं है।


9

आज्ञा देना Let (त्रिज्या) और φ (azimuth) सर्कल के भीतर एक मनमाना बिंदु के ध्रुवीय निर्देशांक के अनुरूप दो यादृच्छिक चर हैं। यदि अंक समान रूप से वितरित किए जाते हैं तो ρ और ly का विस्थापन समारोह क्या है?

किसी भी r के लिए: 0 <r <R त्रिज्या की संभावना ρ कम है तो r समन्वय है

P [ρ <r] = P [बिंदु त्रिज्या r के एक वृत्त के भीतर है] = S1 / S0 = (r / R) 2

जहाँ S1 और S0 क्रमशः त्रिज्या r और R के वृत्त के क्षेत्र हैं। तो सीडीएफ के रूप में दिया जा सकता है:

          0          if r<=0
  CDF =   (r/R)**2   if 0 < r <= R
          1          if r > R

और पीडीएफ:

PDF = d/dr(CDF) = 2 * (r/R**2) (0 < r <= R).

ध्यान दें कि R = 1 यादृच्छिक चर sqrt (X) के लिए जहां X [0, 1) पर समान है, इसमें सटीक CDF है (क्योंकि P [sqrt (X) <y] = P [x <y ** 2] = y * * 2 के लिए 0 <y <= 1)।

Π का वितरण स्पष्ट रूप से 0 से 2 * φ तक एक समान है। अब आप यादृच्छिक ध्रुवीय निर्देशांक बना सकते हैं और त्रिकोणमितीय समीकरणों का उपयोग करके उन्हें कार्टेसियन में बदल सकते हैं:

x = ρ * cos(φ)
y = ρ * sin(φ)

R = 1 के लिए पोस्ट पायथन कोड का विरोध नहीं कर सकते।

from matplotlib import pyplot as plt
import numpy as np

rho = np.sqrt(np.random.uniform(0, 1, 5000))
phi = np.random.uniform(0, 2*np.pi, 5000)

x = rho * np.cos(phi)
y = rho * np.sin(phi)

plt.scatter(x, y, s = 4)

तुम्हे मिल जाएगा

यहां छवि विवरण दर्ज करें


7

यह वास्तव में इस बात पर निर्भर करता है कि 'समान रूप से यादृच्छिक' से आपका क्या मतलब है। यह एक सूक्ष्म बिंदु है और आप विकी पृष्ठ पर इसके बारे में यहां और अधिक पढ़ सकते हैं: http://en.wikipedia.org/wiki/Bertrand_paradox_%28probability%29 , जहां एक ही समस्या, 'समान रूप से यादृच्छिक' के लिए अलग-अलग व्याख्याएं देती है। अलग जवाब!

इस बात पर निर्भर करता है कि आप किस तरह से अंक चुनते हैं, वितरण अलग-अलग हो सकता है, भले ही वे कुछ अर्थों में समान रूप से यादृच्छिक हों ।

ऐसा लगता है कि ब्लॉग प्रविष्टि निम्नलिखित अर्थों में इसे समान रूप से यादृच्छिक बनाने की कोशिश कर रही है: यदि आप एक ही केंद्र के साथ सर्कल के एक उप-सर्कल लेते हैं, तो उस क्षेत्र में बिंदु के क्षेत्र के अनुपात में होने की संभावना क्षेत्र। मेरा मानना ​​है कि, 2 डी क्षेत्रों के लिए 'समान रूप से यादृच्छिक' की अब तक की मानक व्याख्या का पालन करने का प्रयास उन क्षेत्रों के साथ किया गया है : किसी भी क्षेत्र (अच्छी तरह से परिभाषित क्षेत्र) के साथ किसी बिंदु के गिरने की संभावना उस क्षेत्र के क्षेत्र के लिए आनुपातिक है।


5
या यों कहें कि किसी भी मनमाने क्षेत्र में बिंदु गिरने की संभावना क्षेत्र के क्षेत्र के समानुपाती होती है - यह मानते हुए कि क्षेत्र का क्षेत्र है
श्रीवत्सआर

@ श्री: सही है, जो मुझे कोष्ठक में अपने बयान से अभिप्राय है। मैं इसे स्पष्ट कर दूंगा, धन्यवाद। btw, ब्लॉग के बारे में, कोई वास्तविक सबूत नहीं था कि मनमाना क्षेत्र आनुपातिक संभावनाएं देते हैं, इसलिए मैंने इसे इस तरह से वाक्यांश के लिए चुना।

6

numत्रिज्या के एक वृत्त से यादृच्छिक अंक उत्पन्न करने के लिए मेरा पायथन कोड यहाँ है rad:

import matplotlib.pyplot as plt
import numpy as np
rad = 10
num = 1000

t = np.random.uniform(0.0, 2.0*np.pi, num)
r = rad * np.sqrt(np.random.uniform(0.0, 1.0, num))
x = r * np.cos(t)
y = r * np.sin(t)

plt.plot(x, y, "ro", ms=1)
plt.axis([-15, 15, -15, 15])
plt.show()

1
सिर्फ क्यों नहीं r = np.sqrt(np.random.uniform(0.0, rad**2, num))?

4

मुझे लगता है कि इस मामले में ध्रुवीय निर्देशांक का उपयोग समस्या को जटिल करने का एक तरीका है, यह बहुत आसान होगा यदि आप यादृच्छिक बिंदुओं को लंबाई 2R के साथ एक वर्ग में लेते हैं और फिर (x,y)ऐसे बिंदुओं का चयन करते हैं x^2+y^2<=R^2


आपका मतलब है x ^ 2 + y ^ 2 <= R ^ 2 मुझे लगता है।
सिगफ्प

1
यह अस्वीकृति नमूना है। यह ठीक है, लेकिन इसका मतलब यह है कि गणना का समय कुछ भिन्न होता है, जो एक मुद्दा हो सकता है।
स्टीव बेनेट

सभी वर्ग 4-पक्षीय हैं।
xaxxon

यह एल्गोरिथ्म अधिक कुशल है कि कुछ भी जिसमें वर्गमूल या पाप / कॉस कम्प्यूटेशन शामिल हैं। यह वर्ग के 21.5% से कम अंक को अस्वीकार करता है।
इवान कोवटन

3

जावा में समाधान और वितरण उदाहरण (2000 अंक)

public void getRandomPointInCircle() {
    double t = 2 * Math.PI * Math.random();
    double r = Math.sqrt(Math.random());
    double x = r * Math.cos(t);
    double y = r * Math.sin(t);
    System.out.println(x);
    System.out.println(y);
}

वितरण 2000 अंक

प्रीविअस सॉल्यूशन पर आधारित https://stackoverflow.com/a/5838055/5224246 @sigfpe से


2

पहले हम एक cdf उत्पन्न करते हैं [x] जो है

संभावना है कि एक बिंदु सर्कल के केंद्र से दूरी x से कम है। मान लें कि वृत्त का एक त्रिज्या R है।

जाहिर है अगर x शून्य है तो cdf [0] = 0

जाहिर है अगर x R है तो cdf [R] = 1 है

जाहिर है अगर x = r तो cdf [r] = (Pi r ^ 2) / (Pi R ^ 2)

ऐसा इसलिए है क्योंकि सर्कल पर प्रत्येक "छोटे क्षेत्र" को उठाया जाने की समान संभावना है, इसलिए संभावना प्रश्न के क्षेत्र में आनुपातिक है। और सर्कल के केंद्र से दूरी x दिया गया क्षेत्र Pi r ^ 2 है

इसलिए cdf [x] = x ^ 2 / R ^ 2 क्योंकि पाई एक दूसरे को रद्द करते हैं

हमारे पास cdf [x] = x ^ 2 / R ^ 2 है जहाँ x 0 से R तक जाता है

तो हम x के लिए हल करते हैं

R^2 cdf[x] = x^2

x = R Sqrt[ cdf[x] ]

हम अब 0 से 1 तक यादृच्छिक संख्या के साथ cdf को बदल सकते हैं

x = R Sqrt[ RandomReal[{0,1}] ]

आखिरकार

r = R Sqrt[  RandomReal[{0,1}] ];
theta = 360 deg * RandomReal[{0,1}];
{r,theta}

हम ध्रुवीय निर्देशांक प्राप्त करते हैं {0.601168 R, 311.915 deg}


1

त्रिज्या और "त्रिज्या" के पास "अंकों" की संख्या के बीच एक रैखिक संबंध है, इसलिए उसे एक त्रिज्या वितरण का उपयोग करने की आवश्यकता है जो कि त्रिज्या के समान डेटा बिंदुओं की संख्या को rआनुपातिक बनाता है r


1

मैंने एक बार इस विधि का उपयोग किया था: यह पूरी तरह से असत्यापित हो सकता है (अर्थात यह एक बिंदु का उपयोग करता है ताकि इसकी वृहद मंडलियों के लिए अनुपयोगी हो) लेकिन यादृच्छिक वितरण को पर्याप्त प्रदान करता है। आप मैट्रिक्स के निर्माण को छोड़ सकते हैं और यदि आप चाहें तो सीधे आकर्षित कर सकते हैं। विधि एक आयत के सभी बिंदुओं को यादृच्छिक बनाने के लिए है जो सर्कल के अंदर आते हैं।

bool[,] getMatrix(System.Drawing.Rectangle r) {
    bool[,] matrix = new bool[r.Width, r.Height];
    return matrix;
}

void fillMatrix(ref bool[,] matrix, Vector center) {
    double radius = center.X;
    Random r = new Random();
    for (int y = 0; y < matrix.GetLength(0); y++) {
        for (int x = 0; x < matrix.GetLength(1); x++)
        {
            double distance = (center - new Vector(x, y)).Length;
            if (distance < radius) {
                matrix[x, y] = r.NextDouble() > 0.5;
            }
        }
    }

}

private void drawMatrix(Vector centerPoint, double radius, bool[,] matrix) {
    var g = this.CreateGraphics();

    Bitmap pixel = new Bitmap(1,1);
    pixel.SetPixel(0, 0, Color.Black);

    for (int y = 0; y < matrix.GetLength(0); y++)
    {
        for (int x = 0; x < matrix.GetLength(1); x++)
        {
            if (matrix[x, y]) {
                g.DrawImage(pixel, new PointF((float)(centerPoint.X - radius + x), (float)(centerPoint.Y - radius + y)));
            }
        }
    }

    g.Dispose();
}

private void button1_Click(object sender, EventArgs e)
{
    System.Drawing.Rectangle r = new System.Drawing.Rectangle(100,100,200,200);
    double radius = r.Width / 2;
    Vector center = new Vector(r.Left + radius, r.Top + radius);
    Vector normalizedCenter = new Vector(radius, radius);
    bool[,] matrix = getMatrix(r);
    fillMatrix(ref matrix, normalizedCenter);
    drawMatrix(center, radius, matrix);
}

यहां छवि विवरण दर्ज करें


3
वितरण "यादृच्छिक पर्याप्त" नहीं हैं। वे या तो यादृच्छिक की दी गई परिभाषा के लिए यादृच्छिक हैं या नहीं। आपका उत्तर तिरछा है: आप अपने कोड पर टिप्पणी नहीं करते हैं और न ही यह समझाते हैं कि आप इस पर कैसे पहुंचे। ओब्लिक जवाबों का पालन करना मुश्किल है और भरोसा करना मुश्किल है।
रिचर्ड

1

किसी वृत्त में क्षेत्रफल तत्व dA = rdr * dphi है। अतिरिक्त कारक r ने आपके विचार को बेतरतीब ढंग से ar और phi चुनने के लिए नष्ट कर दिया। जबकि फी को फ्लैट वितरित किया जाता है, आर नहीं है, लेकिन 1 / आर में फ्लैट है (यानी "बैल की आंख" की तुलना में आप सीमा को हिट करने की अधिक संभावना है)।

इसलिए समान रूप से वितरित किए गए बिंदुओं को एक फ्लैट वितरण से आर वितरित करने के लिए और 1 / आर वितरण से आर।

वैकल्पिक रूप से मेहरदाद द्वारा प्रस्तावित मोंटे कार्लो पद्धति का उपयोग करें।

संपादित करें

1 / r में एक यादृच्छिक आर फ्लैट लेने के लिए आप अंतराल [1 / R, अनन्तता] से एक यादृच्छिक x चुन सकते हैं और r = 1 / x की गणना कर सकते हैं। आर तो 1 / आर में फ्लैट वितरित किया जाता है।

एक यादृच्छिक फी की गणना करने के लिए अंतराल से एक यादृच्छिक x चुनें [0, 1] और गणना करें phi = 2 * pi * x।


मैं वास्तव में "1 / r वितरण" से r कैसे चुन सकता हूं ?
21

0

मैं नहीं जानता कि क्या यह प्रश्न अभी भी पहले से दिए गए सभी उत्तर के साथ एक नए समाधान के लिए खुला है, लेकिन मुझे स्वयं उसी प्रश्न का सामना करना पड़ा है। मैंने एक समाधान के लिए खुद के साथ "कारण" करने की कोशिश की, और मुझे एक मिला। यह वैसा ही हो सकता है जैसा कि कुछ लोग पहले ही यहाँ सुझा चुके हैं, लेकिन वैसे भी यहाँ यह है:

सर्कल की सतह के दो तत्वों के बराबर होने के लिए, समान ड्रम मानकर, हमारे पास dtheta1 / dtheta2 = r2 / r1 होना चाहिए। उस तत्व के लिए P (r, थीटा) = P {r1 <r <r1 + dr, theta1 <थीटा <dtheta1} = f (r, थीटा) * dr * thetheta1, और दो को सेट करने की संभावना की अभिव्यक्ति लिखना संभाव्यताएं (r1 और r2 के लिए) बराबर हैं, हम (संभालने वाले आर और थीटा स्वतंत्र हैं) f (r1) / r1 = f (r2) / r2 = स्थिर, जो f (r) = c * r देता है। और बाकी, स्थिर सी का निर्धारण एफ (आर) पर एक पीडीएफ होने की स्थिति से होता है।


Dtheta1 / dtheta2 = r2 / r1 के साथ शुरू करने के लिए दिलचस्प दृष्टिकोण। क्या आप इस बारे में विस्तार से बता सकते हैं कि आप उस समीकरण के साथ कैसे आए?
aioobe

जैसा कि अन्य ने उल्लेख किया है (उदाहरण के लिए, उदाहरण के लिए), एक वृत्त की सतह के एक विभेदक तत्व को r dr dtheta के रूप में दिया गया है , इसलिए यदि हम r1 = r2 मान लेते हैं, तो हमारे पास dr1 * dtheta1 = dr2 * dta2 होगा और शेष इस प्रकार है ।
arsaKasra

0

एक प्रोग्रामर समाधान:

  • एक सा नक्शा (बूलियन मूल्यों का एक मैट्रिक्स) बनाएँ। यह जितना चाहें उतना बड़ा हो सकता है।
  • उस बिट मैप में एक वृत्त बनाएं।
  • सर्कल के बिंदुओं की एक लुकअप तालिका बनाएं।
  • इस लुकअप तालिका में एक यादृच्छिक सूचकांक चुनें।
const int RADIUS = 64;
const int MATRIX_SIZE = RADIUS * 2;

bool matrix[MATRIX_SIZE][MATRIX_SIZE] = {0};

struct Point { int x; int y; };

Point lookupTable[MATRIX_SIZE * MATRIX_SIZE];

void init()
{
  int numberOfOnBits = 0;

  for (int x = 0 ; x < MATRIX_SIZE ; ++x)
  {
    for (int y = 0 ; y < MATRIX_SIZE ; ++y)
    {
      if (x * x + y * y < RADIUS * RADIUS) 
      {
        matrix[x][y] = true;

        loopUpTable[numberOfOnBits].x = x;
        loopUpTable[numberOfOnBits].y = y;

        ++numberOfOnBits;

      } // if
    } // for
  } // for
} // ()

Point choose()
{
  int randomIndex = randomInt(numberOfBits);

  return loopUpTable[randomIndex];
} // ()

बिटमैप केवल तर्क की व्याख्या के लिए आवश्यक है। यह बिटमैप के बिना कोड है:

const int RADIUS = 64;
const int MATRIX_SIZE = RADIUS * 2;

struct Point { int x; int y; };

Point lookupTable[MATRIX_SIZE * MATRIX_SIZE];

void init()
{
  int numberOfOnBits = 0;

  for (int x = 0 ; x < MATRIX_SIZE ; ++x)
  {
    for (int y = 0 ; y < MATRIX_SIZE ; ++y)
    {
      if (x * x + y * y < RADIUS * RADIUS) 
      {
        loopUpTable[numberOfOnBits].x = x;
        loopUpTable[numberOfOnBits].y = y;

        ++numberOfOnBits;
      } // if
    } // for
  } // for
} // ()

Point choose()
{
  int randomIndex = randomInt(numberOfBits);

  return loopUpTable[randomIndex];
} // ()

0

मैं अभी भी सटीक '(2 / R2) × r' के बारे में निश्चित नहीं हूं, लेकिन यह स्पष्ट है कि दी गई इकाई 'ड्र' में वितरित किए जाने वाले अंकों की संख्या क्या है अर्थात आर में वृद्धि r2 के अनुपात में होगी और r नहीं।

इस तरह से जाँच करें ... कुछ कोण थीटा और आर (0.1r से 0.2 आर) के बीच के अंकों की संख्या, आर के कुछ अंशों और आर के बीच के अंकों की संख्या (0.6r से 0.7r) के बराबर होगी यदि आप मानक उत्पादन का उपयोग करते हैं, चूंकि अंतर केवल दो अंतरालों के बीच 0.1r है। लेकिन चूंकि अंक (0.6r से 0.7r) के बीच का क्षेत्र 0.1r से 0.2r के बीच आच्छादित क्षेत्र की तुलना में बहुत बड़ा होगा, अंकों की समान संख्या बड़े क्षेत्र में बड़ी दूरी पर होगी, यह मैं आपको पहले से ही जानता हूं, इसलिए फ़ंक्शन रैंडम पॉइंट उत्पन्न करने के लिए रैखिक नहीं बल्कि द्विघात होना चाहिए, (क्योंकि दिए गए यूनिट 'ड्र' में वितरित किए जाने वाले अंकों की संख्या यानी आर में वृद्धि आर 2 और आर नहीं के अनुपातिक होगी), इसलिए इस मामले में इसका उलटा होगा द्विघात, चूंकि डेल्टा हमारे पास है (0)।


आप यहाँ पाइथागोरस प्रमेय का संदर्भ देने वाले पहले व्यक्ति हैं। मुझे अच्छा लगेगा यदि आप अपने स्पष्टीकरण का समर्थन करते हुए एक या दो के साथ इसका विस्तार कर सकते हैं। मेरे पास एक कठिन समय है क्योंकि यह अब खड़ा है :-(
aioobe

@aioobe मैंने उत्तर को पुनःप्रकाशित करने की कोशिश की है, अगर आपको ज़रूरत हो तो मैं आरेख जोड़ सकता हूं :)
चीज़फेस्ट

मैं समझता हूं कि मैं इसे रैखिक रूप से क्यों नहीं फैला सकता। यहाँ जो मुझे समझ नहीं आ रहा है वह पाइथागोरस या पाप / कॉस से संबंधित है। शायद आरेख मुझे यहाँ मदद कर सकता है।
aioobe

पाइथागोरस मेरी गलती है, कृपया इसके बारे में भूल जाएं, लेकिन आशा है कि आप फ़ंक्शन के द्विघात स्वभाव को समझ गए हैं, सटीक (2 / R2) × आर को प्रमाण की आवश्यकता है और मैं इसके लिए किसी भी प्रमाण के साथ आने में असमर्थ हूं
चीज़फेस्ट

0

ऐसी मजेदार समस्या।
धुरी की उत्पत्ति बढ़ने से दूरी के रूप में एक बिंदु को कम करने की संभावना के तर्क को कई बार ऊपर बताया गया है। हम यू [0,1] की जड़ को लेते हैं। यहां पायथन 3 में एक सकारात्मक आर के लिए एक सामान्य समाधान है।

import numpy
import math
import matplotlib.pyplot as plt

def sq_point_in_circle(r):
    """
    Generate a random point in an r radius circle 
    centered around the start of the axis
    """

    t = 2*math.pi*numpy.random.uniform()
    R = (numpy.random.uniform(0,1) ** 0.5) * r

    return(R*math.cos(t), R*math.sin(t))

R = 200 # Radius
N = 1000 # Samples

points = numpy.array([sq_point_in_circle(R) for i in range(N)])
plt.scatter(points[:, 0], points[:,1])

यहां छवि विवरण दर्ज करें


0

आप अपने अंतर्ज्ञान का उपयोग भी कर सकते हैं।

एक वृत्त का क्षेत्र है pi*r^2

के लिये r=1

यह हमें एक क्षेत्र देता है pi। आइए मान लें कि हमारे पास कुछ प्रकार के फ़ंक्शन हैं fजो N=10एक सर्कल के अंदर समान रूप से विचलित करने वाले बिंदु होंगे । यहाँ अनुपात है10 / pi

अब हम क्षेत्र और अंकों की संख्या को दोगुना करते हैं

के लिए r=2औरN=20

यह एक क्षेत्र देता है 4piऔर अनुपात अब 20/4piया है 10/2pi। अनुपात छोटा और छोटा होगा जितना बड़ा त्रिज्या होता है, क्योंकि इसकी वृद्धि द्विघात होती है और Nरैखिक रूप से होती है।

इसे ठीक करने के लिए हम सिर्फ कह सकते हैं

x = r^2
sqrt(x) = r

यदि आप इस तरह के ध्रुवीय निर्देशांक में एक वेक्टर उत्पन्न करेंगे

length = random_0_1();
angle = random_0_2pi();

अधिक अंक केंद्र के चारों ओर उतरेंगे।

length = sqrt(random_0_1());
angle = random_0_2pi();

length अब समान रूप से वितरित नहीं किया गया है, लेकिन वेक्टर अब समान रूप से वितरित किया जाएगा।


-1

1) -1 और 1 के बीच एक यादृच्छिक X चुनें।

var X:Number = Math.random() * 2 - 1;

2) सर्कल सूत्र का उपयोग करके, दिए गए Y के अधिकतम और न्यूनतम मानों की गणना करें और 1 का त्रिज्या।

var YMin:Number = -Math.sqrt(1 - X * X);
var YMax:Number = Math.sqrt(1 - X * X);

3) उन चरम सीमाओं के बीच एक यादृच्छिक वाई चुनें:

var Y:Number = Math.random() * (YMax - YMin) + YMin;

4) अंतिम मूल्य में अपना स्थान और त्रिज्या मान शामिल करें:

var finalX:Number = X * radius + pos.x;
var finalY:Number = Y * radois + pos.y;

2
समान नहीं - [-1, 0] के लिए संभावना [0, 0] की तुलना में बहुत अधिक है, यह देखते हुए कि p ([- 1, Y]) = p ([0, Y]), और केवल एक ही है [-1, Y] के लिए विकल्प और [0, Y] के लिए कई विकल्प।
आमदन

यह समाधान सर्कल के बाएं और दाएं पक्षों की ओर इशारा करता है। शून्य के करीब x वाले बिंदुओं का प्रतिनिधित्व किया जाता है। एक समान वितरण नहीं।
दाऊद इब्न करीम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.