Preciso para gerar um ponto uniformemente aleatório dentro de um círculo de raio R .
Percebo que, apenas escolhendo um ângulo aleatoriamente uniforme no intervalo [0 ... 2π) e raio aleatoriamente uniforme no intervalo (0 ... R ) eu terminaria com mais pontos em direção ao centro, pois para dois dados raios, os pontos no raio menor ficarão mais próximos um do outro do que nos pontos no raio maior.
Encontrei uma entrada de blog sobre isso aqui, mas não entendo o raciocínio dele. Acho que é correto, mas eu realmente gostaria de entender de onde ele recebe (2 / R 2 ) × r e como ele deriva a solução final.
Atualização: 7 anos após postar esta pergunta, eu ainda não recebi uma resposta satisfatória sobre a questão real sobre a matemática por trás do algoritmo de raiz quadrada. Então, eu passei um dia escrevendo uma resposta. Link para a minha resposta .
fonte
Respostas:
Vamos abordar isso como Arquimedes faria.
Como podemos gerar um ponto uniformemente em um triângulo ABC, onde | AB | = | BC |? Vamos facilitar isso estendendo para um paralelogramo ABCD. É fácil gerar pontos uniformemente no ABCD. Escolhemos uniformemente um ponto aleatório X em AB e Y em BC e escolhemos Z de modo que XBYZ seja um paralelogramo. Para obter um ponto uniformemente escolhido no triângulo original, basta dobrar os pontos que aparecem no ADC de volta ao ABC ao longo de AC.
Agora considere um círculo. No limite, podemos pensar nele como infinitos triângulos de isoceles ABC, com B na origem e A e C na circunferência que desaparecem um do outro. Podemos escolher um desses triângulos simplesmente escolhendo um ângulo teta. Portanto, agora precisamos gerar uma distância do centro escolhendo um ponto na tira ABC. Novamente, estenda para ABCD, onde D agora é duas vezes o raio do centro do círculo.
Escolher um ponto aleatório no ABCD é fácil usando o método acima. Escolha um ponto aleatório em AB. Escolha uniformemente um ponto aleatório em BC. Ou seja. escolha um par de números aleatórios x e y uniformemente em [0, R], dando distâncias do centro. Nosso triângulo é uma tira fina, portanto AB e BC são essencialmente paralelos. Portanto, o ponto Z é simplesmente uma distância x + y da origem. Se x + y> R, dobramos novamente.
Aqui está o algoritmo completo para R = 1. Espero que você concorde que é bem simples. Ele usa trigonometria, mas você pode garantir quanto tempo levará e quantas
random()
chamadas serão necessárias, diferentemente da amostragem por rejeição.Aqui está no Mathematica.
fonte
random()+random()+random()
com uma dobra mais complexa (ou seja, uma dobra de 6 direções de um paralelepípedo infinitesimalmente fino com um terahedro). Não estou convencido de que este seja um bom método.Como gerar um ponto aleatório dentro de um círculo de raio R :
(Assumindo que
random()
fornece um valor entre 0 e 1 uniformemente)Se você deseja converter isso em coordenadas cartesianas, pode fazer
Por que
sqrt(random())
?Vamos olhar para a matemática que leva até
sqrt(random())
. Suponha, por simplicidade, que estamos trabalhando com o círculo unitário, ou seja, R = 1.A distância média entre os pontos deve ser a mesma, independentemente da distância do centro que olhamos. Isso significa, por exemplo, que, olhando o perímetro de um círculo com circunferência 2, deveríamos encontrar o dobro de pontos que o número de pontos no perímetro de um círculo com circunferência 1.
Como a circunferência de um círculo (2π r ) cresce linearmente com r , segue-se que o número de pontos aleatórios deve crescer linearmente com r . Em outras palavras, a função de densidade de probabilidade desejada (PDF) cresce linearmente. Como um PDF deve ter uma área igual a 1 e o raio máximo é 1, temos
Portanto, sabemos como deve ser a densidade desejada de nossos valores aleatórios. Agora: como geramos um valor tão aleatório quando tudo o que temos é um valor aleatório uniforme entre 0 e 1?
Usamos um truque chamado amostragem por transformação inversa
Parece complicado? Deixe-me inserir uma citação em bloco com uma pequena faixa lateral que transmite a intuição:
… Então, voltemos a gerar valores aleatórios de raio em que nosso PDF é igual a 2 x .
Etapa 1: criar o CDF:
como trabalhamos com reais, o CDF é expresso como a integral do PDF.
CDF ( x ) = x 2 x = x 2
Etapa 2: espelhe o CDF ao longo de y = x :
Matematicamente isso se resume a trocar x e y e resolvendo para y :
CDF : y = x 2
Troca: x = y 2
Resolva: y = √ x
CDF -1 : y = √ x
Etapa 3: aplique a função resultante a um valor uniforme entre 0 e 1
CDF -1 (aleatório ()) = aleatório ()
Qual é o que nos propusemos a derivar :-)
fonte
random(min_radius², max_radius²)
, você quer dizer algo equivalente arandom() * (max_radius² - min_radius²) + min_radius²
, whererandom()
retorna um valor uniforme entre 0 e 1?Aqui está uma solução rápida e simples.
Escolha dois números aleatórios no intervalo (0, 1), ou seja,
a
eb
. Seb < a
, troque-os. O seu ponto é(b*R*cos(2*pi*a/b), b*R*sin(2*pi*a/b))
.Você pode pensar sobre esta solução da seguinte maneira. Se você pegar o círculo, cortá-lo e endireitá-lo, obterá um triângulo retângulo. Escala que para baixo triângulo, e você teria um triângulo a partir
(0, 0)
de(1, 0)
para(1, 1)
e de volta para(0, 0)
. Todas essas transformações alteram a densidade uniformemente. O que você fez foi escolher uniformemente um ponto aleatório no triângulo e reverter o processo para obter um ponto no círculo.fonte
b < a
podemos conseguir isso! por exemplo, em javascript jsfiddle.net/b0sb5ogL/1Note-se a densidade de pontos na proporcional ao inverso do quadrado do raio, portanto, em vez de escolher
r
a partir[0, r_max]
, escolher[0, r_max^2]
, em seguida, calcular suas coordenadas como:Isso fornecerá uma distribuição uniforme de pontos em um disco.
http://mathworld.wolfram.com/DiskPointPicking.html
fonte
Pense nisso desta maneira. Se você possui um retângulo em que um eixo é raio e outro é ângulo, e você pega os pontos dentro desse retângulo que estão próximos do raio 0. Todos eles ficarão muito próximos da origem (que estão próximos no círculo). os pontos próximos ao raio R, todos cairão perto da borda do círculo (ou seja, afastados um do outro).
Isso pode lhe dar uma idéia de por que você está recebendo esse comportamento.
O fator derivado nesse link informa a quantidade de área correspondente no retângulo que precisa ser ajustada para não depender do raio depois que ele é mapeado para o círculo.
Edit: Então, o que ele escreve no link que você compartilha é: "Isso é fácil o suficiente, calculando o inverso da distribuição cumulativa, e obtemos o r:".
A premissa básica é aqui que você pode criar uma variável com uma distribuição desejada a partir de um uniforme, mapeando o uniforme pela função inversa da função de distribuição cumulativa da função de densidade de probabilidade desejada. Por quê? Apenas tome como garantido por enquanto, mas isso é um fato.
Aqui está a minha explicação intuitiva da matemática. A função de densidade f (r) em relação a r deve ser proporcional a r em si. Compreender esse fato faz parte de qualquer livro de cálculo básico. Veja as seções sobre os elementos da área polar. Alguns outros pôsteres mencionaram isso.
Então, vamos chamá-lo de f (r) = C * r;
Isso acaba sendo a maior parte do trabalho. Agora, como f (r) deve ser uma densidade de probabilidade, você pode facilmente ver que, ao integrar f (r) no intervalo (0, R), obtém-se que C = 2 / R ^ 2 (este é um exercício para o leitor .)
Assim, f (r) = 2 * r / R ^ 2
OK, é assim que você obtém a fórmula no link.
Então, a parte final vai da variável aleatória uniforme u em (0,1), você deve mapear pela função inversa da função de distribuição cumulativa a partir dessa densidade desejada f (r). Para entender por que esse é o caso, é necessário encontrar um texto de probabilidade avançado como Papoulis (ou derivá-lo você mesmo).
Integrando f (r) você obtém F (r) = r ^ 2 / R ^ 2
Para encontrar a função inversa disso, defina u = r ^ 2 / R ^ 2 e depois resolva para r, que fornece r = R * sqrt (u)
Isso também faz sentido de maneira intuitiva, u = 0 deve mapear para r = 0. Além disso, u = 1 shoudl mapeia para r = R. Além disso, ele segue a função de raiz quadrada, que faz sentido e corresponde ao link.
fonte
A razão pela qual a solução ingênua não funciona é que ela fornece uma densidade de probabilidade mais alta para os pontos mais próximos do centro do círculo. Em outras palavras, o círculo que possui o raio r / 2 tem probabilidade r / 2 de obter um ponto selecionado, mas possui a área (número de pontos) pi * r ^ 2/4.
Portanto, queremos que a densidade de probabilidade do raio tenha a seguinte propriedade:
A probabilidade de escolher um raio menor ou igual a um dado r deve ser proporcional à área do círculo com raio r. (porque queremos ter uma distribuição uniforme nos pontos e áreas maiores significam mais pontos)
Em outras palavras, queremos que a probabilidade de escolher um raio entre [0, r] seja igual à sua parcela da área geral do círculo. A área total do círculo é pi * R ^ 2, e a área do círculo com raio r é pi * r ^ 2. Assim, gostaríamos que a probabilidade de escolher um raio entre [0, r] seja (pi * r ^ 2) / (pi * R ^ 2) = r ^ 2 / R ^ 2.
Agora vem a matemática:
A probabilidade de escolher um raio entre [0, r] é a integral de p (r) dr de 0 a r (isso é apenas porque adicionamos todas as probabilidades dos raios menores). Assim, queremos integral (p (r) dr) = r ^ 2 / R ^ 2. Podemos ver claramente que R ^ 2 é uma constante, então tudo o que precisamos fazer é descobrir qual p (r), quando integrado, nos daria algo como r ^ 2. A resposta é claramente r * constante. integral (r * constante dr) = r ^ 2/2 * constante. Isso deve ser igual a r ^ 2 / R ^ 2, portanto constante = 2 / R ^ 2. Assim, você tem a distribuição de probabilidade p (r) = r * 2 / R ^ 2
Nota: Outra maneira mais intuitiva de pensar sobre o problema é imaginar que você está tentando dar a cada círculo de raio uma densidade de probabilidade igual à proporção do número de pontos que ele tem em sua circunferência. Assim, um círculo com raio r terá 2 * pi * r "pontos" em sua circunferência. O número total de pontos é pi * R ^ 2. Portanto, você deve dar ao círculo ra uma probabilidade igual a (2 * pi * r) / (pi * R ^ 2) = 2 * r / R ^ 2. Isso é muito mais fácil de entender e mais intuitivo, mas não é tão matematicamente correto.
fonte
Sejam ρ (raio) e φ (azimute) duas variáveis aleatórias correspondentes às coordenadas polares de um ponto arbitrário dentro do círculo. Se os pontos são distribuídos uniformemente, qual é a função de distribuição de ρ e φ?
Para qualquer r: 0 <r <R, a probabilidade da coordenada do raio ρ ser menor que r é
P [ρ <r] = P [ponto está dentro de um círculo do raio r] = S1 / S0 = (r / R) 2
Onde S1 e S0 são as áreas do círculo de raio re R respectivamente. Portanto, o CDF pode ser dado como:
E PDF:
Observe que para R = 1 variável aleatória sqrt (X) onde X é uniforme em [0, 1) tem esse CDF exato (porque P [sqrt (X) <y] = P [x <y ** 2] = y * * 2 para 0 <y <= 1).
A distribuição de φ é obviamente uniforme de 0 a 2 * π. Agora você pode criar coordenadas polares aleatórias e convertê-las em cartesianas usando equações trigonométricas:
Não consigo resistir a publicar código python para R = 1.
Você vai ter
fonte
Realmente depende do que você quer dizer com 'uniformemente aleatório'. Este é um ponto sutil e você pode ler mais sobre ele na página da wiki aqui: http://en.wikipedia.org/wiki/Bertrand_paradox_%28probability%29 , onde o mesmo problema, dando interpretações diferentes para 'uniformemente aleatório', fornece respostas diferentes!
Dependendo de como você escolhe os pontos, a distribuição pode variar, embora eles sejam uniformemente aleatórios em algum sentido.
Parece que a entrada do blog está tentando torná-la uniformemente aleatória no seguinte sentido: Se você pegar um sub-círculo do círculo, com o mesmo centro, a probabilidade de o ponto cair nessa região é proporcional à área de a região. Isso, acredito, está tentando seguir a interpretação agora padrão de 'uniformemente aleatório' para regiões 2D com áreas definidas : a probabilidade de um ponto cair em qualquer região (com área bem definida) é proporcional à área daquela região.
fonte
Aqui está o meu código Python para gerar
num
pontos aleatórios a partir de um círculo de raiorad
:fonte
r = np.sqrt(np.random.uniform(0.0, rad**2, num))
?Penso que, neste caso, o uso de coordenadas polares é uma maneira de complicar o problema, seria muito mais fácil se você escolher pontos aleatórios em um quadrado com lados de comprimento 2R e depois selecionar os pontos de
(x,y)
modo quex^2+y^2<=R^2
.fonte
Solução em Java e o exemplo de distribuição (2000 pontos)
com base na solução previus https://stackoverflow.com/a/5838055/5224246 from @sigfpe
fonte
Primeiro, geramos um cdf [x] que é
A probabilidade de um ponto estar menor que a distância x do centro do círculo. Suponha que o círculo tenha um raio de R.
obviamente se x é zero então cdf [0] = 0
obviamente se x é R então o cdf [R] = 1
obviamente se x = r então o cdf [r] = (Pi r ^ 2) / (Pi R ^ 2)
Isso ocorre porque cada "pequena área" do círculo tem a mesma probabilidade de ser escolhida. Portanto, a probabilidade é proporcional à área em questão. E a área dada uma distância x do centro do círculo é Pi r ^ 2
então cdf [x] = x ^ 2 / R ^ 2 porque o Pi se cancela
temos cdf [x] = x ^ 2 / R ^ 2 onde x vai de 0 a R
Então resolvemos para x
Agora podemos substituir o cdf por um número aleatório de 0 a 1
Finalmente
obtemos as coordenadas polares {0,601168 R, 311,915 graus}
fonte
Há uma relação linear entre o raio e o número de pontos "próximos" desse raio; portanto, ele precisa usar uma distribuição de raio que também torne o número de pontos de dados próximo de um raio
r
proporcional ar
.fonte
Eu usei uma vez este método: Isso pode ser totalmente não otimizado (ou seja, usa uma matriz de pontos que é inutilizável para grandes círculos), mas fornece distribuição aleatória suficiente. Você pode pular a criação da matriz e desenhar diretamente, se desejar. O método é aleatoriamente todos os pontos em um retângulo que caem dentro do círculo.
fonte
O elemento de área em um círculo é dA = rdr * dphi. Esse fator extra r destruiu sua ideia de escolher aleatoriamente ar e phi. Enquanto o phi é distribuído horizontalmente, r não é, mas horizontalmente em 1 / r (ou seja, é mais provável que você atinja o limite do que "o alvo").
Portanto, para gerar pontos distribuídos uniformemente sobre o círculo, escolha phi a partir de uma distribuição plana er de uma distribuição 1 / r.
Como alternativa, use o método Monte Carlo proposto por Mehrdad.
EDITAR
Para escolher um plano r aleatório em 1 / r, você pode escolher um x aleatório no intervalo [1 / R, infinito] e calcular r = 1 / x. r é então distribuído horizontalmente em 1 / r.
Para calcular um phi aleatório, escolha um x aleatório no intervalo [0, 1] e calcule phi = 2 * pi * x.
fonte
Não sei se essa pergunta ainda está aberta para uma nova solução com toda a resposta já dada, mas, por acaso, eu mesma enfrentei exatamente a mesma pergunta. Tentei "raciocinar" comigo mesmo por uma solução e encontrei uma. Pode ser a mesma coisa que alguns já sugeriram aqui, mas de qualquer maneira aqui está:
para que dois elementos da superfície do círculo sejam iguais, assumindo drs iguais, devemos ter dtheta1 / dtheta2 = r2 / r1. Escrevendo a expressão da probabilidade desse elemento como P (r, teta) = P {r1 <r <r1 + dr, teta1 <teta <teta + dtheta1} = f (r, teta) * dr * dtheta1 e definindo os dois probabilidades (para r1 e r2) iguais, chegamos a (assumindo que r e teta são independentes) f (r1) / r1 = f (r2) / r2 = constante, o que fornece f (r) = c * r. E o restante, determinando a constante c, segue a condição em f (r) como um PDF.
fonte
Uma solução de programador:
O bitmap é necessário apenas para a explicação da lógica. Este é o código sem o bitmap:
fonte
Ainda não tenho certeza sobre o exato '(2 / R2) × r', mas o que é aparente é o número de pontos a serem distribuídos na unidade 'dr', ou seja, o aumento em r será proporcional a r2 e não a r.
marque desta maneira ... o número de pontos em algum ângulo teta e entre r (0,1r a 0,2r), ou seja, a fração de re número de pontos entre r (0,6r a 0,7r) seria igual se você usar a geração padrão, já que a diferença é de apenas 0,1r entre dois intervalos. mas como a área coberta entre pontos (0.6r a 0.7r) será muito maior do que a área coberta entre 0.1r e 0.2r, o número igual de pontos será espaçado esparsamente em uma área maior, isso eu assumo que você já saiba, então a função para gerar os pontos aleatórios não deve ser linear, mas quadrático (já que o número de pontos a serem distribuídos em determinada unidade 'dr', isto é, o aumento em r será proporcional a r2 e não r), portanto, neste caso, será inverso de quadrático, desde o delta que temos (0.
fonte
Um problema tão divertido.
A lógica da probabilidade de um ponto ser escolhido diminuindo à medida que a distância da origem do eixo aumenta é explicada várias vezes acima. Nós explicamos isso tomando a raiz de U [0,1]. Aqui está uma solução geral para um r positivo no Python 3.
fonte
Você também pode usar sua intuição.
A área de um círculo é
pi*r^2
Para
r=1
Isso nos dá uma área de
pi
. Vamos assumir que temos algum tipo de funçãof
que distribuiria uniformemente osN=10
pontos dentro de um círculo. A proporção aqui é10 / pi
Agora dobramos a área e o número de pontos
Para
r=2
eN=20
Isso fornece uma área de
4pi
e a proporção é agora20/4pi
ou10/2pi
. A proporção ficará menor e menor quanto maior o raio, porque seu crescimento é quadrático e asN
escalas linearmente.Para consertar isso, podemos apenas dizer
Se você gerasse um vetor em coordenadas polares como esta
Mais pontos chegariam ao centro.
length
não está mais uniformemente distribuído, mas o vetor agora será distribuído uniformemente.fonte
1) Escolha um X aleatório entre -1 e 1.
2) Usando a fórmula do círculo, calcule os valores máximo e mínimo de Y, dado que X e um raio de 1:
3) Escolha um Y aleatório entre os extremos:
4) Incorpore seus valores de localização e raio no valor final:
fonte