Método de Monte Carlo e transformações

De Física Computacional
Revisão de 19h56min de 29 de abril de 2022 por Jhordan (discussão | contribs)
Ir para navegação Ir para pesquisar

Transformação linear

Sorteando um número aleatório x[0,1) então fazemos uma transformação para obter um número y[a,b). Isto é, obtemos a seguinte transformação f:[0,1)[a,b) da seguinte forma:

y(x)=a+(ba)x

Se todos os números entre 0 e 1 tinham igual probabilidade de serem sorteados, após a transformação todos os números entre a e b também possuem igual probabilidade, pois y varia com x de forma linear, isto é, a distribuição uniforme de números é mantida.Por sua vez, a distribuição uniforme significa que a probabiliade de obter um número entre x e x+dx é dada pela função densidade de probabilidade da seguinte forma:

p(x)dx={dx,0<x<10,outra forma

Sendo p(x)=p constante, temos que: +dx=p01dx=p=1

Pela normalização. Mas se ampliarmos o intervalo dos números possíveis para entre a e b:

+pdx=abpdx=pabdx=p(ba)=1

Então agora p(y)=p=1/(ba). Isto é distribuição de probabilidade continua constante, mas com uma menor probabilidade de sortear um número y qualquer, quando em comparação de sortear um x qualquer.

Transformação não-linear

O mesmo não ocorre com uma transformação não linear. Por exemplo se y(x)=4x2, derivando temos que:

dydx=8xdy=8xdx

Diferente do caso anterior que tínhamos apenas a transformação linear dy=(ba)dx. Podemos ver ainda usando a própria definição de derivada:

y(x+dx)y(x)=4(x+dx)24x2=4x2+4xdx+dx24x2=42xdx+dx2

E sendo dx um diferencial então dx20, logo dy=8xdx. Agora a distribuição de probabilidade é alterada com a transformação. Para uma transformação y(x) qualquer, como a probabilidade se conserva, ainda temos:

|p(y)dy|=|p(x)dx|

Considrando que y=y(x) tem inversa, então x=x(y) então:

|p(y)dy|=|p(x)dx|p(y)|dy|=p(x)|dx|p(y)=p(x)|dxdy|

Sendo y(x)=ln(x) então reescrevendo x=ey, logo dxdy=ey Então temos:

p(y)=p(x)ey

E sendo nossa ditribuição em x uniforme com p(x)=p=1 como vimos anteriormente, ficamos com:

p(y)=ey

Para a transformação y=ln(x). O mais comum é que saibamos a distribuição de probabilidade p(y) que queremos, e uma vez que:

p(y)=|dxdy|

E integramos então para encontrar x(y).

Método da rejeição

Nem sempre o p(y) desejado é fácil de definir matematicamente. O método da rejeição é um método rústico para obtermos p(y).

  • Desenhar a função p(y) desejada dentro dos limites ay<b e 0p(y)pmax.
  • Geramos um ponto aleatório (y,p(y)), se estiver abaixo da curva desejada é aceito.

Se gerarmos pontos aleatórios em grande quantidade, a razão de pontos aceitos para cada y em relação à todos o pontos aleatórios gerados neste y, nos dá uma estimativa de p(y) neste ponto, em relação do pmax. Isto é, se para um y qualquer, metade dos pontos gerado aleatoriamente foram válidos, então p(y)pmax2.

Cálulo de integrais definidas

Em uma ideia bastante análoga à anterior, aqui utilizamos a ideia que a integral definida é cálculo da área sob a curva. Definindo novamente limites xminxxmax e yminyymax no qual a região que queremos calcular está contida, geramos uma série de pontos aleatórios, se gerado pontos suficientes, a razão de pontos que foram gerados dentro da área que queremos calcular em relação ao total de pontos gerados, será a mesma razão da área que queremos calcular em relação à área total definida pelos limites.

#Cálculo da área de um círculo
import matplotlib.pyplot as plt #Plotar gráfico
import numpy as np              #Funções matemáticas
import random                   #Números aleatórios

r=1 #Raio do círculo
Np=1000000 #Número de pontos
hitx=[];hity=[];missx=[];missy=[] #Resultados
for n in range(Np):
  x=random.random()*2-1            #Pontos aleatórios gerados entre -1 e +1 
  y=random.random()*2-1            #Pontos aleatórios gerados entre -1 e +1
  if(np.sqrt(x**2+y**2)<=r):       #Se o ponto caiu dentro do círculo
    hitx.append(x);hity.append(y)
  else:
    missx.append(x);missy.append(y)

#Plotar curvas
x=np.arange(-1,1,1E-5)
plt.plot(x,-np.sqrt(r-x**2),'-k')
plt.plot(x,np.sqrt(r-x**2),'-k')
#Plotar pontos
plt.plot(hitx,hity,'or')
plt.plot(missx,missy,'ob')

a_ret=2*2 #Área do retângulo
a_cir=a_ret*len(hitx)/Np      #A_ret *(hit/N)
print('A área do círculo estimada é: {:.2f}'.format(a_cir))
print('A área do círculo exata    é: {:.2f}'.format(np.pi*r**2))