Monte Carlo integration

Imagine that we want to measure the area of a pond with arbitrary shape. Suppose that this pond is in the middle of a field with known area $A$. If we throw $N$ stones randomly, such that they land within the boundaries of the field, and we count the number of stones that fall in the pond $N_{in}$, the area of the pond will be approximately proportional to the fraction of stones that make a splash, multiplied by $A$: $$A_{pond}=\frac{N_{in}}{N}A.$$ This simple procedure is an example of the “Monte Carlo” method.

Simple Monte Carlo integration

More generaly, imagine a rectangle of height $H$ in the integration interval $[a,b]$, such that the function $f(x)$ is within its boundaries. Compute $n$ pairs of random numbers $(x_i,y_i)$ such that they are uniformly distributed inside this rectangle. The fraction of points that fall within the area contained below $f(x)$, *i. e.*, that satisfy $y_i \leq f(x_i)$ is an estimate of the ratio o fthe integral of $f(x)$ and the area of the rectangle. Hence, the estimate of the integral will be given by: $$\int _a^b{f(x)dx} \simeq I(N) = \frac{N_{in}}{N}H(b-a). $$

Another Monte Carlo procedure is based on the definition: $$\langle g \rangle=\frac{1}{(b-a)} \int _a^b{f(x)dx}. $$ In order to determine this average, we sample the value of $f(x)$: $$\langle f \rangle \simeq \frac{1}{N}\sum_{i=1}^{N}f(x_i),$$ where the $N$ values $x_i$ are distributed unformly in the interval $[a,b]$. The integral will be given by $$I(N)=(b-a) \langle f \rangle .$$

Monte Carlo error analysis

The Monte Carlo method clearly yields approximate results. The accuracy deppends on the number of values $N$ that we use for the average. A possible measure of the error is the “variance” $\sigma^2$ defined by: $$\sigma ^2=\langle f^2 \rangle - \langle f \rangle ^2, $$ where $$\langle f \rangle = \frac{1}{N} \sum_{i=1}^N f(x_i)$$ and $$\langle f^2 \rangle = \frac{1}{N} \sum_{i=1}^{N} f(x_i)^2.$$ The “standard deviation” is $\sigma$. However, we should expect that the error decreases with the number of points $N$, and the quantity $\sigma$ defines by ([mc_sigma]) does not. Hence, this cannot be a good measure of the error.

Imagine that we perform several measurements of the integral, each of them yielding a result $I_n$. These values have been obtained with different sequences of $N$ random numbers. According to the central limit theorem, these values whould be normally dstributed around a mean $\langle I \rangle$. Suppouse that we have a set of $M$ of such measurements ${I_n}$. A convenient measure of the differences of these measurements is the “standard deviation of the means” $\sigma_M$: $$\sigma_M ^2=\langle I^2 \rangle - \langle I \rangle ^2, $$ where $$\langle I \rangle = \frac{1}{M} \sum_{n=1}^M I_n$$ and $$\langle I^2 \rangle = \frac{1}{M} \sum_{n=1}^{M} I_n^2.$$ It can be proven that $$\sigma_M \approx \sigma/\sqrt{N}. $$ This relation becomes exact in the limit of a very large number of measurements. Note that this expression implies that the error decreases with the squere root of the number of trials, meaning that if we want to reduce the error by a factor 10, we need 100 times more points for the average.

Exercise 10.1: One dimensional integration

  1. Write a program that implements the “hit and miss” Monte Carlo integration algorithm. Find the estimate $I(N)$ for the integral of $$f(x)=4\sqrt{1-x^2}$$ as a function of $N$, in the interval $(0,1)$. Choose $H=1$, and sample only the $x$-dependent part $\sqrt{1-x^2}$, and multiply the result by 4. Calculate the difference between $I(N)$ and the exact result $\pi$. This difference is a measure of the error associated with the Monte Carlo estimate. Make a log-log plot of the error as a function of $N$. What is the approximate functional deppendece of the error on $N$ for large $N$?

  2. Estimate the integral of $f(x)$ using the simple Monte Carlo integration by averaging over $N$ points, using ([mc_integral2]), and compute the error as a function of $N$, for $N$ upt to 10,000. Determine the approximate functional deppendence of the error on $N$ for large $N$. How many trials are necessary to determine $I_N$ to two decimal places?

  3. Perform 10 measurements $I_n(N)$, with $N=10,000$ using different random sequences. Show in a table the values of $I_n$ and $\sigma$ according to ([mc_integral2]) and ([mc_sigma]). Use ([mc_sigmam]) to estimate the standard deviation of the means, and compare to the values obtained from ([mc_sigma2]) using the 100,000 values.

  4. To verify that your result for the error is independent of the number of sets you used to divide your data, repeat the previous item grouping your results in 20 groups of 5,000 points each.

Exercise 10.2: Importance of randomness

To examine the effects of a poor random number generator, modify your program to use the linear congruential random number generator using the perameters $a=5$, $c=0$ and the seed $x_1=1$. Repeat the integral of the previous exercise and compare your results.

Challenge 10.1:

Exercise 10.2


In [134]:
%matplotlib inline
import numpy as np
from matplotlib import pyplot

# Hit and miss Monte Carlo integration
ngroups = 16

I = np.zeros(ngroups)
N = np.zeros(ngroups)
E = np.zeros(ngroups)

n0 = 100
for i in range(ngroups):

    N[i] = n0
    x = np.random.random(n0)
    y = np.random.random(n0)
    I[i] = 0.
    Nin = 0
    for j in range(n0):
        if(y[j] < np.sqrt(1-x[j]**2)):
            Nin += 1
            
    I[i] = 4.*float(Nin)/float(n0)
    E[i] = abs(I[i]-np.pi)
    print n0,Nin,I[i],E[i]
    n0 *= 2
    
            
pyplot.plot(N,E,ls='-',c='red',lw=3);
pyplot.plot(N,0.8/np.sqrt(N),ls='-',c='blue',lw=3);

pyplot.xscale('log')
pyplot.yscale('log')


100 75 3.0 0.14159265359
200 159 3.18 0.0384073464102
400 318 3.18 0.0384073464102
800 636 3.18 0.0384073464102
1600 1269 3.1725 0.0309073464102
3200 2500 3.125 0.0165926535898
6400 5045 3.153125 0.0115323464102
12800 10017 3.1303125 0.0112801535898
25600 20188 3.154375 0.0127823464102
51200 40219 3.142109375 0.000516721410207
102400 80318 3.137421875 0.00417077858979
204800 161064 3.14578125 0.00418859641021
409600 321654 3.14115234375 0.000440309839793
819200 643676 3.14294921875 0.00135656516021
1638400 1286191 3.14011474609 0.00147790749604
3276800 2575084 3.14341308594 0.00182043234771

In [43]:
# Simple Monte Carlo Integration
ngroups = 16

I = np.zeros(ngroups)
N = np.zeros(ngroups)
E = np.zeros(ngroups)

n0 = 100
for i in range(ngroups):

    N[i] = n0
    r = np.random.random(n0)
    I[i] = 0.
    for j in range(n0):
        x = r[j]
        I[i] += np.sqrt(1-x**2)
        
    I[i] *= 4./float(n0)
    E[i] = abs(I[i]-np.pi)
    print n0,I[i],E[i]
    n0 *= 2
    
            
pyplot.plot(N,E,ls='-',c='red',lw=3);
pyplot.plot(N,0.8/np.sqrt(N),ls='-',c='blue',lw=3);
pyplot.xscale('log')
pyplot.yscale('log')


100 3.20920994888 0.0676172952856
200 3.19023195241 0.0486392988246
400 3.13539345091 0.00619920268006
800 3.18467753241 0.0430848788188
1600 3.1148121176 0.0267805359933
3200 3.14792033551 0.00632768192034
6400 3.14749188649 0.00589923289621
12800 3.13735813292 0.00423452066773
25600 3.13359006584 0.00800258774604
51200 3.1398924647 0.00170018888973
102400 3.1435290202 0.00193636660599
204800 3.14206545238 0.00047279879124
409600 3.13999805065 0.00159460293962
819200 3.14154966288 4.29907095283e-05
1638400 3.14063731607 0.000955337516072
3276800 3.14223148552 0.000638831930158

In [37]:
n0 = 100000
I = np.zeros(n0)
r = np.random.random(n0)
for j in range(n0):
    x = r[j]
    I[j] = 4*np.sqrt(1-x**2)

def group_measurements(ngroups):
    global I,n0
    
    nmeasurements = n0/ngroups
    for n in range(ngroups):
        Ig = 0.
        Ig2 = 0.
        for i in range(n*nmeasurements,(n+1)*nmeasurements):
            Ig += I[i]
            Ig2 += I[i]**2
        Ig /= nmeasurements
        Ig2 /= nmeasurements
        sigma = Ig2-Ig**2
        print Ig,Ig2,sigma
        
group_measurements(10)
print "============================="
group_measurements(20)
print "============================="
group_measurements(1)


3.14093947721 10.6643035615 0.798802762018
3.1499382371 10.7055506255 0.783439727913
3.13319009661 10.6235086554 0.806628473869
3.13795800203 10.6515853995 0.804804977031
3.13531651984 10.6418893471 0.811679667517
3.13173378372 10.6092906027 0.801534110608
3.13380941075 10.6278067095 0.807045286608
3.16020428513 10.7543778246 0.767486700818
3.14413190095 10.6786028396 0.793037429062
3.13419696292 10.6266539235 0.803463321146
=============================
3.15153961803 10.7326143302 0.800412366189
3.13033933639 10.5959927928 0.796968431876
3.13355454219 10.6259457425 0.806781673606
3.16632193201 10.7851555084 0.759560931301
3.12325523145 10.5737464366 0.819023195819
3.14312496178 10.6732708742 0.794036348827
3.12971418414 10.6123016964 0.817190822021
3.14620181992 10.6908691026 0.792283210975
3.13347136259 10.6306027368 0.811959956686
3.13716167709 10.6531759573 0.811392569138
3.13254956736 10.6148269262 0.80196013421
3.13091800008 10.6037542792 0.801106756001
3.13850922008 10.6499766584 0.799736533867
3.12910960142 10.6056367606 0.814309862934
3.16758589926 10.7971696007 0.763569171544
3.15282267101 10.7115860485 0.771295253638
3.1307753286 10.626421502 0.824667343858
3.1574884733 10.7307841772 0.761050718215
3.11465580988 10.5383340428 0.837253228776
3.15373811595 10.7149738042 0.768909700192
=============================
3.14014186763 10.6583569489 0.797866000074

Variance reduction

If the function being integrated does not fluctuate too much in the interval of integration, and does not differ much from the average value, then the standard Monte Carlo mean-value method should work well with a reasonable number of points. Otherwise, we will find that the variance is very large, meaning that some points will make small contributions, while others will make large contributions to the integral. If this is the case, the algorithm will be very inefficient. The method can be improved by splitting the function $f(x)$ in two $f(x)=f_1(x)+f_2(x)$, such that the integral of $f_1(x)$ is known, and $f_2(x)$ as a small variance. The “variance reduction” technique, consists then in evaluating the integral of $f_2(x)$ to obtain: $$\int _a^b{f(x)dx}=\int _a^b {f_1(x)dx} + \int _a^b{f_2(x)dx} = \int _a^b{f_1(x)dx}+J.$$

Importance Sampling

Imagine that we want to sample the function $f(x)=e^{-x^2}$ in the interval $[0,1]$. It is evident that most of our points will fall in the region where the value of $f(x)$ is very small, and therefore we will need a large number of values to achieve a decent accuracy. A way to improve the measurement by reducing the variance is obtained by “importance sampling”. As the name says, the idea is to sample the regions with larger contributions to the integral. For this goal, we introduce a probability distribution $P(x)$ normalized in the interval of integration $$\int _a^b{P(x)dx} = 1.$$ Then, we can rewrite the integral of $f(x)$ as $$I=\int _a^b{\frac{f(x)}{P(x)}P(x)dx} $$ We can evaluate this integral, by sampling according to the probability distribution $P(x)$ and evaluating the sum $$I(N)=\frac{1}{N} \sum_{i=1}^N \frac{f(x_i)}{P(x_i)}. $$ Note that for the uniform case $P(x)=1/(b-a)$, the expression reduces to the simple Monte Carlo integral.

We are free to choose $P(x)$ now. We wish to do it in a way to reduce and minimize the variance of the integrand $f(x)/P(x)$. The way to to this is picking a $P(x)$ that mimics $f(x)$ where $f(x)$ is large. if we are able to determine an apropiate $P(x)$, the integrand will be slowly varying, and hence the variance will be reduced. Another consideration is that the generation of points according to the distribution $P(x)$ should be a simple task. As an example, let us consider again the integral $$I=\int _0^1 {e^{-x^2}dx}.$$ A reasonable choice for a weigh function is $P(x)=Ae^{-x}$, where $A$ is a normalization constant.

Notice that for $P(x)=f(x)$ the variance is zero! This is known as the zero variance property. There is a catch, though: The probability function $P(x)$ needs to be normalized, implying that in reality, $P(x)=f(x)/\int f(x)dx$, which assumes that we know in advance precisely the integral that we are trying to calculate!

Exercise 10.3: Importance sampling

  1. Choose the weight function $P(x)=e^{-x}$ and evaluate the integral: $$\int _0^{\infty} {x^{3/2}e^{-x}dx}.$$

  2. Choose $P(x)=e^{-ax}$ and estimate the integral $$\int _0^{\pi} \frac{dx}{x^2+\cos ^2{x}}.$$ Determine the value of $a$ that minimizes the variance of the integral.


In [200]:
# Trapezoidal integration
def trapezoids(func, xmin, xmax, nmax):
    Isim = func(xmin)+func(xmax)
    h = (xmax-xmin)/nmax
    for i in range(1,nmax):
        x = xmin+i*h
        Isim += 2*func(x)

    Isim *= h/2
    return Isim

def f(x):
    return x**1.5*np.exp(-x)
    
    
print "Trapezoids: ", trapezoids(f, 0., 20., 100000)

# Simple Monte Carlo integration
n0 = 1000000
r = np.random.random(n0)

x = -np.log(r)
Itot = np.sum(x**1.5)
print "Simple Monte Carlo: ", Itot/n0


Trapezoids:  1.32934018965
Simple Monte Carlo:  1.32519811567

In [201]:
# Trapezoidal integration

def g(x):
    return 1./(x**2+np.cos(x)**2)

print "Trapezoids: ", trapezoids(g, 0., np.pi, 1000000)

# Simple Monte Carlo integration
n0 = 100000
a = np.arange(0.1,2.1,0.1)
I = np.arange(0.1,2.1,0.1)

r = np.random.random(n0)

I0 = np.sum(1./((r*np.pi)**2+np.cos(r*np.pi)**2))
print "Simple Monte Carlo: ", I0/n0*np.pi

# Importance Sampling
print "Importance Sampling:"
x = -np.log(r)
i = 0
for ai in a:
    norm = (1.-np.exp(-ai*np.pi))/ai
    x1 = norm*x/ai
    Itot = 0.
    Nin = 0
    for xi in x1:
        if(xi <= np.pi):
            Nin += 1
            Itot += g(xi)*np.exp(xi*ai)
    Itot *= norm
    I[i] = Itot/Nin
    i += 1
    print ai,Itot/Nin
    
pyplot.plot(a,I,ls='-',marker='o',c='red',lw=3);


Trapezoids:  1.58118797085
Simple Monte Carlo:  1.58232612038
Importance Sampling:
0.1 1.51733652865
0.2 1.50271113189
0.3 1.49497765112
0.4 1.49760515522
0.5 1.51440492709
0.6 1.53705127814
0.7 1.55998782484
0.8 1.57856622469
0.9 1.5850784562
1.0 1.57501692127
1.1 1.54617823139
1.2 1.4988445746
1.3 1.43637280277
1.4 1.36362800283
1.5 1.28410162522
1.6 1.20147734863
1.7 1.12083134139
1.8 1.04338661046
1.9 0.970940233688
2.0 0.904242852582

Exercise 10.4: The Metropolis algorithm

Use the Metropolis algorithm to sample points according to a ditribution and estimate the integral $$\int _0^4 {x^2e^{-x}dx},$$ with $P(x)=e^{-x}$ for $0 \leq x \leq 4$. Plot the number of times the walker is at points $x_0$, $x_1$, $x_2$, ... Is the integrand sampled uniformly? If not, what is the approximate region of $x$ where the integrand is sampled more often?


In [205]:
delta = 2
xmin = 0.
xmax = 4.

def f(x):
    return x**2*np.exp(-x)

def P(x):
    global xmin, xmax
    if(x < xmin or x > xmax):
        return 0.
    return np.exp(-x)


def metropolis(xold):
    global delta
    xtrial = np.random.random()    
    xtrial = xold+(2*xtrial-1)*delta
    weight = P(xtrial)/P(xold)
    xnew = xold
    if(weight >= 1): #Accept
        xnew = xtrial
    elif(weight != 0):
        r = np.random.random()
        if(r <= weight): #Accept
            xnew = xtrial
    return xnew


xwalker = (xmax+xmin)/2.
for i in range(100000):
    xwalker = metropolis(xwalker)

I0 = 0.
N = 300000

x = np.zeros(N)
x[0] = xwalker
for i in range(1,N):
    x[i] = metropolis(x[i-1])
    I0 += x[i]**2

binwidth=0.1
pyplot.hist(x,bins=np.arange(xmin-1, xmax+1, 0.1),normed=True);

print "Trapezoids: ", trapezoids(f,xmin,xmax,10000)
print "Metropolis: ", I0/(1.-np.exp(-4.))/N


Trapezoids:  1.52379338694
Metropolis:  1.58122841473

Challenge 10.1

  • Calculate the integral $\int_0^1 x^2 dx=1/3$ using simple MC integration and importance sampling with $P(x)=x$.

  • Calculate the integral $\int_0^1 \sqrt{x}dx=2/3$ using simple MC integration and $P(x)=1-e^{-ax}$. Find the values of $a$ that minimizes the variance.


In [ ]: