Lesson 15 of 15

Monte Carlo Integration

Monte Carlo Integration

Monte Carlo integration uses random sampling to estimate integrals — particularly powerful in high dimensions where deterministic quadrature becomes infeasible.

Basic Idea

To compute abf(x)dx\int_a^b f(x)\, dx, draw NN uniform random samples xi[a,b]x_i \in [a, b] and estimate:

abf(x)dxbaNi=1Nf(xi)\int_a^b f(x)\, dx \approx \frac{b-a}{N} \sum_{i=1}^N f(x_i)

The error scales as 1/N1/\sqrt{N} regardless of dimension — a huge advantage over grid-based methods in dd dimensions (which scale as 1/N2/d1/N^{2/d}).

Importance Sampling

When ff is sharply peaked, plain sampling is inefficient. Instead, sample from a distribution p(x)p(x) that is large where ff is large:

f(x)dx=f(x)p(x)p(x)dx1Ni=1Nf(xi)p(xi)\int f(x)\, dx = \int \frac{f(x)}{p(x)}\, p(x)\, dx \approx \frac{1}{N} \sum_{i=1}^N \frac{f(x_i)}{p(x_i)}

Optimal choice: p(x)f(x)p(x) \propto |f(x)| (reduces variance to zero for positive ff).

Estimating π

A classic application: generate random points (x,y)[0,1)2(x, y) \in [0,1)^2. The fraction landing inside the unit quarter-circle (x2+y2<1x^2 + y^2 < 1) converges to π/4\pi/4:

π4(points inside circle)N\pi \approx \frac{4 \cdot \text{(points inside circle)}}{N}

Reproducible Randomness: LCG

For reproducibility, we use a Linear Congruential Generator (LCG):

sn+1=(asn+c)modm,xn=sn/ms_{n+1} = (a \cdot s_n + c) \bmod m, \qquad x_n = s_n / m

with parameters a=1,664,525a = 1{,}664{,}525, c=1,013,904,223c = 1{,}013{,}904{,}223, m=232m = 2^{32} (Numerical Recipes constants). Starting from a seed s0s_0, this generates a deterministic sequence of uniform pseudo-random numbers in [0,1)[0, 1).

Implementation

  • lcg_random(seed, n) — returns list of nn uniform [0,1)[0,1) values via LCG
  • monte_carlo_integrate(f_func, a, b, N=10000, seed=42) — plain Monte Carlo estimate
  • monte_carlo_pi(N=10000, seed=42) — estimate π\pi using the unit circle method
import math

def lcg_random(seed, n):
    a = 1664525
    c = 1013904223
    m = 2**32
    state = seed
    result = []
    for _ in range(n):
        state = (a * state + c) % m
        result.append(state / m)
    return result
Python runtime loading...
Loading...
Click "Run" to execute your code.