Chapter 13: Rayleigh Distribution
1. What is the Rayleigh distribution really?
The Rayleigh distribution describes the magnitude (absolute value / length) of a two-dimensional random vector whose components are independent normal random variables with zero mean and equal variance.
In simpler words:
If you have two independent normal random variables X ~ N(0, σ²) and Y ~ N(0, σ²), then the distance from the origin R = √(X² + Y²) follows a Rayleigh distribution with scale parameter σ.
Key intuition (say this sentence out loud):
Rayleigh distribution = distribution of the distance from origin in 2D when you add two independent Gaussian noises with same variance.
This situation appears very frequently when you measure amplitude or envelope of a signal that consists of many small random reflections / contributions.
2. The most important properties (write these down)
| Parameter | Symbol | Meaning / Formula |
|---|---|---|
| Scale parameter | σ | Controls spread (σ > 0) |
| Support | x ≥ 0 | |
| Probability density | f(x) = (x / σ²) × exp(−x² / (2σ²)) for x ≥ 0 | |
| Cumulative (CDF) | F(x) = 1 − exp(−x² / (2σ²)) | |
| Mean | E[R] = σ × √(π/2) ≈ 1.2533 σ | |
| Variance | Var(R) = (4−π)/2 × σ² ≈ 0.4292 σ² | |
| Mode | σ (the peak is exactly at σ) | |
| Median | σ × √(ln 2) ≈ 1.177 σ | |
| Most probable value | σ |
Very useful rule of thumb:
- About 63% of values are below σ × √(ln 4) ≈ 1.177σ (median)
- The mean is roughly 1.25σ
- Standard deviation is roughly 0.655σ
3. Generating Rayleigh random numbers in NumPy / SciPy
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Rayleigh with scale σ = 2 (most common way) rayleigh_data = stats.rayleigh.rvs(scale=2, size=80000) print("First 10 values:", rayleigh_data[:10].round(3)) print("Sample mean:", rayleigh_data.mean().round(3)) print("Theoretical mean:", 2 * np.sqrt(np.pi/2).round(3)) # ≈ 2.5066 print("Sample std :", rayleigh_data.std().round(3)) print("Theoretical std:", 2 * np.sqrt((4-np.pi)/2).round(3)) # ≈ 1.047 |
Alternative way using NumPy (very educational):
|
0 1 2 3 4 5 6 7 8 9 10 11 |
sigma = 2.0 X = np.random.normal(0, sigma, 100000) Y = np.random.normal(0, sigma, 100000) rayleigh_manual = np.sqrt(X**2 + Y**2) # Should be almost identical to stats.rayleigh.rvs(scale=sigma) |
4. Visualizing Rayleigh distribution (very important)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5.5)) scales = [1.0, 2.0, 4.0, 8.0] x = np.linspace(0, 30, 1000) for s in scales: y = stats.rayleigh.pdf(x, scale=s) ax1.plot(x, y, lw=2.3, label=f"σ = {s}", alpha=0.9) ax1.set_title("Rayleigh PDF – different scale parameters", fontsize=13) ax1.set_xlabel("Value (r)", fontsize=11) ax1.set_ylabel("Density", fontsize=11) ax1.set_xlim(0, 30) ax1.legend(title="Scale parameter σ", fontsize=11) # Cumulative distribution function (CDF) for s in scales: ax2.plot(x, stats.rayleigh.cdf(x, scale=s), lw=2.3, label=f"σ = {s}") ax2.set_title("Rayleigh CDF", fontsize=13) ax2.set_xlabel("Value (r)", fontsize=11) ax2.set_ylabel("Cumulative probability", fontsize=11) ax2.legend(title="Scale parameter σ") plt.tight_layout() plt.show() |
What you should always notice:
- Always starts at 0 when x=0
- Has a peak (mode) exactly at σ
- Never negative values
- Right-skewed, but less skewed than exponential
- Larger σ → distribution stretches to the right
- CDF always starts at 0 and approaches 1 smoothly
5. Real-world situations where Rayleigh appears naturally
| Domain | Typical use of Rayleigh distribution |
|---|---|
| Wireless communications (fading) | Magnitude of complex Gaussian fading channel (Rayleigh fading) |
| Radar / sonar | Amplitude of noise / target echo in non-coherent detection |
| Acoustics / audio processing | Envelope of narrowband Gaussian noise |
| MRI / medical imaging | Noise magnitude in magnitude images |
| Wind speed modeling | Speed of wind (often Rayleigh or Weibull) |
| Line-of-sight + multipath signals | Received signal strength when no dominant path |
| Optical scattering | Intensity of scattered light |
Most famous appearance — Rayleigh fading in wireless communications
In mobile communication, the received signal amplitude often follows Rayleigh when there is no line-of-sight path and many small reflections arrive from different directions.
6. Realistic code patterns you will actually write
Pattern 1 – Simulate Rayleigh fading channel coefficients
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Wireless channel – Rayleigh fading with average power = 1 sigma = 1 / np.sqrt(2) # because Var = 2σ² = 1 → σ = 1/√2 channel_real = np.random.normal(0, sigma, 100000) channel_imag = np.random.normal(0, sigma, 100000) channel_amplitude = np.sqrt(channel_real**2 + channel_imag**2) print("Average amplitude:", channel_amplitude.mean().round(4)) # ≈ 1.253 print("Theoretical mean:", sigma * np.sqrt(np.pi).round(4)) # ≈ 1.253 |
Pattern 2 – Simulate signal + Rayleigh fading + noise
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# Transmitted signal amplitude = 2.0 signal = 2.0 # Rayleigh fading h = stats.rayleigh.rvs(scale=1, size=50000) # Additive Gaussian noise (SNR simulation) noise_power = 0.1 noise = np.random.normal(0, np.sqrt(noise_power), 50000) received = h * signal + noise received_amplitude = np.abs(received) sns.histplot(received_amplitude, bins=80, stat="density", kde=True, color="teal", alpha=0.7) plt.title("Received signal amplitude (Rayleigh fading + noise)") plt.xlabel("Amplitude") plt.show() |
Pattern 3 – Probability that amplitude exceeds a threshold
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
sigma = 1.5 threshold = 4.0 # P(R > threshold) = exp(-threshold² / (2σ²)) theoretical_prob = np.exp(-threshold**2 / (2 * sigma**2)) # Simulate samples = stats.rayleigh.rvs(scale=sigma, size=100000) empirical_prob = np.mean(samples > threshold) print(f"Theoretical P(R > {threshold}) = {theoretical_prob:.5f}") print(f"Empirical P(R > {threshold}) = {empirical_prob:.5f}") |
Summary – Rayleigh Distribution Quick Reference
| Property | Value / Formula |
|---|---|
| Shape | Right-skewed, peak at σ, no left tail |
| Defined by | scale parameter σ (σ > 0) |
| Mean | σ × √(π/2) ≈ 1.2533 σ |
| Variance | (4−π)/2 × σ² ≈ 0.4292 σ² |
| Mode | σ (peak exactly at σ) |
| Median | σ × √(ln 2) ≈ 1.177 σ |
| Support | x ≥ 0 |
| (x / σ²) exp(−x² / (2σ²)) for x ≥ 0 | |
| CDF | 1 − exp(−x² / (2σ²)) |
| NumPy / SciPy | scipy.stats.rayleigh.rvs(scale=σ, size=…) |
| Most common use cases | Signal envelope, fading channels, radar cross-section, magnitude of 2D Gaussian |
Final teacher messages
- Whenever you are looking at the magnitude / amplitude / envelope of a signal that comes from two independent Gaussian components → think Rayleigh.
- Rayleigh = special case of Rice distribution when there is no line-of-sight component (non-centrality = 0).
- Rayleigh fading is one of the most famous applications — you will see it constantly if you work in wireless communications or signal processing.
Would you like to continue with any of these next?
- Rayleigh vs Rician distribution (when there is a dominant path)
- How to estimate σ from real data
- Rayleigh fading simulation for communication systems
- Realistic mini-project: simulate signal strength + fading + noise
- Comparing Rayleigh with exponential, chi-square, gamma
Just tell me what you want to explore next! 😊
