diff --git a/docs/source/api_reference/distributions.rst b/docs/source/api_reference/distributions.rst index 3cdf53f5..cafbee45 100644 --- a/docs/source/api_reference/distributions.rst +++ b/docs/source/api_reference/distributions.rst @@ -55,6 +55,7 @@ Continuous support - non-negative reals Beta ChiSquared Exponential + Erlang Fisk Gamma HalfCauchy diff --git a/skpro/distributions/__init__.py b/skpro/distributions/__init__.py index 9abf8b09..fef2e644 100644 --- a/skpro/distributions/__init__.py +++ b/skpro/distributions/__init__.py @@ -10,6 +10,7 @@ "ChiSquared", "Delta", "Empirical", + "Erlang", "Exponential", "Fisk", "Gamma", @@ -46,6 +47,7 @@ from skpro.distributions.compose import IID from skpro.distributions.delta import Delta from skpro.distributions.empirical import Empirical +from skpro.distributions.erlang import Erlang from skpro.distributions.exponential import Exponential from skpro.distributions.fisk import Fisk from skpro.distributions.gamma import Gamma diff --git a/skpro/distributions/erlang.py b/skpro/distributions/erlang.py new file mode 100644 index 00000000..9cda0ee2 --- /dev/null +++ b/skpro/distributions/erlang.py @@ -0,0 +1,80 @@ +# copyright: skpro developers, BSD-3-Clause License (see LICENSE file) +"""Erlang probability distribution.""" + +__author__ = ["RUPESH-KUMAR01"] + +import pandas as pd +from scipy.stats import erlang + +from skpro.distributions.adapters.scipy import _ScipyAdapter + + +class Erlang(_ScipyAdapter): + r"""Erlang Distribution. + + Most methods wrap ``scipy.stats.erlang``. + + The Erlang Distribution is parameterized by shape :math:`k` + and rate :math:`\lambda`, such that the pdf is + + .. math:: f(x) = \frac{x^{k-1}\exp\left(-\lambda x\right) \lambda^{k}}{(k-1)!} + + Parameters + ---------- + rate : float or array of float (1D or 2D) + Represents the rate parameter, which is also the inverse of the scale parameter. + k : int or array of int (1D or 2D), optional, default = 1 + Represents the shape parameter. + index : pd.Index, optional, default = RangeIndex + columns : pd.Index, optional, default = RangeIndex + + Examples + -------- + >>> from skpro.distributions.erlang import Erlang + + >>> d = Erlang(rate=[[1, 1], [2, 3], [4, 5]], shape=2) + """ + + _tags = { + "capabilities:approx": ["energy", "pdfnorm"], + "capabilities:exact": ["mean", "var", "pdf", "log_pdf", "cdf", "ppf"], + "distr:measuretype": "continuous", + "distr:paramtype": "parametric", + "broadcast_init": "on", + } + + def __init__(self, rate, k=1, index=None, columns=None): + if rate <= 0: + raise ValueError("Rate must be greater than 0.") + if k <= 0: + raise ValueError("shape must be a positive integer.") + self.rate = rate + self.k = k + + super().__init__(index=index, columns=columns) + + def _get_scipy_object(self): + return erlang + + def _get_scipy_param(self): + rate = self._bc_params["rate"] + k = self._bc_params["k"] + + return [], {"scale": 1 / rate, "a": k} + + @classmethod + def get_test_params(cls, parameter_set="default"): + """Return testing parameter settings for the estimator.""" + # Array case examples + params1 = { + "rate": 2.0, + "k": 3, + "index": pd.Index([0, 1, 2]), + "columns": pd.Index(["x", "y"]), + } + # Scalar case examples + params2 = {"rate": 0.8, "k": 2} + + params3 = {"rate": 3.0, "k": 1} + + return [params1, params2, params3]