Monte Carlo Integration

Example: find the area of a circle

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
r  = 1.0                          # circle radius
Asquare = (2*r)**2                     # area of square enclosing circle
n  = 1000000                      # number of tries
rx = np.random.rand(n)*2*r - r    # -1 to 1; x locations
ry = np.random.rand(n)*2*r - r    # -1 to 1; y locations

rr = np.sqrt(rx**2 + ry**2)      # radial location
nhits = len(np.where(rr<r)[0])   # number of "hits"
I = float(nhits)/n * Asquare     # integral of circle

Aexact = np.pi*r**2
print('A_mc    =', I)
print('A_exact =', Aexact)
A_mc    = 3.142156
A_exact = 3.141592653589793

Relative Error

$$\epsilon_r \propto\frac{1}{\sqrt{n_{tot}}}.$$
i_n = np.zeros(n)
i_n[rr<r] = 1

itry  = np.arange(1,n+1)
Areas = np.cumsum(i_n)/itry*Asquare
errs  = np.abs((Areas-Aexact)/Aexact)

plt.rc('font', size=14)
plt.plot(np.log10(itry), np.log10(errs));
plt.plot(np.array([0, np.log10(n)]), 
         np.array([np.log10(errs[0]), np.log10(errs[0])-0.5*np.log10(n)]));

plt.xlabel(r'$\log_{10}(n_{tot})$');
plt.ylabel(r'$\log_{10}(\epsilon_r)$');
plt.legend(['Relative error', 'Slope=-1/2'], frameon=False);
MC

Visual Illustration

r  = 1.0                          # circle radius
As = (2*r)**2                     # area of square enclosing circle
n  = 10000                         # number of tries
rx = np.random.rand(n)*2*r - r    # -1 to 1; x locations
ry = np.random.rand(n)*2*r - r    # -1 to 1; y locations

rr = np.sqrt(rx**2 + ry**2)      # radial location
plt.plot(rx[rr<r], ry[rr<r], '.', markersize=1);
plt.plot(rx[rr>r], ry[rr>r], 'rx', markersize=1);
plt.axis('equal');
MC

Generic function

$$I = \int_a^bf(x)dx,$$

we define a rectagle whose base is $[a,\,b]$, and whose height is larger than the maximum value of $f$ on $[a,\,b]$.

$$I \approx A_{rectangle}\frac{n_{hits}}{n_{tot}}.$$

Example

x = np.sort(np.random.rand(10))
y = np.random.rand(10)
p = np.polyfit(x,y,5)
x = np.linspace(0,1,1000)
y = np.polyval(p,x)
yshift = np.abs(np.min(y))
y += yshift

n = 10000
rx = np.random.rand(n)
ry = np.random.rand(n)*np.max(y)
fx = np.polyval(p,rx) + yshift

yhit  = ry[ry<=fx]
xhit  = rx[ry<=fx]
ymiss = ry[ry>fx]
xmiss = rx[ry>fx]

plt.plot(xhit,  yhit,  'b.', markersize=2)
plt.plot(xmiss, ymiss, 'r.', markersize=2)
plt.plot(x,y, linewidth=5, color='black')
plt.ylim([0,1.1*np.max(y)])

Arectangle = 1*np.max(y)
I = Arectangle*len(xhit)/n

Ie = p[0]/6 + p[1]/5 + p[2]/4 + p[3]/3 + p[4]/2 + p[5] + yshift

print("I_mc    = ", I)
print("I_exact = ", Ie)
I_mc    =  1.140563269736279
I_exact =  1.1432022133192445
MC

Uses