Probability distributions Exercise 1

Probability distributions Exercise 1#

import numpy as np
import matplotlib.pyplot as plt

seed = 5885
rng = np.random.default_rng(seed)
# We'll need this a few times, so write a function to take the x values and 
# plot a histogram comparing to the analytic function func
def plot_distribution(x, func):
    plt.clf()
    plt.hist(x, density=True, bins=100, histtype = 'step')
    xx = np.linspace(0.0,max(x),100)
    plt.plot(xx, func(xx),':')
    plt.yscale('log')
    plt.xlabel('x')
    plt.show()

Rejection method#

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

xmax = 10
x = xmax * rng.uniform(size = 10**5)    # Generate x values up to xmax
y = rng.uniform(size = 10**5)

# Reject
ind = np.where(y <= f(x))
ind2 = np.where(y > f(x))

# Plot the points to show which ones are accepted and which rejected
plt.plot(x[ind2],y[ind2], 'bo', ms=0.1)
plt.plot(x[ind],y[ind], 'ro', ms=0.1)
# Plot the analytic solution for the boundary (see below)
xx = np.linspace(0.0,xmax,100)
plt.plot(xx, f(xx), 'k')
plt.xlabel('x')
plt.show()

plot_distribution(x[ind], f)
_images/4843e4e23df6e5070f344e65a77ae5b9644d6b3f2b5caddb0c05f7732e6e364c.png _images/2d9713e7549256859ce7684fb3916f9f5ad45f85fd4e35000c0c181785f3ab8a.png

Transformation method#

y = rng.uniform(size = 10**5)

x = - np.log(y)

# Plot the distribution of x and compare with the exponential distribution
plot_distribution(x, f)

# Plot 1-y(x) to illustrate that y is related to the cumulative distribution function
plt.clf()
plt.plot(x, 1-y, '.', ms=0.1)
xx = np.linspace(0.0,xmax,100)
plt.plot(xx, 1-f(xx), 'k:')
plt.xlabel('x')
plt.ylabel('1-y')
plt.show()
_images/f5a00afdc5cc5f8858ede093444ae2ff3cf74edb2b0cb24945a5248faec96c14.png _images/d6db953bd3e2fb6d3d55d9b0c814f3fcc2f2e10e40c5b1d716198d8fd608ed22.png

Ratio of uniforms#

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

u = rng.uniform(size = 10**5)
v = rng.uniform(size = 10**5)
# choose which points to keep -- we renormalize f here to drop the factor of 2
ind = np.where(u <= np.sqrt(f(v/u)))
ind2 = np.where(u > np.sqrt(f(v/u)))
x = v[ind]/u[ind]

# Plot the points to show which ones are accepted and which rejected
plt.plot(u[ind2],v[ind2], 'bo', ms=0.1)
plt.plot(u[ind],v[ind], 'ro', ms=0.1)
# Plot the analytic solution for the boundary (see below)
uu = np.linspace(0.001,1.0,100)
plt.plot(uu, -2*uu*np.log(uu), 'k')
plt.xlabel('u')
plt.ylabel('v')
plt.show()

# Plot the distribution f(x)
plot_distribution(x, f)
_images/637034df2b6e389fd8a2f06e5c3be374df471464c2aaa9b101474e8e55a91fc5.png _images/e13ef90e551e2edb3f7091890f864499cf076827a75aacf32594f753ad24f651.png

The black curve above separates the accepted and rejected points. To derive this, start with

\[u \leq \sqrt{\exp\left(-{v\over u}\right)}\]

and invert this to get \(v\):

\[u^2 \leq \exp\left(-{v\over u}\right)\]
\[2\ln u \leq -{v\over u}\]
\[2 u \ln u \leq -v\]
\[v \leq -2 u \ln u\]

which is plotted as the black curve in the figure.