import torch
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
# Retina display
%config InlineBackend.figure_format = 'retina'
import warnings
'ignore') warnings.filterwarnings(
from tueplots import bundles
plt.rcParams.update(bundles.beamer_moml())
# Also add despine to the bundle using rcParams
'axes.spines.right'] = False
plt.rcParams['axes.spines.top'] = False
plt.rcParams[
# Increase font size to match Beamer template
'font.size'] = 16
plt.rcParams[# Make background transparent
'figure.facecolor'] = 'none' plt.rcParams[
= torch.pi
true_pi true_pi
3.141592653589793
import torch
import torch.distributions as dist
def estimate_pi(N, seed):
torch.manual_seed(seed)= torch.rand(N, 2) # Generate N random points in [0, 1] × [0, 1]
xy = torch.sqrt(xy[:, 0]**2 + xy[:, 1]**2) # Calculate distance from the origin
distance = distance <= 1.0 # Check if point falls inside the quarter circle
inside_circle = torch.sum(inside_circle).item() # Count points inside the quarter circle
points_inside = (points_inside / N) * 4.0 # Calculate the π estimate
pi_estimate return pi_estimate
= 10000
N = 42
seed
torch.manual_seed(seed)= torch.rand(N, 2)
xy = xy[:, 0]
x1 = xy[:, 1]
x2
= torch.sqrt(x1**2 + x2**2)
distances
= distances <= 1.0
c
= c.float())
plt.scatter(x1, x2, c 'equal')
plt.gca().set_aspect(
sum().item()/N)*4) plt.title((c.
Text(0.5, 1.0, '3.1464')
# Different random seeds and sample sizes
= [0, 1, 2, 3, 4, 5]
random_seeds = [1, 2, 3, 4, 5, 6, 7, 8]
log_sample_sizes = [10**i for i in log_sample_sizes]
sample_sizes
= []
pi_estimates for seed in random_seeds:
for N in sample_sizes:
= estimate_pi(N, seed)
pi_estimate
pi_estimates.append((seed, N, pi_estimate))
seed | N | pi_estimate | |
---|---|---|---|
0 | 0 | 10 | 3.200000 |
1 | 0 | 100 | 3.200000 |
2 | 0 | 1000 | 3.140000 |
3 | 0 | 10000 | 3.139200 |
4 | 0 | 100000 | 3.137200 |
5 | 0 | 1000000 | 3.140544 |
6 | 0 | 10000000 | 3.141136 |
7 | 0 | 100000000 | 3.141476 |
8 | 1 | 10 | 3.600000 |
9 | 1 | 100 | 2.880000 |
# Create a Pandas DataFrame from the list of tuples
= pd.DataFrame(pi_estimates, columns=["seed", "N", "pi_estimate"])
df 20) df.head(
seed | N | pi_estimate | |
---|---|---|---|
0 | 0 | 10 | 3.200000 |
1 | 0 | 100 | 3.200000 |
2 | 0 | 1000 | 3.140000 |
3 | 0 | 10000 | 3.139200 |
4 | 0 | 100000 | 3.137200 |
5 | 0 | 1000000 | 3.140544 |
6 | 0 | 10000000 | 3.141136 |
7 | 0 | 100000000 | 3.141476 |
8 | 1 | 10 | 3.600000 |
9 | 1 | 100 | 2.880000 |
10 | 1 | 1000 | 3.096000 |
11 | 1 | 10000 | 3.144000 |
12 | 1 | 100000 | 3.139640 |
13 | 1 | 1000000 | 3.143724 |
14 | 1 | 10000000 | 3.142105 |
15 | 1 | 100000000 | 3.141681 |
16 | 2 | 10 | 3.600000 |
17 | 2 | 100 | 3.120000 |
18 | 2 | 1000 | 3.140000 |
19 | 2 | 10000 | 3.144000 |
= df.groupby("N").agg(["mean", "std"])["pi_estimate"]
df_grouped df_grouped
mean | std | |
---|---|---|
N | ||
10 | 3.200000 | 0.357771 |
100 | 3.120000 | 0.153883 |
1000 | 3.147333 | 0.090099 |
10000 | 3.147200 | 0.007065 |
100000 | 3.140580 | 0.007081 |
1000000 | 3.142121 | 0.001377 |
10000000 | 3.141548 | 0.000712 |
100000000 | 3.141659 | 0.000162 |
# Plot the estimates using mean and standard deviation
=(8, 6))
plt.figure(figsize"mean"].plot(yerr=df_grouped["std"], capsize=5, marker="o")
df_grouped[="black", linestyle="--")
plt.axhline(true_pi, color"Sample Size")
plt.xlabel("Estimated π")
plt.ylabel("Estimating π using Monte Carlo Sampling")
plt.title(# log scale on x-axis
"log") plt.xscale(
findfont: Font family ['cursive'] not found. Falling back to DejaVu Sans.
findfont: Generic family 'cursive' not found because none of the following families were found: Apple Chancery, Textile, Zapf Chancery, Sand, Script MT, Felipa, Comic Neue, Comic Sans MS, cursive
# Plot only 10^4 and higher
=(8, 6))
plt.figure(figsize= df_grouped.query("N >= 10**4")
subset "mean"].plot(yerr=subset["std"], capsize=5, marker="o")
subset["Sample Size")
plt.xlabel("Estimated π")
plt.ylabel("Estimating π using Monte Carlo Sampling")
plt.title(# log scale on x-axis
"log")
plt.xscale("log")
plt.yscale(
="black", linestyle="--")
plt.axhline(true_pi, color
# plot true_pi +- 0.0001
- 0.0001, true_pi + 0.0001, color="black", alpha=0.2, label="True π ± 0.0001")
plt.axhspan(true_pi plt.legend()
<matplotlib.legend.Legend at 0x7f6b93cb3d90>