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 Xi.

Parameters:
X: rv_continuous | rv_histogram

The distribution of the i.i.d. random variables Xi.

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=X1+X2++Xn.

Notes

Given a random variable X with PDF fX(x), we compute the PDF of Z=X1+X2++Xn, where X1,X2,,Xn are independent and identically distributed (i.i.d.), as follows.

The PDF of Z, denoted fZ(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=X1+X2. The PDF of Z is

fZ(z)=fX(x)fX(zx)dx

For n>2, the PDF of Z=X1+X2++Xn is computed recursively

fZ(z)=fX(x)fZn1(zx)dx

where fZn1(z) is the PDF of the sum of n1 random variables.

For large n, the Central Limit Theorem may be used as an approximation. If Xi have mean μ and variance σ2, then Z approximately follows ZN(nμ,nσ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