Skip to content

Commit

Permalink
Add the Irwin-Hall distribution
Browse files Browse the repository at this point in the history
Appease linter for line length
  • Loading branch information
nimish committed Apr 15, 2024
1 parent 23eb838 commit 3167ba1
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 5 deletions.
1 change: 1 addition & 0 deletions scipy/stats/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
invgamma -- Inverse Gamma
invgauss -- Inverse Gaussian
invweibull -- Inverse Weibull
irwinhall -- Irwin-Hall
jf_skew_t -- Jones and Faddy Skew-T
johnsonsb -- Johnson SB
johnsonsu -- Johnson SU
Expand Down
84 changes: 83 additions & 1 deletion scipy/stats/_continuous_distns.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import numpy as np
from numpy.polynomial import Polynomial
from scipy.interpolate import BSpline
from scipy._lib.doccer import (extend_notes_in_docstring,
replace_notes_in_docstring,
inherit_docstring_from)
Expand All @@ -24,7 +25,7 @@
from ._tukeylambda_stats import (tukeylambda_variance as _tlvar,
tukeylambda_kurtosis as _tlkurt)
from ._distn_infrastructure import (
get_distribution_names, _kurtosis,
get_distribution_names, _kurtosis, _isintegral,
rv_continuous, _skew, _get_fixed_fit_value, _check_shape, _ShapeInfo)
from ._ksstats import kolmogn, kolmognp, kolmogni
from ._constants import (_XMIN, _LOGXMIN, _EULER, _ZETA3, _SQRT_PI,
Expand Down Expand Up @@ -9033,6 +9034,87 @@ def _munp(self, n, b):

rice = rice_gen(a=0.0, name="rice")

class irwinhall_gen(rv_continuous):
r"""
An Irwin-Hall continuous random variable is the sum of :math`n` independent
standard uniform r.v.'s.
%(before_notes)s
Notes
-----
Applications include Rao's Spacing Test,
a more powerful alternative to the Rayleigh test
when the data are not unimodal, and radar.
Conveniently, the pdf and cdf are the :math`n`-fold convolution of
the ones for the standard uniform distribution,
which are well known to be just cardinal B-splines of degree :math`n-1`
with knots :math`\left{0,1,\dots,n-1\right}`.
%(after_notes)s
References
----------
.. [1] "Irwin-Hall distribution",
https://en.wikipedia.org/wiki/Irwin-Hall_distribution
[2] "Rao's Spacing Test",
https://jammalam.faculty.pstat.ucsb.edu/html/favorite/test.htm
[3] HALL PHILIP, "THE DISTRIBUTION OF MEANS FOR SAMPLES OF SIZE N DRAWN
FROM A POPULATION IN WHICH THE VARIATE TAKES VALUES BETWEEN 0 AND 1,
ALL SUCH VALUES BEING EQUALLY PROBABLE",
Biometrika, Volume 19, Issue 3-4, December 1927, Pages 240-244,
https://doi.org/10.1093/biomet/19.3-4.240
[4] J. O. IRWIN, "ON THE FREQUENCY DISTRIBUTION OF THE MEANS OF SAMPLES
FROM A POPULATION HAVING ANY LAW OF FREQUENCY WITH FINITE MOMENTS,
WITH SPECIAL REFERENCE TO PEARSON'S TYPE II",
Biometrika, Volume 19, Issue 3-4, December 1927, Pages 225-239,
https://doi.org/10.1093/biomet/19.3-4.225
[5] K. Buchanan, T. Adeyemi, C. Flores-Molina, S. Wheeland and D. Overturf,
"Sidelobe behavior and bandwidth characteristics
of distributed antenna arrays,"
2018 United States National Committee of
URSI National Radio Science Meeting (USNC-URSI NRSM),
Boulder, CO, USA, 2018, pp. 1-2.
https://www.usnc-ursi-archive.org/nrsm/2018/papers/B15-9.pdf
%(example)s
from scipy.stats import irwinhall
bates = irwinhall(n, name="bates", scale=1/n)
"""

def _argcheck(self, n):
return (n > 0) & _isintegral(n)

def _get_support(self, n):
return 0, n

def _shape_info(self):
return [_ShapeInfo("n", True, (1, np.inf), (True, False))]

def _munp(self, n, t):
return (sc.expm1(t)/t)**n

@staticmethod
def _cardinal_bspline(n):
t = np.arange(n+1)
return BSpline.basis_element(t, extrapolate=False)

def _pdf(self, x, n):
return self._cardinal_bspline(n)(x)

def _cdf(self, x, n):
cdf = self._cardinal_bspline(n).antiderivative()
return cdf(x)

def _stats(self, n):
# mgf = ((exp(t) - 1)/t)**n
# m'th derivative follows from the generalized Leibniz rule

return n/2, n/12, 0, 3-6/(5*n)

irwinhall = irwinhall_gen(name="irwinhall")

class recipinvgauss_gen(rv_continuous):
r"""A reciprocal inverse Gaussian continuous random variable.
Expand Down
5 changes: 1 addition & 4 deletions scipy/stats/_discrete_distns.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,13 @@
import numpy as np

from ._distn_infrastructure import (rv_discrete, get_distribution_names,
_check_shape, _ShapeInfo)
_check_shape, _ShapeInfo, _isintegral)
from ._biasedurn import (_PyFishersNCHypergeometric,
_PyWalleniusNCHypergeometric,
_PyStochasticLib3)
import scipy.special._ufuncs as scu


def _isintegral(x):
return x == np.round(x)


class binom_gen(rv_discrete):
r"""A binomial discrete random variable.
Expand Down
2 changes: 2 additions & 0 deletions scipy/stats/_distn_infrastructure.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,8 @@ def _fit_determine_optimizer(optimizer):
raise ValueError("%s is not a valid optimizer" % optimizer) from e
return optimizer

def _isintegral(x):
return x == np.round(x)

def _sum_finite(x):
"""
Expand Down
2 changes: 2 additions & 0 deletions scipy/stats/_distr_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
['invgamma', (4.0668996136993067,)],
['invgauss', (0.14546264555347513,)],
['invweibull', (10.58,)],
['irwinhall', (10)],
['jf_skew_t', (8, 4)],
['johnsonsb', (4.3172675099141058, 3.1837781130785063)],
['johnsonsu', (2.554395574161155, 2.2482281679651965)],
Expand Down Expand Up @@ -226,6 +227,7 @@
['invgamma', (-1, )],
['invgauss', (-1, )],
['invweibull', (-1, )],
['irwinhall', (-1, 0, 0.5)],
['jf_skew_t', (-1, 0)],
['johnsonsb', (1, -2)],
['johnsonsu', (1, -2)],
Expand Down

0 comments on commit 3167ba1

Please sign in to comment.