Source code for comyx.fading.nakagami

from __future__ import annotations

from typing import Any, Tuple, Union

import numpy as np
import numpy.typing as npt
import scipy.stats as stats
from scipy.special import gamma

NDArrayFloat = npt.NDArray[np.floating[Any]]


[docs] class Nakagami: r"""Represents the :math:`\text{Nakagami}(m, \Omega)` distribution. The Nakagami distribution or the Nakagami-m distribution is a probability distribution related to the gamma distribution. The family of Nakagami distributions has two parameters: a shape parameter :math:`m` with :math:`m\geq 1/2` and a second parameter controlling spread :math:`\Omega > 0`. Density Function .. math:: f(x; m, \Omega) = \frac{2m^m}{\Gamma(m)\Omega^m} x^{2m - 1} \exp\left(-\frac{m}{\Omega}x^2\right) , where :math:`\Gamma(.)` is the gamma function. Expected value .. math:: \sqrt{\frac{\Omega}{m}} \frac{\Gamma\left(m + \frac{1}{2}\right)}{\Gamma(m)} Variance .. math:: \Omega \left(1 - \frac{1}{m}\left(\frac{\Gamma\left(m + \frac{1}{2}\right)}{\Gamma(m)}\right)^2\right) Reference: https://en.wikipedia.org/wiki/Nakagami_distribution """ def __init__(self, m: float, omega: float = 1) -> None: """Initialize the Nakagami distribution with the given parameters. Args: m: Shape parameter, which is the fading severity. It must be greater than or equal to 0.5. omega: Scale parameter, which controls the spread of the distribution. It must be greater than 0. """ assert m >= 0.5, "The shape parameter must be greater than or equal to 0.5." assert omega > 0, "The scale parameter must be greater than 0." self.m = m self.omega = omega
[docs] def pdf(self, x: NDArrayFloat) -> NDArrayFloat: """Probability density function of the Nakagami distribution. Args: x: Value at which pdf is evaluated. Returns: Value of the probability density function evaluated at x. """ return ( 2 * self.m**self.m / (gamma(self.m) * self.omega**self.m) * x ** (2 * self.m - 1) * np.exp(-self.m * x**2 / self.omega) )
[docs] def cdf(self, x: NDArrayFloat) -> NDArrayFloat: """Cumulative distribution function of the Nakagami distribution. Args: x: Value at which cdf is evaluated. Returns: Value of the cumulative distribution function evaluated at x. """ return stats.nakagami.cdf(x, self.m, scale=np.sqrt(self.omega))
[docs] def expected_value(self) -> float: """Returns the expected value of the Nakagami distribution.""" return gamma(self.m + 1 / 2) / gamma(self.m) * np.sqrt(self.omega / self.m)
[docs] def variance(self) -> float: """Returns the variance of the Nakagami distribution.""" return self.omega * ( 1 - 1 / self.m * (gamma(self.m + 1 / 2) / gamma(self.m)) ** 2 )
[docs] def get_samples( self, size: Union[int, Tuple[int, ...]], seed: int = None ) -> NDArrayFloat: """Generate random variables from the Nakagami distribution. Args: size: Number of random variables to generate. seed: Seed for the random number generator. Returns: An array of size `size` containing random variables from the Nakagami distribution. """ return np.array( stats.nakagami.rvs( self.m, scale=np.sqrt(self.omega), size=size, random_state=seed ), )
__all__ = ["Nakagami"]