Bir daire içinde rastgele bir nokta oluşturun (eşit olarak)


212

Yarıçapı R olan bir daire içinde düzgün rasgele bir nokta üretmem gerekiyor .

Sadece [0 ... 2π) aralığında eşit olarak rastgele bir açı ve (0 ... R ) aralığında eşit olarak rastgele bir yarıçap seçerek , merkeze doğru daha fazla nokta ile sonuçlanacağımı fark ediyorum. daha küçük yarıçaptaki noktalar, daha büyük yarıçaptaki noktalardan daha yakın olacaktır.

Burada bununla ilgili bir blog girdisi buldum, ancak onun mantığını anlamıyorum. Bunun doğru olduğunu varsayalım, ama ben gerçekten o (2 / almakta olduğu anlamak gibi olur R 2 ) × r ve o nasıl türettiği nihai çözüm.


Güncelleme: Bu soruyu gönderdikten 7 yıl sonra, karekök algoritmasının arkasındaki matematikle ilgili asıl soru hakkında tatmin edici bir cevap almadım. Bir gün kendime cevap yazarak geçirdim. Cevabımın bağlantısı .


18
Reddetme örneklemesinin dezavantajı gerçekten önemli midir? Beklenen deneme sayısı 4 / π ≈ 1,27'dir ve k denemeden daha fazlasına ihtiyacınız olma olasılığı (1-π / 4) ^ k'dır. İçin k = 20 , bu ≈ .00000000000004 ve k = 50 için, 10 ^ sırasına var {- 34}. Bu oranları her gün alabilirsiniz; iyi olacaksın.
ShreevatsaR

3
Aslında, reddetme örneklemesi sonlandırma için bir garanti sağlar. Oranlar, algoritmanızın asla sonlandırmayacağı sonsuz düşük (kesin olarak sıfır).
Jared Nielsen

2
Kanımca, reddetme örneklemesinin dezavantajının önemi, reddetmeyi önleyen bir örnekleme yöntemi kullanma kolaylığı ile orantılıdır. Bu durumda, dezavantaj önemlidir çünkü reddetmeden numune almak basittir.
spex

4
@spex Uygulamada, reddetme tekniği daha hızlıdır çünkü aşkın fonksiyon değerlendirme ihtiyacını ortadan kaldırır.
pjs

2
(devam) ret: 0.52s Hepsi özdeş araçlar ve standart sapmalar verdi (3 sig. şekle). Beklendiği gibi, reddetme örneklemesi zamanın% 27'sinde başarısız oldu (4 / pi-1) btilly'den% 27 daha fazla, ancak sigfpe'den% 15 daha az rastgele sayıya ihtiyaç duydu. Bu, pjs ve diğerleri tarafından, rastgele örneklemenin çok pahalı olmadığı sürece, reddedilme örneklemesinin muhtemelen en iyi yaklaşım olduğunu söyleyen yorumları doğrular.
Peter Davidson

Yanıtlar:


189

Arşimet'in sahip olduğu gibi buna yaklaşalım.

ABC üçgeninde eşit olarak nasıl bir nokta oluşturabiliriz, nerede | AB | = | BC |? Bir paralelkenar ABCD'ye uzanarak bunu daha kolaylaştıralım. ABCD'de eşit olarak puan oluşturmak kolaydır. AB üzerinde Y ve BC üzerinde Y rastgele bir X noktası seçeriz ve Z'yi seçeriz, böylece XBYZ bir paralelkenar olur. Orijinal üçgende eşit olarak seçilmiş bir nokta elde etmek için, ADC'de görünen noktaları AC boyunca ABC'ye geri katlarız.

Şimdi bir daire düşünün. Sınırda, sonsuz sayıda birçok izosel üçgeni, başlangıçta B ile ABC ve çevredeki A ve C, kaybolan bir şekilde birbirine yakın olarak düşünebiliriz. Bu üçgenlerden birini sadece teta açısı seçerek seçebiliriz. Bu yüzden şimdi ABC şeridinde bir nokta seçerek merkezden bir mesafe oluşturmamız gerekiyor. Yine, ABCD'ye uzanın, burada D şimdi daire merkezinden yarıçapın iki katıdır.

Yukarıdaki yöntemi kullanarak ABCD'de rastgele bir nokta seçmek kolaydır. AB'de rastgele bir nokta seçin. Düzgün bir şekilde BC'de rastgele bir nokta seçin. Yani. merkezden mesafeler vererek [0, R] üzerinde eşit olarak bir çift rastgele sayı x ve y seçin. Üçgenimiz ince bir şerittir, bu nedenle AB ve BC esasen paraleldir. Yani Z noktası, başlangıç ​​noktasından x + y mesafesidir. X + y> R ise geri katlanırız.

İşte R = 1 için tam algoritma. Umarım oldukça basittir. Trig kullanır, ancak random()reddetme örneklemesinden farklı olarak ne kadar süreceği ve kaç çağrıya ihtiyaç duyduğuna dair bir garanti verebilirsiniz .

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

İşte Mathematica'da.

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]

resim açıklamasını buraya girin


6
@Karelzarath Bir ucunda hala diğer ucundan daha geniş olan sonsuz ince bir üçgenin sezgisel anlayışını seviyorum :-) Doğru cevabı alır.
sigfpe

2
@hammar n boyutlarına iyi genel geldiğinden emin değilim. Ama 3d için Arşimet tarafından başka bir sonuç kullanabilirsiniz! Silindir üzerinde bir nokta oluşturmak için "hat-box" teoremini kullanın (kolay!) Ve sonra tekrar küreye eşleyin. Bu bir yön veriyor. Şimdi random()+random()+random()biraz daha karmaşık katlama ile kullanın (yani terahedrona paralel olarak sonsuz küçüklükte bir 6-kat kat). Ancak bu iyi bir yöntem olduğuna ikna olmadım.
sigfpe

2
Rasgele () + rasgele () ve 2 * rasgele () arasındaki farkı anlamak için 1 dakika düşündüm ... Çok aptalım: /
JiminP

3
@Tharwen Bir daire içinde 0.9-1.0 yarıçapında 0.0-0.1 yarıçapından daha fazla nokta olduğuna dikkat edin. random () + random () yarıçapı 1.0 civarındadır ancak 0.0-2.0 aralığındadır. Katlandığında, 1.0 civarında ve her zaman 0.0-1.0 aralığında olma olasılığı daha yüksektir. Dahası, bu yorumun ilk cümlesinde tam olarak gereken oran. Sadece yarıya indirmek 0.5 işareti etrafında daha fazla sayı üretir ve bu yanlış olur.
sigfpe

2
@Tharwen Rasgele sayılar üretmek ve elde ettiğiniz değerleri görmek için her iki şemayı da kullanmayı deneyin. 2 * random (), 0 ila 2 aralığında eşit olarak dağıtılmış sayılar verir. Random () + random () size 0 ila 2 aralığında sayılar verir, ancak (genellikle) 1.0'a yakın 0.0 veya 2.0'dan daha fazla sayı olacaktır. İki zarın yuvarlanması ve toplanmanın diğer sayılara göre 7 verme olasılığı daha yüksektir.
sigfpe

133

R yarıçapı dairesinde rastgele bir nokta nasıl oluşturulur :

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

( random()0 ile 1 arasında eşit olarak bir değer verdiğini varsayarsak )

Bunu Kartezyen koordinatlarına dönüştürmek istiyorsanız,

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


Neden sqrt(random())?

Gelen matematiğe bakalım sqrt(random()). Basitlik için birim çemberle çalıştığımızı varsayalım, yani R = 1.

Noktalar arasındaki ortalama mesafe, merkezden ne kadar uzakta göründüğümüzden bağımsız olarak aynı olmalıdır. Bu, örneğin, çevresi 2 olan bir dairenin çevresine baktığımızda, çevresi 1 olan bir dairenin çevresindeki nokta sayısından iki kat daha fazla nokta bulmamız gerektiği anlamına gelir.


                

Bir daire (2π çevresi yana r ) ile lineer büyür r , rasgele nokta sayısı ile doğrusal büyümesi gerektiğini aşağıdaki r . Başka bir deyişle, istenen olasılık yoğunluk fonksiyonu (PDF) doğrusal olarak büyür. Bir PDF'nin alanı 1'e eşit olduğundan ve maksimum yarıçap 1 olduğunda,


                

Bu yüzden rastgele değerlerimizin istenen yoğunluğunun nasıl olması gerektiğini biliyoruz. Şimdi: Elimizdeki tek şey 0 ile 1 arasında tekdüze rastgele bir değer olduğunda nasıl böyle rastgele bir değer üretebiliriz?

Ters dönüşüm örnekleme adı verilen bir numara kullanıyoruz

  1. PDF'den kümülatif dağıtım işlevini (CDF) oluşturun
  2. Bunu y = x boyunca yansıt
  3. Ortaya çıkan işlevi 0 ile 1 arasında eşit bir değere uygulayın.

Kulağa karmaşık mı geliyor? Sezgiyi ileten küçük bir yan iz içeren bir blok ekleyeyim:

Aşağıdaki dağıtımla rastgele bir nokta oluşturmak istediğimizi varsayalım:

                

Yani

  • 1/2 arasındaki noktaların 1/5'i eşit ve
  • 4/5 puan 2 ve 3 arasında eşit olarak.

CDF, adından da anlaşılacağı gibi, PDF'nin kümülatif sürümüdür. Sezgisel olarak: PDF (iken X ) rastgele değerleri sayısını tarif x'in CDF ( X ) rastgele değerleri sayısını tarif az x'den .

Bu durumda CDF şöyle görünecektir:

                

Bunun nasıl faydalı olduğunu görmek için mermilerin soldan sağa düzgün dağılmış yüksekliklerde ateş ettiğimizi hayal edin. Mermiler çizgiyi vurduğunda yere düşer:

                

Yerdeki mermilerin yoğunluğunun istenen dağılımımıza nasıl karşılık geldiğini görün! Neredeyse geldik!

Sorun, bu işlev için y ekseninin çıkış ve x ekseninin giriş olmasıdır . Biz sadece "yerden mermi ateţ edebiliriz!" Ters fonksiyona ihtiyacımız var!

Bu yüzden her şeyi yansıtıyoruz; X olur y ve y olur x :

                

Biz buna CDF -1 diyoruz . İstenilen dağılıma göre değerler elde etmek için CDF -1 (random ()) kullanıyoruz.

… Böylece, PDF'imizin 2 x'e eşit olduğu yerde rastgele yarıçap değerleri üretmeye geri dönelim .

Adım 1: CDF'yi oluşturun:

Gerçeklerle çalıştığımızdan, CDF PDF'nin ayrılmazı olarak ifade edilir.

CDF ( x ) = ∫ 2 x = x 2

Adım 2: CDF'yi y = x boyunca yansıtın :

Matematiksel olarak bu takas için aşağı kaynar x ve y ve çözme için y :

CDF :      y = x 2
Değiştirme:    x = y 2
Çözme:    y = √ x
CDF -1 :   y = √ x

Adım 3: Ortaya çıkan işlevi 0 ile 1 arasında eşit bir değere uygulayın

CDF -1 (rastgele ()) = √random ()

Hangi türetmek için yola çıktı :-)


Bu algoritma, halka üzerinde verimli bir şekilde noktalar oluşturmak için kullanılabilir.
Ivan Kovtun

Halkada mı? Sabit bir yarıçap gibi mi? Sorunuzu anladığımdan emin değilim, ancak sabit bir yarıçapınız varsa, açıyı rastgele ayarlamanız gerekir.
aioobe

2
İki eşmerkezli daireyle sınırlanmış Annulus yerine daha basit bir kelime olan "Yüzük" kullanmaya çalıştım. Bu durumda reddetme algoritması etkili olmaz ve ilk üst algoritmayı genellemek zordur. Ve bir yarıçaplı köşe kutusu da algoritmanızla kaplıdır. Min_radius == max_radius olsa bile yarıçapı sqrt (rastgele (min_radius ^ 2, max_radius ^ 2)) olarak üretiriz.
Ivan Kovtun

1
Oh iyi! Açık olmak gerekirse, derken random(min_radius², max_radius²), Sizin ortalama eşdeğer özellikte yapmak random() * (max_radius² - min_radius²) + min_radius², nereye random()döner, 0 ile 1 arasında bir üniforma değeri?
aioobe

evet, tam olarak bunu kastediyorum: radius = sqrt (random () * (max_radius² - min_radius²) + min_radius²).
Ivan Kovtun

27

İşte hızlı ve basit bir çözüm.

(0, 1) aralığında iki rasgele sayı seçin, ave b. Eğer b < aonları değiştirin. Demek istediğin (b*R*cos(2*pi*a/b), b*R*sin(2*pi*a/b)).

Bu çözümü aşağıdaki gibi düşünebilirsiniz. Daireyi aldıysanız, kesin, sonra düzeltin, dik açılı bir üçgen elde edersiniz. Bu üçgeni ölçeklendirdiğinizde, (0, 0)ile (1, 0)arasında (1, 1)ve tekrar arasında bir üçgen olur (0, 0). Bütün bu dönüşümler yoğunluğu eşit olarak değiştirir. Yaptığınız şey üçgende rastgele bir nokta seçmek ve daire içinde bir nokta almak için işlemi tersine çevirmek.


Bu, bazı nedenlerden ötürü, kabul edilen cevaba göre çok daha düzgün bir dağılım sağlıyor, ancak koordinatı yarıçapla bölmem gerekiyordu, aksi takdirde R ^ 2
Greg Zaal

3
Teşekkürler, bu Java kodunuz, belki birisi yararlı bulabilirsiniz: float random1 = MathUtils.random (); float random2 = MathUtils.random (); rasgele rastgeleXPoint = rasgele2 * yarıçapı MathUtils.cos (MathUtils.PI2 * rasgele1 / rasgele2); rasgele floatYPoint = rasgele2 * yarıçap MathUtils.sin (MathUtils.PI2 * rasgele1 / rasgele2);
Tony Ceralva

çok iyi! Noktaları merkezileştirmek için daha fazla olasılık fikrini seviyorum, bu yüzden b < abunu başarabildiğimiz zaman değişmezsek ! örneğin javascript jsfiddle.net/b0sb5ogL/1
Guilherme

Bence çözümünüz kötü. Eşit sonuçlar vermiyor. Bu ekran görüntüsünü kontrol et prntscr.com/fizxgc
bolec_kolec

4
Daireyi nasıl kesip düzeltebileceğinizi biraz daha açıklayabilir misiniz?
kec

21

Bu nedenle bunun yerine çekme bölgesinin yarıçapının kare ters orantılı nokta yoğunluğu Not rarasından [0, r_max]seçim yapmak, [0, r_max^2]ardından koordinatları olarak hesaplamak:

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

Bu size bir disk üzerinde tekdüze nokta dağılımı verecektir.

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


12

Bu şekilde düşünün. Bir eksenin yarıçapı ve diğerinin açılı olduğu bir dikdörtgeniz varsa ve bu dikdörtgenin içinde yarıçap 0'a yakın olan noktaları alırsanız, bunların tümü başlangıç ​​noktasına çok yakın olacaktır (daire üzerinde birbirine yakındır.) Ancak, R yarıçapına yakın noktalar, bunların hepsi dairenin kenarına yakın (yani, birbirinden çok uzak).

Bu, bu davranışı neden aldığınıza dair bir fikir verebilir.

Bu bağlantıdan türetilen faktör, daireye eşlendikten sonra dikdörtgendeki karşılık gelen alanın yarıçapa bağlı olmayacak şekilde ayarlanması gerektiğini gösterir.

Düzenleme: Yani o paylaştığınız bağlantıda ne yazıyor, "Bu kümülatif dağılımın tersini hesaplayarak yapmak kadar kolay, ve biz r olsun:".

Temel dayanak noktası, üniformayı istenen olasılık yoğunluk fonksiyonunun kümülatif dağılım fonksiyonunun ters fonksiyonu ile eşleştirerek üniformdan istenen bir dağılımla bir değişken oluşturabileceğinizdir. Neden? Şimdilik bunu kabul et, ama bu bir gerçek.

İşte benim matematiğin sezgisel açıklaması. R'ye göre f (r) yoğunluk fonksiyonu r ile orantılı olmalıdır. Bu gerçeği anlamak temel matematik kitaplarının bir parçasıdır. Polar alan elemanları ile ilgili bölümlere bakınız. Diğer bazı posterler de bundan bahsetti.

Yani buna f (r) = C * r diyeceğiz;

Bu işin çoğu olduğu ortaya çıkıyor. Şimdi, f (r) bir olasılık yoğunluğu olması gerektiğinden, f (r) 'yi (0, R) aralığı üzerine entegre ederek C = 2 / R ^ 2 elde edersiniz (bu okuyucu için bir alıştırmadır) .)

Böylece, f (r) = 2 * r / R ^ 2

Tamam, formülü bağlantıya böyle ekliyorsunuz.

Daha sonra, son kısım, (0,1) 'deki tekdüze rastgele değişken u'dan gidiyor ve bu istenen f (r) yoğunluğundan kümülatif dağılım fonksiyonunun ters fonksiyonu ile eşlemelisiniz. Bunun neden böyle olduğunu anlamak için muhtemelen Papoulis gibi gelişmiş bir olasılık metni bulmanız gerekir (veya kendiniz türetebilirsiniz).

F (r) ile entegre edildiğinde F (r) = r ^ 2 / R ^ 2 elde edersiniz

Bunun ters fonksiyonunu bulmak için u = r ^ 2 / R ^ 2 ayarlayıp r'yi çözün, bu da size r = R * sqrt (u)

Bu tamamen sezgisel olarak anlamlıdır, u = 0 r = 0 ile eşlenmelidir. Ayrıca, u = 1 shoudl haritası ile r = R olur. Ayrıca, mantıklı olan ve bağlantıya uyan kare kök fonksiyonu ile gider.


10

Saf çözümün işe yaramamasının nedeni, daire merkezine daha yakın noktalara daha yüksek olasılık yoğunluğu vermesidir. Başka bir deyişle, r / 2 yarıçapına sahip dairenin içinde bir nokta seçilme olasılığı r / 2, fakat pi * r ^ 2/4 alanı (nokta sayısı) vardır.

Bu nedenle, yarıçap olasılık yoğunluğunun aşağıdaki özelliğe sahip olmasını istiyoruz:

Belirli bir r'ye eşit veya daha küçük bir yarıçap seçme olasılığı, yarıçap r olan dairenin alanı ile orantılı olmalıdır. (çünkü noktalar üzerinde tekdüze bir dağılım yapmak istiyoruz ve daha büyük alanlar daha fazla puan anlamına geliyor)

Başka bir deyişle, [0, r] arasında bir yarıçap seçme olasılığının dairenin genel alanındaki payına eşit olmasını istiyoruz. Toplam daire alanı pi * R ^ 2'dir ve r yarıçapına sahip dairenin alanı pi * r ^ 2'dir. Bu nedenle, [0, r] arasında bir yarıçap seçme olasılığını (pi * r ^ 2) / (pi * R ^ 2) = r ^ 2 / R ^ 2 olarak istiyoruz.

Şimdi matematik geliyor:

[0, r] arasında bir yarıçap seçme olasılığı, 0'dan r'ye kadar olan p (r) dr'nin integralidir (bunun nedeni sadece daha küçük yarıçapların tüm olasılıklarını eklememizdir). Böylece integral (p (r) dr) = r ^ 2 / R ^ 2 istiyoruz. R ^ 2'nin sabit olduğunu açıkça görebiliyoruz, bu yüzden tek yapmamız gereken hangi p (r) 'nin entegre edildiğinde bize r ^ 2 gibi bir şey vereceğini bulmak. Cevap açıkça r * sabittir. integral (r * sabit dr) = r ^ 2/2 * sabit. Bu r ^ 2 / R ^ 2'ye eşit olmalıdır, bu nedenle sabit = 2 / R ^ 2 olmalıdır. Böylece olasılık dağılımınız p (r) = r * 2 / R ^ 2

Not: Sorunu düşünmenin daha sezgisel bir yolu da, yarıçap ra olasılık yoğunluğunun her bir çevresini, çevresine sahip olduğu nokta sayısının oranına eşit olarak vermeye çalıştığınızı düşünmektir. Böylece, yarıçapı r olan bir dairenin çevresinde 2 * pi * r "noktası" olacaktır. Toplam puan sayısı pi * R ^ 2'dir. Bu nedenle daire ra olasılığını (2 * pi * r) / (pi * R ^ 2) = 2 * r / R ^ 2'ye eşit vermelisiniz. Bu anlaşılması çok daha kolay ve daha sezgiseldir, ancak matematiksel olarak sağlam değildir.


9

Ρ (yarıçap) ve φ (azimut) dairenin içindeki rastgele bir noktanın kutupsal koordinatlarına karşılık gelen iki rastgele değişken olsun. Eğer noktalar eşit olarak dağılmışsa, ρ ve φ 'nın ayırma işlevi nedir?

Herhangi bir r: 0 <r <R için ρ yarıçap koordinatının r'den küçük olma olasılığı,

P [ρ <r] = P [nokta r yarıçapı dairesi içindedir] = S1 / S0 = (r / R) 2

Burada S1 ve S0, sırasıyla r ve R yarıçapı dairelerinin alanlarıdır. Böylece CDF şu şekilde verilebilir:

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

Ve PDF:

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

X'in [0, 1) üzerinde eşit olduğu R = 1 rasgele değişken sqrt (X) için bu tam CDF'ye sahip olduğuna dikkat edin (çünkü P [sqrt (X) <y] = P [x <y ** 2] = y * 0 <y <= 1 için * 2).

Φ dağılımı açıkça 0 ila 2 * uniform arasında eşittir. Artık rastgele kutupsal koordinatlar oluşturabilir ve trigonometrik denklemleri kullanarak bunları Kartezyen'e dönüştürebilirsiniz:

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

R = 1 için python kodu yayınlamak için direnemiyorum.

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)

Alacaksın

resim açıklamasını buraya girin


7

Gerçekten 'eşit olarak rasgele' ile ne demek istediğine bağlı. Bu ince bir noktadır ve bu konuda wiki sayfasında daha fazla bilgi edinebilirsiniz: http://en.wikipedia.org/wiki/Bertrand_paradox_%28probability%29 , burada aynı sorun, 'tekdüze rastgele' için farklı yorumlar verir farklı cevaplar!

Noktaları nasıl seçtiğinize bağlı olarak, bir anlamda eşit olarak rastgele olmalarına rağmen dağılım değişebilir .

Blog girişi aşağıdaki anlamda tekdüze rastgele yapmaya çalışıyor gibi görünüyor: Aynı merkezle dairenin bir alt dairesini alırsanız, o bölgedeki noktanın düşme olasılığı, alanla orantılıdır. bölge. İnanıyorum ki, 2B bölgeler için şimdi tanımlanmış alanları olan 'tekdüze rastgele' standart yorumunu izlemeye çalışıyorum : herhangi bir bölgede (iyi tanımlanmış alan ile) bir noktanın düşme olasılığı o bölgenin alanıyla orantılıdır.


5
Ya da daha ziyade, noktanın herhangi bir keyfi bölgede düşme olasılığı , bölgenin bir alanı olduğu varsayılarak, bölgenin alanı ile orantılıdır .
ShreevatsaR

@Shree: Doğru, parantez içindeki ifademle ima ettiğim şey bu. Açıklığa kavuşturacağım, teşekkürler. btw, blog hakkında, keyfi alanların orantılı olasılıklar verdiğine dair gerçek bir kanıt yoktu, bu yüzden onu bu şekilde ifade etmeyi seçtim.

6

numYarıçap çemberinden rastgele noktalar oluşturmak için Python kodum 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
Neden sadece r = np.sqrt(np.random.uniform(0.0, rad**2, num))?

4

Kutup koordinatları kullanarak bu durumda sorun, uzunluk 2R kenarlara sahip bir kare içine rastgele sayı seçerseniz çok daha kolay ve daha sonra noktaları seçecek karmaşık hale bir yol olduğunu düşünüyorum (x,y)böyle x^2+y^2<=R^2.


Yani x ^ 2 + y ^ 2 <= R ^ 2 sanırım.
sigfpe

1
Bu reddetme örneklemesi. Tamam, ancak hesaplama süresinin biraz değiştiği anlamına geliyor, bu da bir sorun olabilir.
Steve Bennett

Tüm kareler 4 kenarlıdır.
xaxxon

Bu algoritma, karekök veya sin / cos hesaplamaları içeren her şeyden daha etkilidir. Meydanın% 21.5'inden azını reddediyor.
Ivan Kovtun

3

Java'da çözüm ve dağıtım örneği (2000 puan)

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);
}

Dağıtım 2000 puan

Önceki çözüme dayalı https://stackoverflow.com/a/5838055/5224246 @sigfpe


2

İlk önce bir cdf [x]

Bir noktanın dairenin merkezinden x uzaklığından daha az olma olasılığı. Dairenin yarıçapı R olduğunu varsayalım.

Açıkçası x sıfırsa, cdf [0] = 0

Açıkçası x R ise cdf [R] = 1

açıkçası x = r ise cdf [r] = (Pi r ^ 2) / (Pi R ^ 2)

Bunun nedeni, daire üzerindeki her "küçük alan" ın aynı toplama olasılığına sahip olmasıdır, Bu nedenle olasılık, söz konusu alanla orantılıdır. Ve dairenin merkezinden x uzaklığı verilen alan Pi r ^ 2

yani cdf [x] = x ^ 2 / R ^ 2 çünkü Pi birbirini iptal ediyor

cdf [x] = x ^ 2 / R ^ 2 var, burada x 0'dan R'ye gider

Bu yüzden x için çözüyoruz

R^2 cdf[x] = x^2

x = R Sqrt[ cdf[x] ]

Şimdi cdf'yi 0'dan 1'e rastgele bir sayıyla değiştirebiliriz

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

En sonunda

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

kutupsal koordinatları alıyoruz {0.601168 R, 311.915 derece}


1

Yarıçap ile bu yarıçapın "yakınındaki" nokta sayısı arasında doğrusal bir ilişki vardır, bu nedenle yarıçap yakınındaki veri noktalarının sayısını rorantılı yapan bir yarıçap dağılımı kullanması gerekir r.


1

Bu yöntemi bir kez kullandım: Bu tamamen optimize edilmemiş olabilir (yani büyük daireler için kullanılamaz bir nokta noktası kullanır), ancak yeterince rasgele dağıtım verir. Matrisin oluşturulmasını atlayabilir ve isterseniz doğrudan çizebilirsiniz. Yöntem, dairenin içine giren bir dikdörtgendeki tüm noktaları rastgele ayarlamaktır.

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);
}

resim açıklamasını buraya girin


3
Dağıtımlar "yeterince rasgele" değildir. Belirli bir rasgele tanımı için ya rasgele ya da rasgele değildirler. Cevabınız eğik: kodunuzu yorumlamıyor veya kodunuza nasıl geldiğinizi açıklamıyorsunuz. Eğik cevapları takip etmek ve güvenmek daha zordur.
Richard

1

Bir daire içindeki alan elemanı dA = rdr * dphi'dir. Bu ekstra faktör r ar ve phi rastgele seçmek için fikrinizi yok etti. Phi düz dağıtılırken, r düz değil, 1 / r'de düzdür (yani sınıra “boğanın gözünden” daha fazla vurursunuz).

Böylece daire üzerinde eşit olarak dağıtılmış noktalar oluşturmak için düz bir dağıtımdan phi ve 1 / r dağılımından r seçin.

Alternatif olarak Mehrdad'ın önerdiği Monte Carlo yöntemini kullanın.

DÜZENLE

1 / r'de rastgele bir r düz seçmek için [1 / R, sonsuzluk] aralığından rastgele bir x seçebilir ve r = 1 / x hesaplayabilirsiniz. r daha sonra 1 / r'de düz olarak dağıtılır.

Rasgele bir phi hesaplamak için [0, 1] aralığından rastgele bir x seçin ve phi = 2 * pi * x hesaplayın.


"A / r dağılımı" ndan tam olarak nasıl r seçerim ?
aioobe

0

Bu sorunun hâlihazırda verilen tüm cevaplarla yeni bir çözüme açık olup olmadığını bilmiyorum, ama kendimle aynı soruyla karşılaştım. Bir çözüm bulmak için kendimle "akıl yürütmeye" çalıştım ve bir çözüm buldum. Bazılarının burada önerdiği ile aynı şey olabilir, ancak yine de burada:

dairenin yüzeyinin iki elemanının eşit olması için, dr'lerin eşit olduğu varsayılarak, dtheta1 / dtheta2 = r2 / r1 olmalıdır. Söz konusu öğenin olasılığının P (r, teta) = P {r1 <r <r1 + dr, teta1 <teta + teta1} = f (r, teta) * dr * dtheta1 olarak yazılması ve ikisinin ayarlanması olasılıklar (r1 ve r2 için) eşittir, (r ve teta'nın bağımsız olduğu varsayılarak) f (r1) / r1 = f (r2) / r2 = sabitine ulaşırız, bu da f (r) = c * r verir. Ve geri kalanı, c sabitini belirlemek, f (r) 'nin PDF olması koşulunu izler.


Dtheta1 / dtheta2 = r2 / r1 ile başlamak için ilginç bir yaklaşım. Bu denklemi nasıl bulduğunuzu açıklayabilir misiniz?
aioobe

Diğerlerinin de belirttiği gibi (örneğin honk), bir dairenin yüzeyinin diferansiyel bir elemanı r dr dtheta olarak verilir , bu nedenle r1 = r2 olduğunu varsayarsak, dr1 * dtheta1 = dr2 * dtheta2 olur ve gerisi .
arsaKasra

0

Bir programcı çözümü:

  • Bir bit haritası oluşturun (boole değerleri matrisi). İstediğiniz kadar büyük olabilir.
  • Bu bit haritasında bir daire çizin.
  • Dairenin noktalarına ilişkin bir arama tablosu oluşturun.
  • Bu arama tablosunda rastgele bir dizin seçin.
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];
} // ()

Bitmap yalnızca mantığın açıklaması için gereklidir. Bitmap olmayan kod budur:

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

Hala kesin '(2 / R2) × r' hakkında emin değilim ama belirgin olan 'dr' biriminde dağıtılması gereken nokta sayısıdır, yani r'deki artış r değil r2 ile orantılı olacaktır.

bu şekilde kontrol edin ... bir miktar tetadaki ve r (0.1r ila 0.2r) arasındaki nokta sayısı, yani r'nin kesri ve r (0.6r ila 0.7r) arasındaki nokta sayısı, standart üretimi kullanırsanız, çünkü fark iki aralık arasında sadece 0.1r'dir. ancak noktalar (0.6r ila 0.7r) arasındaki alan 0.1r ila 0.2r arasındaki alandan çok daha büyük olacağından, eşit sayıda nokta daha geniş alanda seyrek aralıklı olacağından, zaten bildiğinizi varsayalım, yani fonksiyon Rastgele noktaları oluşturmak için lineer değil, ikinci dereceden olmamalıdır (belirli bir 'dr' biriminde dağıtılması gereken nokta sayısı yani r'deki artış r değil, r2 ile orantılı olacaktır), bu durumda ters olacaktır ikinci dereceden, deltadan beri (0.


Burada Pisagor teoremini referans alan ilk kişi sizsiniz. Bunu, açıklamanızı destekleyen bir ya da iki rakamla genişletmeyi çok isterdim. Şu anda olduğu gibi takip etmek zor bir zaman var :-(
aioobe

@aioobe Cevabı yeniden anlatmaya çalıştım, gerekirse diyagram ekleyebilirim :)
cheesefest

Neden doğrusal olarak dağıtamayacağımı anlıyorum. Burada anlamadığım şey Pisagor veya sin / cos ile bağlantı. Belki diyagramlar burada bana yardımcı olabilir.
aioobe

Pisagor benim hatam, lütfen unut gitsin, ama umarım fonksiyonun ikinci dereceden doğasını anlarsın, tam (2 / R2) × r kanıt gerektirir ve bunun için herhangi bir kanıt
bulamadım

0

Çok eğlenceli bir problem.
Eksen kaynağından uzaklık arttıkça bir noktanın düşürülme olasılığının gerekçesi, yukarıda birçok kez açıklanmaktadır. Bunu U [0,1] 'in kökünü alarak açıklıyoruz. İşte Python 3'te pozitif bir r için genel bir çözüm.

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])

resim açıklamasını buraya girin


0

Sezginizi de kullanabilirsiniz.

Bir dairenin alanı pi*r^2

İçin r=1

Bu bize bir alan verir pi. Bir daire içindeki noktaları feşit olarak dağıtacak bir fonksiyonumuz olduğunu varsayalım N=10. Buradaki oran10 / pi

Şimdi alanı ve puan sayısını ikiye katlıyoruz

için r=2veN=20

Bu bir alan verir 4pive oran şimdi 20/4piveya 10/2pi. Yarıçap büyüdükçe oran küçülür ve küçülür, çünkü büyümesi ikinci dereceden veN ölçekler doğrusaldır.

Bunu düzeltmek için şunu söyleyebiliriz:

x = r^2
sqrt(x) = r

Kutupsal koordinatlarda böyle bir vektör oluşturursanız

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

Merkezin etrafına daha fazla puan düşecekti.

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

length artık tekdüze bir şekilde dağıtılmaz, ancak vektör artık tekdüze olarak dağıtılır.


-1

1) -1 ile 1 arasında rastgele bir X seçin.

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

2) Daire formülünü kullanarak, X ve 1 yarıçapı verildiğinde Y'nin maksimum ve minimum değerlerini hesaplayın:

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

3) Bu uçlar arasında rastgele bir Y seçin:

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

4) Konumunuzu ve yarıçap değerlerinizi son değere ekleyin:

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

2
Düzgün değil - [-1, 0] olasılığı, p ([- 1, Y]) = p ([0, Y]) göz önüne alındığında [0, 0] 'dan çok daha yüksektir ve sadece tek bir [-1, Y] için seçim ve [0, Y] için birçok seçenek.
Amadan

Bu çözüm dairenin sol ve sağ taraflarına yönelik noktaları tercih eder. Sıfıra yakın x olan noktalar yetersiz temsil edilir. Tekdüze bir dağılım değil.
Dawood ibn Kareem
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.