Transforming Random Variables
TODO: describe the theory and formulae
For random variables \(X\) and \(Y\) with PDFs \(f_X\) and \(f_Y\), and with invertible transformation \(Y = g(X)\), we have the linear approximation \[ f_Y(y) = \left.\frac{1}{|d y/d x|} f_X(x)\right|_{x \mapsto g^{-1}(y)}. \qquad{(1)}\]
Suppose we are to probabilistically quantify a parachutist’s chances of landing within a certain horizontal distance of a landing target, accounting for random wind displacements. Develop a PDF for the random variable R, the landing distance from the target.
Without much intuition, no data, or a very good physical model of the situation, we are left to bootstrap a solution. A toehold can perhaps be found by narrowing the problem to a drop of a fixed, relatively short distance, such as that shown in [@fig:skyfall1].
For each vertical drop of 10 m, we might expect a horizontal displacement of a few meters. Without any information about average prevailing winds, we cannot expect any particular direction to be most likely. It seems more likely that wind gusts would displace the parachutist a small amount than a large amount, and even less likely to displace a very large amount. These facts suggest a reasonable model to start with is a Gaussian distribution with PDF $$ f_X(x) = \frac{1}{\sqrt{2 \pi} \sigma} \exp\frac{-(x - \mu)^2}{2 \sigma^2}, $$ where μ = 0 m and σ = 5 m. This model could clearly be improved with some data or a detailed analysis of the physics involved, but this seems to be a reasonable place to begin.
From here, we can extrapolate. For one 10-m drop, the displacement random variable is X. For two 10-m drops, the displacement random variable is 2X, and so on. We conclude that for N drops of 10 m, the landing displacement random variable R is R = NX. Here we have assumed the parachutist lands after N drops of 10 m. Another way of writing this is R = h(X) = NX. The function h transforms random variable X (with value x) to random variable R with value (r).
We can apply [@eq:rv_transformation_invertible] directly to find the PDF of R as follows: Letting μ′ = Nμ and σ′ = Nσ, we obtain $$ f_R(r) = \frac{1}{\sqrt{2 \pi} \sigma'} \exp\frac{-(x - \mu')^2}{2 \sigma'^2}. $$ That is, R also has a Gaussian PDF. We see that the linear transformation has simply transformed the mean μ and standard deviation σ accordingly.
We observe that for greater N (higher jumps), the standard deviation is also greater. This is an intuitive result. We now turn to Python for graphical and simulation purposes.
Load the necessary packages:
import numpy as np
import sympy as sp
import matplotlib.pyplot as plt
Define fixed parameters:
= 0.0 # Mean of the Gaussian distribution for the 10 m drop
mu = 5.0 # Standard deviation of the Gaussian distribution for the 10 m drop sigma
Define the 10 m drop Gaussian distribution fX(x) symbolically
= sp.symbols('x, r, N', real=True)
x, r, N = 1/(sigma * sp.sqrt(2 * sp.pi)) * sp.exp(-(x - mu)**2 / (2 * sigma**2))
f_X print(f_X)
0.1*sqrt(2)*exp(-0.02*x**2)/sqrt(pi)
Define the functional relationship between X and R, the horizontal distance from the initial drop point
= sp.Eq(r, N * x)
h_eq = sp.solve(h_eq, r, dict=True)[0]
h_sol = sp.solve(h_eq, x, dict=True)[0]
h_inv = sp.diff(h_sol[r], x)
dr_dx print(dr_dx)
N
Define symbolically fR(r), the probability density function for the horizontal distance from the initial drop point:
= 1/sp.Abs(dr_dx) * f_X.subs(h_inv)
f_R print(f_R)
0.1*sqrt(2)*exp(-0.02*r**2/N**2)/(sqrt(pi)*Abs(N))
Lambdify the PDF for numerical evaluation
= sp.lambdify((r, N), f_R, 'numpy') f_R_fun
Plot the PDF fR(r) for several values of N:
= np.array([600, 800, 1000])/10 # Drop steps of 10 m
N_vals = np.linspace(-1000, 1000, 1001)
r_vals = plt.subplots()
fig, ax for N_val in N_vals:
= f_R_fun(r_vals, N_val)
p_vals =f'N = {N_val}')
ax.plot(r_vals, p_vals, label'$r_f$ (m)')
ax.set_xlabel('$p(r_f)$')
ax.set_ylabel(
ax.legend() plt.draw()
Compute the probability of landing within ± 500 m of the initial drop point:
= -500, 500
r_min, r_max = sp.integrate(f_R, (r, r_min, r_max))
p_landing print(p_landing)
Piecewise((0.707106781186548*sqrt(2)*Abs(N)*erf(70.7106781186548/Abs(N))/N, N >= 0), (-0.707106781186548*sqrt(2)*Abs(N)*erf(70.7106781186548/Abs(N))/N, True))
Plot the probability of landing within ± 500 m of the initial drop point as a function of N:
= np.linspace(1, 1200, 1001)
N_vals = sp.lambdify(N, p_landing, 'numpy')
p_landing_fun = np.zeros(N_vals.shape[0]) # Preallocate
p_landing_vals for i, N_val in enumerate(N_vals):
= p_landing_fun(N_val) # Evaluate
p_landing_vals[i] = plt.subplots()
fig, ax * 10, p_landing_vals)
ax.plot(N_vals 'Drop height (m)')
ax.set_xlabel('$p(\pm 500 m)$')
ax.set_ylabel( plt.draw()
Define a function to take one 10 m drop:
def take_drop(x_previous):
= x_previous + np.random.normal(mu, sigma)
x_new return x_new
Define a function to simulate a random walk:
def simulate_random_walk(N_sim):
= np.flip(np.arange(0, N_sim + 1)) * 10 # Heights
y_sim = np.zeros(N_sim + 1) # Preallocate
x_sim 0] = 0 # Initial drop point
x_sim[for i in range(1, N_sim + 1):
= take_drop(x_sim[i - 1])
x_sim[i] return x_sim, y_sim
Simulate several random walks (drops) for various values of N:
= [60, 80, 100]
N_vals = 50 # Number of simulations
n_sim = [np.zeros((n_sim, N_val+1)) for N_val in N_vals] # Preallocate
x_sims = [np.zeros((n_sim, N_val+1)) for N_val in N_vals] # Preallocate
y_sims for i, N_val in enumerate(N_vals):
for j in range(n_sim):
= simulate_random_walk(N_val)
x_sim, y_sim = x_sim
x_sims[i][j] = y_sim y_sims[i][j]
Plot the random walks (drops) for several values of N:
= plt.subplots()
fig, ax for i, N_val in enumerate(N_vals):
for j in range(n_sim):
ax.plot(
x_sims[i][j], y_sims[i][j], =f'C{i}', alpha=[0.7, 0.5, 0.3][i]
color
)'Horizontal distance (m)')
ax.set_xlabel('Height (m)')
ax.set_ylabel( plt.show()
Online Resources for Section 3.9
No online resources.