Skip to content

Commit

Permalink
👽️ stats: 1.15.0 new Mixture and ContinuousDistribution
Browse files Browse the repository at this point in the history
  • Loading branch information
jorenham committed Dec 20, 2024
1 parent b00bf2c commit 4c84d62
Show file tree
Hide file tree
Showing 4 changed files with 503 additions and 248 deletions.
6 changes: 2 additions & 4 deletions .mypyignore-todo
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
scipy\.stats\.__all__
scipy\.stats\.(Uniform|Normal|Mixture)
scipy\.stats\.(abs|truncate|exp|log)
scipy\.stats\.make_distribution
scipy\.stats\.order_statistic
scipy\.stats\.(Normal|Uniform)
scipy\.stats\.(_distribution_infrastructure\.)?(abs|exp|log|make_distribution|order_statistic|truncate)
22 changes: 13 additions & 9 deletions scipy-stubs/stats/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ from ._bws_test import bws_test
from ._censored_data import CensoredData
from ._correlation import chatterjeexi
from ._covariance import Covariance

# TODO(jorenham)
from ._distribution_infrastructure import Mixture # , abs, exp, log, make_distribution, order_statistic, truncate
from ._entropy import differential_entropy, entropy
from ._fit import fit, goodness_of_fit
from ._hypotests import (
Expand Down Expand Up @@ -72,6 +75,7 @@ from ._multivariate import (
vonmises_fisher,
wishart,
)
from ._new_distributions import Normal, Uniform
from ._page_trend_test import page_trend_test
from ._resampling import (
BootstrapMethod,
Expand Down Expand Up @@ -302,9 +306,13 @@ __all__ = [
"Covariance",
"DegenerateDataWarning",
"FitError",
"Mixture",
"MonteCarloMethod",
"NearConstantInputWarning",
"Normal",
"PermutationMethod",
"Uniform",
# "abs",
"alexandergovern",
"alpha",
"anderson",
Expand Down Expand Up @@ -371,6 +379,7 @@ __all__ = [
"entropy",
"epps_singleton_2samp",
"erlang",
# "exp",
"expectile",
"expon",
"exponnorm",
Expand Down Expand Up @@ -450,6 +459,7 @@ __all__ = [
"levy_stable",
"linregress",
"lmoment",
# "log",
"loggamma",
"logistic",
"loglaplace",
Expand All @@ -458,6 +468,7 @@ __all__ = [
"logser",
"loguniform",
"lomax",
# "make_distribution",
"mannwhitneyu",
"matrix_normal",
"maxwell",
Expand Down Expand Up @@ -493,6 +504,7 @@ __all__ = [
"normaltest",
"norminvgauss",
"obrientransform",
# "order_statistic",
"ortho_group",
"page_trend_test",
"pareto",
Expand Down Expand Up @@ -560,6 +572,7 @@ __all__ = [
"trim1",
"trim_mean",
"trimboth",
# "truncate",
"truncexpon",
"truncnorm",
"truncpareto",
Expand Down Expand Up @@ -598,13 +611,4 @@ __all__ = [
"zipfian",
"zmap",
"zscore",
# "Mixture",
# "Normal",
# "Uniform",
# "abs",
# "exp",
# "log",
# "make_distribution",
# "order_statistic",
# "truncate",
]
148 changes: 134 additions & 14 deletions scipy-stubs/stats/_distribution_infrastructure.pyi
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# mypy: disable-error-code="explicit-override"
# pyright: reportUnannotatedClassAttribute=false

import abc
from collections.abc import Mapping, Sequence, Set as AbstractSet
from typing import Any, Final, Literal as L, TypeAlias, overload
from typing_extensions import LiteralString, TypeVar, override
from typing import Any, ClassVar, Final, Generic, Literal as L, TypeAlias, overload
from typing_extensions import LiteralString, Self, TypeVar, override

import numpy as np
import optype as op
import optype.numpy as onp
import optype.typing as opt
from scipy._typing import ToRNG
from scipy._typing import AnyShape, ToRNG
from ._probability_distribution import _BaseDistribution

# TODO:
Expand Down Expand Up @@ -157,41 +159,159 @@ class _Parameterization:

###

class ContinuousDistribution(_BaseDistribution):
_XT_co = TypeVar("_XT_co", bound=np.number[Any], default=np.float64, covariant=True)
_InexactT_co = TypeVar("_InexactT_co", bound=np.inexact[Any], default=np.float64, covariant=True)
_ShapeT0_co = TypeVar("_ShapeT0_co", bound=tuple[int, ...], default=tuple[int, ...], covariant=True)
_DistrT_co = TypeVar(
"_DistrT_co",
bound=ContinuousDistribution[np.number[Any]],
default=ContinuousDistribution[np.number[Any]],
covariant=True,
)

# placeholder for `matplotlib.axes.Axes`
_Axes: TypeAlias = object
_AxesT = TypeVar("_AxesT", bound=_Axes, default=Any)

_PlotQuantity: TypeAlias = L["x", "cdf", "ccdf", "icdf", "iccdf", "logcdf", "logccdf", "ilogcdf", "ilogccdf"]

_JustFloat: TypeAlias = opt.Just[float] | np.floating[Any]
_Null: TypeAlias = opt.Just[object]

_null: Final[_Null] = ...

class ContinuousDistribution(_BaseDistribution[_XT_co, _ShapeT0_co], Generic[_XT_co, _ShapeT0_co]):
__array_priority__: ClassVar[float] = 1

@property
def tol(self, /) -> float | np.float64 | _Null | None: ...
@tol.setter
def tol(self, tol: float | np.float64 | _Null | None, /) -> None: ...
#
@property
def validation_policy(self, /) -> _ValidationPolicy: ...
@validation_policy.setter
def validation_policy(self, validation_policy: _ValidationPolicy, /) -> None: ...
#
@property
def cache_policy(self, /) -> _CachePolicy: ...
@cache_policy.setter
def cache_policy(self, cache_policy: _CachePolicy, /) -> None: ...
#
def __init__(
self,
/,
*,
tol: opt.Just[float],
tol: opt.Just[float] | _Null = ...,
validation_policy: _ValidationPolicy = None,
cache_policy: _CachePolicy = None,
) -> None: ...

#
def __neg__(self, /) -> ShiftedScaledDistribution[Self, _ShapeT0_co]: ...
def __abs__(self, /) -> FoldedDistribution[Self, _ShapeT0_co]: ...

# TODO(jorenham): Accept `onp.ToFloatND`?
def __add__(self, rshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _ShapeT0_co]: ...
def __sub__(self, lshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _ShapeT0_co]: ...
def __mul__(self, scale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _ShapeT0_co]: ...
def __truediv__(self, iscale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _ShapeT0_co]: ...
def __pow__(self, exp: onp.ToInt, /) -> MonotonicTransformedDistribution[Self, _ShapeT0_co]: ...
__radd__ = __add__
__rsub__ = __sub__
__rmul__ = __mul__
__rtruediv__ = __truediv__
__rpow__ = __pow__

#
def reset_cache(self, /) -> None: ...

class TransformedDistribution(ContinuousDistribution):
# TODO(jorenham)
...
#
def plot(
self,
x: str = "x",
y: str = "pdf",
*,
t: tuple[_PlotQuantity, _JustFloat, _JustFloat] = ("cdf", 0.0005, 0.9995),
ax: _AxesT | None = None,
) -> _AxesT: ...

class TruncatedDistribution(TransformedDistribution):
#
@overload
def llf(self, sample: onp.ToFloat | onp.ToFloatND, /, *, axis: None) -> np.float64: ...
@overload
def llf(self, sample: onp.ToFloat | onp.ToFloatStrict1D, /, *, axis: AnyShape | None = -1) -> np.float64: ...
@overload
def llf(self, sample: onp.ToFloatStrict2D, /, *, axis: op.CanIndex | tuple[op.CanIndex] = -1) -> onp.Array1D[np.float64]: ...
@overload
def llf(self, sample: onp.ToFloatStrict2D, /, *, axis: tuple[op.CanIndex, op.CanIndex]) -> np.float64: ...
@overload
def llf(self, sample: onp.ToFloatStrict3D, /, *, axis: op.CanIndex | tuple[op.CanIndex] = -1) -> onp.Array2D[np.float64]: ...
@overload
def llf(self, sample: onp.ToFloatStrict3D, /, *, axis: tuple[op.CanIndex, op.CanIndex]) -> onp.Array1D[np.float64]: ...
@overload
def llf(self, sample: onp.ToFloatStrict3D, /, *, axis: tuple[op.CanIndex, op.CanIndex, op.CanIndex]) -> np.float64: ...
@overload
def llf(
self,
sample: onp.ToFloat | onp.ToFloatND,
/,
*,
axis: AnyShape | None = -1,
) -> np.float64 | onp.ArrayND[np.float64]: ...

#

class TransformedDistribution(ContinuousDistribution[np.float64, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]):
# TODO(jorenham)
...

class ShiftedScaledDistribution(TransformedDistribution):
class TruncatedDistribution(TransformedDistribution[_DistrT_co, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]):
# TODO(jorenham)
...

class OrderStatisticDistribution(TransformedDistribution):
class ShiftedScaledDistribution(TransformedDistribution[_DistrT_co, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]):
# TODO(jorenham)
...

class MonotonicTransformedDistribution(TransformedDistribution):
class OrderStatisticDistribution(TransformedDistribution[_DistrT_co, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]):
# TODO(jorenham)
...

class FoldedDistribution(TransformedDistribution):
class MonotonicTransformedDistribution(TransformedDistribution[_DistrT_co, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]):
# TODO(jorenham)
...

class Mixture(_BaseDistribution):
class FoldedDistribution(TransformedDistribution[_DistrT_co, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]):
# TODO(jorenham)
...

class Mixture(_BaseDistribution[_InexactT_co, tuple[()]], Generic[_InexactT_co]):
_shape: tuple[()]
_dtype: np.dtype[_InexactT_co]
_components: Sequence[ContinuousDistribution[_InexactT_co, tuple[()]]]
_weights: onp.Array1D[_InexactT_co]
validation_policy: None

@property
def components(self, /) -> list[ContinuousDistribution[_InexactT_co, tuple[()]]]: ...
@property
def weights(self, /) -> onp.Array1D[_InexactT_co]: ...

#
def __init__(
self,
/,
components: Sequence[ContinuousDistribution[_InexactT_co, tuple[()]]],
*,
weights: onp.ToFloat1D | None = None,
) -> None: ...

#
@override
def kurtosis( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
self,
/,
*,
method: L["formula", "general", "transform", "normalize", "cache"] | None = None,
) -> np.float64 | np.longdouble: ...
Loading

0 comments on commit 4c84d62

Please sign in to comment.