2015-06-01 60 views
5

Zastanawiam się, w jaki sposób mogę generować losowe liczby, które pojawiają się w dystrybucji kołowej.Jak generować losowe punkty w kolistej dystrybucji

jestem w stanie generować losowe punkty w rozkładzie prostokątnym tak, że punkty są generowane wewnątrz kwadratu (0 < = x = y < 1000):

jak pójdę na do generowania punktów wewnątrz okręgu, takich że:

(x-500)^2 + (y-500)^2 < 250000?

+2

Należy jednak zachować ostrożność przy wykonywaniu obliczeń. Jeśli celem jest posiadanie równomiernie rozłożonych wartości losowych (x, y) w kręgu, wiele z potencjalnych sposobów wykonania obliczeń nie da takiego wyniku. – Simon

+0

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

+2

Przeczytaj [to] (http://stats.stackexchange.com/questions/120527/how-to-generate-random-points-uniformly-distributed-in- koło). – vsoftco

Odpowiedz

5

PIERWSZA ODPOWIEDŹ: Łatwym rozwiązaniem byłoby sprawdzenie, czy wynik spełnia twoje równanie przed kontynuowaniem.

generowanie X, Y (są sposoby losowo do wybrać zakres)

Sprawdź, czy ((x-500)^2 + (y-500)^2 < 250000) jest prawdziwe jeśli nie, zregenerować.

Jedynym minusem byłaby nieefektywność.

Druga odpowiedź:

OR, można zrobić coś podobnego do sum Riemanna jak dla zbliżenia całki. Przybliż swój krąg, dzieląc go na wiele prostokątów. (im więcej prostokątów, tym dokładniejsze) i użyj algorytmu prostokąta dla każdego prostokąta w twoim okręgu.

+3

Pierwsza odpowiedź ma podwójne zalety: jest prosta i poprawnie zapewnia równomierny rozkład wartości (x, y). Nieefektywność jest stosunkowo niewielka, ponieważ tylko część 1- (0,25 * PI) par zostanie odrzucona. – Simon

+1

Jest całkiem prawdopodobne, że będzie to * szybsze * niż robienie tego "poprawnie", jeśli używa się szybkiego generatora liczb losowych, ponieważ unika trygonometrii, korzeni, dużych liczb i używa tylko jednego połączenia do "losowego" średnio. – Veedrac

4
import random 
import math 

# radius of the circle 
circle_r = 10 
# center of the circle (x, y) 
circle_x = 5 
circle_y = 7 

# random angle 
alpha = 2 * math.pi * random.random() 
# random radius 
r = circle_r * random.random() 
# calculating coordinates 
x = r * math.cos(alpha) + circle_x 
y = r * math.sin(alpha) + circle_y 

print("Random point", (x, y)) 

W przykładzie circle_x 500 jako circle_y jest. circle_r wynosi 500.

Inna wersja obliczenia promień aby równomiernie rozmieszczone punkty, na podstawie this answer

u = random.random() + random.random() 
r = circle_r * (2 - u if u > 1 else u) 
+5

Nie wiem, czy OP tego potrzebuje, ale to * nie * będzie jednolitą dystrybucją. – andars

+2

To podejście daje nierównomiernie rozłożone wartości (x, y) - będą bardziej skoncentrowane w środku niż na brzegu koła. Jeśli jest to pożądany wynik, to jest dobrze i dobrze, ale jeśli wymagana jest jednorodna dystrybucja, to tego nie dostarczy. – Simon

+0

Jest to doskonała okazja, aby połączyć się z jednym z największych problemów w teorii prawdopodobieństwa: [paradoks Bertranda] (https://en.wikipedia.org/wiki/Bertrand_paradox_ (prawdopodobieństwo)). – naught101

0

chciałbym użyć współrzędnych biegunowych:

r_squared, theta = [random.randint(0,250000), 2*math.pi*random.random()]

wówczas R jest zawsze mniejsza niż lub równy promieniu i theta zawsze pomiędzy 0 a 2 * pi radianów.

Od r nie jest źródłem, zawsze będziesz przekształcić go w wektorze wyśrodkowany przy 500, 500, jeśli dobrze rozumiem

x = 500 + math.sqrt(r_squared)*math.cos(theta) y = 500 + math.sqrt(r_squared)*math.sin(theta)

Wybierz r_squared losowo powodu this

+3

Rozkład (x, y) wytworzony według tego podejścia nie będzie jednolity. – Simon

+0

'x = 500 + r * math.cos (theta)' 'y = 500 + r * math.sin (theta)' Tak? – fiacre

+0

@imon, widzę problem: Zmień powyższy kod na: 'r_sqared, theta = [random.randint (0,250000), 2 * math.pi * random.random()]' Następnie zastosuj transformację 'x = 500 + math.sqrt (r_squared) * math.cos (theta)' 'y = 500 + math.sqrt (r_squared) * math.sin (theta)' – fiacre

4

Co potrzebujesz próbki z (formy polarnej):

r, theta = [math.sqrt(random.randint(0,500))*math.sqrt(500), 2*math.pi*random.random()] 

Następnie można przetransformować r i theta z powrotem do współrzędnych kartezjańskich x i y poprzez

x = 500 + r * math.cos(theta) 
y = 500 + r * math.sin(theta) 

Related (chociaż nie Python), ale daje pomysł.

+0

Jak zauważono w innych odpowiedziach, to wygrało ' t doprowadzić do jednolitej dystrybucji punktów. – naught101

+0

@ naught101 Nie, wygeneruje równomiernie rozmieszczone punkty na dysku, zauważ, że generuję jednolitą pierwiastek kwadratowy promienia, a nie sam promień (który w rzeczywistości nie spowoduje jednolitego rozkładu na dysku) . – vsoftco

+0

Ach, prawda, widzę, co robisz. Myślę, że może to być czystsze, jeśli po prostu próbkowałeś z koła jednostek, następnie pomnożono i dodawano później, zamiast próbkowania z r = 500 kół. – naught101

0

Możesz użyć rejection sampling, wygenerować losowy punkt w obrębie kwadratu (2r)×(2r), który pokrywa okrąg, powtarzać, aż uzyskasz jeden punkt w okręgu.