In this notebook is an implementation of Monte Carlo method for calculating $\pi$.
import numpy as np
import multiprocessing
import itertools
from sage.repl.image import Image
from sage.plot.circle import Circle
from sage.plot.polygon import Polygon
from sage.plot.plot3d.base import SHOW_DEFAULTS
from IPython import display
SHOW_DEFAULTS['aspect_ratio'] = (1,1,1)
SHOW_DEFAULTS['frame_aspect_ratio'] = (1,1,1)
SHOW_DEFAULTS['perspective_depth'] = false
from sage.plot.scatter_plot import ScatterPlot
The proportion of points calculated to be inside the circle is an approximation of the ratio of the area of a circle to a square. Since the area of the square is $(2r)^2$ and the area of the circle is $\pi r^2$, that ratio is $$ \frac{\text{# samples in}}{\text{# samples out}} \approx \frac{\pi r^2}{(2r)^2} = \frac{\pi}{4}$$ This means that we can approximate $\pi$ as $$ \pi \approx 4 \frac{\text{# samples in}}{\text{# samples out}}$$
# Next two parameters control total samples and display update
total_samples = 10000
display_interval = 500
points = []
numInCircle = 0
circlePlot = circle((0, 0), 1)
squarePlot = polygon2d(((1,1), (1,-1), (-1,-1), (-1,1)), fill=False)
for i in range(1, total_samples+1):
point = np.random.uniform(-1, 1, 2)
points.append(point)
if np.dot(point, point) < 1:
numInCircle += 1
if mod(i,display_interval) == 0 :
piApprox = 4*numInCircle/i
title = 'Pi is roughly ' + str(piApprox.n()) + ' with ' + str(i) + ' samples'
pointPlot = scatter_plot(points, marker='.', aspect_ratio=1, figsize=10, title=title)
display.clear_output(wait=True)
display.display(sum([pointPlot, circlePlot, squarePlot]))