Simulazione Monte Carlo#
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import arviz as az
%config InlineBackend.figure_format = 'retina'
RANDOM_SEED = 42
rng = np.random.default_rng(RANDOM_SEED)
az.style.use("arviz-darkgrid")
sns.set_theme(palette="colorblind")
Stima dell’integrale di un cerchio#
In questo esempio, usiamo il metodo di Monte Carlo per stimare l’area di una regione geometrica, ovvero un cerchio. Il metodo di Monte Carlo si basa sulla generazione casuale di punti all’interno di un dominio conosciuto e sulla valutazione di quanti di questi punti cadono all’interno della regione di interesse. L’idea è che la frazione di punti all’interno della regione rispetto al totale dei punti generati sia proporzionale all’area della regione stessa.
Nella figura seguente, coppie casuali di numeri (ad esempio, x e y) sono scelti all’interno di un quadrato di dimensioni \(2 \times 2\). Calcolando il rapporto tra il numero di punti che cadono all’interno del cerchio e tutti i campioni, possiamo ottenere un’approssimazione dell’area del cerchio moltiplicando l’area del quadrato per il rapporto dei campioni. Questo tipo di algoritmo è una forma di rejection sampling di Monte Carlo. Dopo aver eseguito il codice con un grande numero di campioni, l’area stimata del cerchio si avvicina al valore teorico di π (pi greco), che è il valore atteso per l’area di un cerchio unitario. La precisione della stima aumenta con il numero di campioni usati.
Ecco come funziona il codice Python presentato di seguito:
Iniziamo generando “samples” punti casuali all’interno di un quadrato con vertici (-1, -1) e (1, 1). Questo quadrato contiene il cerchio di raggio 1 in cui desideriamo calcolare l’area.
Per ciascun punto generato, calcoliamo la distanza dal centro del cerchio utilizzando la formula della distanza euclidea:
distance = x**2 + y**2
.Se la distanza calcolata è minore o uguale a 1, il punto è all’interno del cerchio, quindi incrementiamo la variabile “inside_circle” e aggiungiamo le coordinate (x, y) a due elenchi separati: “x_inside” e “y_inside”. Altrimenti, aggiungiamo le coordinate ad altri due elenchi separati: “x_outside” e “y_outside”.
Alla fine del ciclo, calcoliamo l’area stimata del cerchio utilizzando la formula:
area_estimate = (inside_circle / samples) * 4
(la lunghezza di ogni lato del quadrato è pari a 2). Questo perché il rapporto tra i punti all’interno del cerchio e il totale dei punti generati è proporzionale all’area del cerchio rispetto all’area del quadrato circoscritto.Infine, motriamo una rappresentazione visiva del cerchio, dei punti interni (in verde) e dei punti esterni (in blu) attraverso un grafico a dispersione.
def monte_carlo_circle_area(samples):
inside_circle = 0
# Per la visualizzazione
x_inside = []
y_inside = []
x_outside = []
y_outside = []
for _ in range(samples):
x, y = np.random.uniform(-1, 1), np.random.uniform(-1, 1) # Punti casuali nel quadrato
distance = x**2 + y**2 # Distanza dal centro
if distance <= 1: # Se il punto è dentro il cerchio
inside_circle += 1
x_inside.append(x)
y_inside.append(y)
else:
x_outside.append(x)
y_outside.append(y)
# Calcolo dell'area
area_estimate = (inside_circle / samples) * 4
# Visualizzazione
fig, ax = plt.subplots(figsize=(4, 4))
circle = plt.Circle((0, 0), 1, color='black', fill=False)
ax.add_artist(circle)
ax.scatter(x_inside, y_inside, color='green', s=1)
ax.scatter(x_outside, y_outside, color='blue', s=1)
ax.set_xlim([-1, 1])
ax.set_ylim([-1, 1])
ax.set_aspect('equal', adjustable='box')
plt.title(f"Stima dell'Area del Cerchio con {samples} Campioni")
plt.show()
return area_estimate
# Test dell'algoritmo con 1000 campioni
estimated_area = monte_carlo_circle_area(1000)
estimated_area
![../_images/e08ddd5fe901ad1a208d21aec74b2202c57885b0b7d1d3e639c1ce055e000f2d.png](../_images/e08ddd5fe901ad1a208d21aec74b2202c57885b0b7d1d3e639c1ce055e000f2d.png)
3.14
In questo esempio ottieniamo una stima dell’area del cerchio usando il metodo di Monte Carlo con 1000 campioni. Questo metodo può essere esteso a un numero maggiore di campioni per ottenere una stima più precisa, poiché la precisione della stima aumenta con il numero di campioni generati.