sdr.add_iid_rvs(X: rv_continuous | rv_histogram, n_vars: int, p: float = 1e-16) rv_histogram

Numerically calculates the distribution of the sum of \(n\) i.i.d. random variables \(X_i\).

Parameters:
X: rv_continuous | rv_histogram

The distribution of the i.i.d. random variables \(X_i\).

n_vars: int

The number \(n\) of random variables.

p: float = 1e-16

The probability of exceeding the x axis, on either side, for each distribution. This is used to determine the bounds on the x axis for the numerical convolution. Smaller values of \(p\) will result in more accurate analysis, but will require more computation.

Returns:

The distribution of the sum \(Z = X_1 + X_2 + \dots + X_n\).

Notes

Given a random variable \(X\) with PDF \(f_X(x)\), we compute the PDF of \(Z = X_1 + X_2 + \dots + X_n\), where \(X_1, X_2, \dots, X_n\) are independent and identically distributed (i.i.d.), as follows.

The PDF of \(Z\), denoted \(f_Z(z)\), can be obtained by using the convolution formula for independent random variables. Specifically, the PDF of the sum of \(n\) i.i.d. random variables is given by the \(n\)-fold convolution of the PDF of \(X\) with itself.

For \(n = 2\), \(Z = X_1 + X_2\). The PDF of \(Z\) is

\[f_Z(z) = \int_{-\infty}^\infty f_X(x) f_X(z - x) \, dx\]

For \(n > 2\), the PDF of \(Z = X_1 + X_2 + \dots + X_n\) is computed recursively

\[f_Z(z) = \int_{-\infty}^\infty f_X(x) f_{Z_{n-1}}(z - x) \, dx\]

where \(f_{Z_{n-1}}(z)\) is the PDF of the sum of \(n-1\) random variables.

For large \(n\), the Central Limit Theorem may be used as an approximation. If \(X_i\) have mean \(\mu\) and variance \(\sigma^2\), then \(Z\) approximately follows \(Z \sim \mathcal{N}(n\mu, n\sigma^2)\) for sufficiently large \(n\).

Examples

Compute the distribution of the sum of two normal random variables.

In [1]: X = scipy.stats.norm(loc=-1, scale=0.5)

In [2]: n_vars = 2

In [3]: x = np.linspace(-6, 2, 1_001)

In [4]: plt.figure(); \
   ...: plt.plot(x, X.pdf(x), label="X"); \
   ...: plt.plot(x, sdr.add_iid_rvs(X, n_vars).pdf(x), label="$X_1 + X_2$"); \
   ...: plt.hist(X.rvs((100_000, n_vars)).sum(axis=1), bins=101, density=True, histtype="step", label="$X_1 + X_2$ empirical"); \
   ...: plt.legend(); \
   ...: plt.xlabel("Random variable"); \
   ...: plt.ylabel("Probability density"); \
   ...: plt.title("Sum of two normal random variables");
   ...: 
../../_images/sdr_add_iid_rvs_1.png

Compute the distribution of the sum of three Rayleigh random variables.

In [5]: X = scipy.stats.rayleigh(scale=1)

In [6]: n_vars = 3

In [7]: x = np.linspace(0, 10, 1_001)

In [8]: plt.figure(); \
   ...: plt.plot(x, X.pdf(x), label="X"); \
   ...: plt.plot(x, sdr.add_iid_rvs(X, n_vars).pdf(x), label="$X_1 + X_2 + X_3$"); \
   ...: plt.hist(X.rvs((100_000, n_vars)).sum(axis=1), bins=101, density=True, histtype="step", label="$X_1 + X_2 + X_3$ empirical"); \
   ...: plt.legend(); \
   ...: plt.xlabel("Random variable"); \
   ...: plt.ylabel("Probability density"); \
   ...: plt.title("Sum of three Rayleigh random variables");
   ...: 
../../_images/sdr_add_iid_rvs_2.png

Compute the distribution of the sum of four Rician random variables.

In [9]: X = scipy.stats.rice(2)

In [10]: n_vars = 4

In [11]: x = np.linspace(0, 18, 1_001)

In [12]: plt.figure(); \
   ....: plt.plot(x, X.pdf(x), label="X"); \
   ....: plt.plot(x, sdr.add_iid_rvs(X, n_vars).pdf(x), label="$X_1 + X_2 + X_3 + X_4$"); \
   ....: plt.hist(X.rvs((100_000, n_vars)).sum(axis=1), bins=101, density=True, histtype="step", label="$X_1 + X_2 + X_3 + X_4$ empirical"); \
   ....: plt.legend(); \
   ....: plt.xlabel("Random variable"); \
   ....: plt.ylabel("Probability density"); \
   ....: plt.title("Sum of four Rician random variables");
   ....: 
../../_images/sdr_add_iid_rvs_3.png