From daea3e3ce17adf12b4cef0743c490102a3aaec0a Mon Sep 17 00:00:00 2001 From: jorenham Date: Fri, 20 Dec 2024 03:13:21 +0100 Subject: [PATCH 01/16] =?UTF-8?q?=F0=9F=91=BD=EF=B8=8F=20`stats`:=201.15.0?= =?UTF-8?q?=20new=20`=5FProbabilityDistribution`=20ABC=20and=20type-check-?= =?UTF-8?q?only=20helper=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stats/_probability_distribution.pyi | 684 ++++++++++++++++++ 1 file changed, 684 insertions(+) create mode 100644 scipy-stubs/stats/_probability_distribution.pyi diff --git a/scipy-stubs/stats/_probability_distribution.pyi b/scipy-stubs/stats/_probability_distribution.pyi new file mode 100644 index 00000000..d7eed6e0 --- /dev/null +++ b/scipy-stubs/stats/_probability_distribution.pyi @@ -0,0 +1,684 @@ +# mypy: disable-error-code="explicit-override" + +import abc +from collections.abc import Iterable +from typing import Any, Generic, Literal as L, TypeAlias, overload, type_check_only +from typing_extensions import TypeVar + +import numpy as np +import optype as op +import optype.numpy as onp +from scipy._typing import ToRNG +from ._qmc import QMCEngine + +_T = TypeVar("_T") +_XT = TypeVar("_XT", bound=np.number[Any], default=np.number[Any]) +_XT_co = TypeVar("_XT_co", bound=np.number[Any], default=np.float64, covariant=True) +_ShapeT = TypeVar("_ShapeT", bound=onp.AtLeast1D, default=onp.AtLeast1D) +_ShapeT0 = TypeVar("_ShapeT0", bound=tuple[int, ...], default=tuple[int, ...]) +_ShapeT0_co = TypeVar("_ShapeT0_co", bound=tuple[int, ...], default=tuple[int, ...], covariant=True) + +_Tuple2: TypeAlias = tuple[_T, _T] +_ToQRNG: TypeAlias = QMCEngine | ToRNG + +_SampleMethod: TypeAlias = L["formula", "inverse_transform"] | None +_RMomentMethod: TypeAlias = L["formula", "transform", "quadrature", "cache"] | None +_CMomentMethod: TypeAlias = L["formula", "transform", "quadrature", "cache", "normalize"] | None +_SMomentMethod: TypeAlias = L["formula", "transform", "general", "cache", "normalize"] | None +_MedianMethod: TypeAlias = L["formula", "icdf"] | None +_ModeMethod: TypeAlias = L["formula", "optimization"] | None +_EntropyMethod: TypeAlias = L["formula", "logexp", "quadrature"] | None + +_PDFMethod: TypeAlias = L["formula", "logexp"] | None +_CDFMethod: TypeAlias = L["formula", "logexp", "complement", "quadrature", "subtraction"] | None +_CCDFMethod: TypeAlias = L["formula", "logexp", "complement", "quadrature", "addition"] | None +_ICDFMethod: TypeAlias = L["formula", "complement", "inversion"] | None + +_Float: TypeAlias = np.float64 | np.longdouble +_Float1D: TypeAlias = onp.Array1D[_Float] +_Float2D: TypeAlias = onp.Array2D[_Float] +_Float3D: TypeAlias = onp.Array3D[_Float] +_FloatND: TypeAlias = onp.ArrayND[_Float, _ShapeT] + +_Complex: TypeAlias = np.complex128 | np.clongdouble +_ComplexND: TypeAlias = onp.ArrayND[_Complex, _ShapeT] + +_ToFloatND: TypeAlias = onp.CanArrayND[np.floating[Any] | np.integer[Any] | np.bool_, _ShapeT] +_ToFloat0ND: TypeAlias = onp.ToFloat | onp.ToFloatND +_ToFloatMax1D: TypeAlias = onp.ToFloatStrict1D | onp.ToFloat +_ToFloatMax2D: TypeAlias = onp.ToFloatStrict2D | _ToFloatMax1D +_ToFloatMax3D: TypeAlias = onp.ToFloatStrict3D | _ToFloatMax2D +_ToFloatMaxND: TypeAlias = _ToFloatND[_ShapeT] | _ToFloatMax1D + +### + +class _ProbabilityDistribution(Generic[_XT_co], metaclass=abc.ABCMeta): + @abc.abstractmethod + def support(self, /) -> _Tuple2[_XT_co | onp.ArrayND[_XT_co]]: ... + @abc.abstractmethod + def median(self, /, *, method: _MedianMethod) -> _XT_co | onp.ArrayND[_XT_co]: ... + @abc.abstractmethod + def mode(self, /, *, method: _ModeMethod) -> _XT_co | onp.ArrayND[_XT_co]: ... + @abc.abstractmethod + def sample( + self, + /, + shape: int | tuple[int, ...], + *, + method: _SampleMethod, + rng: _ToQRNG, + ) -> _XT_co | onp.Array[Any, _XT_co]: ... # `Any` shape is needed on `numpy<2.1` + + # + @abc.abstractmethod + def mean(self, /, *, method: _RMomentMethod) -> _Float | _FloatND: ... + @abc.abstractmethod + def variance(self, /, *, method: _CMomentMethod) -> _Float | _FloatND: ... + @abc.abstractmethod + def standard_deviation(self, /, *, method: _CMomentMethod) -> _Float | _FloatND: ... + @abc.abstractmethod + def skewness(self, /, *, method: _SMomentMethod) -> _Float | _FloatND: ... + @abc.abstractmethod + def kurtosis(self, /, *, method: _SMomentMethod) -> _Float | _FloatND: ... + + # + @overload + @abc.abstractmethod + def moment(self, /, order: onp.ToInt, kind: L["raw"], *, method: _RMomentMethod) -> _Float | _FloatND: ... + @overload + @abc.abstractmethod + def moment(self, /, order: onp.ToInt, kind: L["central"], *, method: _CMomentMethod) -> _Float | _FloatND: ... + @overload + @abc.abstractmethod + def moment(self, /, order: onp.ToInt, kind: L["standardized"], *, method: _SMomentMethod) -> _Float | _FloatND: ... + + # + @abc.abstractmethod + def entropy(self, /, *, method: _EntropyMethod) -> _Float | _FloatND: ... + @abc.abstractmethod + def logentropy(self, /, *, method: _EntropyMethod) -> _Complex | _ComplexND: ... + + # + @abc.abstractmethod + def pdf(self, x: _ToFloat0ND, /, *, method: _PDFMethod) -> _Float | _FloatND: ... + @abc.abstractmethod + def logpdf(self, x: _ToFloat0ND, /, *, method: _PDFMethod) -> _Float | _FloatND: ... + + # + @abc.abstractmethod + def cdf(self, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _Float | _FloatND: ... + @abc.abstractmethod + def icdf(self, p: _ToFloat0ND, /, *, method: _ICDFMethod) -> _Float | _FloatND: ... + @abc.abstractmethod + def ccdf(self, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _Float | _FloatND: ... + @abc.abstractmethod + def iccdf(self, p: _ToFloat0ND, /, *, method: _ICDFMethod) -> _Float | _FloatND: ... + @abc.abstractmethod + def logcdf(self, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _Float | _FloatND: ... + @abc.abstractmethod + def ilogcdf(self, logp: _ToFloat0ND, /, *, method: _ICDFMethod) -> _Float | _FloatND: ... + @abc.abstractmethod + def logccdf(self, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _Float | _FloatND: ... + @abc.abstractmethod + def ilogccdf(self, logp: _ToFloat0ND, /, *, method: _ICDFMethod) -> _Float | _FloatND: ... + +### + +_Self: TypeAlias = _BaseDistribution[_XT, _ShapeT0] +_Self0: TypeAlias = _Self[_XT, tuple[()]] +_Self1: TypeAlias = _Self[_XT, tuple[int]] +_Self2: TypeAlias = _Self[_XT, tuple[int, int]] +_Self3: TypeAlias = _Self[_XT, tuple[int, int, int]] +_Self1_: TypeAlias = _Self[_XT, onp.AtLeast1D] + +@type_check_only +class _BaseDistribution(_ProbabilityDistribution[_XT_co], Generic[_XT_co, _ShapeT0_co]): + @overload + def support(self: _Self0[_XT], /) -> _Tuple2[_XT_co]: ... + @overload + def support(self: _Self[_XT, _ShapeT], /) -> _Tuple2[onp.Array[_ShapeT, _XT]]: ... + + # + @overload + def median(self: _Self0[_XT], /, *, method: _MedianMethod) -> _XT: ... + @overload + def median(self: _Self[_XT, _ShapeT], /, *, method: _MedianMethod) -> onp.Array[_ShapeT, _XT]: ... + + # + @overload + def mode(self: _Self0[_XT], /, *, method: _ModeMethod) -> _XT: ... + @overload + def mode(self: _Self[_XT, _ShapeT], /, *, method: _ModeMethod) -> onp.Array[_ShapeT, _XT]: ... + + # + @overload + def sample(self: _Self0[_XT], /, shape: tuple[()], *, method: _SampleMethod, rng: _ToQRNG) -> _XT: ... + @overload + def sample(self: _Self0[_XT], /, shape: op.CanIndex, *, method: _SampleMethod, rng: _ToQRNG) -> onp.Array1D[_XT]: ... + @overload + def sample(self: _Self0[_XT], /, shape: _ShapeT, *, method: _SampleMethod, rng: _ToQRNG) -> onp.ArrayND[_XT, _ShapeT]: ... + @overload + def sample( + self: _Self[_XT, _ShapeT], + /, + shape: tuple[()], + *, + method: _SampleMethod, + rng: _ToQRNG, + ) -> onp.ArrayND[_XT, _ShapeT]: ... + @overload + def sample( + self: _Self[_XT, _ShapeT], + /, + shape: op.CanIndex | Iterable[op.CanIndex], + *, + method: _SampleMethod, + rng: _ToQRNG, + ) -> onp.ArrayND[_XT, _ShapeT] | onp.ArrayND[_XT]: ... # first union type is needed on `numpy<2.1` + @overload + def sample( + self, + /, + shape: op.CanIndex | Iterable[op.CanIndex], + *, + method: _SampleMethod, + rng: _ToQRNG, + ) -> _XT_co | onp.ArrayND[_XT_co, _ShapeT] | onp.ArrayND[_XT_co]: ... # first union type is needed on `numpy<2.1` + + # + @overload + def mean(self: _Self0, /, *, method: _RMomentMethod) -> _Float: ... + @overload + def mean(self: _Self[Any, _ShapeT], /, *, method: _RMomentMethod) -> _FloatND[_ShapeT]: ... + + # + @overload + def variance(self: _Self0, /, *, method: _CMomentMethod) -> _Float: ... + @overload + def variance(self: _Self[Any, _ShapeT], /, *, method: _CMomentMethod) -> _FloatND[_ShapeT]: ... + + # + @overload + def standard_deviation(self: _Self0, /, *, method: _CMomentMethod) -> _Float: ... + @overload + def standard_deviation(self: _Self[Any, _ShapeT], /, *, method: _CMomentMethod) -> _FloatND[_ShapeT]: ... + + # + @overload + def skewness(self: _Self0, /, *, method: _SMomentMethod) -> _Float: ... + @overload + def skewness(self: _Self[Any, _ShapeT], /, *, method: _SMomentMethod) -> _FloatND[_ShapeT]: ... + + # + # where is the `convention` parameter? + @overload + def kurtosis(self: _Self0, /, *, method: _SMomentMethod) -> _Float: ... + @overload + def kurtosis(self: _Self[Any, _ShapeT], /, *, method: _SMomentMethod) -> _FloatND[_ShapeT]: ... + + # + @overload + def moment(self: _Self0, /, order: onp.ToInt, kind: L["raw"], *, method: _RMomentMethod) -> _Float: ... + @overload + def moment(self: _Self0, /, order: onp.ToInt, kind: L["central"], *, method: _CMomentMethod) -> _Float: ... + @overload + def moment(self: _Self0, /, order: onp.ToInt, kind: L["standardized"], *, method: _SMomentMethod) -> _Float: ... + @overload + def moment( + self: _Self[Any, _ShapeT], + /, + order: onp.ToInt, + kind: L["raw"], + *, + method: _RMomentMethod, + ) -> _FloatND[_ShapeT]: ... + @overload + def moment( + self: _Self[Any, _ShapeT], + /, + order: onp.ToInt, + kind: L["central"], + *, + method: _CMomentMethod, + ) -> _FloatND[_ShapeT]: ... + @overload + def moment( # pyright: ignore[reportIncompatibleMethodOverride] # pyright false positive bug + self: _Self[Any, _ShapeT], + /, + order: onp.ToInt, + kind: L["standardized"], + *, + method: _SMomentMethod, + ) -> _FloatND[_ShapeT]: ... + + # + @overload + def entropy(self: _Self0, /, *, method: _EntropyMethod) -> _Float: ... + @overload + def entropy(self: _Self[Any, _ShapeT], /, *, method: _EntropyMethod) -> _FloatND[_ShapeT]: ... + + # + @overload + def logentropy(self: _Self0, /, *, method: _EntropyMethod) -> _Complex: ... + @overload + def logentropy(self: _Self[Any, _ShapeT], /, *, method: _EntropyMethod) -> _ComplexND[_ShapeT]: ... + + # + # NOTE: The signatures of `pdf` and `logpdf` are equivalent + @overload # self: T1-d, x: 0-d + def pdf(self: _Self[Any, _ShapeT], x: onp.ToFloat, /, *, method: _PDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: 0-d + def pdf(self: _Self0, x: onp.ToFloat, /, *, method: _PDFMethod) -> _Float: ... + @overload # self: 0-d, x: 1-d + def pdf(self: _Self0, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod) -> _Float1D: ... + @overload # self: 0-d, x: 2-d + def pdf(self: _Self0, x: onp.ToFloatStrict2D, /, *, method: _PDFMethod) -> _Float2D: ... + @overload # self: 0-d, x: 3-d + def pdf(self: _Self0, x: onp.ToFloatStrict3D, /, *, method: _PDFMethod) -> _Float3D: ... + @overload # self: 0-d, x: T1-d + def pdf(self: _Self0, x: _ToFloatND[_ShapeT], /, *, method: _PDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: >=1-d + def pdf( # first union type is needed on `numpy<2.1` + self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _PDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 1-d, x: 1-d + def pdf(self: _Self1, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod) -> _Float2D: ... + @overload # self: 1-d, x: 2-d + def pdf(self: _Self1, x: onp.ToFloatStrict2D, /, *, method: _PDFMethod) -> _Float3D: ... + @overload # self: 1-d, x: >=-d + def pdf(self: _Self1, x: onp.ToFloatND, /, *, method: _PDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 2-d, x: 1-d + def pdf(self: _Self2, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod) -> _Float3D: ... + @overload # self: 2-d, x: >=1-d + def pdf(self: _Self2, x: onp.ToFloatND, /, *, method: _PDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 3-d, x: >=1-d + def pdf(self: _Self3, x: onp.ToFloatND, /, *, method: _PDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: >=1-d + def pdf(self: _Self1_, x: _ToFloat0ND, /, *, method: _PDFMethod) -> _FloatND: ... + + # + @overload # self: T1-d, x: 0-d + def logpdf(self: _Self[Any, _ShapeT], x: onp.ToFloat, /, *, method: _PDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: 0-d + def logpdf(self: _Self0, x: onp.ToFloat, /, *, method: _PDFMethod) -> _Float: ... + @overload # self: 0-d, x: 1-d + def logpdf(self: _Self0, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod) -> _Float1D: ... + @overload # self: 0-d, x: 2-d + def logpdf(self: _Self0, x: onp.ToFloatStrict2D, /, *, method: _PDFMethod) -> _Float2D: ... + @overload # self: 0-d, x: 3-d + def logpdf(self: _Self0, x: onp.ToFloatStrict3D, /, *, method: _PDFMethod) -> _Float3D: ... + @overload # self: 0-d, x: T1-d + def logpdf(self: _Self0, x: _ToFloatND[_ShapeT], /, *, method: _PDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: >=1-d + def logpdf( # first union type is needed on `numpy<2.1` + self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _PDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 1-d, x: 1-d + def logpdf(self: _Self1, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod) -> _Float2D: ... + @overload # self: 1-d, x: 2-d + def logpdf(self: _Self1, x: onp.ToFloatStrict2D, /, *, method: _PDFMethod) -> _Float3D: ... + @overload # self: 1-d, x: >=1-d + def logpdf(self: _Self1, x: onp.ToFloatND, /, *, method: _PDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 2-d, x: 1-d + def logpdf(self: _Self2, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod) -> _Float3D: ... + @overload # self: 2-d, x: >=1-d + def logpdf(self: _Self2, x: onp.ToFloatND, /, *, method: _PDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 3-d, x: >=1-d + def logpdf(self: _Self3, x: onp.ToFloatND, /, *, method: _PDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: >=1-d + def logpdf(self: _Self1_, x: _ToFloat0ND, /, *, method: _PDFMethod) -> _FloatND: ... + + # + # NOTE: Apart from the `method` type, the signatures of `[log]cdf` and `[log]ccdf` are equivalent + @overload # self: T1-d, x: 0-d, y?: 0-d + def cdf(self: _Self[Any, _ShapeT], x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: 0-d, y?: 0-d + def cdf(self: _Self0, x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CDFMethod) -> _Float: ... + @overload # self: 0-d, x: 1-d, y?: <=1-d + def cdf(self: _Self0, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _Float1D: ... + @overload # self: 0-d, x: <=1-d, y: 1-d + def cdf(self: _Self0, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod) -> _Float1D: ... + @overload # self: 0-d, x: 2-d, y?: <=2-d + def cdf(self: _Self0, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CDFMethod) -> _Float2D: ... + @overload # self: 0-d, x: <=2-d, y: 2-d + def cdf(self: _Self0, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CDFMethod) -> _Float2D: ... + @overload # self: 0-d, x: 3-d, y?: <=3-d + def cdf(self: _Self0, x: onp.ToFloatStrict3D, y: _ToFloatMax3D | None, /, *, method: _CDFMethod) -> _Float3D: ... + @overload # self: 0-d, x: <=3-d, y: 3-d + def cdf(self: _Self0, x: _ToFloatMax3D, y: onp.ToFloatStrict3D, /, *, method: _CDFMethod) -> _Float3D: ... + @overload # self: 0-d, x: T1-d, y?: T1-d | <=1-d + def cdf(self: _Self0, x: _ToFloatND[_ShapeT], y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: T1-d | <=1-d, y: T1-d + def cdf(self: _Self0, x: _ToFloatMaxND[_ShapeT], y: _ToFloatND[_ShapeT], /, *, method: _CDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: >=1-d, y?: >=0-d + def cdf( # first union type is needed on `numpy<2.1` + self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 0-d, x: >=0-d, y: >=1-d + def cdf( # first union type is needed on `numpy<2.1` + self: _Self0, x: _ToFloat0ND, y: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _CDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 1-d, x: 1-d, y?: <=1-d + def cdf(self: _Self1, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _Float2D: ... + @overload # self: 1-d, x: <=1-d, y: 1-d + def cdf(self: _Self1, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod) -> _Float2D: ... + @overload # self: 1-d, x: 2-d, y?: <=2-d + def cdf(self: _Self1, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CDFMethod) -> _Float3D: ... + @overload # self: 1-d, x: <=2-d, y: 2-d + def cdf(self: _Self1, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CDFMethod) -> _Float3D: ... + @overload # self: 1-d, x: >=1-d, y?: >=0-d + def cdf(self: _Self1, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 1-d, x: >=0-d, y: >=1-d + def cdf(self: _Self1, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 2-d, x: 1-d, y?: <=1-d + def cdf(self: _Self2, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _Float3D: ... + @overload # self: 2-d, x: <=1-d, y: 1-d + def cdf(self: _Self2, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod) -> _Float3D: ... + @overload # self: 2-d, x: >=1-d, y?: >=0-d + def cdf(self: _Self2, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 2-d, x: >=0-d, y: >=1-d + def cdf(self: _Self2, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 3-d, x: >=0-d, y?: >=0-d + def cdf(self: _Self3, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: >=1-d, x: >=0-d, y?: >=0-d + def cdf(self: _Self1_, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND: ... + + # + @overload # self: T1-d, x: 0-d, y?: 0-d + def logcdf( + self: _Self[Any, _ShapeT], x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CDFMethod + ) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: 0-d, y?: 0-d + def logcdf(self: _Self0, x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CDFMethod) -> _Float: ... + @overload # self: 0-d, x: 1-d, y?: <=1-d + def logcdf(self: _Self0, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _Float1D: ... + @overload # self: 0-d, x: <=1-d, y: 1-d + def logcdf(self: _Self0, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod) -> _Float1D: ... + @overload # self: 0-d, x: 2-d, y?: <=2-d + def logcdf(self: _Self0, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CDFMethod) -> _Float2D: ... + @overload # self: 0-d, x: <=2-d, y: 2-d + def logcdf(self: _Self0, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CDFMethod) -> _Float2D: ... + @overload # self: 0-d, x: 3-d, y?: <=3-d + def logcdf(self: _Self0, x: onp.ToFloatStrict3D, y: _ToFloatMax3D | None, /, *, method: _CDFMethod) -> _Float3D: ... + @overload # self: 0-d, x: <=3-d, y: 3-d + def logcdf(self: _Self0, x: _ToFloatMax3D, y: onp.ToFloatStrict3D, /, *, method: _CDFMethod) -> _Float3D: ... + @overload # self: 0-d, x: T1-d, y?: T1-d | <=1-d + def logcdf(self: _Self0, x: _ToFloatND[_ShapeT], y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: T1-d | <=1-d, y: T1-d + def logcdf( + self: _Self0, x: _ToFloatMaxND[_ShapeT], y: _ToFloatND[_ShapeT], /, *, method: _CDFMethod + ) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: >=1-d, y?: >=0-d + def logcdf( # first union type is needed on `numpy<2.1` + self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 0-d, x: >=0-d, y: >=1-d + def logcdf( # first union type is needed on `numpy<2.1` + self: _Self0, x: _ToFloat0ND, y: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _CDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 1-d, x: 1-d, y?: <=1-d + def logcdf(self: _Self1, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _Float2D: ... + @overload # self: 1-d, x: <=1-d, y: 1-d + def logcdf(self: _Self1, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod) -> _Float2D: ... + @overload # self: 1-d, x: 2-d, y?: <=2-d + def logcdf(self: _Self1, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CDFMethod) -> _Float3D: ... + @overload # self: 1-d, x: <=2-d, y: 2-d + def logcdf(self: _Self1, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CDFMethod) -> _Float3D: ... + @overload # self: 1-d, x: >=1-d, y?: >=0-d + def logcdf(self: _Self1, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 1-d, x: >=0-d, y: >=1-d + def logcdf(self: _Self1, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 2-d, x: 1-d, y?: <=1-d + def logcdf(self: _Self2, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _Float3D: ... + @overload # self: 2-d, x: <=1-d, y: 1-d + def logcdf(self: _Self2, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod) -> _Float3D: ... + @overload # self: 2-d, x: >=1-d, y?: >=0-d + def logcdf(self: _Self2, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 2-d, x: >=0-d, y: >=1-d + def logcdf(self: _Self2, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 3-d, x: >=0-d, y?: >=0-d + def logcdf(self: _Self3, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: >=1-d, x: >=0-d, y?: >=0-d + def logcdf(self: _Self1_, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND: ... + + # + @overload # self: T1-d, x: 0-d, y?: 0-d + def ccdf( + self: _Self[Any, _ShapeT], x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CCDFMethod + ) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: 0-d, y?: 0-d + def ccdf(self: _Self0, x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CCDFMethod) -> _Float: ... + @overload # self: 0-d, x: 1-d, y?: <=1-d + def ccdf(self: _Self0, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _Float1D: ... + @overload # self: 0-d, x: <=1-d, y: 1-d + def ccdf(self: _Self0, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod) -> _Float1D: ... + @overload # self: 0-d, x: 2-d, y?: <=2-d + def ccdf(self: _Self0, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CCDFMethod) -> _Float2D: ... + @overload # self: 0-d, x: <=2-d, y: 2-d + def ccdf(self: _Self0, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CCDFMethod) -> _Float2D: ... + @overload # self: 0-d, x: 3-d, y?: <=3-d + def ccdf(self: _Self0, x: onp.ToFloatStrict3D, y: _ToFloatMax3D | None, /, *, method: _CCDFMethod) -> _Float3D: ... + @overload # self: 0-d, x: <=3-d, y: 3-d + def ccdf(self: _Self0, x: _ToFloatMax3D, y: onp.ToFloatStrict3D, /, *, method: _CCDFMethod) -> _Float3D: ... + @overload # self: 0-d, x: T1-d, y?: T1-d | <=1-d + def ccdf(self: _Self0, x: _ToFloatND[_ShapeT], y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: T1-d | <=1-d, y: T1-d + def ccdf(self: _Self0, x: _ToFloatMaxND[_ShapeT], y: _ToFloatND[_ShapeT], /, *, method: _CCDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: >=1-d, y?: >=0-d + def ccdf( # first union type is needed on `numpy<2.1` + self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 0-d, x: >=0-d, y: >=1-d + def ccdf( # first union type is needed on `numpy<2.1` + self: _Self0, x: _ToFloat0ND, y: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _CCDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 1-d, x: 1-d, y?: <=1-d + def ccdf(self: _Self1, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _Float2D: ... + @overload # self: 1-d, x: <=1-d, y: 1-d + def ccdf(self: _Self1, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod) -> _Float2D: ... + @overload # self: 1-d, x: 2-d, y?: <=2-d + def ccdf(self: _Self1, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CCDFMethod) -> _Float3D: ... + @overload # self: 1-d, x: <=2-d, y: 2-d + def ccdf(self: _Self1, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CCDFMethod) -> _Float3D: ... + @overload # self: 1-d, x: >=1-d, y?: >=0-d + def ccdf(self: _Self1, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 1-d, x: >=0-d, y: >=1-d + def ccdf(self: _Self1, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 2-d, x: 1-d, y?: <=1-d + def ccdf(self: _Self2, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _Float3D: ... + @overload # self: 2-d, x: <=1-d, y: 1-d + def ccdf(self: _Self2, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod) -> _Float3D: ... + @overload # self: 2-d, x: >=1-d, y?: >=0-d + def ccdf(self: _Self2, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 2-d, x: >=0-d, y: >=1-d + def ccdf(self: _Self2, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 3-d, x: >=0-d, y?: >=0-d + def ccdf(self: _Self3, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: >=1-d, x: >=0-d, y?: >=0-d + def ccdf(self: _Self1_, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND: ... + + # + @overload # self: T1-d, x: 0-d, y?: 0-d + def logccdf( + self: _Self[Any, _ShapeT], x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CCDFMethod + ) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: 0-d, y?: 0-d + def logccdf(self: _Self0, x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CCDFMethod) -> _Float: ... + @overload # self: 0-d, x: 1-d, y?: <=1-d + def logccdf(self: _Self0, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _Float1D: ... + @overload # self: 0-d, x: <=1-d, y: 1-d + def logccdf(self: _Self0, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod) -> _Float1D: ... + @overload # self: 0-d, x: 2-d, y?: <=2-d + def logccdf(self: _Self0, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CCDFMethod) -> _Float2D: ... + @overload # self: 0-d, x: <=2-d, y: 2-d + def logccdf(self: _Self0, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CCDFMethod) -> _Float2D: ... + @overload # self: 0-d, x: 3-d, y?: <=3-d + def logccdf(self: _Self0, x: onp.ToFloatStrict3D, y: _ToFloatMax3D | None, /, *, method: _CCDFMethod) -> _Float3D: ... + @overload # self: 0-d, x: <=3-d, y: 3-d + def logccdf(self: _Self0, x: _ToFloatMax3D, y: onp.ToFloatStrict3D, /, *, method: _CCDFMethod) -> _Float3D: ... + @overload # self: 0-d, x: T1-d, y?: T1-d | <=1-d + def logccdf( + self: _Self0, x: _ToFloatND[_ShapeT], y: _ToFloatMax1D | None, /, *, method: _CCDFMethod + ) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: T1-d | <=1-d, y: T1-d + def logccdf( + self: _Self0, x: _ToFloatMaxND[_ShapeT], y: _ToFloatND[_ShapeT], /, *, method: _CCDFMethod + ) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, x: >=1-d, y?: >=0-d + def logccdf( # first union type is needed on `numpy<2.1` + self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 0-d, x: >=0-d, y: >=1-d + def logccdf( # first union type is needed on `numpy<2.1` + self: _Self0, x: _ToFloat0ND, y: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _CCDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 1-d, x: 1-d, y?: <=1-d + def logccdf(self: _Self1, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _Float2D: ... + @overload # self: 1-d, x: <=1-d, y: 1-d + def logccdf(self: _Self1, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod) -> _Float2D: ... + @overload # self: 1-d, x: 2-d, y?: <=2-d + def logccdf(self: _Self1, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CCDFMethod) -> _Float3D: ... + @overload # self: 1-d, x: <=2-d, y: 2-d + def logccdf(self: _Self1, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CCDFMethod) -> _Float3D: ... + @overload # self: 1-d, x: >=1-d, y?: >=0-d + def logccdf(self: _Self1, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 1-d, x: >=0-d, y: >=1-d + def logccdf(self: _Self1, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 2-d, x: 1-d, y?: <=1-d + def logccdf(self: _Self2, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _Float3D: ... + @overload # self: 2-d, x: <=1-d, y: 1-d + def logccdf(self: _Self2, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod) -> _Float3D: ... + @overload # self: 2-d, x: >=1-d, y?: >=0-d + def logccdf(self: _Self2, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 2-d, x: >=0-d, y: >=1-d + def logccdf(self: _Self2, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 3-d, x: >=0-d, y?: >=0-d + def logccdf(self: _Self3, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: >=1-d, x: >=0-d, y?: >=0-d + def logccdf(self: _Self1_, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND: ... + + # NOTE: Apart from the `method` type, the signatures of `i[log]cdf` and `i[log]ccdf` are equivalent to those of `[log]pdf` + @overload # self: T1-d, p: 0-d + def icdf(self: _Self[Any, _ShapeT], p: onp.ToFloat, /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, p: 0-d + def icdf(self: _Self0, p: onp.ToFloat, /, *, method: _ICDFMethod) -> _Float: ... + @overload # self: 0-d, p: 1-d + def icdf(self: _Self0, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float1D: ... + @overload # self: 0-d, p: 2-d + def icdf(self: _Self0, p: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float2D: ... + @overload # self: 0-d, p: 3-d + def icdf(self: _Self0, p: onp.ToFloatStrict3D, /, *, method: _ICDFMethod) -> _Float3D: ... + @overload # self: 0-d, p: T1-d + def icdf(self: _Self0, p: _ToFloatND[_ShapeT], /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, p: >=1-d + def icdf( # first union type is needed on `numpy<2.1` + self: _Self0, p: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _ICDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 1-d, p: 1-d + def icdf(self: _Self1, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float2D: ... + @overload # self: 1-d, p: 2-d + def icdf(self: _Self1, p: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float3D: ... + @overload # self: 1-d, p: >=-d + def icdf(self: _Self1, p: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 2-d, p: 1-d + def icdf(self: _Self2, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float3D: ... + @overload # self: 2-d, p: >=1-d + def icdf(self: _Self2, p: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 3-d, p: >=1-d + def icdf(self: _Self3, p: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: >=1-d + def icdf(self: _Self1_, p: _ToFloat0ND, /, *, method: _ICDFMethod) -> _FloatND: ... + # + @overload # self: T1-d, logp: 0-d + def ilogcdf(self: _Self[Any, _ShapeT], logp: onp.ToFloat, /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, logp: 0-d + def ilogcdf(self: _Self0, logp: onp.ToFloat, /, *, method: _ICDFMethod) -> _Float: ... + @overload # self: 0-d, logp: 1-d + def ilogcdf(self: _Self0, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float1D: ... + @overload # self: 0-d, logp: 2-d + def ilogcdf(self: _Self0, logp: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float2D: ... + @overload # self: 0-d, logp: 3-d + def ilogcdf(self: _Self0, logp: onp.ToFloatStrict3D, /, *, method: _ICDFMethod) -> _Float3D: ... + @overload # self: 0-d, logp: T1-d + def ilogcdf(self: _Self0, logp: _ToFloatND[_ShapeT], /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, p: >=1-d + def ilogcdf( # first union type is needed on `numpy<2.1` + self: _Self0, logp: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _ICDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 1-d, logp: 1-d + def ilogcdf(self: _Self1, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float2D: ... + @overload # self: 1-d, logp: 2-d + def ilogcdf(self: _Self1, logp: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float3D: ... + @overload # self: 1-d, logp: >=-d + def ilogcdf(self: _Self1, logp: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 2-d, logp: 1-ds + def ilogcdf(self: _Self2, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float3D: ... + @overload # self: 2-d, logp: >=1-d + def ilogcdf(self: _Self2, logp: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 3-d, logp: >=1-d + def ilogcdf(self: _Self3, logp: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: >=1-d + def ilogcdf(self: _Self1_, logp: _ToFloat0ND, /, *, method: _ICDFMethod) -> _FloatND: ... + + # + @overload # self: T1-d, p: 0-d + def iccdf(self: _Self[Any, _ShapeT], p: onp.ToFloat, /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, p: 0-d + def iccdf(self: _Self0, p: onp.ToFloat, /, *, method: _ICDFMethod) -> _Float: ... + @overload # self: 0-d, p: 1-d + def iccdf(self: _Self0, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float1D: ... + @overload # self: 0-d, p: 2-d + def iccdf(self: _Self0, p: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float2D: ... + @overload # self: 0-d, p: 3-d + def iccdf(self: _Self0, p: onp.ToFloatStrict3D, /, *, method: _ICDFMethod) -> _Float3D: ... + @overload # self: 0-d, p: T1-d + def iccdf(self: _Self0, p: _ToFloatND[_ShapeT], /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, p: >=1-d + def iccdf( # first union type is needed on `numpy<2.1` + self: _Self0, p: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _ICDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 1-d, p: 1-d + def iccdf(self: _Self1, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float2D: ... + @overload # self: 1-d, p: 2-d + def iccdf(self: _Self1, p: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float3D: ... + @overload # self: 1-d, p: >=-d + def iccdf(self: _Self1, p: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 2-d, p: 1-d + def iccdf(self: _Self2, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float3D: ... + @overload # self: 2-d, p: >=1-d + def iccdf(self: _Self2, p: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 3-d, p: >=1-d + def iccdf(self: _Self3, p: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: >=1-d + def iccdf(self: _Self1_, p: _ToFloat0ND, /, *, method: _ICDFMethod) -> _FloatND: ... + # + @overload # self: T1-d, logp: 0-d + def ilogccdf(self: _Self[Any, _ShapeT], logp: onp.ToFloat, /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, logp: 0-d + def ilogccdf(self: _Self0, logp: onp.ToFloat, /, *, method: _ICDFMethod) -> _Float: ... + @overload # self: 0-d, logp: 1-d + def ilogccdf(self: _Self0, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float1D: ... + @overload # self: 0-d, logp: 2-d + def ilogccdf(self: _Self0, logp: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float2D: ... + @overload # self: 0-d, logp: 3-d + def ilogccdf(self: _Self0, logp: onp.ToFloatStrict3D, /, *, method: _ICDFMethod) -> _Float3D: ... + @overload # self: 0-d, logp: T1-d + def ilogccdf(self: _Self0, logp: _ToFloatND[_ShapeT], /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + @overload # self: 0-d, q: >=1-d + def ilogccdf( # first union type is needed on `numpy<2.1` + self: _Self0, logp: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _ICDFMethod + ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... + @overload # self: 1-d, logp: 1-d + def ilogccdf(self: _Self1, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float2D: ... + @overload # self: 1-d, logp: 2-d + def ilogccdf(self: _Self1, logp: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float3D: ... + @overload # self: 1-d, logp: >=-d + def ilogccdf(self: _Self1, logp: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast2D]: ... + @overload # self: 2-d, logp: 1-d + def ilogccdf(self: _Self2, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float3D: ... + @overload # self: 2-d, logp: >=1-d + def ilogccdf(self: _Self2, logp: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: 3-d, logp: >=1-d + def ilogccdf(self: _Self3, logp: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + @overload # self: >=1-d + def ilogccdf(self: _Self1_, logp: _ToFloat0ND, /, *, method: _ICDFMethod) -> _FloatND: ... From 7f6dcee8a3f609cf252b7ee10f3ee3406990faee Mon Sep 17 00:00:00 2001 From: jorenham Date: Fri, 20 Dec 2024 05:20:58 +0100 Subject: [PATCH 02/16] =?UTF-8?q?=F0=9F=9A=A7=20`stats`:=201.15.0=20prelim?= =?UTF-8?q?inary=20`=5Fdistribution=5Finfrastructure`=20annotations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stats/_distribution_infrastructure.pyi | 195 ++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 scipy-stubs/stats/_distribution_infrastructure.pyi diff --git a/scipy-stubs/stats/_distribution_infrastructure.pyi b/scipy-stubs/stats/_distribution_infrastructure.pyi new file mode 100644 index 00000000..e6bc80d4 --- /dev/null +++ b/scipy-stubs/stats/_distribution_infrastructure.pyi @@ -0,0 +1,195 @@ +# mypy: disable-error-code="explicit-override" + +import abc +from collections.abc import Mapping, Sequence, Set as AbstractSet +from typing import Any, ClassVar, Final, Literal as L, TypeAlias, overload +from typing_extensions import LiteralString, TypeVar, override + +import numpy as np +import optype.numpy as onp +import optype.typing as opt +from scipy._typing import ToRNG +from ._probability_distribution import _BaseDistribution + +# TODO: +# `__all__ = ["Mixture", "abs", "exp", "log", "make_distribution", "order_statistic", "truncate"] + +_ValidationPolicy: TypeAlias = L["skip_all"] | None +_CachePolicy: TypeAlias = L["no_cache"] | None + +_FloatT = TypeVar("_FloatT", bound=np.floating[Any]) + +### + +# TODO(jorenham): Generic dtype +class _Domain(abc.ABC): + symbols: ClassVar[Mapping[float, LiteralString]] + + @abc.abstractmethod + @override + def __str__(self, /) -> str: ... + + # + @abc.abstractmethod + def contains(self, /, x: onp.ArrayND[Any]) -> onp.ArrayND[np.bool_]: ... + + # + @abc.abstractmethod + def draw(self, /, n: int) -> onp.ArrayND[np.float64]: ... + + # + @abc.abstractmethod + def get_numerical_endpoints( + self, + /, + x: Mapping[str, onp.ToFloat | onp.ToFloatND], + ) -> tuple[onp.ArrayND[np.float64], onp.ArrayND[np.float64]]: ... + +# TODO(jorenham): Generic dtype +class _SimpleDomain(_Domain, metaclass=abc.ABCMeta): + def __init__(self, /, endpoints: tuple[float, float] = ..., inclusive: tuple[bool, bool] = (False, False)) -> None: ... + @override + def __str__(self, /) -> str: ... # noqa: PYI029 + + # + def define_parameters(self, /, *parameters: _Parameter) -> None: ... + + # + @override + def get_numerical_endpoints( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + self, + /, + parameter_values: Mapping[str, onp.ToFloat | onp.ToFloatND], + ) -> tuple[onp.ArrayND[np.float64], onp.ArrayND[np.float64]]: ... + + # + @override + def contains( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + self, + /, + item: onp.ArrayND[np.integer[Any] | np.floating[Any]], + parameter_values: Mapping[str, onp.ToFloat | onp.ToFloatND] | None = None, + ) -> onp.ArrayND[np.bool_]: ... + +class _RealDomain(_SimpleDomain): + @override + def draw( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + self, + /, + n: int, + type_: L["in", "out", "on", "nan"], + min: onp.ArrayND[np.floating[Any]], + max: onp.ArrayND[np.floating[Any]], + squeezed_base_shape: tuple[int, ...], + rng: ToRNG = None, + ) -> onp.ArrayND[np.float64]: ... + +# +class _Parameter(abc.ABC): + def __init__( + self, + /, + name: str, + *, + domain: _Domain, + symbol: str | None = None, + typical: _Domain | tuple[int | str, int | str] | None = None, + ) -> None: ... + + # + def draw( + self, + /, + size: tuple[int, ...] | None = None, + *, + rng: ToRNG = None, + region: L["domain", "typical"] = "domain", + proportions: tuple[onp.ToFloat, onp.ToFloat, onp.ToFloat, onp.ToFloat] | None = None, + parameter_values: Mapping[str, onp.ToFloat | onp.ToFloatND] | None = None, + ) -> onp.ArrayND[np.float64]: ... + + # + @overload + @abc.abstractmethod + def validate(self, /, arr: onp.ToFloat) -> tuple[_FloatT, np.dtype[_FloatT], onp.Array0D[np.bool_]]: ... + @overload + @abc.abstractmethod + def validate(self, /, arr: onp.ToFloatND) -> tuple[onp.ArrayND[_FloatT], np.dtype[_FloatT], onp.ArrayND[np.bool_]]: ... + +class _RealParameter(_Parameter): + @overload # type: ignore[override] + def validate( + self, + /, + arr: onp.ToFloat, + parameter_values: Mapping[str, onp.ToFloat | onp.ToFloatND], + ) -> tuple[_FloatT, np.dtype[_FloatT], onp.Array0D[np.bool_]]: ... + @overload + def validate( # pyright: ignore[reportIncompatibleMethodOverride] + self, + /, + arr: onp.ToFloatND, + parameter_values: Mapping[str, onp.ToFloat | onp.ToFloatND], + ) -> tuple[onp.ArrayND[_FloatT], np.dtype[_FloatT], onp.ArrayND[np.bool_]]: ... + +class _Parameterization: + parameters: Final[Mapping[str, _Parameter]] + + def __init__(self, /, *parameters: _Parameter) -> None: ... + def __len__(self, /) -> int: ... + def copy(self, /) -> _Parameterization: ... + def matches(self, /, parameters: AbstractSet[str]) -> bool: ... + def validation( + self, + /, + parameter_values: Mapping[str, _Parameter], + ) -> tuple[onp.ArrayND[np.bool] | np.dtype[np.floating[Any]]]: ... + def draw( + self, + /, + sizes: tuple[int, ...] | Sequence[tuple[int, ...]] | None = None, + rng: ToRNG = None, + proportions: tuple[onp.ToFloat, onp.ToFloat, onp.ToFloat, onp.ToFloat] | None = None, + region: L["domain", "typical"] = "domain", + ) -> dict[str, onp.ArrayND[np.float64]]: ... + +### + +class ContinuousDistribution(_BaseDistribution): + def __init__( + self, + /, + *, + tol: opt.Just[float], + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + def reset_cache(self, /) -> None: ... + +class TransformedDistribution(ContinuousDistribution): + # TODO(jorenham) + ... + +class TruncatedDistribution(TransformedDistribution): + # TODO(jorenham) + ... + +class ShiftedScaledDistribution(TransformedDistribution): + # TODO(jorenham) + ... + +class OrderStatisticDistribution(TransformedDistribution): + # TODO(jorenham) + ... + +class MonotonicTransformedDistribution(TransformedDistribution): + # TODO(jorenham) + ... + +class FoldedDistribution(TransformedDistribution): + # TODO(jorenham) + ... + +class Mixture(_BaseDistribution): + # TODO(jorenham) + ... From 60908d1a24d8df5d85fa9cde69bb6d92e3524630 Mon Sep 17 00:00:00 2001 From: jorenham Date: Fri, 20 Dec 2024 15:18:09 +0100 Subject: [PATCH 03/16] =?UTF-8?q?=F0=9F=A9=B9=20`stats`:=20adjust=20`=5Fdi?= =?UTF-8?q?stribution=5Finfrastructure.=5FDomain.symbol`=20after=20scipy/s?= =?UTF-8?q?cipy#22137?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scipy-stubs/stats/_distribution_infrastructure.pyi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scipy-stubs/stats/_distribution_infrastructure.pyi b/scipy-stubs/stats/_distribution_infrastructure.pyi index e6bc80d4..cb936bec 100644 --- a/scipy-stubs/stats/_distribution_infrastructure.pyi +++ b/scipy-stubs/stats/_distribution_infrastructure.pyi @@ -2,7 +2,7 @@ import abc from collections.abc import Mapping, Sequence, Set as AbstractSet -from typing import Any, ClassVar, Final, Literal as L, TypeAlias, overload +from typing import Any, Final, Literal as L, TypeAlias, overload from typing_extensions import LiteralString, TypeVar, override import numpy as np @@ -23,7 +23,9 @@ _FloatT = TypeVar("_FloatT", bound=np.floating[Any]) # TODO(jorenham): Generic dtype class _Domain(abc.ABC): - symbols: ClassVar[Mapping[float, LiteralString]] + # NOTE: This is a `ClassVar[dict[str, float]]` that's overridden as instance attribute in `_SimpleDomain`. + # https://github.com/scipy/scipy/pull/22139 + symbols: Mapping[float, LiteralString] = ... @abc.abstractmethod @override From b00bf2c7090840b009fe2d3b05ec2bafc75ff4f2 Mon Sep 17 00:00:00 2001 From: jorenham Date: Fri, 20 Dec 2024 15:19:37 +0100 Subject: [PATCH 04/16] =?UTF-8?q?=F0=9F=A9=B9=20`stats`:=20fix=20`np.bool`?= =?UTF-8?q?=20usage=20in=20=5Fdistribution=5Finfrastructure`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scipy-stubs/stats/_distribution_infrastructure.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scipy-stubs/stats/_distribution_infrastructure.pyi b/scipy-stubs/stats/_distribution_infrastructure.pyi index cb936bec..4df13ef5 100644 --- a/scipy-stubs/stats/_distribution_infrastructure.pyi +++ b/scipy-stubs/stats/_distribution_infrastructure.pyi @@ -145,7 +145,7 @@ class _Parameterization: self, /, parameter_values: Mapping[str, _Parameter], - ) -> tuple[onp.ArrayND[np.bool] | np.dtype[np.floating[Any]]]: ... + ) -> tuple[onp.ArrayND[np.bool_] | np.dtype[np.floating[Any]]]: ... def draw( self, /, From 4c84d625172ee8234ab101532bb3195a2be25903 Mon Sep 17 00:00:00 2001 From: jorenham Date: Fri, 20 Dec 2024 16:26:07 +0100 Subject: [PATCH 05/16] =?UTF-8?q?=F0=9F=91=BD=EF=B8=8F=20`stats`:=201.15.0?= =?UTF-8?q?=20new=20`Mixture`=20and=20`ContinuousDistribution`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .mypyignore-todo | 6 +- scipy-stubs/stats/__init__.pyi | 22 +- .../stats/_distribution_infrastructure.pyi | 148 ++++- .../stats/_probability_distribution.pyi | 575 +++++++++++------- 4 files changed, 503 insertions(+), 248 deletions(-) diff --git a/.mypyignore-todo b/.mypyignore-todo index 67f1b9ed..f040755d 100644 --- a/.mypyignore-todo +++ b/.mypyignore-todo @@ -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) diff --git a/scipy-stubs/stats/__init__.pyi b/scipy-stubs/stats/__init__.pyi index 4cbfc76e..834a2a58 100644 --- a/scipy-stubs/stats/__init__.pyi +++ b/scipy-stubs/stats/__init__.pyi @@ -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 ( @@ -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, @@ -302,9 +306,13 @@ __all__ = [ "Covariance", "DegenerateDataWarning", "FitError", + "Mixture", "MonteCarloMethod", "NearConstantInputWarning", + "Normal", "PermutationMethod", + "Uniform", + # "abs", "alexandergovern", "alpha", "anderson", @@ -371,6 +379,7 @@ __all__ = [ "entropy", "epps_singleton_2samp", "erlang", + # "exp", "expectile", "expon", "exponnorm", @@ -450,6 +459,7 @@ __all__ = [ "levy_stable", "linregress", "lmoment", + # "log", "loggamma", "logistic", "loglaplace", @@ -458,6 +468,7 @@ __all__ = [ "logser", "loguniform", "lomax", + # "make_distribution", "mannwhitneyu", "matrix_normal", "maxwell", @@ -493,6 +504,7 @@ __all__ = [ "normaltest", "norminvgauss", "obrientransform", + # "order_statistic", "ortho_group", "page_trend_test", "pareto", @@ -560,6 +572,7 @@ __all__ = [ "trim1", "trim_mean", "trimboth", + # "truncate", "truncexpon", "truncnorm", "truncpareto", @@ -598,13 +611,4 @@ __all__ = [ "zipfian", "zmap", "zscore", - # "Mixture", - # "Normal", - # "Uniform", - # "abs", - # "exp", - # "log", - # "make_distribution", - # "order_statistic", - # "truncate", ] diff --git a/scipy-stubs/stats/_distribution_infrastructure.pyi b/scipy-stubs/stats/_distribution_infrastructure.pyi index 4df13ef5..bac18902 100644 --- a/scipy-stubs/stats/_distribution_infrastructure.pyi +++ b/scipy-stubs/stats/_distribution_infrastructure.pyi @@ -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: @@ -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: ... diff --git a/scipy-stubs/stats/_probability_distribution.pyi b/scipy-stubs/stats/_probability_distribution.pyi index d7eed6e0..1897a317 100644 --- a/scipy-stubs/stats/_probability_distribution.pyi +++ b/scipy-stubs/stats/_probability_distribution.pyi @@ -21,12 +21,13 @@ _ShapeT0_co = TypeVar("_ShapeT0_co", bound=tuple[int, ...], default=tuple[int, . _Tuple2: TypeAlias = tuple[_T, _T] _ToQRNG: TypeAlias = QMCEngine | ToRNG +_MedianMethod: TypeAlias = L["formula", "icdf"] | None +_ModeMethod: TypeAlias = L["formula", "optimization"] | None _SampleMethod: TypeAlias = L["formula", "inverse_transform"] | None _RMomentMethod: TypeAlias = L["formula", "transform", "quadrature", "cache"] | None _CMomentMethod: TypeAlias = L["formula", "transform", "quadrature", "cache", "normalize"] | None _SMomentMethod: TypeAlias = L["formula", "transform", "general", "cache", "normalize"] | None -_MedianMethod: TypeAlias = L["formula", "icdf"] | None -_ModeMethod: TypeAlias = L["formula", "optimization"] | None +_KurtosisConvention: TypeAlias = L["non-excess", "excess"] _EntropyMethod: TypeAlias = L["formula", "logexp", "quadrature"] | None _PDFMethod: TypeAlias = L["formula", "logexp"] | None @@ -131,40 +132,55 @@ _Self2: TypeAlias = _Self[_XT, tuple[int, int]] _Self3: TypeAlias = _Self[_XT, tuple[int, int, int]] _Self1_: TypeAlias = _Self[_XT, onp.AtLeast1D] +# TODO(jorenham): Merge into ContinuousDistribution? @type_check_only class _BaseDistribution(_ProbabilityDistribution[_XT_co], Generic[_XT_co, _ShapeT0_co]): @overload - def support(self: _Self0[_XT], /) -> _Tuple2[_XT_co]: ... + def support(self: _Self0[_XT], /) -> _Tuple2[_XT]: ... @overload def support(self: _Self[_XT, _ShapeT], /) -> _Tuple2[onp.Array[_ShapeT, _XT]]: ... # @overload - def median(self: _Self0[_XT], /, *, method: _MedianMethod) -> _XT: ... + def median(self: _Self0[_XT], /, *, method: _MedianMethod = None) -> _XT: ... @overload - def median(self: _Self[_XT, _ShapeT], /, *, method: _MedianMethod) -> onp.Array[_ShapeT, _XT]: ... + def median(self: _Self[_XT, _ShapeT], /, *, method: _MedianMethod = None) -> onp.Array[_ShapeT, _XT]: ... # @overload - def mode(self: _Self0[_XT], /, *, method: _ModeMethod) -> _XT: ... + def mode(self: _Self0[_XT], /, *, method: _ModeMethod = None) -> _XT: ... @overload - def mode(self: _Self[_XT, _ShapeT], /, *, method: _ModeMethod) -> onp.Array[_ShapeT, _XT]: ... + def mode(self: _Self[_XT, _ShapeT], /, *, method: _ModeMethod = None) -> onp.Array[_ShapeT, _XT]: ... # @overload - def sample(self: _Self0[_XT], /, shape: tuple[()], *, method: _SampleMethod, rng: _ToQRNG) -> _XT: ... + def sample(self: _Self0[_XT], /, shape: tuple[()] = (), *, method: _SampleMethod = None, rng: _ToQRNG = None) -> _XT: ... @overload - def sample(self: _Self0[_XT], /, shape: op.CanIndex, *, method: _SampleMethod, rng: _ToQRNG) -> onp.Array1D[_XT]: ... + def sample( + self: _Self0[_XT], + /, + shape: op.CanIndex, + *, + method: _SampleMethod = None, + rng: _ToQRNG = None, + ) -> onp.Array1D[_XT]: ... @overload - def sample(self: _Self0[_XT], /, shape: _ShapeT, *, method: _SampleMethod, rng: _ToQRNG) -> onp.ArrayND[_XT, _ShapeT]: ... + def sample( + self: _Self0[_XT], + /, + shape: _ShapeT, + *, + method: _SampleMethod = None, + rng: _ToQRNG = None, + ) -> onp.ArrayND[_XT, _ShapeT]: ... @overload def sample( self: _Self[_XT, _ShapeT], /, - shape: tuple[()], + shape: tuple[()] = (), *, - method: _SampleMethod, - rng: _ToQRNG, + method: _SampleMethod = None, + rng: _ToQRNG = None, ) -> onp.ArrayND[_XT, _ShapeT]: ... @overload def sample( @@ -172,8 +188,8 @@ class _BaseDistribution(_ProbabilityDistribution[_XT_co], Generic[_XT_co, _Shape /, shape: op.CanIndex | Iterable[op.CanIndex], *, - method: _SampleMethod, - rng: _ToQRNG, + method: _SampleMethod = None, + rng: _ToQRNG = None, ) -> onp.ArrayND[_XT, _ShapeT] | onp.ArrayND[_XT]: ... # first union type is needed on `numpy<2.1` @overload def sample( @@ -181,56 +197,71 @@ class _BaseDistribution(_ProbabilityDistribution[_XT_co], Generic[_XT_co, _Shape /, shape: op.CanIndex | Iterable[op.CanIndex], *, - method: _SampleMethod, - rng: _ToQRNG, + method: _SampleMethod = None, + rng: _ToQRNG = None, ) -> _XT_co | onp.ArrayND[_XT_co, _ShapeT] | onp.ArrayND[_XT_co]: ... # first union type is needed on `numpy<2.1` # @overload - def mean(self: _Self0, /, *, method: _RMomentMethod) -> _Float: ... + def mean(self: _Self0, /, *, method: _RMomentMethod = None) -> _Float: ... @overload - def mean(self: _Self[Any, _ShapeT], /, *, method: _RMomentMethod) -> _FloatND[_ShapeT]: ... + def mean(self: _Self[Any, _ShapeT], /, *, method: _RMomentMethod = None) -> _FloatND[_ShapeT]: ... # @overload - def variance(self: _Self0, /, *, method: _CMomentMethod) -> _Float: ... + def variance(self: _Self0, /, *, method: _CMomentMethod = None) -> _Float: ... @overload - def variance(self: _Self[Any, _ShapeT], /, *, method: _CMomentMethod) -> _FloatND[_ShapeT]: ... + def variance(self: _Self[Any, _ShapeT], /, *, method: _CMomentMethod = None) -> _FloatND[_ShapeT]: ... # @overload - def standard_deviation(self: _Self0, /, *, method: _CMomentMethod) -> _Float: ... + def standard_deviation(self: _Self0, /, *, method: _CMomentMethod = None) -> _Float: ... @overload - def standard_deviation(self: _Self[Any, _ShapeT], /, *, method: _CMomentMethod) -> _FloatND[_ShapeT]: ... + def standard_deviation(self: _Self[Any, _ShapeT], /, *, method: _CMomentMethod = None) -> _FloatND[_ShapeT]: ... # @overload - def skewness(self: _Self0, /, *, method: _SMomentMethod) -> _Float: ... + def skewness(self: _Self0, /, *, method: _SMomentMethod = None) -> _Float: ... @overload - def skewness(self: _Self[Any, _ShapeT], /, *, method: _SMomentMethod) -> _FloatND[_ShapeT]: ... + def skewness(self: _Self[Any, _ShapeT], /, *, method: _SMomentMethod = None) -> _FloatND[_ShapeT]: ... # - # where is the `convention` parameter? @overload - def kurtosis(self: _Self0, /, *, method: _SMomentMethod) -> _Float: ... + def kurtosis( + self: _Self0, + /, + *, + method: _SMomentMethod = None, + convention: _KurtosisConvention = "non-excess", + ) -> _Float: ... @overload - def kurtosis(self: _Self[Any, _ShapeT], /, *, method: _SMomentMethod) -> _FloatND[_ShapeT]: ... + def kurtosis( + self: _Self[Any, _ShapeT], + /, + *, + method: _SMomentMethod = None, + convention: _KurtosisConvention = "non-excess", + ) -> _FloatND[_ShapeT]: ... # @overload - def moment(self: _Self0, /, order: onp.ToInt, kind: L["raw"], *, method: _RMomentMethod) -> _Float: ... + def moment(self: _Self0, /, order: onp.ToInt = 1, kind: L["raw"] = "raw", *, method: _RMomentMethod = None) -> _Float: ... + @overload + def moment(self: _Self0, /, order: onp.ToInt, kind: L["central"], *, method: _CMomentMethod = None) -> _Float: ... + @overload + def moment(self: _Self0, /, order: onp.ToInt = 1, *, kind: L["central"], method: _CMomentMethod = None) -> _Float: ... @overload - def moment(self: _Self0, /, order: onp.ToInt, kind: L["central"], *, method: _CMomentMethod) -> _Float: ... + def moment(self: _Self0, /, order: onp.ToInt, kind: L["standardized"], *, method: _SMomentMethod = None) -> _Float: ... @overload - def moment(self: _Self0, /, order: onp.ToInt, kind: L["standardized"], *, method: _SMomentMethod) -> _Float: ... + def moment(self: _Self0, /, order: onp.ToInt = 1, *, kind: L["standardized"], method: _SMomentMethod = None) -> _Float: ... @overload def moment( self: _Self[Any, _ShapeT], /, - order: onp.ToInt, - kind: L["raw"], + order: onp.ToInt = 1, + kind: L["raw"] = "raw", *, - method: _RMomentMethod, + method: _RMomentMethod = None, ) -> _FloatND[_ShapeT]: ... @overload def moment( @@ -239,446 +270,548 @@ class _BaseDistribution(_ProbabilityDistribution[_XT_co], Generic[_XT_co, _Shape order: onp.ToInt, kind: L["central"], *, - method: _CMomentMethod, + method: _CMomentMethod = None, ) -> _FloatND[_ShapeT]: ... @overload - def moment( # pyright: ignore[reportIncompatibleMethodOverride] # pyright false positive bug + def moment( + self: _Self[Any, _ShapeT], + /, + order: onp.ToInt = 1, + *, + kind: L["central"], + method: _CMomentMethod = None, + ) -> _FloatND[_ShapeT]: ... + @overload + def moment( self: _Self[Any, _ShapeT], /, order: onp.ToInt, kind: L["standardized"], *, - method: _SMomentMethod, + method: _SMomentMethod = None, + ) -> _FloatND[_ShapeT]: ... + @overload + def moment( # pyright: ignore[reportIncompatibleMethodOverride] # pyright false positive bug + self: _Self[Any, _ShapeT], + /, + order: onp.ToInt = 1, + *, + kind: L["standardized"], + method: _SMomentMethod = None, ) -> _FloatND[_ShapeT]: ... # @overload - def entropy(self: _Self0, /, *, method: _EntropyMethod) -> _Float: ... + def entropy(self: _Self0, /, *, method: _EntropyMethod = None) -> _Float: ... @overload - def entropy(self: _Self[Any, _ShapeT], /, *, method: _EntropyMethod) -> _FloatND[_ShapeT]: ... + def entropy(self: _Self[Any, _ShapeT], /, *, method: _EntropyMethod = None) -> _FloatND[_ShapeT]: ... # @overload - def logentropy(self: _Self0, /, *, method: _EntropyMethod) -> _Complex: ... + def logentropy(self: _Self0, /, *, method: _EntropyMethod = None) -> _Complex: ... @overload - def logentropy(self: _Self[Any, _ShapeT], /, *, method: _EntropyMethod) -> _ComplexND[_ShapeT]: ... + def logentropy(self: _Self[Any, _ShapeT], /, *, method: _EntropyMethod = None) -> _ComplexND[_ShapeT]: ... # # NOTE: The signatures of `pdf` and `logpdf` are equivalent @overload # self: T1-d, x: 0-d - def pdf(self: _Self[Any, _ShapeT], x: onp.ToFloat, /, *, method: _PDFMethod) -> _FloatND[_ShapeT]: ... + def pdf(self: _Self[Any, _ShapeT], x: onp.ToFloat, /, *, method: _PDFMethod = None) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: 0-d - def pdf(self: _Self0, x: onp.ToFloat, /, *, method: _PDFMethod) -> _Float: ... + def pdf(self: _Self0, x: onp.ToFloat, /, *, method: _PDFMethod = None) -> _Float: ... @overload # self: 0-d, x: 1-d - def pdf(self: _Self0, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod) -> _Float1D: ... + def pdf(self: _Self0, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod = None) -> _Float1D: ... @overload # self: 0-d, x: 2-d - def pdf(self: _Self0, x: onp.ToFloatStrict2D, /, *, method: _PDFMethod) -> _Float2D: ... + def pdf(self: _Self0, x: onp.ToFloatStrict2D, /, *, method: _PDFMethod = None) -> _Float2D: ... @overload # self: 0-d, x: 3-d - def pdf(self: _Self0, x: onp.ToFloatStrict3D, /, *, method: _PDFMethod) -> _Float3D: ... + def pdf(self: _Self0, x: onp.ToFloatStrict3D, /, *, method: _PDFMethod = None) -> _Float3D: ... @overload # self: 0-d, x: T1-d - def pdf(self: _Self0, x: _ToFloatND[_ShapeT], /, *, method: _PDFMethod) -> _FloatND[_ShapeT]: ... + def pdf(self: _Self0, x: _ToFloatND[_ShapeT], /, *, method: _PDFMethod = None) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: >=1-d def pdf( # first union type is needed on `numpy<2.1` - self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _PDFMethod + self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _PDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 1-d, x: 1-d - def pdf(self: _Self1, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod) -> _Float2D: ... + def pdf(self: _Self1, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod = None) -> _Float2D: ... @overload # self: 1-d, x: 2-d - def pdf(self: _Self1, x: onp.ToFloatStrict2D, /, *, method: _PDFMethod) -> _Float3D: ... + def pdf(self: _Self1, x: onp.ToFloatStrict2D, /, *, method: _PDFMethod = None) -> _Float3D: ... @overload # self: 1-d, x: >=-d - def pdf(self: _Self1, x: onp.ToFloatND, /, *, method: _PDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def pdf(self: _Self1, x: onp.ToFloatND, /, *, method: _PDFMethod = None) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 2-d, x: 1-d - def pdf(self: _Self2, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod) -> _Float3D: ... + def pdf(self: _Self2, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod = None) -> _Float3D: ... @overload # self: 2-d, x: >=1-d - def pdf(self: _Self2, x: onp.ToFloatND, /, *, method: _PDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def pdf(self: _Self2, x: onp.ToFloatND, /, *, method: _PDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 3-d, x: >=1-d - def pdf(self: _Self3, x: onp.ToFloatND, /, *, method: _PDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def pdf(self: _Self3, x: onp.ToFloatND, /, *, method: _PDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: >=1-d - def pdf(self: _Self1_, x: _ToFloat0ND, /, *, method: _PDFMethod) -> _FloatND: ... + def pdf(self: _Self1_, x: _ToFloat0ND, /, *, method: _PDFMethod = None) -> _FloatND: ... # @overload # self: T1-d, x: 0-d - def logpdf(self: _Self[Any, _ShapeT], x: onp.ToFloat, /, *, method: _PDFMethod) -> _FloatND[_ShapeT]: ... + def logpdf(self: _Self[Any, _ShapeT], x: onp.ToFloat, /, *, method: _PDFMethod = None) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: 0-d - def logpdf(self: _Self0, x: onp.ToFloat, /, *, method: _PDFMethod) -> _Float: ... + def logpdf(self: _Self0, x: onp.ToFloat, /, *, method: _PDFMethod = None) -> _Float: ... @overload # self: 0-d, x: 1-d - def logpdf(self: _Self0, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod) -> _Float1D: ... + def logpdf(self: _Self0, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod = None) -> _Float1D: ... @overload # self: 0-d, x: 2-d - def logpdf(self: _Self0, x: onp.ToFloatStrict2D, /, *, method: _PDFMethod) -> _Float2D: ... + def logpdf(self: _Self0, x: onp.ToFloatStrict2D, /, *, method: _PDFMethod = None) -> _Float2D: ... @overload # self: 0-d, x: 3-d - def logpdf(self: _Self0, x: onp.ToFloatStrict3D, /, *, method: _PDFMethod) -> _Float3D: ... + def logpdf(self: _Self0, x: onp.ToFloatStrict3D, /, *, method: _PDFMethod = None) -> _Float3D: ... @overload # self: 0-d, x: T1-d - def logpdf(self: _Self0, x: _ToFloatND[_ShapeT], /, *, method: _PDFMethod) -> _FloatND[_ShapeT]: ... + def logpdf(self: _Self0, x: _ToFloatND[_ShapeT], /, *, method: _PDFMethod = None) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: >=1-d def logpdf( # first union type is needed on `numpy<2.1` - self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _PDFMethod + self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _PDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 1-d, x: 1-d - def logpdf(self: _Self1, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod) -> _Float2D: ... + def logpdf(self: _Self1, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod = None) -> _Float2D: ... @overload # self: 1-d, x: 2-d - def logpdf(self: _Self1, x: onp.ToFloatStrict2D, /, *, method: _PDFMethod) -> _Float3D: ... + def logpdf(self: _Self1, x: onp.ToFloatStrict2D, /, *, method: _PDFMethod = None) -> _Float3D: ... @overload # self: 1-d, x: >=1-d - def logpdf(self: _Self1, x: onp.ToFloatND, /, *, method: _PDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def logpdf(self: _Self1, x: onp.ToFloatND, /, *, method: _PDFMethod = None) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 2-d, x: 1-d - def logpdf(self: _Self2, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod) -> _Float3D: ... + def logpdf(self: _Self2, x: onp.ToFloatStrict1D, /, *, method: _PDFMethod = None) -> _Float3D: ... @overload # self: 2-d, x: >=1-d - def logpdf(self: _Self2, x: onp.ToFloatND, /, *, method: _PDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def logpdf(self: _Self2, x: onp.ToFloatND, /, *, method: _PDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 3-d, x: >=1-d - def logpdf(self: _Self3, x: onp.ToFloatND, /, *, method: _PDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def logpdf(self: _Self3, x: onp.ToFloatND, /, *, method: _PDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: >=1-d - def logpdf(self: _Self1_, x: _ToFloat0ND, /, *, method: _PDFMethod) -> _FloatND: ... + def logpdf(self: _Self1_, x: _ToFloat0ND, /, *, method: _PDFMethod = None) -> _FloatND: ... # # NOTE: Apart from the `method` type, the signatures of `[log]cdf` and `[log]ccdf` are equivalent @overload # self: T1-d, x: 0-d, y?: 0-d - def cdf(self: _Self[Any, _ShapeT], x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CDFMethod) -> _FloatND[_ShapeT]: ... + def cdf( + self: _Self[Any, _ShapeT], x: onp.ToFloat, y: onp.ToFloat | None = None, /, *, method: _CDFMethod = None + ) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: 0-d, y?: 0-d - def cdf(self: _Self0, x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CDFMethod) -> _Float: ... + def cdf(self: _Self0, x: onp.ToFloat, y: onp.ToFloat | None = None, /, *, method: _CDFMethod = None) -> _Float: ... @overload # self: 0-d, x: 1-d, y?: <=1-d - def cdf(self: _Self0, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _Float1D: ... + def cdf( + self: _Self0, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None = None, /, *, method: _CDFMethod = None + ) -> _Float1D: ... @overload # self: 0-d, x: <=1-d, y: 1-d - def cdf(self: _Self0, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod) -> _Float1D: ... + def cdf(self: _Self0, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod = None) -> _Float1D: ... @overload # self: 0-d, x: 2-d, y?: <=2-d - def cdf(self: _Self0, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CDFMethod) -> _Float2D: ... + def cdf( + self: _Self0, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None = None, /, *, method: _CDFMethod = None + ) -> _Float2D: ... @overload # self: 0-d, x: <=2-d, y: 2-d - def cdf(self: _Self0, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CDFMethod) -> _Float2D: ... + def cdf(self: _Self0, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CDFMethod = None) -> _Float2D: ... @overload # self: 0-d, x: 3-d, y?: <=3-d - def cdf(self: _Self0, x: onp.ToFloatStrict3D, y: _ToFloatMax3D | None, /, *, method: _CDFMethod) -> _Float3D: ... + def cdf( + self: _Self0, x: onp.ToFloatStrict3D, y: _ToFloatMax3D | None = None, /, *, method: _CDFMethod = None + ) -> _Float3D: ... @overload # self: 0-d, x: <=3-d, y: 3-d - def cdf(self: _Self0, x: _ToFloatMax3D, y: onp.ToFloatStrict3D, /, *, method: _CDFMethod) -> _Float3D: ... + def cdf(self: _Self0, x: _ToFloatMax3D, y: onp.ToFloatStrict3D, /, *, method: _CDFMethod = None) -> _Float3D: ... @overload # self: 0-d, x: T1-d, y?: T1-d | <=1-d - def cdf(self: _Self0, x: _ToFloatND[_ShapeT], y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _FloatND[_ShapeT]: ... + def cdf( + self: _Self0, x: _ToFloatND[_ShapeT], y: _ToFloatMax1D | None = None, /, *, method: _CDFMethod = None + ) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: T1-d | <=1-d, y: T1-d - def cdf(self: _Self0, x: _ToFloatMaxND[_ShapeT], y: _ToFloatND[_ShapeT], /, *, method: _CDFMethod) -> _FloatND[_ShapeT]: ... + def cdf( + self: _Self0, x: _ToFloatMaxND[_ShapeT], y: _ToFloatND[_ShapeT], /, *, method: _CDFMethod = None + ) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: >=1-d, y?: >=0-d def cdf( # first union type is needed on `numpy<2.1` - self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CDFMethod + self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, y: _ToFloat0ND | None = None, /, *, method: _CDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 0-d, x: >=0-d, y: >=1-d def cdf( # first union type is needed on `numpy<2.1` - self: _Self0, x: _ToFloat0ND, y: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _CDFMethod + self: _Self0, x: _ToFloat0ND, y: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _CDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 1-d, x: 1-d, y?: <=1-d - def cdf(self: _Self1, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _Float2D: ... + def cdf( + self: _Self1, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None = None, /, *, method: _CDFMethod = None + ) -> _Float2D: ... @overload # self: 1-d, x: <=1-d, y: 1-d - def cdf(self: _Self1, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod) -> _Float2D: ... + def cdf(self: _Self1, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod = None) -> _Float2D: ... @overload # self: 1-d, x: 2-d, y?: <=2-d - def cdf(self: _Self1, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CDFMethod) -> _Float3D: ... + def cdf( + self: _Self1, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None = None, /, *, method: _CDFMethod = None + ) -> _Float3D: ... @overload # self: 1-d, x: <=2-d, y: 2-d - def cdf(self: _Self1, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CDFMethod) -> _Float3D: ... + def cdf(self: _Self1, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CDFMethod = None) -> _Float3D: ... @overload # self: 1-d, x: >=1-d, y?: >=0-d - def cdf(self: _Self1, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def cdf( + self: _Self1, x: onp.ToFloatND, y: _ToFloat0ND | None = None, /, *, method: _CDFMethod = None + ) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 1-d, x: >=0-d, y: >=1-d - def cdf(self: _Self1, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def cdf(self: _Self1, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CDFMethod = None) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 2-d, x: 1-d, y?: <=1-d - def cdf(self: _Self2, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _Float3D: ... + def cdf( + self: _Self2, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None = None, /, *, method: _CDFMethod = None + ) -> _Float3D: ... @overload # self: 2-d, x: <=1-d, y: 1-d - def cdf(self: _Self2, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod) -> _Float3D: ... + def cdf(self: _Self2, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod = None) -> _Float3D: ... @overload # self: 2-d, x: >=1-d, y?: >=0-d - def cdf(self: _Self2, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def cdf( + self: _Self2, x: onp.ToFloatND, y: _ToFloat0ND | None = None, /, *, method: _CDFMethod = None + ) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 2-d, x: >=0-d, y: >=1-d - def cdf(self: _Self2, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def cdf(self: _Self2, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 3-d, x: >=0-d, y?: >=0-d - def cdf(self: _Self3, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def cdf( + self: _Self3, x: _ToFloat0ND, y: _ToFloat0ND | None = None, /, *, method: _CDFMethod = None + ) -> _FloatND[onp.AtLeast3D]: ... @overload # self: >=1-d, x: >=0-d, y?: >=0-d - def cdf(self: _Self1_, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND: ... + def cdf(self: _Self1_, x: _ToFloat0ND, y: _ToFloat0ND | None = None, /, *, method: _CDFMethod = None) -> _FloatND: ... # @overload # self: T1-d, x: 0-d, y?: 0-d def logcdf( - self: _Self[Any, _ShapeT], x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CDFMethod + self: _Self[Any, _ShapeT], x: onp.ToFloat, y: onp.ToFloat | None = None, /, *, method: _CDFMethod = None ) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: 0-d, y?: 0-d - def logcdf(self: _Self0, x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CDFMethod) -> _Float: ... + def logcdf(self: _Self0, x: onp.ToFloat, y: onp.ToFloat | None = None, /, *, method: _CDFMethod = None) -> _Float: ... @overload # self: 0-d, x: 1-d, y?: <=1-d - def logcdf(self: _Self0, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _Float1D: ... + def logcdf( + self: _Self0, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None = None, /, *, method: _CDFMethod = None + ) -> _Float1D: ... @overload # self: 0-d, x: <=1-d, y: 1-d - def logcdf(self: _Self0, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod) -> _Float1D: ... + def logcdf(self: _Self0, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod = None) -> _Float1D: ... @overload # self: 0-d, x: 2-d, y?: <=2-d - def logcdf(self: _Self0, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CDFMethod) -> _Float2D: ... + def logcdf( + self: _Self0, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None = None, /, *, method: _CDFMethod = None + ) -> _Float2D: ... @overload # self: 0-d, x: <=2-d, y: 2-d - def logcdf(self: _Self0, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CDFMethod) -> _Float2D: ... + def logcdf(self: _Self0, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CDFMethod = None) -> _Float2D: ... @overload # self: 0-d, x: 3-d, y?: <=3-d - def logcdf(self: _Self0, x: onp.ToFloatStrict3D, y: _ToFloatMax3D | None, /, *, method: _CDFMethod) -> _Float3D: ... + def logcdf( + self: _Self0, x: onp.ToFloatStrict3D, y: _ToFloatMax3D | None = None, /, *, method: _CDFMethod = None + ) -> _Float3D: ... @overload # self: 0-d, x: <=3-d, y: 3-d - def logcdf(self: _Self0, x: _ToFloatMax3D, y: onp.ToFloatStrict3D, /, *, method: _CDFMethod) -> _Float3D: ... + def logcdf(self: _Self0, x: _ToFloatMax3D, y: onp.ToFloatStrict3D, /, *, method: _CDFMethod = None) -> _Float3D: ... @overload # self: 0-d, x: T1-d, y?: T1-d | <=1-d - def logcdf(self: _Self0, x: _ToFloatND[_ShapeT], y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _FloatND[_ShapeT]: ... + def logcdf( + self: _Self0, x: _ToFloatND[_ShapeT], y: _ToFloatMax1D | None = None, /, *, method: _CDFMethod = None + ) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: T1-d | <=1-d, y: T1-d def logcdf( - self: _Self0, x: _ToFloatMaxND[_ShapeT], y: _ToFloatND[_ShapeT], /, *, method: _CDFMethod + self: _Self0, x: _ToFloatMaxND[_ShapeT], y: _ToFloatND[_ShapeT], /, *, method: _CDFMethod = None ) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: >=1-d, y?: >=0-d def logcdf( # first union type is needed on `numpy<2.1` - self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CDFMethod + self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, y: _ToFloat0ND | None = None, /, *, method: _CDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 0-d, x: >=0-d, y: >=1-d def logcdf( # first union type is needed on `numpy<2.1` - self: _Self0, x: _ToFloat0ND, y: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _CDFMethod + self: _Self0, x: _ToFloat0ND, y: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _CDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 1-d, x: 1-d, y?: <=1-d - def logcdf(self: _Self1, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _Float2D: ... + def logcdf( + self: _Self1, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None = None, /, *, method: _CDFMethod = None + ) -> _Float2D: ... @overload # self: 1-d, x: <=1-d, y: 1-d - def logcdf(self: _Self1, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod) -> _Float2D: ... + def logcdf(self: _Self1, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod = None) -> _Float2D: ... @overload # self: 1-d, x: 2-d, y?: <=2-d - def logcdf(self: _Self1, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CDFMethod) -> _Float3D: ... + def logcdf( + self: _Self1, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None = None, /, *, method: _CDFMethod = None + ) -> _Float3D: ... @overload # self: 1-d, x: <=2-d, y: 2-d - def logcdf(self: _Self1, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CDFMethod) -> _Float3D: ... + def logcdf(self: _Self1, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CDFMethod = None) -> _Float3D: ... @overload # self: 1-d, x: >=1-d, y?: >=0-d - def logcdf(self: _Self1, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def logcdf( + self: _Self1, x: onp.ToFloatND, y: _ToFloat0ND | None = None, /, *, method: _CDFMethod = None + ) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 1-d, x: >=0-d, y: >=1-d - def logcdf(self: _Self1, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def logcdf(self: _Self1, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CDFMethod = None) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 2-d, x: 1-d, y?: <=1-d - def logcdf(self: _Self2, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CDFMethod) -> _Float3D: ... + def logcdf( + self: _Self2, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None = None, /, *, method: _CDFMethod = None + ) -> _Float3D: ... @overload # self: 2-d, x: <=1-d, y: 1-d - def logcdf(self: _Self2, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod) -> _Float3D: ... + def logcdf(self: _Self2, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CDFMethod = None) -> _Float3D: ... @overload # self: 2-d, x: >=1-d, y?: >=0-d - def logcdf(self: _Self2, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def logcdf( + self: _Self2, x: onp.ToFloatND, y: _ToFloat0ND | None = None, /, *, method: _CDFMethod = None + ) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 2-d, x: >=0-d, y: >=1-d - def logcdf(self: _Self2, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def logcdf(self: _Self2, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 3-d, x: >=0-d, y?: >=0-d - def logcdf(self: _Self3, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def logcdf( + self: _Self3, x: _ToFloat0ND, y: _ToFloat0ND | None = None, /, *, method: _CDFMethod = None + ) -> _FloatND[onp.AtLeast3D]: ... @overload # self: >=1-d, x: >=0-d, y?: >=0-d - def logcdf(self: _Self1_, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CDFMethod) -> _FloatND: ... + def logcdf(self: _Self1_, x: _ToFloat0ND, y: _ToFloat0ND | None = None, /, *, method: _CDFMethod = None) -> _FloatND: ... # @overload # self: T1-d, x: 0-d, y?: 0-d def ccdf( - self: _Self[Any, _ShapeT], x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CCDFMethod + self: _Self[Any, _ShapeT], x: onp.ToFloat, y: onp.ToFloat | None = None, /, *, method: _CCDFMethod = None ) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: 0-d, y?: 0-d - def ccdf(self: _Self0, x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CCDFMethod) -> _Float: ... + def ccdf(self: _Self0, x: onp.ToFloat, y: onp.ToFloat | None = None, /, *, method: _CCDFMethod = None) -> _Float: ... @overload # self: 0-d, x: 1-d, y?: <=1-d - def ccdf(self: _Self0, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _Float1D: ... + def ccdf( + self: _Self0, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None = None, /, *, method: _CCDFMethod = None + ) -> _Float1D: ... @overload # self: 0-d, x: <=1-d, y: 1-d - def ccdf(self: _Self0, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod) -> _Float1D: ... + def ccdf(self: _Self0, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod = None) -> _Float1D: ... @overload # self: 0-d, x: 2-d, y?: <=2-d - def ccdf(self: _Self0, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CCDFMethod) -> _Float2D: ... + def ccdf( + self: _Self0, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None = None, /, *, method: _CCDFMethod = None + ) -> _Float2D: ... @overload # self: 0-d, x: <=2-d, y: 2-d - def ccdf(self: _Self0, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CCDFMethod) -> _Float2D: ... + def ccdf(self: _Self0, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CCDFMethod = None) -> _Float2D: ... @overload # self: 0-d, x: 3-d, y?: <=3-d - def ccdf(self: _Self0, x: onp.ToFloatStrict3D, y: _ToFloatMax3D | None, /, *, method: _CCDFMethod) -> _Float3D: ... + def ccdf( + self: _Self0, x: onp.ToFloatStrict3D, y: _ToFloatMax3D | None = None, /, *, method: _CCDFMethod = None + ) -> _Float3D: ... @overload # self: 0-d, x: <=3-d, y: 3-d - def ccdf(self: _Self0, x: _ToFloatMax3D, y: onp.ToFloatStrict3D, /, *, method: _CCDFMethod) -> _Float3D: ... + def ccdf(self: _Self0, x: _ToFloatMax3D, y: onp.ToFloatStrict3D, /, *, method: _CCDFMethod = None) -> _Float3D: ... @overload # self: 0-d, x: T1-d, y?: T1-d | <=1-d - def ccdf(self: _Self0, x: _ToFloatND[_ShapeT], y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _FloatND[_ShapeT]: ... + def ccdf( + self: _Self0, x: _ToFloatND[_ShapeT], y: _ToFloatMax1D | None = None, /, *, method: _CCDFMethod = None + ) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: T1-d | <=1-d, y: T1-d - def ccdf(self: _Self0, x: _ToFloatMaxND[_ShapeT], y: _ToFloatND[_ShapeT], /, *, method: _CCDFMethod) -> _FloatND[_ShapeT]: ... + def ccdf( + self: _Self0, x: _ToFloatMaxND[_ShapeT], y: _ToFloatND[_ShapeT], /, *, method: _CCDFMethod = None + ) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: >=1-d, y?: >=0-d def ccdf( # first union type is needed on `numpy<2.1` - self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod + self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, y: _ToFloat0ND | None = None, /, *, method: _CCDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 0-d, x: >=0-d, y: >=1-d def ccdf( # first union type is needed on `numpy<2.1` - self: _Self0, x: _ToFloat0ND, y: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _CCDFMethod + self: _Self0, x: _ToFloat0ND, y: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _CCDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 1-d, x: 1-d, y?: <=1-d - def ccdf(self: _Self1, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _Float2D: ... + def ccdf( + self: _Self1, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None = None, /, *, method: _CCDFMethod = None + ) -> _Float2D: ... @overload # self: 1-d, x: <=1-d, y: 1-d - def ccdf(self: _Self1, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod) -> _Float2D: ... + def ccdf(self: _Self1, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod = None) -> _Float2D: ... @overload # self: 1-d, x: 2-d, y?: <=2-d - def ccdf(self: _Self1, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CCDFMethod) -> _Float3D: ... + def ccdf( + self: _Self1, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None = None, /, *, method: _CCDFMethod = None + ) -> _Float3D: ... @overload # self: 1-d, x: <=2-d, y: 2-d - def ccdf(self: _Self1, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CCDFMethod) -> _Float3D: ... + def ccdf(self: _Self1, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CCDFMethod = None) -> _Float3D: ... @overload # self: 1-d, x: >=1-d, y?: >=0-d - def ccdf(self: _Self1, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def ccdf( + self: _Self1, x: onp.ToFloatND, y: _ToFloat0ND | None = None, /, *, method: _CCDFMethod = None + ) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 1-d, x: >=0-d, y: >=1-d - def ccdf(self: _Self1, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def ccdf(self: _Self1, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CCDFMethod = None) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 2-d, x: 1-d, y?: <=1-d - def ccdf(self: _Self2, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _Float3D: ... + def ccdf( + self: _Self2, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None = None, /, *, method: _CCDFMethod = None + ) -> _Float3D: ... @overload # self: 2-d, x: <=1-d, y: 1-d - def ccdf(self: _Self2, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod) -> _Float3D: ... + def ccdf(self: _Self2, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod = None) -> _Float3D: ... @overload # self: 2-d, x: >=1-d, y?: >=0-d - def ccdf(self: _Self2, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def ccdf( + self: _Self2, x: onp.ToFloatND, y: _ToFloat0ND | None = None, /, *, method: _CCDFMethod = None + ) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 2-d, x: >=0-d, y: >=1-d - def ccdf(self: _Self2, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def ccdf(self: _Self2, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CCDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 3-d, x: >=0-d, y?: >=0-d - def ccdf(self: _Self3, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def ccdf( + self: _Self3, x: _ToFloat0ND, y: _ToFloat0ND | None = None, /, *, method: _CCDFMethod = None + ) -> _FloatND[onp.AtLeast3D]: ... @overload # self: >=1-d, x: >=0-d, y?: >=0-d - def ccdf(self: _Self1_, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND: ... + def ccdf(self: _Self1_, x: _ToFloat0ND, y: _ToFloat0ND | None = None, /, *, method: _CCDFMethod = None) -> _FloatND: ... # @overload # self: T1-d, x: 0-d, y?: 0-d def logccdf( - self: _Self[Any, _ShapeT], x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CCDFMethod + self: _Self[Any, _ShapeT], x: onp.ToFloat, y: onp.ToFloat | None = None, /, *, method: _CCDFMethod = None ) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: 0-d, y?: 0-d - def logccdf(self: _Self0, x: onp.ToFloat, y: onp.ToFloat | None, /, *, method: _CCDFMethod) -> _Float: ... + def logccdf(self: _Self0, x: onp.ToFloat, y: onp.ToFloat | None = None, /, *, method: _CCDFMethod = None) -> _Float: ... @overload # self: 0-d, x: 1-d, y?: <=1-d - def logccdf(self: _Self0, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _Float1D: ... + def logccdf( + self: _Self0, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None = None, /, *, method: _CCDFMethod = None + ) -> _Float1D: ... @overload # self: 0-d, x: <=1-d, y: 1-d - def logccdf(self: _Self0, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod) -> _Float1D: ... + def logccdf(self: _Self0, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod = None) -> _Float1D: ... @overload # self: 0-d, x: 2-d, y?: <=2-d - def logccdf(self: _Self0, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CCDFMethod) -> _Float2D: ... + def logccdf( + self: _Self0, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None = None, /, *, method: _CCDFMethod = None + ) -> _Float2D: ... @overload # self: 0-d, x: <=2-d, y: 2-d - def logccdf(self: _Self0, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CCDFMethod) -> _Float2D: ... + def logccdf(self: _Self0, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CCDFMethod = None) -> _Float2D: ... @overload # self: 0-d, x: 3-d, y?: <=3-d - def logccdf(self: _Self0, x: onp.ToFloatStrict3D, y: _ToFloatMax3D | None, /, *, method: _CCDFMethod) -> _Float3D: ... + def logccdf( + self: _Self0, x: onp.ToFloatStrict3D, y: _ToFloatMax3D | None = None, /, *, method: _CCDFMethod = None + ) -> _Float3D: ... @overload # self: 0-d, x: <=3-d, y: 3-d - def logccdf(self: _Self0, x: _ToFloatMax3D, y: onp.ToFloatStrict3D, /, *, method: _CCDFMethod) -> _Float3D: ... + def logccdf(self: _Self0, x: _ToFloatMax3D, y: onp.ToFloatStrict3D, /, *, method: _CCDFMethod = None) -> _Float3D: ... @overload # self: 0-d, x: T1-d, y?: T1-d | <=1-d def logccdf( - self: _Self0, x: _ToFloatND[_ShapeT], y: _ToFloatMax1D | None, /, *, method: _CCDFMethod + self: _Self0, x: _ToFloatND[_ShapeT], y: _ToFloatMax1D | None = None, /, *, method: _CCDFMethod = None ) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: T1-d | <=1-d, y: T1-d def logccdf( - self: _Self0, x: _ToFloatMaxND[_ShapeT], y: _ToFloatND[_ShapeT], /, *, method: _CCDFMethod + self: _Self0, x: _ToFloatMaxND[_ShapeT], y: _ToFloatND[_ShapeT], /, *, method: _CCDFMethod = None ) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, x: >=1-d, y?: >=0-d def logccdf( # first union type is needed on `numpy<2.1` - self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod + self: _Self0, x: _ToFloatND[_ShapeT] | onp.ToFloatND, y: _ToFloat0ND | None = None, /, *, method: _CCDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 0-d, x: >=0-d, y: >=1-d def logccdf( # first union type is needed on `numpy<2.1` - self: _Self0, x: _ToFloat0ND, y: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _CCDFMethod + self: _Self0, x: _ToFloat0ND, y: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _CCDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 1-d, x: 1-d, y?: <=1-d - def logccdf(self: _Self1, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _Float2D: ... + def logccdf( + self: _Self1, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None = None, /, *, method: _CCDFMethod = None + ) -> _Float2D: ... @overload # self: 1-d, x: <=1-d, y: 1-d - def logccdf(self: _Self1, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod) -> _Float2D: ... + def logccdf(self: _Self1, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod = None) -> _Float2D: ... @overload # self: 1-d, x: 2-d, y?: <=2-d - def logccdf(self: _Self1, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None, /, *, method: _CCDFMethod) -> _Float3D: ... + def logccdf( + self: _Self1, x: onp.ToFloatStrict2D, y: _ToFloatMax2D | None = None, /, *, method: _CCDFMethod = None + ) -> _Float3D: ... @overload # self: 1-d, x: <=2-d, y: 2-d - def logccdf(self: _Self1, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CCDFMethod) -> _Float3D: ... + def logccdf(self: _Self1, x: _ToFloatMax2D, y: onp.ToFloatStrict2D, /, *, method: _CCDFMethod = None) -> _Float3D: ... @overload # self: 1-d, x: >=1-d, y?: >=0-d - def logccdf(self: _Self1, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def logccdf( + self: _Self1, x: onp.ToFloatND, y: _ToFloat0ND | None = None, /, *, method: _CCDFMethod = None + ) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 1-d, x: >=0-d, y: >=1-d - def logccdf(self: _Self1, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def logccdf(self: _Self1, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CCDFMethod = None) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 2-d, x: 1-d, y?: <=1-d - def logccdf(self: _Self2, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None, /, *, method: _CCDFMethod) -> _Float3D: ... + def logccdf( + self: _Self2, x: onp.ToFloatStrict1D, y: _ToFloatMax1D | None = None, /, *, method: _CCDFMethod = None + ) -> _Float3D: ... @overload # self: 2-d, x: <=1-d, y: 1-d - def logccdf(self: _Self2, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod) -> _Float3D: ... + def logccdf(self: _Self2, x: _ToFloatMax1D, y: onp.ToFloatStrict1D, /, *, method: _CCDFMethod = None) -> _Float3D: ... @overload # self: 2-d, x: >=1-d, y?: >=0-d - def logccdf(self: _Self2, x: onp.ToFloatND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def logccdf( + self: _Self2, x: onp.ToFloatND, y: _ToFloat0ND | None = None, /, *, method: _CCDFMethod = None + ) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 2-d, x: >=0-d, y: >=1-d - def logccdf(self: _Self2, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def logccdf(self: _Self2, x: _ToFloat0ND, y: onp.ToFloatND, /, *, method: _CCDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 3-d, x: >=0-d, y?: >=0-d - def logccdf(self: _Self3, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def logccdf( + self: _Self3, x: _ToFloat0ND, y: _ToFloat0ND | None = None, /, *, method: _CCDFMethod = None + ) -> _FloatND[onp.AtLeast3D]: ... @overload # self: >=1-d, x: >=0-d, y?: >=0-d - def logccdf(self: _Self1_, x: _ToFloat0ND, y: _ToFloat0ND | None, /, *, method: _CCDFMethod) -> _FloatND: ... + def logccdf(self: _Self1_, x: _ToFloat0ND, y: _ToFloat0ND | None = None, /, *, method: _CCDFMethod = None) -> _FloatND: ... # NOTE: Apart from the `method` type, the signatures of `i[log]cdf` and `i[log]ccdf` are equivalent to those of `[log]pdf` @overload # self: T1-d, p: 0-d - def icdf(self: _Self[Any, _ShapeT], p: onp.ToFloat, /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + def icdf(self: _Self[Any, _ShapeT], p: onp.ToFloat, /, *, method: _ICDFMethod = None) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, p: 0-d - def icdf(self: _Self0, p: onp.ToFloat, /, *, method: _ICDFMethod) -> _Float: ... + def icdf(self: _Self0, p: onp.ToFloat, /, *, method: _ICDFMethod = None) -> _Float: ... @overload # self: 0-d, p: 1-d - def icdf(self: _Self0, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float1D: ... + def icdf(self: _Self0, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod = None) -> _Float1D: ... @overload # self: 0-d, p: 2-d - def icdf(self: _Self0, p: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float2D: ... + def icdf(self: _Self0, p: onp.ToFloatStrict2D, /, *, method: _ICDFMethod = None) -> _Float2D: ... @overload # self: 0-d, p: 3-d - def icdf(self: _Self0, p: onp.ToFloatStrict3D, /, *, method: _ICDFMethod) -> _Float3D: ... + def icdf(self: _Self0, p: onp.ToFloatStrict3D, /, *, method: _ICDFMethod = None) -> _Float3D: ... @overload # self: 0-d, p: T1-d - def icdf(self: _Self0, p: _ToFloatND[_ShapeT], /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + def icdf(self: _Self0, p: _ToFloatND[_ShapeT], /, *, method: _ICDFMethod = None) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, p: >=1-d def icdf( # first union type is needed on `numpy<2.1` - self: _Self0, p: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _ICDFMethod + self: _Self0, p: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _ICDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 1-d, p: 1-d - def icdf(self: _Self1, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float2D: ... + def icdf(self: _Self1, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod = None) -> _Float2D: ... @overload # self: 1-d, p: 2-d - def icdf(self: _Self1, p: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float3D: ... + def icdf(self: _Self1, p: onp.ToFloatStrict2D, /, *, method: _ICDFMethod = None) -> _Float3D: ... @overload # self: 1-d, p: >=-d - def icdf(self: _Self1, p: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def icdf(self: _Self1, p: onp.ToFloatND, /, *, method: _ICDFMethod = None) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 2-d, p: 1-d - def icdf(self: _Self2, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float3D: ... + def icdf(self: _Self2, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod = None) -> _Float3D: ... @overload # self: 2-d, p: >=1-d - def icdf(self: _Self2, p: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def icdf(self: _Self2, p: onp.ToFloatND, /, *, method: _ICDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 3-d, p: >=1-d - def icdf(self: _Self3, p: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def icdf(self: _Self3, p: onp.ToFloatND, /, *, method: _ICDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: >=1-d - def icdf(self: _Self1_, p: _ToFloat0ND, /, *, method: _ICDFMethod) -> _FloatND: ... + def icdf(self: _Self1_, p: _ToFloat0ND, /, *, method: _ICDFMethod = None) -> _FloatND: ... # @overload # self: T1-d, logp: 0-d - def ilogcdf(self: _Self[Any, _ShapeT], logp: onp.ToFloat, /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + def ilogcdf(self: _Self[Any, _ShapeT], logp: onp.ToFloat, /, *, method: _ICDFMethod = None) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, logp: 0-d - def ilogcdf(self: _Self0, logp: onp.ToFloat, /, *, method: _ICDFMethod) -> _Float: ... + def ilogcdf(self: _Self0, logp: onp.ToFloat, /, *, method: _ICDFMethod = None) -> _Float: ... @overload # self: 0-d, logp: 1-d - def ilogcdf(self: _Self0, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float1D: ... + def ilogcdf(self: _Self0, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod = None) -> _Float1D: ... @overload # self: 0-d, logp: 2-d - def ilogcdf(self: _Self0, logp: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float2D: ... + def ilogcdf(self: _Self0, logp: onp.ToFloatStrict2D, /, *, method: _ICDFMethod = None) -> _Float2D: ... @overload # self: 0-d, logp: 3-d - def ilogcdf(self: _Self0, logp: onp.ToFloatStrict3D, /, *, method: _ICDFMethod) -> _Float3D: ... + def ilogcdf(self: _Self0, logp: onp.ToFloatStrict3D, /, *, method: _ICDFMethod = None) -> _Float3D: ... @overload # self: 0-d, logp: T1-d - def ilogcdf(self: _Self0, logp: _ToFloatND[_ShapeT], /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + def ilogcdf(self: _Self0, logp: _ToFloatND[_ShapeT], /, *, method: _ICDFMethod = None) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, p: >=1-d def ilogcdf( # first union type is needed on `numpy<2.1` - self: _Self0, logp: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _ICDFMethod + self: _Self0, logp: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _ICDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 1-d, logp: 1-d - def ilogcdf(self: _Self1, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float2D: ... + def ilogcdf(self: _Self1, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod = None) -> _Float2D: ... @overload # self: 1-d, logp: 2-d - def ilogcdf(self: _Self1, logp: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float3D: ... + def ilogcdf(self: _Self1, logp: onp.ToFloatStrict2D, /, *, method: _ICDFMethod = None) -> _Float3D: ... @overload # self: 1-d, logp: >=-d - def ilogcdf(self: _Self1, logp: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def ilogcdf(self: _Self1, logp: onp.ToFloatND, /, *, method: _ICDFMethod = None) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 2-d, logp: 1-ds - def ilogcdf(self: _Self2, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float3D: ... + def ilogcdf(self: _Self2, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod = None) -> _Float3D: ... @overload # self: 2-d, logp: >=1-d - def ilogcdf(self: _Self2, logp: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def ilogcdf(self: _Self2, logp: onp.ToFloatND, /, *, method: _ICDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 3-d, logp: >=1-d - def ilogcdf(self: _Self3, logp: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def ilogcdf(self: _Self3, logp: onp.ToFloatND, /, *, method: _ICDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: >=1-d - def ilogcdf(self: _Self1_, logp: _ToFloat0ND, /, *, method: _ICDFMethod) -> _FloatND: ... + def ilogcdf(self: _Self1_, logp: _ToFloat0ND, /, *, method: _ICDFMethod = None) -> _FloatND: ... # @overload # self: T1-d, p: 0-d - def iccdf(self: _Self[Any, _ShapeT], p: onp.ToFloat, /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + def iccdf(self: _Self[Any, _ShapeT], p: onp.ToFloat, /, *, method: _ICDFMethod = None) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, p: 0-d - def iccdf(self: _Self0, p: onp.ToFloat, /, *, method: _ICDFMethod) -> _Float: ... + def iccdf(self: _Self0, p: onp.ToFloat, /, *, method: _ICDFMethod = None) -> _Float: ... @overload # self: 0-d, p: 1-d - def iccdf(self: _Self0, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float1D: ... + def iccdf(self: _Self0, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod = None) -> _Float1D: ... @overload # self: 0-d, p: 2-d - def iccdf(self: _Self0, p: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float2D: ... + def iccdf(self: _Self0, p: onp.ToFloatStrict2D, /, *, method: _ICDFMethod = None) -> _Float2D: ... @overload # self: 0-d, p: 3-d - def iccdf(self: _Self0, p: onp.ToFloatStrict3D, /, *, method: _ICDFMethod) -> _Float3D: ... + def iccdf(self: _Self0, p: onp.ToFloatStrict3D, /, *, method: _ICDFMethod = None) -> _Float3D: ... @overload # self: 0-d, p: T1-d - def iccdf(self: _Self0, p: _ToFloatND[_ShapeT], /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + def iccdf(self: _Self0, p: _ToFloatND[_ShapeT], /, *, method: _ICDFMethod = None) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, p: >=1-d def iccdf( # first union type is needed on `numpy<2.1` - self: _Self0, p: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _ICDFMethod + self: _Self0, p: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _ICDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 1-d, p: 1-d - def iccdf(self: _Self1, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float2D: ... + def iccdf(self: _Self1, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod = None) -> _Float2D: ... @overload # self: 1-d, p: 2-d - def iccdf(self: _Self1, p: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float3D: ... + def iccdf(self: _Self1, p: onp.ToFloatStrict2D, /, *, method: _ICDFMethod = None) -> _Float3D: ... @overload # self: 1-d, p: >=-d - def iccdf(self: _Self1, p: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def iccdf(self: _Self1, p: onp.ToFloatND, /, *, method: _ICDFMethod = None) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 2-d, p: 1-d - def iccdf(self: _Self2, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float3D: ... + def iccdf(self: _Self2, p: onp.ToFloatStrict1D, /, *, method: _ICDFMethod = None) -> _Float3D: ... @overload # self: 2-d, p: >=1-d - def iccdf(self: _Self2, p: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def iccdf(self: _Self2, p: onp.ToFloatND, /, *, method: _ICDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 3-d, p: >=1-d - def iccdf(self: _Self3, p: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def iccdf(self: _Self3, p: onp.ToFloatND, /, *, method: _ICDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: >=1-d - def iccdf(self: _Self1_, p: _ToFloat0ND, /, *, method: _ICDFMethod) -> _FloatND: ... + def iccdf(self: _Self1_, p: _ToFloat0ND, /, *, method: _ICDFMethod = None) -> _FloatND: ... # @overload # self: T1-d, logp: 0-d - def ilogccdf(self: _Self[Any, _ShapeT], logp: onp.ToFloat, /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + def ilogccdf(self: _Self[Any, _ShapeT], logp: onp.ToFloat, /, *, method: _ICDFMethod = None) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, logp: 0-d - def ilogccdf(self: _Self0, logp: onp.ToFloat, /, *, method: _ICDFMethod) -> _Float: ... + def ilogccdf(self: _Self0, logp: onp.ToFloat, /, *, method: _ICDFMethod = None) -> _Float: ... @overload # self: 0-d, logp: 1-d - def ilogccdf(self: _Self0, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float1D: ... + def ilogccdf(self: _Self0, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod = None) -> _Float1D: ... @overload # self: 0-d, logp: 2-d - def ilogccdf(self: _Self0, logp: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float2D: ... + def ilogccdf(self: _Self0, logp: onp.ToFloatStrict2D, /, *, method: _ICDFMethod = None) -> _Float2D: ... @overload # self: 0-d, logp: 3-d - def ilogccdf(self: _Self0, logp: onp.ToFloatStrict3D, /, *, method: _ICDFMethod) -> _Float3D: ... + def ilogccdf(self: _Self0, logp: onp.ToFloatStrict3D, /, *, method: _ICDFMethod = None) -> _Float3D: ... @overload # self: 0-d, logp: T1-d - def ilogccdf(self: _Self0, logp: _ToFloatND[_ShapeT], /, *, method: _ICDFMethod) -> _FloatND[_ShapeT]: ... + def ilogccdf(self: _Self0, logp: _ToFloatND[_ShapeT], /, *, method: _ICDFMethod = None) -> _FloatND[_ShapeT]: ... @overload # self: 0-d, q: >=1-d def ilogccdf( # first union type is needed on `numpy<2.1` - self: _Self0, logp: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _ICDFMethod + self: _Self0, logp: _ToFloatND[_ShapeT] | onp.ToFloatND, /, *, method: _ICDFMethod = None ) -> _FloatND[_ShapeT] | _FloatND[onp.AtLeast1D]: ... @overload # self: 1-d, logp: 1-d - def ilogccdf(self: _Self1, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float2D: ... + def ilogccdf(self: _Self1, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod = None) -> _Float2D: ... @overload # self: 1-d, logp: 2-d - def ilogccdf(self: _Self1, logp: onp.ToFloatStrict2D, /, *, method: _ICDFMethod) -> _Float3D: ... + def ilogccdf(self: _Self1, logp: onp.ToFloatStrict2D, /, *, method: _ICDFMethod = None) -> _Float3D: ... @overload # self: 1-d, logp: >=-d - def ilogccdf(self: _Self1, logp: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast2D]: ... + def ilogccdf(self: _Self1, logp: onp.ToFloatND, /, *, method: _ICDFMethod = None) -> _FloatND[onp.AtLeast2D]: ... @overload # self: 2-d, logp: 1-d - def ilogccdf(self: _Self2, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod) -> _Float3D: ... + def ilogccdf(self: _Self2, logp: onp.ToFloatStrict1D, /, *, method: _ICDFMethod = None) -> _Float3D: ... @overload # self: 2-d, logp: >=1-d - def ilogccdf(self: _Self2, logp: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def ilogccdf(self: _Self2, logp: onp.ToFloatND, /, *, method: _ICDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: 3-d, logp: >=1-d - def ilogccdf(self: _Self3, logp: onp.ToFloatND, /, *, method: _ICDFMethod) -> _FloatND[onp.AtLeast3D]: ... + def ilogccdf(self: _Self3, logp: onp.ToFloatND, /, *, method: _ICDFMethod = None) -> _FloatND[onp.AtLeast3D]: ... @overload # self: >=1-d - def ilogccdf(self: _Self1_, logp: _ToFloat0ND, /, *, method: _ICDFMethod) -> _FloatND: ... + def ilogccdf(self: _Self1_, logp: _ToFloat0ND, /, *, method: _ICDFMethod = None) -> _FloatND: ... From cc15c07163ed71f2deb1da0c4a39d515c0f62529 Mon Sep 17 00:00:00 2001 From: jorenham Date: Fri, 20 Dec 2024 16:33:16 +0100 Subject: [PATCH 06/16] =?UTF-8?q?=F0=9F=9A=A7=20`stats`:=20temporarily=20i?= =?UTF-8?q?gnore=20stubtest=20errors=20of=20unfinished=20stuff?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .mypyignore-todo | 1 + scipy-stubs/stats/__init__.pyi | 8 +++++--- scipy-stubs/stats/_new_distributions.pyi | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 scipy-stubs/stats/_new_distributions.pyi diff --git a/.mypyignore-todo b/.mypyignore-todo index f040755d..c787d7ab 100644 --- a/.mypyignore-todo +++ b/.mypyignore-todo @@ -1,3 +1,4 @@ scipy\.stats\.__all__ scipy\.stats\.(Normal|Uniform) scipy\.stats\.(_distribution_infrastructure\.)?(abs|exp|log|make_distribution|order_statistic|truncate) +scipy\.stats\._distribution_infrastructure\.((Monotonic)?Transformed|Folded|Truncated|OrderStatistic)Distribution\.__init__ diff --git a/scipy-stubs/stats/__init__.pyi b/scipy-stubs/stats/__init__.pyi index 834a2a58..78046c7d 100644 --- a/scipy-stubs/stats/__init__.pyi +++ b/scipy-stubs/stats/__init__.pyi @@ -75,7 +75,9 @@ from ._multivariate import ( vonmises_fisher, wishart, ) -from ._new_distributions import Normal, Uniform + +# TODO(jorenham) +# `from ._new_distributions import Normal, Uniform from ._page_trend_test import page_trend_test from ._resampling import ( BootstrapMethod, @@ -309,9 +311,9 @@ __all__ = [ "Mixture", "MonteCarloMethod", "NearConstantInputWarning", - "Normal", + # "Normal", "PermutationMethod", - "Uniform", + # "Uniform", # "abs", "alexandergovern", "alpha", diff --git a/scipy-stubs/stats/_new_distributions.pyi b/scipy-stubs/stats/_new_distributions.pyi new file mode 100644 index 00000000..12a1c5bc --- /dev/null +++ b/scipy-stubs/stats/_new_distributions.pyi @@ -0,0 +1,15 @@ +from ._distribution_infrastructure import ContinuousDistribution + +__all__ = ["Normal", "Uniform"] + +class Normal(ContinuousDistribution): + # TODO(jorenham) + ... + +class StandardNormal(Normal): + # TODO(jorenham) + ... + +class Uniform(ContinuousDistribution): + # TODO(jorenham) + ... From ed01cea942c24f1e59f8ab466181faeb598614bc Mon Sep 17 00:00:00 2001 From: jorenham Date: Fri, 20 Dec 2024 17:36:48 +0100 Subject: [PATCH 07/16] =?UTF-8?q?=F0=9F=91=BD=EF=B8=8F=20`stats`:=201.15.0?= =?UTF-8?q?=20new=20`truncate`=20and=20`TruncatedDistribution`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .mypyignore-todo | 4 +- scipy-stubs/stats/__init__.pyi | 4 +- .../stats/_distribution_infrastructure.pyi | 191 +++++++++++++++--- 3 files changed, 164 insertions(+), 35 deletions(-) diff --git a/.mypyignore-todo b/.mypyignore-todo index c787d7ab..c9f2b790 100644 --- a/.mypyignore-todo +++ b/.mypyignore-todo @@ -1,4 +1,4 @@ scipy\.stats\.__all__ scipy\.stats\.(Normal|Uniform) -scipy\.stats\.(_distribution_infrastructure\.)?(abs|exp|log|make_distribution|order_statistic|truncate) -scipy\.stats\._distribution_infrastructure\.((Monotonic)?Transformed|Folded|Truncated|OrderStatistic)Distribution\.__init__ +scipy\.stats\.(_distribution_infrastructure\.)?(abs|exp|log|make_distribution|order_statistic) +scipy\.stats\._distribution_infrastructure\.(MonotonicTransformed|Folded|OrderStatistic)Distribution\.__init__ diff --git a/scipy-stubs/stats/__init__.pyi b/scipy-stubs/stats/__init__.pyi index 78046c7d..d9d39a53 100644 --- a/scipy-stubs/stats/__init__.pyi +++ b/scipy-stubs/stats/__init__.pyi @@ -7,7 +7,7 @@ from ._correlation import chatterjeexi from ._covariance import Covariance # TODO(jorenham) -from ._distribution_infrastructure import Mixture # , abs, exp, log, make_distribution, order_statistic, truncate +from ._distribution_infrastructure import Mixture, truncate # , abs, exp, log, make_distribution, order_statistic from ._entropy import differential_entropy, entropy from ._fit import fit, goodness_of_fit from ._hypotests import ( @@ -574,7 +574,7 @@ __all__ = [ "trim1", "trim_mean", "trimboth", - # "truncate", + "truncate", "truncexpon", "truncnorm", "truncpareto", diff --git a/scipy-stubs/stats/_distribution_infrastructure.pyi b/scipy-stubs/stats/_distribution_infrastructure.pyi index bac18902..013f4cd1 100644 --- a/scipy-stubs/stats/_distribution_infrastructure.pyi +++ b/scipy-stubs/stats/_distribution_infrastructure.pyi @@ -4,7 +4,7 @@ import abc from collections.abc import Mapping, Sequence, Set as AbstractSet from typing import Any, ClassVar, Final, Generic, Literal as L, TypeAlias, overload -from typing_extensions import LiteralString, Self, TypeVar, override +from typing_extensions import LiteralString, Never, Self, TypeVar, override import numpy as np import optype as op @@ -16,11 +16,11 @@ from ._probability_distribution import _BaseDistribution # TODO: # `__all__ = ["Mixture", "abs", "exp", "log", "make_distribution", "order_statistic", "truncate"] +_FloatT = TypeVar("_FloatT", bound=np.floating[Any]) + _ValidationPolicy: TypeAlias = L["skip_all"] | None _CachePolicy: TypeAlias = L["no_cache"] | None -_FloatT = TypeVar("_FloatT", bound=np.floating[Any]) - ### # TODO(jorenham): Generic dtype @@ -159,13 +159,14 @@ class _Parameterization: ### -_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) +_XT = TypeVar("_XT", bound=np.inexact[Any]) +_XT_co = TypeVar("_XT_co", bound=np.inexact[Any], default=np.float64, covariant=True) +_ShapeT0 = TypeVar("_ShapeT0", bound=tuple[int, ...]) _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]], + bound=ContinuousDistribution[np.inexact[Any]], + default=ContinuousDistribution[np.inexact[Any]], covariant=True, ) @@ -197,6 +198,7 @@ class ContinuousDistribution(_BaseDistribution[_XT_co, _ShapeT0_co], Generic[_XT def cache_policy(self, /) -> _CachePolicy: ... @cache_policy.setter def cache_policy(self, cache_policy: _CachePolicy, /) -> None: ... + # def __init__( self, @@ -208,15 +210,15 @@ class ContinuousDistribution(_BaseDistribution[_XT_co, _ShapeT0_co], Generic[_XT ) -> None: ... # - def __neg__(self, /) -> ShiftedScaledDistribution[Self, _ShapeT0_co]: ... - def __abs__(self, /) -> FoldedDistribution[Self, _ShapeT0_co]: ... + def __neg__(self, /) -> ShiftedScaledDistribution[Self, _XT_co, _ShapeT0_co]: ... + def __abs__(self, /) -> FoldedDistribution[Self, _XT_co, _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]: ... + def __add__(self, rshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _XT_co, _ShapeT0_co]: ... + def __sub__(self, lshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _XT_co, _ShapeT0_co]: ... + def __mul__(self, scale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _XT_co, _ShapeT0_co]: ... + def __truediv__(self, iscale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _XT_co, _ShapeT0_co]: ... + def __pow__(self, exp: onp.ToInt, /) -> MonotonicTransformedDistribution[Self, _XT_co, _ShapeT0_co]: ... __radd__ = __add__ __rsub__ = __sub__ __rmul__ = __mul__ @@ -262,47 +264,174 @@ class ContinuousDistribution(_BaseDistribution[_XT_co, _ShapeT0_co], Generic[_XT # -class TransformedDistribution(ContinuousDistribution[np.float64, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]): - # TODO(jorenham) - ... +class TransformedDistribution(ContinuousDistribution[_XT_co, _ShapeT0_co], Generic[_DistrT_co, _XT_co, _ShapeT0_co]): + def __init__( + self: TransformedDistribution[ContinuousDistribution[_XT, _ShapeT0], _XT, _ShapeT0], # nice trick, eh? + X: _DistrT_co, + /, + *args: Never, + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... -class TruncatedDistribution(TransformedDistribution[_DistrT_co, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]): +class MonotonicTransformedDistribution( + TransformedDistribution[_DistrT_co, _XT_co, _ShapeT0_co], + Generic[_DistrT_co, _XT_co, _ShapeT0_co], +): # TODO(jorenham) ... -class ShiftedScaledDistribution(TransformedDistribution[_DistrT_co, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]): - # TODO(jorenham) - ... +_DistrT0f = TypeVar("_DistrT0f", bound=ContinuousDistribution[np.floating[Any], tuple[()]]) +_DistrT1f = TypeVar("_DistrT1f", bound=ContinuousDistribution[np.floating[Any], tuple[int]]) +_DistrT2f = TypeVar("_DistrT2f", bound=ContinuousDistribution[np.floating[Any], tuple[int, int]]) +_DistrT3f = TypeVar("_DistrT3f", bound=ContinuousDistribution[np.floating[Any], tuple[int, int, int]]) +_DistrTNf = TypeVar("_DistrTNf", bound=ContinuousDistribution[np.floating[Any], tuple[int, ...]]) + +# still waiting on the intersection type PEP... +@overload +def truncate( + X: _DistrT0f, + lb: onp.ToFloat = ..., + ub: onp.ToFloat = ..., +) -> TruncatedDistribution[_DistrT0f, np.floating[Any], tuple[()]]: ... +@overload +def truncate( + X: _DistrT1f, + lb: onp.ToFloat | onp.ToFloatStrict1D = ..., + ub: onp.ToFloat | onp.ToFloatStrict1D = ..., +) -> TruncatedDistribution[_DistrT1f, np.floating[Any], tuple[int]]: ... +@overload +def truncate( + X: _DistrT2f, + lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., + ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., +) -> TruncatedDistribution[_DistrT2f, np.floating[Any], tuple[int, int]]: ... +@overload +def truncate( + X: _DistrT3f, + lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., + ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., +) -> TruncatedDistribution[_DistrT3f, np.floating[Any], tuple[int, int, int]]: ... +@overload +def truncate( + X: _DistrTNf, + lb: onp.ToFloat | onp.ToFloatND = ..., + ub: onp.ToFloat | onp.ToFloatND = ..., +) -> TruncatedDistribution[_DistrTNf, np.floating[Any], tuple[int, ...]]: ... +@overload +def truncate( + X: ContinuousDistribution[_XT, _ShapeT0], + lb: onp.ToFloat = ..., + ub: onp.ToFloat = ..., +) -> TruncatedDistribution[ContinuousDistribution[_XT, _ShapeT0], _XT, _ShapeT0]: ... +@overload +def truncate( + X: ContinuousDistribution[_XT], + lb: onp.ToFloat | onp.ToFloatND = ..., + ub: onp.ToFloat | onp.ToFloatND = ..., +) -> TruncatedDistribution[ContinuousDistribution[_XT], _XT]: ... + +class TruncatedDistribution(TransformedDistribution[_DistrT_co, _XT_co, _ShapeT0_co], Generic[_DistrT_co, _XT_co, _ShapeT0_co]): + lb: _XT_co | onp.ArrayND[_XT_co, _ShapeT0_co] + ub: _XT_co | onp.ArrayND[_XT_co, _ShapeT0_co] + + @overload + def __init__( + self: TruncatedDistribution[_DistrT0f, np.floating[Any], tuple[()]], + X: _DistrT0f, + /, + *args: Never, + lb: onp.ToFloat = ..., + ub: onp.ToFloat = ..., + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + @overload + def __init__( + self: TruncatedDistribution[_DistrT1f, np.floating[Any], tuple[int]], + X: _DistrT1f, + /, + *args: Never, + lb: onp.ToFloat | onp.ToFloatStrict1D = ..., + ub: onp.ToFloat | onp.ToFloatStrict1D = ..., + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + @overload + def __init__( + self: TruncatedDistribution[_DistrT2f, np.floating[Any], tuple[int, int]], + X: _DistrT2f, + /, + *args: Never, + lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., + ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + @overload + def __init__( + self: TruncatedDistribution[_DistrT3f, np.floating[Any], tuple[int, int, int]], + X: _DistrT3f, + /, + *args: Never, + lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., + ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + @overload + def __init__( + self: TruncatedDistribution[_DistrTNf, np.floating[Any], tuple[int, ...]], + X: _DistrTNf, + /, + *args: Never, + lb: onp.ToFloat | onp.ToFloatND = ..., + ub: onp.ToFloat | onp.ToFloatND = ..., + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... -class OrderStatisticDistribution(TransformedDistribution[_DistrT_co, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]): +class FoldedDistribution( + TransformedDistribution[_DistrT_co, _XT_co, _ShapeT0_co], + Generic[_DistrT_co, _XT_co, _ShapeT0_co], +): # TODO(jorenham) ... -class MonotonicTransformedDistribution(TransformedDistribution[_DistrT_co, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]): +class ShiftedScaledDistribution( + TransformedDistribution[_DistrT_co, _XT_co, _ShapeT0_co], + Generic[_DistrT_co, _XT_co, _ShapeT0_co], +): # TODO(jorenham) ... -class FoldedDistribution(TransformedDistribution[_DistrT_co, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]): +class OrderStatisticDistribution(TransformedDistribution[_DistrT_co, np.float64, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]): # TODO(jorenham) ... -class Mixture(_BaseDistribution[_InexactT_co, tuple[()]], Generic[_InexactT_co]): +class Mixture(_BaseDistribution[_XT_co, tuple[()]], Generic[_XT_co]): _shape: tuple[()] - _dtype: np.dtype[_InexactT_co] - _components: Sequence[ContinuousDistribution[_InexactT_co, tuple[()]]] - _weights: onp.Array1D[_InexactT_co] + _dtype: np.dtype[_XT_co] + _components: Sequence[ContinuousDistribution[_XT_co, tuple[()]]] + _weights: onp.Array1D[_XT_co] validation_policy: None @property - def components(self, /) -> list[ContinuousDistribution[_InexactT_co, tuple[()]]]: ... + def components(self, /) -> list[ContinuousDistribution[_XT_co, tuple[()]]]: ... @property - def weights(self, /) -> onp.Array1D[_InexactT_co]: ... + def weights(self, /) -> onp.Array1D[_XT_co]: ... # def __init__( self, /, - components: Sequence[ContinuousDistribution[_InexactT_co, tuple[()]]], + components: Sequence[ContinuousDistribution[_XT_co, tuple[()]]], *, weights: onp.ToFloat1D | None = None, ) -> None: ... From 940c53d53975fb49cf54bd6543411234d7f57ae7 Mon Sep 17 00:00:00 2001 From: jorenham Date: Fri, 20 Dec 2024 17:38:03 +0100 Subject: [PATCH 08/16] =?UTF-8?q?=F0=9F=9A=A7=20`stats`:=20temporarily=20r?= =?UTF-8?q?emove=20the=20`=5Fnew=5Fdistributions`=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scipy-stubs/stats/_new_distributions.pyi | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 scipy-stubs/stats/_new_distributions.pyi diff --git a/scipy-stubs/stats/_new_distributions.pyi b/scipy-stubs/stats/_new_distributions.pyi deleted file mode 100644 index 12a1c5bc..00000000 --- a/scipy-stubs/stats/_new_distributions.pyi +++ /dev/null @@ -1,15 +0,0 @@ -from ._distribution_infrastructure import ContinuousDistribution - -__all__ = ["Normal", "Uniform"] - -class Normal(ContinuousDistribution): - # TODO(jorenham) - ... - -class StandardNormal(Normal): - # TODO(jorenham) - ... - -class Uniform(ContinuousDistribution): - # TODO(jorenham) - ... From 650fc6b3445b38be8f87c077dc394d42fbc4f8e3 Mon Sep 17 00:00:00 2001 From: jorenham Date: Fri, 20 Dec 2024 23:18:09 +0100 Subject: [PATCH 09/16] =?UTF-8?q?=F0=9F=8E=A8=20`stats`:=201.15.0=20new=20?= =?UTF-8?q?disribution=20infrastructure=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stats/_distribution_infrastructure.pyi | 406 +++++++++--------- .../stats/_probability_distribution.pyi | 1 + 2 files changed, 205 insertions(+), 202 deletions(-) diff --git a/scipy-stubs/stats/_distribution_infrastructure.pyi b/scipy-stubs/stats/_distribution_infrastructure.pyi index 013f4cd1..7c15ebd1 100644 --- a/scipy-stubs/stats/_distribution_infrastructure.pyi +++ b/scipy-stubs/stats/_distribution_infrastructure.pyi @@ -16,14 +16,56 @@ from ._probability_distribution import _BaseDistribution # TODO: # `__all__ = ["Mixture", "abs", "exp", "log", "make_distribution", "order_statistic", "truncate"] -_FloatT = TypeVar("_FloatT", bound=np.floating[Any]) +_Float: TypeAlias = np.float64 | np.longdouble +_FloatingT = TypeVar("_FloatingT", bound=np.floating[Any], default=np.floating[Any]) +_FloatingT_co = TypeVar("_FloatingT_co", bound=np.floating[Any], default=np.floating[Any], covariant=True) +_RealT = TypeVar("_RealT", bound=np.floating[Any] | np.integer[Any], default=np.floating[Any] | np.integer[Any]) +_RealT_co = TypeVar( + "_RealT_co", + bound=np.floating[Any] | np.integer[Any], + default=np.floating[Any] | np.integer[Any], + covariant=True, +) + +_ShapeT0 = TypeVar("_ShapeT0", bound=tuple[int, ...], default=tuple[int, ...]) +_ShapeT1 = TypeVar("_ShapeT1", bound=onp.AtLeast1D, default=onp.AtLeast1D) +_ShapeT0_co = TypeVar("_ShapeT0_co", bound=tuple[int, ...], default=tuple[int, ...], covariant=True) + +_CDistT0 = TypeVar("_CDistT0", bound=_CDist0) +_CDistT1 = TypeVar("_CDistT1", bound=_CDist[tuple[int]]) +_CDistT2 = TypeVar("_CDistT2", bound=_CDist[tuple[int, int]]) +_CDistT3 = TypeVar("_CDistT3", bound=_CDist[tuple[int, int, int]]) +_CDistT = TypeVar("_CDistT", bound=ContinuousDistribution) +_CDistT_co = TypeVar("_CDistT_co", bound=ContinuousDistribution, default=ContinuousDistribution, covariant=True) + +# placeholder for `matplotlib.axes.Axes` +_Axes: TypeAlias = object +_AxesT = TypeVar("_AxesT", bound=_Axes, default=Any) + +### +_JustFloat: TypeAlias = opt.Just[float] | np.floating[Any] +_Null: TypeAlias = opt.Just[object] + +_DomainRegion: TypeAlias = L["domain", "typical"] +_DomainDrawType: TypeAlias = L["in", "out", "on", "nan"] _ValidationPolicy: TypeAlias = L["skip_all"] | None _CachePolicy: TypeAlias = L["no_cache"] | None +_PlotQuantity: TypeAlias = L["x", "pdf", "cdf", "ccdf", "icdf", "iccdf", "logpdf", "logcdf", "logccdf", "ilogcdf", "ilogccdf"] +_SMomentMethod: TypeAlias = L["formula", "general", "transform", "normalize", "cache"] + +_ParamValues: TypeAlias = Mapping[str, onp.ToFloat | onp.ToFloatND] +_ToDomain: TypeAlias = _Domain | tuple[onp.ToFloat | str, onp.ToFloat | str] +_DrawProportions: TypeAlias = tuple[onp.ToFloat, onp.ToFloat, onp.ToFloat, onp.ToFloat] + +_CDist: TypeAlias = ContinuousDistribution[np.floating[Any], _ShapeT0] +_CDist0: TypeAlias = ContinuousDistribution[_FloatingT, tuple[()]] ### -# TODO(jorenham): Generic dtype +_null: Final[_Null] = ... + +# TODO(jorenham): Generic dtype and shape class _Domain(abc.ABC): # NOTE: This is a `ClassVar[dict[str, float]]` that's overridden as instance attribute in `_SimpleDomain`. # https://github.com/scipy/scipy/pull/22139 @@ -32,73 +74,73 @@ class _Domain(abc.ABC): @abc.abstractmethod @override def __str__(self, /) -> str: ... - - # @abc.abstractmethod def contains(self, /, x: onp.ArrayND[Any]) -> onp.ArrayND[np.bool_]: ... - - # @abc.abstractmethod - def draw(self, /, n: int) -> onp.ArrayND[np.float64]: ... - - # + def draw(self, /, n: int) -> onp.ArrayND[_FloatingT]: ... @abc.abstractmethod def get_numerical_endpoints( self, /, - x: Mapping[str, onp.ToFloat | onp.ToFloatND], - ) -> tuple[onp.ArrayND[np.float64], onp.ArrayND[np.float64]]: ... + x: _ParamValues, + ) -> tuple[onp.ArrayND[_Float], onp.ArrayND[_Float]]: ... # TODO(jorenham): Generic dtype class _SimpleDomain(_Domain, metaclass=abc.ABCMeta): - def __init__(self, /, endpoints: tuple[float, float] = ..., inclusive: tuple[bool, bool] = (False, False)) -> None: ... - @override - def __str__(self, /) -> str: ... # noqa: PYI029 - - # - def define_parameters(self, /, *parameters: _Parameter) -> None: ... + def __init__( + self, + /, + endpoints: tuple[onp.ToFloat | str, onp.ToFloat | str] = ..., + inclusive: tuple[bool, bool] = (False, False), + ) -> None: ... # @override + def __str__(self, /) -> str: ... # noqa: PYI029 + @override def get_numerical_endpoints( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] self, /, - parameter_values: Mapping[str, onp.ToFloat | onp.ToFloatND], - ) -> tuple[onp.ArrayND[np.float64], onp.ArrayND[np.float64]]: ... - - # + parameter_values: _ParamValues, + ) -> tuple[onp.ArrayND[_Float], onp.ArrayND[_Float]]: ... @override def contains( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] self, /, item: onp.ArrayND[np.integer[Any] | np.floating[Any]], - parameter_values: Mapping[str, onp.ToFloat | onp.ToFloatND] | None = None, + parameter_values: _ParamValues | None = None, ) -> onp.ArrayND[np.bool_]: ... + # + def define_parameters(self, /, *parameters: _Parameter) -> None: ... + class _RealDomain(_SimpleDomain): @override def draw( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] self, /, n: int, - type_: L["in", "out", "on", "nan"], - min: onp.ArrayND[np.floating[Any]], - max: onp.ArrayND[np.floating[Any]], + type_: _DomainDrawType, + min: onp.ArrayND[np.floating[Any] | np.integer[Any]], + max: onp.ArrayND[np.floating[Any] | np.integer[Any]], squeezed_base_shape: tuple[int, ...], rng: ToRNG = None, ) -> onp.ArrayND[np.float64]: ... +_ParamValidated0D: TypeAlias = tuple[_RealT, np.dtype[_RealT], onp.Array0D[np.bool_]] +_ParamValidatedND: TypeAlias = tuple[onp.ArrayND[_RealT, _ShapeT1], np.dtype[_RealT], onp.ArrayND[np.bool_, _ShapeT1]] + # -class _Parameter(abc.ABC): - def __init__( - self, - /, - name: str, - *, - domain: _Domain, - symbol: str | None = None, - typical: _Domain | tuple[int | str, int | str] | None = None, - ) -> None: ... +class _Parameter(abc.ABC, Generic[_RealT_co]): + def __init__(self, /, name: str, *, domain: _Domain, symbol: str | None = None, typical: _ToDomain | None = None) -> None: ... + + # + @overload + @abc.abstractmethod + def validate(self, /, arr: onp.ToFloat) -> _ParamValidated0D[_RealT_co]: ... + @overload + @abc.abstractmethod + def validate(self, /, arr: onp.ToFloatND) -> _ParamValidatedND[_RealT_co]: ... # def draw( @@ -107,82 +149,46 @@ class _Parameter(abc.ABC): size: tuple[int, ...] | None = None, *, rng: ToRNG = None, - region: L["domain", "typical"] = "domain", - proportions: tuple[onp.ToFloat, onp.ToFloat, onp.ToFloat, onp.ToFloat] | None = None, - parameter_values: Mapping[str, onp.ToFloat | onp.ToFloatND] | None = None, - ) -> onp.ArrayND[np.float64]: ... - - # - @overload - @abc.abstractmethod - def validate(self, /, arr: onp.ToFloat) -> tuple[_FloatT, np.dtype[_FloatT], onp.Array0D[np.bool_]]: ... - @overload - @abc.abstractmethod - def validate(self, /, arr: onp.ToFloatND) -> tuple[onp.ArrayND[_FloatT], np.dtype[_FloatT], onp.ArrayND[np.bool_]]: ... + region: _DomainRegion = "domain", + proportions: _DrawProportions | None = None, + parameter_values: _ParamValues | None = None, + ) -> onp.ArrayND[_RealT_co]: ... -class _RealParameter(_Parameter): +class _RealParameter(_Parameter[_FloatingT_co], Generic[_FloatingT_co]): @overload # type: ignore[override] - def validate( - self, - /, - arr: onp.ToFloat, - parameter_values: Mapping[str, onp.ToFloat | onp.ToFloatND], - ) -> tuple[_FloatT, np.dtype[_FloatT], onp.Array0D[np.bool_]]: ... + def validate(self, /, arr: onp.ToFloat, parameter_values: _ParamValues) -> _ParamValidated0D[_FloatingT_co]: ... @overload - def validate( # pyright: ignore[reportIncompatibleMethodOverride] - self, - /, - arr: onp.ToFloatND, - parameter_values: Mapping[str, onp.ToFloat | onp.ToFloatND], - ) -> tuple[onp.ArrayND[_FloatT], np.dtype[_FloatT], onp.ArrayND[np.bool_]]: ... + def validate(self, /, arr: onp.ToFloatND, parameter_values: _ParamValues) -> _ParamValidatedND[_FloatingT_co]: ... # pyright: ignore[reportIncompatibleMethodOverride] class _Parameterization: parameters: Final[Mapping[str, _Parameter]] def __init__(self, /, *parameters: _Parameter) -> None: ... def __len__(self, /) -> int: ... - def copy(self, /) -> _Parameterization: ... + def copy(self, /) -> Self: ... def matches(self, /, parameters: AbstractSet[str]) -> bool: ... def validation( self, /, parameter_values: Mapping[str, _Parameter], - ) -> tuple[onp.ArrayND[np.bool_] | np.dtype[np.floating[Any]]]: ... + ) -> tuple[onp.ArrayND[np.bool_], np.dtype[np.floating[Any]]]: ... def draw( self, /, sizes: tuple[int, ...] | Sequence[tuple[int, ...]] | None = None, rng: ToRNG = None, - proportions: tuple[onp.ToFloat, onp.ToFloat, onp.ToFloat, onp.ToFloat] | None = None, - region: L["domain", "typical"] = "domain", - ) -> dict[str, onp.ArrayND[np.float64]]: ... + proportions: _DrawProportions | None = None, + region: _DomainRegion = "domain", + ) -> dict[str, onp.ArrayND[np.floating[Any]]]: ... ### -_XT = TypeVar("_XT", bound=np.inexact[Any]) -_XT_co = TypeVar("_XT_co", bound=np.inexact[Any], default=np.float64, covariant=True) -_ShapeT0 = TypeVar("_ShapeT0", bound=tuple[int, ...]) -_ShapeT0_co = TypeVar("_ShapeT0_co", bound=tuple[int, ...], default=tuple[int, ...], covariant=True) -_DistrT_co = TypeVar( - "_DistrT_co", - bound=ContinuousDistribution[np.inexact[Any]], - default=ContinuousDistribution[np.inexact[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]): +class ContinuousDistribution(_BaseDistribution[_FloatingT_co, _ShapeT0_co], Generic[_FloatingT_co, _ShapeT0_co]): __array_priority__: ClassVar[float] = 1 + _parameterizations: ClassVar[Sequence[_Parameterization]] + + _not_implemented: Final[str] + _original_parameters: dict[str, _FloatingT_co | onp.ArrayND[_FloatingT_co, _ShapeT0_co]] @property def tol(self, /) -> float | np.float64 | _Null | None: ... @@ -210,15 +216,24 @@ class ContinuousDistribution(_BaseDistribution[_XT_co, _ShapeT0_co], Generic[_XT ) -> None: ... # - def __neg__(self, /) -> ShiftedScaledDistribution[Self, _XT_co, _ShapeT0_co]: ... - def __abs__(self, /) -> FoldedDistribution[Self, _XT_co, _ShapeT0_co]: ... + def _update_parameters( + self, + /, + *, + validation_policy: _ValidationPolicy = None, + **params: onp.ToFloat | onp.ToFloatND, + ) -> None: ... + + # + def __neg__(self, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... + def __abs__(self, /) -> FoldedDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... # TODO(jorenham): Accept `onp.ToFloatND`? - def __add__(self, rshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _XT_co, _ShapeT0_co]: ... - def __sub__(self, lshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _XT_co, _ShapeT0_co]: ... - def __mul__(self, scale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _XT_co, _ShapeT0_co]: ... - def __truediv__(self, iscale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _XT_co, _ShapeT0_co]: ... - def __pow__(self, exp: onp.ToInt, /) -> MonotonicTransformedDistribution[Self, _XT_co, _ShapeT0_co]: ... + def __add__(self, rshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... + def __sub__(self, lshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... + def __mul__(self, scale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... + def __truediv__(self, iscale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... + def __pow__(self, exp: onp.ToInt, /) -> MonotonicTransformedDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... __radd__ = __add__ __rsub__ = __sub__ __rmul__ = __mul__ @@ -231,43 +246,54 @@ class ContinuousDistribution(_BaseDistribution[_XT_co, _ShapeT0_co], Generic[_XT # def plot( self, - x: str = "x", - y: str = "pdf", + x: _PlotQuantity = "x", + y: _PlotQuantity = "pdf", *, t: tuple[_PlotQuantity, _JustFloat, _JustFloat] = ("cdf", 0.0005, 0.9995), ax: _AxesT | None = None, ) -> _AxesT: ... # + # TODO: This will be removed after 1.15.0rc1 (1.15.0rc2 perhaps?): https://github.com/scipy/scipy/pull/22149 @overload - def llf(self, sample: onp.ToFloat | onp.ToFloatND, /, *, axis: None) -> np.float64: ... + def llf(self, sample: onp.ToFloat | onp.ToFloatND, /, *, axis: None) -> _Float: ... @overload - def llf(self, sample: onp.ToFloat | onp.ToFloatStrict1D, /, *, axis: AnyShape | None = -1) -> np.float64: ... + def llf(self: _CDist0, sample: onp.ToFloat | onp.ToFloatStrict1D, /, *, axis: AnyShape | None = -1) -> _Float: ... @overload - def llf(self, sample: onp.ToFloatStrict2D, /, *, axis: op.CanIndex | tuple[op.CanIndex] = -1) -> onp.Array1D[np.float64]: ... + def llf( + self: _CDist[_ShapeT1], sample: onp.ToFloat | onp.ToFloatStrict1D, /, *, axis: AnyShape = -1 + ) -> onp.ArrayND[_Float, _ShapeT1]: ... @overload - def llf(self, sample: onp.ToFloatStrict2D, /, *, axis: tuple[op.CanIndex, op.CanIndex]) -> np.float64: ... + def llf( + self: _CDist0, sample: onp.ToFloatStrict2D, /, *, axis: op.CanIndex | tuple[op.CanIndex] = -1 + ) -> onp.Array1D[_Float]: ... @overload - def llf(self, sample: onp.ToFloatStrict3D, /, *, axis: op.CanIndex | tuple[op.CanIndex] = -1) -> onp.Array2D[np.float64]: ... + def llf(self: _CDist0, sample: onp.ToFloatStrict2D, /, *, axis: tuple[op.CanIndex, op.CanIndex]) -> _Float: ... + @overload + def llf( + self: _CDist0, sample: onp.ToFloatStrict3D, /, *, axis: op.CanIndex | tuple[op.CanIndex] = -1 + ) -> onp.Array2D[_Float]: ... @overload - def llf(self, sample: onp.ToFloatStrict3D, /, *, axis: tuple[op.CanIndex, op.CanIndex]) -> onp.Array1D[np.float64]: ... + def llf(self: _CDist0, sample: onp.ToFloatStrict3D, /, *, axis: tuple[op.CanIndex, op.CanIndex]) -> onp.Array1D[_Float]: ... @overload - def llf(self, sample: onp.ToFloatStrict3D, /, *, axis: tuple[op.CanIndex, op.CanIndex, op.CanIndex]) -> np.float64: ... + def llf(self: _CDist0, sample: onp.ToFloatStrict3D, /, *, axis: tuple[op.CanIndex, op.CanIndex, op.CanIndex]) -> _Float: ... @overload def llf( - self, - sample: onp.ToFloat | onp.ToFloatND, - /, - *, - axis: AnyShape | None = -1, - ) -> np.float64 | onp.ArrayND[np.float64]: ... + self: _CDist[onp.AtLeast1D], sample: onp.ToFloat | onp.ToFloatND, /, *, axis: AnyShape = -1 + ) -> onp.ArrayND[_Float]: ... + @overload + def llf(self, sample: onp.ToFloat | onp.ToFloatND, /, *, axis: AnyShape | None = -1) -> _Float | onp.ArrayND[_Float]: ... # -class TransformedDistribution(ContinuousDistribution[_XT_co, _ShapeT0_co], Generic[_DistrT_co, _XT_co, _ShapeT0_co]): +# 7 years of asking and >400 upvotes, but still no higher-kinded typing support: https://github.com/python/typing/issues/548 +class TransformedDistribution( + ContinuousDistribution[_FloatingT_co, _ShapeT0_co], + Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], +): def __init__( - self: TransformedDistribution[ContinuousDistribution[_XT, _ShapeT0], _XT, _ShapeT0], # nice trick, eh? - X: _DistrT_co, + self: TransformedDistribution[ContinuousDistribution[_FloatingT, _ShapeT0], _FloatingT, _ShapeT0], # nice trick, eh? + X: _CDistT_co, /, *args: Never, tol: opt.Just[float] | _Null = ..., @@ -276,70 +302,23 @@ class TransformedDistribution(ContinuousDistribution[_XT_co, _ShapeT0_co], Gener ) -> None: ... class MonotonicTransformedDistribution( - TransformedDistribution[_DistrT_co, _XT_co, _ShapeT0_co], - Generic[_DistrT_co, _XT_co, _ShapeT0_co], + TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], + Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], ): # TODO(jorenham) ... -_DistrT0f = TypeVar("_DistrT0f", bound=ContinuousDistribution[np.floating[Any], tuple[()]]) -_DistrT1f = TypeVar("_DistrT1f", bound=ContinuousDistribution[np.floating[Any], tuple[int]]) -_DistrT2f = TypeVar("_DistrT2f", bound=ContinuousDistribution[np.floating[Any], tuple[int, int]]) -_DistrT3f = TypeVar("_DistrT3f", bound=ContinuousDistribution[np.floating[Any], tuple[int, int, int]]) -_DistrTNf = TypeVar("_DistrTNf", bound=ContinuousDistribution[np.floating[Any], tuple[int, ...]]) - -# still waiting on the intersection type PEP... -@overload -def truncate( - X: _DistrT0f, - lb: onp.ToFloat = ..., - ub: onp.ToFloat = ..., -) -> TruncatedDistribution[_DistrT0f, np.floating[Any], tuple[()]]: ... -@overload -def truncate( - X: _DistrT1f, - lb: onp.ToFloat | onp.ToFloatStrict1D = ..., - ub: onp.ToFloat | onp.ToFloatStrict1D = ..., -) -> TruncatedDistribution[_DistrT1f, np.floating[Any], tuple[int]]: ... -@overload -def truncate( - X: _DistrT2f, - lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., - ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., -) -> TruncatedDistribution[_DistrT2f, np.floating[Any], tuple[int, int]]: ... -@overload -def truncate( - X: _DistrT3f, - lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., - ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., -) -> TruncatedDistribution[_DistrT3f, np.floating[Any], tuple[int, int, int]]: ... -@overload -def truncate( - X: _DistrTNf, - lb: onp.ToFloat | onp.ToFloatND = ..., - ub: onp.ToFloat | onp.ToFloatND = ..., -) -> TruncatedDistribution[_DistrTNf, np.floating[Any], tuple[int, ...]]: ... -@overload -def truncate( - X: ContinuousDistribution[_XT, _ShapeT0], - lb: onp.ToFloat = ..., - ub: onp.ToFloat = ..., -) -> TruncatedDistribution[ContinuousDistribution[_XT, _ShapeT0], _XT, _ShapeT0]: ... -@overload -def truncate( - X: ContinuousDistribution[_XT], - lb: onp.ToFloat | onp.ToFloatND = ..., - ub: onp.ToFloat | onp.ToFloatND = ..., -) -> TruncatedDistribution[ContinuousDistribution[_XT], _XT]: ... - -class TruncatedDistribution(TransformedDistribution[_DistrT_co, _XT_co, _ShapeT0_co], Generic[_DistrT_co, _XT_co, _ShapeT0_co]): - lb: _XT_co | onp.ArrayND[_XT_co, _ShapeT0_co] - ub: _XT_co | onp.ArrayND[_XT_co, _ShapeT0_co] +class TruncatedDistribution( + TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], + Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], +): + lb: _FloatingT_co | onp.ArrayND[_FloatingT_co, _ShapeT0_co] + ub: _FloatingT_co | onp.ArrayND[_FloatingT_co, _ShapeT0_co] @overload def __init__( - self: TruncatedDistribution[_DistrT0f, np.floating[Any], tuple[()]], - X: _DistrT0f, + self: TruncatedDistribution[_CDistT0, np.floating[Any], tuple[()]], + X: _CDistT0, /, *args: Never, lb: onp.ToFloat = ..., @@ -350,8 +329,8 @@ class TruncatedDistribution(TransformedDistribution[_DistrT_co, _XT_co, _ShapeT0 ) -> None: ... @overload def __init__( - self: TruncatedDistribution[_DistrT1f, np.floating[Any], tuple[int]], - X: _DistrT1f, + self: TruncatedDistribution[_CDistT1, np.floating[Any], tuple[int]], + X: _CDistT1, /, *args: Never, lb: onp.ToFloat | onp.ToFloatStrict1D = ..., @@ -362,8 +341,8 @@ class TruncatedDistribution(TransformedDistribution[_DistrT_co, _XT_co, _ShapeT0 ) -> None: ... @overload def __init__( - self: TruncatedDistribution[_DistrT2f, np.floating[Any], tuple[int, int]], - X: _DistrT2f, + self: TruncatedDistribution[_CDistT2, np.floating[Any], tuple[int, int]], + X: _CDistT2, /, *args: Never, lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., @@ -374,8 +353,8 @@ class TruncatedDistribution(TransformedDistribution[_DistrT_co, _XT_co, _ShapeT0 ) -> None: ... @overload def __init__( - self: TruncatedDistribution[_DistrT3f, np.floating[Any], tuple[int, int, int]], - X: _DistrT3f, + self: TruncatedDistribution[_CDistT3, np.floating[Any], tuple[int, int, int]], + X: _CDistT3, /, *args: Never, lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., @@ -386,8 +365,8 @@ class TruncatedDistribution(TransformedDistribution[_DistrT_co, _XT_co, _ShapeT0 ) -> None: ... @overload def __init__( - self: TruncatedDistribution[_DistrTNf, np.floating[Any], tuple[int, ...]], - X: _DistrTNf, + self: TruncatedDistribution[_CDistT, np.floating[Any], tuple[int, ...]], + X: _CDistT, /, *args: Never, lb: onp.ToFloat | onp.ToFloatND = ..., @@ -398,49 +377,72 @@ class TruncatedDistribution(TransformedDistribution[_DistrT_co, _XT_co, _ShapeT0 ) -> None: ... class FoldedDistribution( - TransformedDistribution[_DistrT_co, _XT_co, _ShapeT0_co], - Generic[_DistrT_co, _XT_co, _ShapeT0_co], + TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], + Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], ): # TODO(jorenham) ... class ShiftedScaledDistribution( - TransformedDistribution[_DistrT_co, _XT_co, _ShapeT0_co], - Generic[_DistrT_co, _XT_co, _ShapeT0_co], + TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], + Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], ): # TODO(jorenham) ... -class OrderStatisticDistribution(TransformedDistribution[_DistrT_co, np.float64, _ShapeT0_co], Generic[_DistrT_co, _ShapeT0_co]): +class OrderStatisticDistribution(TransformedDistribution[_CDistT_co, np.float64, _ShapeT0_co], Generic[_CDistT_co, _ShapeT0_co]): # TODO(jorenham) ... -class Mixture(_BaseDistribution[_XT_co, tuple[()]], Generic[_XT_co]): +class Mixture(_BaseDistribution[_FloatingT_co, tuple[()]], Generic[_FloatingT_co]): _shape: tuple[()] - _dtype: np.dtype[_XT_co] - _components: Sequence[ContinuousDistribution[_XT_co, tuple[()]]] - _weights: onp.Array1D[_XT_co] + _dtype: np.dtype[_FloatingT_co] + _components: Sequence[_CDist0[_FloatingT_co]] + _weights: onp.Array1D[_FloatingT_co] validation_policy: None @property - def components(self, /) -> list[ContinuousDistribution[_XT_co, tuple[()]]]: ... + def components(self, /) -> list[_CDist0[_FloatingT_co]]: ... @property - def weights(self, /) -> onp.Array1D[_XT_co]: ... + def weights(self, /) -> onp.Array1D[_FloatingT_co]: ... # - def __init__( - self, - /, - components: Sequence[ContinuousDistribution[_XT_co, tuple[()]]], - *, - weights: onp.ToFloat1D | None = None, - ) -> None: ... + def __init__(self, /, components: Sequence[_CDist0[_FloatingT_co]], *, 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: ... + def kurtosis(self, /, *, method: _SMomentMethod | None = None) -> _Float: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + +### + +# still waiting on the intersection type PEP... +@overload +def truncate( + X: _CDistT0, + lb: onp.ToFloat = ..., + ub: onp.ToFloat = ..., +) -> TruncatedDistribution[_CDistT0, np.floating[Any], tuple[()]]: ... +@overload +def truncate( + X: _CDistT1, + lb: onp.ToFloat | onp.ToFloatStrict1D = ..., + ub: onp.ToFloat | onp.ToFloatStrict1D = ..., +) -> TruncatedDistribution[_CDistT1, np.floating[Any], tuple[int]]: ... +@overload +def truncate( + X: _CDistT2, + lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., + ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., +) -> TruncatedDistribution[_CDistT2, np.floating[Any], tuple[int, int]]: ... +@overload +def truncate( + X: _CDistT3, + lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., + ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., +) -> TruncatedDistribution[_CDistT3, np.floating[Any], tuple[int, int, int]]: ... +@overload +def truncate( + X: _CDistT, + lb: onp.ToFloat | onp.ToFloatND = ..., + ub: onp.ToFloat | onp.ToFloatND = ..., +) -> TruncatedDistribution[_CDistT, np.floating[Any], tuple[int, ...]]: ... diff --git a/scipy-stubs/stats/_probability_distribution.pyi b/scipy-stubs/stats/_probability_distribution.pyi index 1897a317..2b6a8a3b 100644 --- a/scipy-stubs/stats/_probability_distribution.pyi +++ b/scipy-stubs/stats/_probability_distribution.pyi @@ -313,6 +313,7 @@ class _BaseDistribution(_ProbabilityDistribution[_XT_co], Generic[_XT_co, _Shape def logentropy(self: _Self[Any, _ShapeT], /, *, method: _EntropyMethod = None) -> _ComplexND[_ShapeT]: ... # + # TODO(jorenham): Adjust these, depending on the result of https://github.com/scipy/scipy/issues/22145 # NOTE: The signatures of `pdf` and `logpdf` are equivalent @overload # self: T1-d, x: 0-d def pdf(self: _Self[Any, _ShapeT], x: onp.ToFloat, /, *, method: _PDFMethod = None) -> _FloatND[_ShapeT]: ... From ea5b6eb086a79f19f32352c832680ff81188df92 Mon Sep 17 00:00:00 2001 From: jorenham Date: Sat, 21 Dec 2024 01:08:20 +0100 Subject: [PATCH 10/16] =?UTF-8?q?=E2=9C=A8=20`stats`:=20casually=20invent?= =?UTF-8?q?=20a=20way=20to=20do=20overload=20attributes=20(it=20even=20wor?= =?UTF-8?q?ks=20on=20mypy)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stats/_distribution_infrastructure.pyi | 58 +++++++++++++++---- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/scipy-stubs/stats/_distribution_infrastructure.pyi b/scipy-stubs/stats/_distribution_infrastructure.pyi index 7c15ebd1..30cb4911 100644 --- a/scipy-stubs/stats/_distribution_infrastructure.pyi +++ b/scipy-stubs/stats/_distribution_infrastructure.pyi @@ -2,8 +2,8 @@ # pyright: reportUnannotatedClassAttribute=false import abc -from collections.abc import Mapping, Sequence, Set as AbstractSet -from typing import Any, ClassVar, Final, Generic, Literal as L, TypeAlias, overload +from collections.abc import Callable, Mapping, Sequence, Set as AbstractSet +from typing import Any, ClassVar, Final, Generic, Literal as L, Protocol, TypeAlias, overload, type_check_only from typing_extensions import LiteralString, Never, Self, TypeVar, override import numpy as np @@ -61,6 +61,24 @@ _DrawProportions: TypeAlias = tuple[onp.ToFloat, onp.ToFloat, onp.ToFloat, onp.T _CDist: TypeAlias = ContinuousDistribution[np.floating[Any], _ShapeT0] _CDist0: TypeAlias = ContinuousDistribution[_FloatingT, tuple[()]] +@type_check_only +class _ParameterField(Protocol[_FloatingT_co, _ShapeT0_co]): + # This actually works (even on mypy)! + @overload + def __get__( + self: _ParameterField[_FloatingT, tuple[()]], + instance: object, + owner: type | None = None, + /, + ) -> _FloatingT: ... + @overload + def __get__( + self: _ParameterField[_FloatingT, _ShapeT1], + instance: object, + owner: type | None = None, + /, + ) -> onp.ArrayND[_FloatingT, _ShapeT1]: ... + ### _null: Final[_Null] = ... @@ -233,7 +251,7 @@ class ContinuousDistribution(_BaseDistribution[_FloatingT_co, _ShapeT0_co], Gene def __sub__(self, lshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... def __mul__(self, scale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... def __truediv__(self, iscale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... - def __pow__(self, exp: onp.ToInt, /) -> MonotonicTransformedDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... + def __pow__(self, exp: onp.ToInt, /) -> MonotonicTransformedDistribution[Self, _ShapeT0_co]: ... __radd__ = __add__ __rsub__ = __sub__ __rmul__ = __mul__ @@ -284,7 +302,7 @@ class ContinuousDistribution(_BaseDistribution[_FloatingT_co, _ShapeT0_co], Gene @overload def llf(self, sample: onp.ToFloat | onp.ToFloatND, /, *, axis: AnyShape | None = -1) -> _Float | onp.ArrayND[_Float]: ... - # +_ElementwiseFunction: TypeAlias = Callable[[onp.ArrayND[np.float64]], onp.ArrayND[_FloatingT]] # 7 years of asking and >400 upvotes, but still no higher-kinded typing support: https://github.com/python/typing/issues/548 class TransformedDistribution( @@ -302,18 +320,38 @@ class TransformedDistribution( ) -> None: ... class MonotonicTransformedDistribution( - TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], - Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], + TransformedDistribution[_CDistT_co, np.float64, _ShapeT0_co], + Generic[_CDistT_co, _ShapeT0_co], ): - # TODO(jorenham) - ... + _g: Final[_ElementwiseFunction] + _h: Final[_ElementwiseFunction] + _dh: Final[_ElementwiseFunction] + _logdh: Final[_ElementwiseFunction] + _increasing: Final[bool] + _repr_pattern: Final[str] + + def __init__( + self: MonotonicTransformedDistribution[_CDist[_ShapeT0], _ShapeT0], + X: _CDistT_co, + /, + *args: Never, + g: _ElementwiseFunction, + h: _ElementwiseFunction, + dh: _ElementwiseFunction, + logdh: _ElementwiseFunction | None = None, + increasing: bool = True, + repr_pattern: str | None = None, + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... class TruncatedDistribution( TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], ): - lb: _FloatingT_co | onp.ArrayND[_FloatingT_co, _ShapeT0_co] - ub: _FloatingT_co | onp.ArrayND[_FloatingT_co, _ShapeT0_co] + lb: _ParameterField[_FloatingT_co, _ShapeT0_co] + ub: _ParameterField[_FloatingT_co, _ShapeT0_co] @overload def __init__( From 22266f39227ccd64018564d16e1484f9158da3c7 Mon Sep 17 00:00:00 2001 From: jorenham Date: Sat, 21 Dec 2024 01:49:21 +0100 Subject: [PATCH 11/16] =?UTF-8?q?=F0=9F=91=BD=EF=B8=8F=20`stats`:=201.15.0?= =?UTF-8?q?=20`exp`=20&=20`log`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .mypyignore-todo | 4 +- scipy-stubs/stats/__init__.pyi | 6 +- .../stats/_distribution_infrastructure.pyi | 251 ++++++++++++++---- 3 files changed, 200 insertions(+), 61 deletions(-) diff --git a/.mypyignore-todo b/.mypyignore-todo index c9f2b790..6150cb02 100644 --- a/.mypyignore-todo +++ b/.mypyignore-todo @@ -1,4 +1,4 @@ scipy\.stats\.__all__ scipy\.stats\.(Normal|Uniform) -scipy\.stats\.(_distribution_infrastructure\.)?(abs|exp|log|make_distribution|order_statistic) -scipy\.stats\._distribution_infrastructure\.(MonotonicTransformed|Folded|OrderStatistic)Distribution\.__init__ +scipy\.stats\.(_distribution_infrastructure\.)?(abs|exp|make_distribution|order_statistic) +scipy\.stats\._distribution_infrastructure\.(Folded|OrderStatistic)Distribution\.__init__ diff --git a/scipy-stubs/stats/__init__.pyi b/scipy-stubs/stats/__init__.pyi index d9d39a53..a69f8aa7 100644 --- a/scipy-stubs/stats/__init__.pyi +++ b/scipy-stubs/stats/__init__.pyi @@ -7,7 +7,7 @@ from ._correlation import chatterjeexi from ._covariance import Covariance # TODO(jorenham) -from ._distribution_infrastructure import Mixture, truncate # , abs, exp, log, make_distribution, order_statistic +from ._distribution_infrastructure import Mixture, exp, log, truncate # abs, make_distribution, order_statistic from ._entropy import differential_entropy, entropy from ._fit import fit, goodness_of_fit from ._hypotests import ( @@ -381,7 +381,7 @@ __all__ = [ "entropy", "epps_singleton_2samp", "erlang", - # "exp", + "exp", "expectile", "expon", "exponnorm", @@ -461,7 +461,7 @@ __all__ = [ "levy_stable", "linregress", "lmoment", - # "log", + "log", "loggamma", "logistic", "loglaplace", diff --git a/scipy-stubs/stats/_distribution_infrastructure.pyi b/scipy-stubs/stats/_distribution_infrastructure.pyi index 30cb4911..6d279b84 100644 --- a/scipy-stubs/stats/_distribution_infrastructure.pyi +++ b/scipy-stubs/stats/_distribution_infrastructure.pyi @@ -33,8 +33,11 @@ _ShapeT0_co = TypeVar("_ShapeT0_co", bound=tuple[int, ...], default=tuple[int, . _CDistT0 = TypeVar("_CDistT0", bound=_CDist0) _CDistT1 = TypeVar("_CDistT1", bound=_CDist[tuple[int]]) +_CDistT_1 = TypeVar("_CDistT_1", bound=_CDist[onp.AtMost1D]) _CDistT2 = TypeVar("_CDistT2", bound=_CDist[tuple[int, int]]) +_CDistT_2 = TypeVar("_CDistT_2", bound=_CDist[onp.AtMost2D]) _CDistT3 = TypeVar("_CDistT3", bound=_CDist[tuple[int, int, int]]) +_CDistT_3 = TypeVar("_CDistT_3", bound=_CDist[onp.AtMost3D]) _CDistT = TypeVar("_CDistT", bound=ContinuousDistribution) _CDistT_co = TypeVar("_CDistT_co", bound=ContinuousDistribution, default=ContinuousDistribution, covariant=True) @@ -233,35 +236,132 @@ class ContinuousDistribution(_BaseDistribution[_FloatingT_co, _ShapeT0_co], Gene cache_policy: _CachePolicy = None, ) -> None: ... - # - def _update_parameters( - self, - /, - *, - validation_policy: _ValidationPolicy = None, - **params: onp.ToFloat | onp.ToFloatND, - ) -> None: ... - # def __neg__(self, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... def __abs__(self, /) -> FoldedDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... - # TODO(jorenham): Accept `onp.ToFloatND`? - def __add__(self, rshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... - def __sub__(self, lshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... - def __mul__(self, scale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... - def __truediv__(self, iscale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... - def __pow__(self, exp: onp.ToInt, /) -> MonotonicTransformedDistribution[Self, _ShapeT0_co]: ... + # + @overload + def __add__( + self, rshift: float | np.integer[Any] | np.bool_, / + ) -> ShiftedScaledDistribution[Self, np.float64 | _FloatingT_co, _ShapeT0_co]: ... + @overload + def __add__(self, rshift: _FloatingT, /) -> ShiftedScaledDistribution[Self, _FloatingT | _FloatingT_co, _ShapeT0_co]: ... + @overload + def __add__(self, rshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, np.floating[Any], _ShapeT0_co]: ... + @overload + def __add__( + self: _CDistT0, rshift: onp.CanArrayND[_FloatingT, _ShapeT0], / + ) -> ShiftedScaledDistribution[_CDistT0, _FloatingT | _FloatingT_co, _ShapeT0]: ... + @overload + def __add__( + self: _CDistT_1, rshift: onp.ToFloatStrict1D, / + ) -> ShiftedScaledDistribution[_CDistT_1, np.floating[Any], tuple[int]]: ... + @overload + def __add__( + self: _CDistT_2, rshift: onp.ToFloatStrict2D, / + ) -> ShiftedScaledDistribution[_CDistT_2, np.floating[Any], tuple[int, int]]: ... + @overload + def __add__( + self: _CDistT_3, rshift: onp.ToFloatStrict3D, / + ) -> ShiftedScaledDistribution[_CDistT_3, np.floating[Any], tuple[int, int, int]]: ... + @overload + def __add__(self, rshift: onp.ToFloatND, /) -> ShiftedScaledDistribution[Self]: ... __radd__ = __add__ + + # + @overload + def __sub__( + self, lshift: float | np.integer[Any] | np.bool_, / + ) -> ShiftedScaledDistribution[Self, np.float64 | _FloatingT_co, _ShapeT0_co]: ... + @overload + def __sub__(self, lshift: _FloatingT, /) -> ShiftedScaledDistribution[Self, _FloatingT | _FloatingT_co, _ShapeT0_co]: ... + @overload + def __sub__(self, lshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, np.floating[Any], _ShapeT0_co]: ... + @overload + def __sub__( + self: _CDistT0, lshift: onp.CanArrayND[_FloatingT, _ShapeT0], / + ) -> ShiftedScaledDistribution[_CDistT0, _FloatingT | _FloatingT_co, _ShapeT0]: ... + @overload + def __sub__( + self: _CDistT_1, lshift: onp.ToFloatStrict1D, / + ) -> ShiftedScaledDistribution[_CDistT_1, np.floating[Any], tuple[int]]: ... + @overload + def __sub__( + self: _CDistT_2, lshift: onp.ToFloatStrict2D, / + ) -> ShiftedScaledDistribution[_CDistT_2, np.floating[Any], tuple[int, int]]: ... + @overload + def __sub__( + self: _CDistT_3, lshift: onp.ToFloatStrict3D, / + ) -> ShiftedScaledDistribution[_CDistT_3, np.floating[Any], tuple[int, int, int]]: ... + @overload + def __sub__(self, lshift: onp.ToFloatND, /) -> ShiftedScaledDistribution[Self]: ... __rsub__ = __sub__ + + # + @overload + def __mul__( + self, scale: float | np.integer[Any] | np.bool_, / + ) -> ShiftedScaledDistribution[Self, np.float64 | _FloatingT_co, _ShapeT0_co]: ... + @overload + def __mul__(self, scale: _FloatingT, /) -> ShiftedScaledDistribution[Self, _FloatingT | _FloatingT_co, _ShapeT0_co]: ... + @overload + def __mul__(self, scale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, np.floating[Any], _ShapeT0_co]: ... + @overload + def __mul__( + self: _CDistT0, scale: onp.CanArrayND[_FloatingT, _ShapeT0], / + ) -> ShiftedScaledDistribution[_CDistT0, _FloatingT | _FloatingT_co, _ShapeT0]: ... + @overload + def __mul__( + self: _CDistT_1, scale: onp.ToFloatStrict1D, / + ) -> ShiftedScaledDistribution[_CDistT_1, np.floating[Any], tuple[int]]: ... + @overload + def __mul__( + self: _CDistT_2, scale: onp.ToFloatStrict2D, / + ) -> ShiftedScaledDistribution[_CDistT_2, np.floating[Any], tuple[int, int]]: ... + @overload + def __mul__( + self: _CDistT_3, scale: onp.ToFloatStrict3D, / + ) -> ShiftedScaledDistribution[_CDistT_3, np.floating[Any], tuple[int, int, int]]: ... + @overload + def __mul__(self, scale: onp.ToFloatND, /) -> ShiftedScaledDistribution[Self]: ... __rmul__ = __mul__ + + # + @overload + def __truediv__( + self, iscale: float | np.integer[Any] | np.bool_, / + ) -> ShiftedScaledDistribution[Self, np.float64 | _FloatingT_co, _ShapeT0_co]: ... + @overload + def __truediv__(self, iscale: _FloatingT, /) -> ShiftedScaledDistribution[Self, _FloatingT | _FloatingT_co, _ShapeT0_co]: ... + @overload + def __truediv__(self, iscale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, np.floating[Any], _ShapeT0_co]: ... + @overload + def __truediv__( + self: _CDistT0, iscale: onp.CanArrayND[_FloatingT, _ShapeT0], / + ) -> ShiftedScaledDistribution[_CDistT0, _FloatingT | _FloatingT_co, _ShapeT0]: ... + @overload + def __truediv__( + self: _CDistT_1, iscale: onp.ToFloatStrict1D, / + ) -> ShiftedScaledDistribution[_CDistT_1, np.floating[Any], tuple[int]]: ... + @overload + def __truediv__( + self: _CDistT_2, iscale: onp.ToFloatStrict2D, / + ) -> ShiftedScaledDistribution[_CDistT_2, np.floating[Any], tuple[int, int]]: ... + @overload + def __truediv__( + self: _CDistT_3, iscale: onp.ToFloatStrict3D, / + ) -> ShiftedScaledDistribution[_CDistT_3, np.floating[Any], tuple[int, int, int]]: ... + @overload + def __truediv__(self, iscale: onp.ToFloatND, /) -> ShiftedScaledDistribution[Self]: ... __rtruediv__ = __truediv__ - __rpow__ = __pow__ # - def reset_cache(self, /) -> None: ... + def __pow__(self, exp: onp.ToInt, /) -> MonotonicTransformedDistribution[Self, _ShapeT0_co]: ... + __rpow__ = __pow__ # + def reset_cache(self, /) -> None: ... def plot( self, x: _PlotQuantity = "x", @@ -272,7 +372,7 @@ class ContinuousDistribution(_BaseDistribution[_FloatingT_co, _ShapeT0_co], Gene ) -> _AxesT: ... # - # TODO: This will be removed after 1.15.0rc1 (1.15.0rc2 perhaps?): https://github.com/scipy/scipy/pull/22149 + # NOTE: This will be removed in 1.15.0rc2, see https://github.com/scipy/scipy/pull/22149 @overload def llf(self, sample: onp.ToFloat | onp.ToFloatND, /, *, axis: None) -> _Float: ... @overload @@ -297,8 +397,8 @@ class ContinuousDistribution(_BaseDistribution[_FloatingT_co, _ShapeT0_co], Gene def llf(self: _CDist0, sample: onp.ToFloatStrict3D, /, *, axis: tuple[op.CanIndex, op.CanIndex, op.CanIndex]) -> _Float: ... @overload def llf( - self: _CDist[onp.AtLeast1D], sample: onp.ToFloat | onp.ToFloatND, /, *, axis: AnyShape = -1 - ) -> onp.ArrayND[_Float]: ... + self: _CDist[_ShapeT1], sample: onp.ToFloat | onp.ToFloatND, /, *, axis: AnyShape = -1 + ) -> onp.Array[_ShapeT1, _Float] | onp.ArrayND[_Float]: ... # the first union type is needed on numpy <2.1 @overload def llf(self, sample: onp.ToFloat | onp.ToFloatND, /, *, axis: AnyShape | None = -1) -> _Float | onp.ArrayND[_Float]: ... @@ -319,37 +419,38 @@ class TransformedDistribution( cache_policy: _CachePolicy = None, ) -> None: ... -class MonotonicTransformedDistribution( - TransformedDistribution[_CDistT_co, np.float64, _ShapeT0_co], - Generic[_CDistT_co, _ShapeT0_co], +class ShiftedScaledDistribution( + TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], + Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], ): - _g: Final[_ElementwiseFunction] - _h: Final[_ElementwiseFunction] - _dh: Final[_ElementwiseFunction] - _logdh: Final[_ElementwiseFunction] - _increasing: Final[bool] - _repr_pattern: Final[str] + _loc_domain: ClassVar[_RealDomain] = ... + _loc_param: ClassVar[_RealParameter] = ... - def __init__( - self: MonotonicTransformedDistribution[_CDist[_ShapeT0], _ShapeT0], - X: _CDistT_co, - /, - *args: Never, - g: _ElementwiseFunction, - h: _ElementwiseFunction, - dh: _ElementwiseFunction, - logdh: _ElementwiseFunction | None = None, - increasing: bool = True, - repr_pattern: str | None = None, - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, - ) -> None: ... + _scale_domain: ClassVar[_RealDomain] = ... + _scale_param: ClassVar[_RealParameter] = ... + + loc: _ParameterField[_FloatingT_co, _ShapeT0_co] + scale: _ParameterField[_FloatingT_co, _ShapeT0_co] + + # TODO(jorenham): override `__[r]{add,sub,mul,truediv}__` so that it returns a `Self` (but maybe with different shape) + +class FoldedDistribution( + TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], + Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], +): + # TODO(jorenham) + ... class TruncatedDistribution( TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], ): + _lb_domain: ClassVar[_RealDomain] = ... + _lb_param: ClassVar[_RealParameter] = ... + + _ub_domain: ClassVar[_RealDomain] = ... + _ub_param: ClassVar[_RealParameter] = ... + lb: _ParameterField[_FloatingT_co, _ShapeT0_co] ub: _ParameterField[_FloatingT_co, _ShapeT0_co] @@ -414,23 +515,37 @@ class TruncatedDistribution( cache_policy: _CachePolicy = None, ) -> None: ... -class FoldedDistribution( - TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], - Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], -): +class OrderStatisticDistribution(TransformedDistribution[_CDistT_co, np.float64, _ShapeT0_co], Generic[_CDistT_co, _ShapeT0_co]): # TODO(jorenham) ... -class ShiftedScaledDistribution( - TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], - Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], +# without HKT there's no reasonable way tot determine the floating scalar type +class MonotonicTransformedDistribution( + TransformedDistribution[_CDistT_co, np.floating[Any], _ShapeT0_co], + Generic[_CDistT_co, _ShapeT0_co], ): - # TODO(jorenham) - ... + _g: Final[_ElementwiseFunction] + _h: Final[_ElementwiseFunction] + _dh: Final[_ElementwiseFunction] + _logdh: Final[_ElementwiseFunction] + _increasing: Final[bool] + _repr_pattern: Final[str] -class OrderStatisticDistribution(TransformedDistribution[_CDistT_co, np.float64, _ShapeT0_co], Generic[_CDistT_co, _ShapeT0_co]): - # TODO(jorenham) - ... + def __init__( + self: MonotonicTransformedDistribution[_CDist[_ShapeT0], _ShapeT0], + X: _CDistT_co, + /, + *args: Never, + g: _ElementwiseFunction, + h: _ElementwiseFunction, + dh: _ElementwiseFunction, + logdh: _ElementwiseFunction | None = None, + increasing: bool = True, + repr_pattern: str | None = None, + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... class Mixture(_BaseDistribution[_FloatingT_co, tuple[()]], Generic[_FloatingT_co]): _shape: tuple[()] @@ -484,3 +599,27 @@ def truncate( lb: onp.ToFloat | onp.ToFloatND = ..., ub: onp.ToFloat | onp.ToFloatND = ..., ) -> TruncatedDistribution[_CDistT, np.floating[Any], tuple[int, ...]]: ... + +# +@overload +def exp(X: _CDistT0, /) -> MonotonicTransformedDistribution[_CDistT0, tuple[()]]: ... +@overload +def exp(X: _CDistT1, /) -> MonotonicTransformedDistribution[_CDistT1, tuple[int]]: ... +@overload +def exp(X: _CDistT2, /) -> MonotonicTransformedDistribution[_CDistT2, tuple[int, int]]: ... +@overload +def exp(X: _CDistT3, /) -> MonotonicTransformedDistribution[_CDistT3, tuple[int, int, int]]: ... +@overload +def exp(X: _CDistT, /) -> MonotonicTransformedDistribution[_CDistT, tuple[int, ...]]: ... + +# +@overload +def log(X: _CDistT0, /) -> MonotonicTransformedDistribution[_CDistT0, tuple[()]]: ... +@overload +def log(X: _CDistT1, /) -> MonotonicTransformedDistribution[_CDistT1, tuple[int]]: ... +@overload +def log(X: _CDistT2, /) -> MonotonicTransformedDistribution[_CDistT2, tuple[int, int]]: ... +@overload +def log(X: _CDistT3, /) -> MonotonicTransformedDistribution[_CDistT3, tuple[int, int, int]]: ... +@overload +def log(X: _CDistT, /) -> MonotonicTransformedDistribution[_CDistT, tuple[int, ...]]: ... From 35465619d871ffbf2974b6546e62ac847238f00c Mon Sep 17 00:00:00 2001 From: jorenham Date: Sat, 21 Dec 2024 02:01:27 +0100 Subject: [PATCH 12/16] =?UTF-8?q?=F0=9F=91=BD=EF=B8=8F=20`stats`:=201.15.0?= =?UTF-8?q?=20annotate=20`abs`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .mypyignore-todo | 2 +- scipy-stubs/stats/__init__.pyi | 4 +- .../stats/_distribution_infrastructure.pyi | 72 +++++++++++++++++-- 3 files changed, 69 insertions(+), 9 deletions(-) diff --git a/.mypyignore-todo b/.mypyignore-todo index 6150cb02..cf72c506 100644 --- a/.mypyignore-todo +++ b/.mypyignore-todo @@ -1,4 +1,4 @@ scipy\.stats\.__all__ scipy\.stats\.(Normal|Uniform) -scipy\.stats\.(_distribution_infrastructure\.)?(abs|exp|make_distribution|order_statistic) +scipy\.stats\.(_distribution_infrastructure\.)?(make_distribution|order_statistic) scipy\.stats\._distribution_infrastructure\.(Folded|OrderStatistic)Distribution\.__init__ diff --git a/scipy-stubs/stats/__init__.pyi b/scipy-stubs/stats/__init__.pyi index a69f8aa7..ef0b0e18 100644 --- a/scipy-stubs/stats/__init__.pyi +++ b/scipy-stubs/stats/__init__.pyi @@ -7,7 +7,7 @@ from ._correlation import chatterjeexi from ._covariance import Covariance # TODO(jorenham) -from ._distribution_infrastructure import Mixture, exp, log, truncate # abs, make_distribution, order_statistic +from ._distribution_infrastructure import Mixture, abs, exp, log, truncate # make_distribution, order_statistic from ._entropy import differential_entropy, entropy from ._fit import fit, goodness_of_fit from ._hypotests import ( @@ -314,7 +314,7 @@ __all__ = [ # "Normal", "PermutationMethod", # "Uniform", - # "abs", + "abs", "alexandergovern", "alpha", "anderson", diff --git a/scipy-stubs/stats/_distribution_infrastructure.pyi b/scipy-stubs/stats/_distribution_infrastructure.pyi index 6d279b84..ad92e599 100644 --- a/scipy-stubs/stats/_distribution_infrastructure.pyi +++ b/scipy-stubs/stats/_distribution_infrastructure.pyi @@ -438,8 +438,56 @@ class FoldedDistribution( TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], ): - # TODO(jorenham) - ... + @overload + def __init__( + self: FoldedDistribution[_CDistT0, np.floating[Any], tuple[()]], + X: _CDistT0, + /, + *args: Never, + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + @overload + def __init__( + self: FoldedDistribution[_CDistT1, np.floating[Any], tuple[int]], + X: _CDistT1, + /, + *args: Never, + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + @overload + def __init__( + self: FoldedDistribution[_CDistT2, np.floating[Any], tuple[int, int]], + X: _CDistT2, + /, + *args: Never, + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + @overload + def __init__( + self: FoldedDistribution[_CDistT3, np.floating[Any], tuple[int, int, int]], + X: _CDistT3, + /, + *args: Never, + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + @overload + def __init__( + self: FoldedDistribution[_CDistT, np.floating[Any], tuple[int, ...]], + X: _CDistT, + /, + *args: Never, + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... class TruncatedDistribution( TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], @@ -515,10 +563,6 @@ class TruncatedDistribution( cache_policy: _CachePolicy = None, ) -> None: ... -class OrderStatisticDistribution(TransformedDistribution[_CDistT_co, np.float64, _ShapeT0_co], Generic[_CDistT_co, _ShapeT0_co]): - # TODO(jorenham) - ... - # without HKT there's no reasonable way tot determine the floating scalar type class MonotonicTransformedDistribution( TransformedDistribution[_CDistT_co, np.floating[Any], _ShapeT0_co], @@ -547,6 +591,10 @@ class MonotonicTransformedDistribution( cache_policy: _CachePolicy = None, ) -> None: ... +class OrderStatisticDistribution(TransformedDistribution[_CDistT_co, np.float64, _ShapeT0_co], Generic[_CDistT_co, _ShapeT0_co]): + # TODO(jorenham) + ... + class Mixture(_BaseDistribution[_FloatingT_co, tuple[()]], Generic[_FloatingT_co]): _shape: tuple[()] _dtype: np.dtype[_FloatingT_co] @@ -600,6 +648,18 @@ def truncate( ub: onp.ToFloat | onp.ToFloatND = ..., ) -> TruncatedDistribution[_CDistT, np.floating[Any], tuple[int, ...]]: ... +# +@overload +def abs(X: _CDistT0, /) -> FoldedDistribution[_CDistT0, np.floating[Any], tuple[()]]: ... +@overload +def abs(X: _CDistT1, /) -> FoldedDistribution[_CDistT1, np.floating[Any], tuple[int]]: ... +@overload +def abs(X: _CDistT2, /) -> FoldedDistribution[_CDistT2, np.floating[Any], tuple[int, int]]: ... +@overload +def abs(X: _CDistT3, /) -> FoldedDistribution[_CDistT3, np.floating[Any], tuple[int, int, int]]: ... +@overload +def abs(X: _CDistT, /) -> FoldedDistribution[_CDistT, np.floating[Any], tuple[int, ...]]: ... + # @overload def exp(X: _CDistT0, /) -> MonotonicTransformedDistribution[_CDistT0, tuple[()]]: ... From 3160f1dc5e80910c3f7fc2322fb66cc56c2587d8 Mon Sep 17 00:00:00 2001 From: jorenham Date: Sat, 21 Dec 2024 03:40:00 +0100 Subject: [PATCH 13/16] =?UTF-8?q?=F0=9F=91=BD=EF=B8=8F=20`stats`:=201.15.0?= =?UTF-8?q?=20annotate=20`order=5Fstatistic`=20and=20`make=5Fdistribution`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .mypyignore-todo | 2 - scipy-stubs/stats/__init__.pyi | 8 +- .../stats/_distribution_infrastructure.pyi | 172 +++++++++++++++--- .../stats/_probability_distribution.pyi | 84 +++------ 4 files changed, 169 insertions(+), 97 deletions(-) diff --git a/.mypyignore-todo b/.mypyignore-todo index cf72c506..fe71ef66 100644 --- a/.mypyignore-todo +++ b/.mypyignore-todo @@ -1,4 +1,2 @@ scipy\.stats\.__all__ scipy\.stats\.(Normal|Uniform) -scipy\.stats\.(_distribution_infrastructure\.)?(make_distribution|order_statistic) -scipy\.stats\._distribution_infrastructure\.(Folded|OrderStatistic)Distribution\.__init__ diff --git a/scipy-stubs/stats/__init__.pyi b/scipy-stubs/stats/__init__.pyi index ef0b0e18..44388cd1 100644 --- a/scipy-stubs/stats/__init__.pyi +++ b/scipy-stubs/stats/__init__.pyi @@ -5,9 +5,7 @@ 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, truncate # make_distribution, order_statistic +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 ( @@ -470,7 +468,7 @@ __all__ = [ "logser", "loguniform", "lomax", - # "make_distribution", + "make_distribution", "mannwhitneyu", "matrix_normal", "maxwell", @@ -506,7 +504,7 @@ __all__ = [ "normaltest", "norminvgauss", "obrientransform", - # "order_statistic", + "order_statistic", "ortho_group", "page_trend_test", "pareto", diff --git a/scipy-stubs/stats/_distribution_infrastructure.pyi b/scipy-stubs/stats/_distribution_infrastructure.pyi index ad92e599..a97dcef2 100644 --- a/scipy-stubs/stats/_distribution_infrastructure.pyi +++ b/scipy-stubs/stats/_distribution_infrastructure.pyi @@ -4,13 +4,14 @@ import abc from collections.abc import Callable, Mapping, Sequence, Set as AbstractSet from typing import Any, ClassVar, Final, Generic, Literal as L, Protocol, TypeAlias, overload, type_check_only -from typing_extensions import LiteralString, Never, Self, TypeVar, override +from typing_extensions import LiteralString, Never, Self, TypeIs, TypeVar, override import numpy as np import optype as op import optype.numpy as onp import optype.typing as opt from scipy._typing import AnyShape, ToRNG +from ._distn_infrastructure import rv_continuous from ._probability_distribution import _BaseDistribution # TODO: @@ -86,6 +87,8 @@ class _ParameterField(Protocol[_FloatingT_co, _ShapeT0_co]): _null: Final[_Null] = ... +def _isnull(x: object) -> TypeIs[_Null | None]: ... + # TODO(jorenham): Generic dtype and shape class _Domain(abc.ABC): # NOTE: This is a `ClassVar[dict[str, float]]` that's overridden as instance attribute in `_SimpleDomain`. @@ -100,11 +103,7 @@ class _Domain(abc.ABC): @abc.abstractmethod def draw(self, /, n: int) -> onp.ArrayND[_FloatingT]: ... @abc.abstractmethod - def get_numerical_endpoints( - self, - /, - x: _ParamValues, - ) -> tuple[onp.ArrayND[_Float], onp.ArrayND[_Float]]: ... + def get_numerical_endpoints(self, /, x: _ParamValues) -> tuple[onp.ArrayND[_Float], onp.ArrayND[_Float]]: ... # TODO(jorenham): Generic dtype class _SimpleDomain(_Domain, metaclass=abc.ABCMeta): @@ -189,9 +188,7 @@ class _Parameterization: def copy(self, /) -> Self: ... def matches(self, /, parameters: AbstractSet[str]) -> bool: ... def validation( - self, - /, - parameter_values: Mapping[str, _Parameter], + self, /, parameter_values: Mapping[str, _Parameter] ) -> tuple[onp.ArrayND[np.bool_], np.dtype[np.floating[Any]]]: ... def draw( self, @@ -211,6 +208,8 @@ class ContinuousDistribution(_BaseDistribution[_FloatingT_co, _ShapeT0_co], Gene _not_implemented: Final[str] _original_parameters: dict[str, _FloatingT_co | onp.ArrayND[_FloatingT_co, _ShapeT0_co]] + _variable: _Parameter + @property def tol(self, /) -> float | np.float64 | _Null | None: ... @tol.setter @@ -409,6 +408,8 @@ class TransformedDistribution( ContinuousDistribution[_FloatingT_co, _ShapeT0_co], Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], ): + _dist: _CDistT_co # readonly + def __init__( self: TransformedDistribution[ContinuousDistribution[_FloatingT, _ShapeT0], _FloatingT, _ShapeT0], # nice trick, eh? X: _CDistT_co, @@ -490,8 +491,8 @@ class FoldedDistribution( ) -> None: ... class TruncatedDistribution( - TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], - Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], + TransformedDistribution[_CDistT_co, np.floating[Any], _ShapeT0_co], + Generic[_CDistT_co, _ShapeT0_co], ): _lb_domain: ClassVar[_RealDomain] = ... _lb_param: ClassVar[_RealParameter] = ... @@ -499,12 +500,12 @@ class TruncatedDistribution( _ub_domain: ClassVar[_RealDomain] = ... _ub_param: ClassVar[_RealParameter] = ... - lb: _ParameterField[_FloatingT_co, _ShapeT0_co] - ub: _ParameterField[_FloatingT_co, _ShapeT0_co] + lb: _ParameterField[np.floating[Any], _ShapeT0_co] + ub: _ParameterField[np.floating[Any], _ShapeT0_co] @overload def __init__( - self: TruncatedDistribution[_CDistT0, np.floating[Any], tuple[()]], + self: TruncatedDistribution[_CDistT0, tuple[()]], X: _CDistT0, /, *args: Never, @@ -516,7 +517,7 @@ class TruncatedDistribution( ) -> None: ... @overload def __init__( - self: TruncatedDistribution[_CDistT1, np.floating[Any], tuple[int]], + self: TruncatedDistribution[_CDistT1, tuple[int]], X: _CDistT1, /, *args: Never, @@ -528,7 +529,7 @@ class TruncatedDistribution( ) -> None: ... @overload def __init__( - self: TruncatedDistribution[_CDistT2, np.floating[Any], tuple[int, int]], + self: TruncatedDistribution[_CDistT2, tuple[int, int]], X: _CDistT2, /, *args: Never, @@ -540,7 +541,7 @@ class TruncatedDistribution( ) -> None: ... @overload def __init__( - self: TruncatedDistribution[_CDistT3, np.floating[Any], tuple[int, int, int]], + self: TruncatedDistribution[_CDistT3, tuple[int, int, int]], X: _CDistT3, /, *args: Never, @@ -552,7 +553,7 @@ class TruncatedDistribution( ) -> None: ... @overload def __init__( - self: TruncatedDistribution[_CDistT, np.floating[Any], tuple[int, ...]], + self: TruncatedDistribution[_CDistT, tuple[int, ...]], X: _CDistT, /, *args: Never, @@ -563,6 +564,76 @@ class TruncatedDistribution( cache_policy: _CachePolicy = None, ) -> None: ... +# always float64 or longdouble +class OrderStatisticDistribution(TransformedDistribution[_CDistT_co, _Float, _ShapeT0_co], Generic[_CDistT_co, _ShapeT0_co]): + # these should actually be integral; but the `_IntegerDomain` isn't finished yet + _r_domain: ClassVar[_RealDomain] = ... + _r_param: ClassVar[_RealParameter] = ... + + _n_domain: ClassVar[_RealDomain] = ... + _n_param: ClassVar[_RealParameter] = ... + + @overload + def __init__( + self: OrderStatisticDistribution[_CDistT0, tuple[()]], + dist: _CDistT0, + /, + *args: Never, + r: onp.ToJustInt, + n: onp.ToJustInt, + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + @overload + def __init__( + self: OrderStatisticDistribution[_CDistT1, tuple[int]], + dist: _CDistT1, + /, + *args: Never, + r: onp.ToJustInt | onp.ToJustIntStrict1D, + n: onp.ToJustInt | onp.ToJustIntStrict1D, + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + @overload + def __init__( + self: OrderStatisticDistribution[_CDistT2, tuple[int, int]], + dist: _CDistT2, + /, + *args: Never, + r: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D, + n: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D, + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + @overload + def __init__( + self: OrderStatisticDistribution[_CDistT3, tuple[int, int, int]], + dist: _CDistT3, + /, + *args: Never, + r: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D | onp.ToJustIntStrict3D, + n: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D | onp.ToJustIntStrict3D, + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + @overload + def __init__( + self: OrderStatisticDistribution[_CDistT, tuple[int, ...]], + X: _CDistT, + /, + *args: Never, + r: onp.ToJustInt | onp.ToJustIntND, + n: onp.ToJustInt | onp.ToJustIntND, + tol: opt.Just[float] | _Null = ..., + validation_policy: _ValidationPolicy = None, + cache_policy: _CachePolicy = None, + ) -> None: ... + # without HKT there's no reasonable way tot determine the floating scalar type class MonotonicTransformedDistribution( TransformedDistribution[_CDistT_co, np.floating[Any], _ShapeT0_co], @@ -591,10 +662,6 @@ class MonotonicTransformedDistribution( cache_policy: _CachePolicy = None, ) -> None: ... -class OrderStatisticDistribution(TransformedDistribution[_CDistT_co, np.float64, _ShapeT0_co], Generic[_CDistT_co, _ShapeT0_co]): - # TODO(jorenham) - ... - class Mixture(_BaseDistribution[_FloatingT_co, tuple[()]], Generic[_FloatingT_co]): _shape: tuple[()] _dtype: np.dtype[_FloatingT_co] @@ -606,10 +673,8 @@ class Mixture(_BaseDistribution[_FloatingT_co, tuple[()]], Generic[_FloatingT_co def components(self, /) -> list[_CDist0[_FloatingT_co]]: ... @property def weights(self, /) -> onp.Array1D[_FloatingT_co]: ... - # def __init__(self, /, components: Sequence[_CDist0[_FloatingT_co]], *, weights: onp.ToFloat1D | None = None) -> None: ... - # @override def kurtosis(self, /, *, method: _SMomentMethod | None = None) -> _Float: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] @@ -622,31 +687,73 @@ def truncate( X: _CDistT0, lb: onp.ToFloat = ..., ub: onp.ToFloat = ..., -) -> TruncatedDistribution[_CDistT0, np.floating[Any], tuple[()]]: ... +) -> TruncatedDistribution[_CDistT0, tuple[()]]: ... @overload def truncate( X: _CDistT1, lb: onp.ToFloat | onp.ToFloatStrict1D = ..., ub: onp.ToFloat | onp.ToFloatStrict1D = ..., -) -> TruncatedDistribution[_CDistT1, np.floating[Any], tuple[int]]: ... +) -> TruncatedDistribution[_CDistT1, tuple[int]]: ... @overload def truncate( X: _CDistT2, lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., -) -> TruncatedDistribution[_CDistT2, np.floating[Any], tuple[int, int]]: ... +) -> TruncatedDistribution[_CDistT2, tuple[int, int]]: ... @overload def truncate( X: _CDistT3, lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., -) -> TruncatedDistribution[_CDistT3, np.floating[Any], tuple[int, int, int]]: ... +) -> TruncatedDistribution[_CDistT3, tuple[int, int, int]]: ... @overload def truncate( X: _CDistT, lb: onp.ToFloat | onp.ToFloatND = ..., ub: onp.ToFloat | onp.ToFloatND = ..., -) -> TruncatedDistribution[_CDistT, np.floating[Any], tuple[int, ...]]: ... +) -> TruncatedDistribution[_CDistT, tuple[int, ...]]: ... + +# +@overload +def order_statistic( + X: _CDistT0, + /, + *, + r: onp.ToJustInt, + n: onp.ToJustInt, +) -> OrderStatisticDistribution[_CDistT0, tuple[()]]: ... +@overload +def order_statistic( + X: _CDistT1, + /, + *, + r: onp.ToJustInt | onp.ToJustIntStrict1D, + n: onp.ToJustInt | onp.ToJustIntStrict1D, +) -> OrderStatisticDistribution[_CDistT1, tuple[int]]: ... +@overload +def order_statistic( + X: _CDistT2, + /, + *, + r: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D, + n: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D, +) -> OrderStatisticDistribution[_CDistT2, tuple[int, int]]: ... +@overload +def order_statistic( + X: _CDistT3, + /, + *, + r: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D | onp.ToJustIntStrict3D, + n: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D | onp.ToJustIntStrict3D, +) -> OrderStatisticDistribution[_CDistT3, tuple[int, int, int]]: ... +@overload +def order_statistic( + X: _CDistT, + /, + *, + r: onp.ToJustInt | onp.ToJustIntND, + n: onp.ToJustInt | onp.ToJustIntND, +) -> OrderStatisticDistribution[_CDistT, tuple[int, ...]]: ... # @overload @@ -683,3 +790,10 @@ def log(X: _CDistT2, /) -> MonotonicTransformedDistribution[_CDistT2, tuple[int, def log(X: _CDistT3, /) -> MonotonicTransformedDistribution[_CDistT3, tuple[int, int, int]]: ... @overload def log(X: _CDistT, /) -> MonotonicTransformedDistribution[_CDistT, tuple[int, ...]]: ... + +# NOTE: These currently don't support >0-d parameters, and it looks like they always return float64, regardless of dtype +@type_check_only +class CustomDistribution(ContinuousDistribution[np.float64, tuple[()]]): + _dtype: np.dtype[np.floating[Any]] # ignored + +def make_distribution(dist: rv_continuous) -> type[CustomDistribution]: ... diff --git a/scipy-stubs/stats/_probability_distribution.pyi b/scipy-stubs/stats/_probability_distribution.pyi index 2b6a8a3b..611cc21f 100644 --- a/scipy-stubs/stats/_probability_distribution.pyi +++ b/scipy-stubs/stats/_probability_distribution.pyi @@ -62,25 +62,20 @@ class _ProbabilityDistribution(Generic[_XT_co], metaclass=abc.ABCMeta): def mode(self, /, *, method: _ModeMethod) -> _XT_co | onp.ArrayND[_XT_co]: ... @abc.abstractmethod def sample( - self, - /, - shape: int | tuple[int, ...], - *, - method: _SampleMethod, - rng: _ToQRNG, + self, /, shape: int | tuple[int, ...], *, method: _SampleMethod, rng: _ToQRNG ) -> _XT_co | onp.Array[Any, _XT_co]: ... # `Any` shape is needed on `numpy<2.1` # @abc.abstractmethod - def mean(self, /, *, method: _RMomentMethod) -> _Float | _FloatND: ... + def mean(self, /, *, method: _RMomentMethod) -> _XT_co | onp.ArrayND[_XT_co]: ... @abc.abstractmethod - def variance(self, /, *, method: _CMomentMethod) -> _Float | _FloatND: ... + def variance(self, /, *, method: _CMomentMethod) -> _XT_co | onp.ArrayND[_XT_co]: ... @abc.abstractmethod - def standard_deviation(self, /, *, method: _CMomentMethod) -> _Float | _FloatND: ... + def standard_deviation(self, /, *, method: _CMomentMethod) -> _XT_co | onp.ArrayND[_XT_co]: ... @abc.abstractmethod - def skewness(self, /, *, method: _SMomentMethod) -> _Float | _FloatND: ... + def skewness(self, /, *, method: _SMomentMethod) -> _XT_co | onp.ArrayND[_XT_co]: ... @abc.abstractmethod - def kurtosis(self, /, *, method: _SMomentMethod) -> _Float | _FloatND: ... + def kurtosis(self, /, *, method: _SMomentMethod) -> _XT_co | onp.ArrayND[_XT_co]: ... # @overload @@ -203,45 +198,37 @@ class _BaseDistribution(_ProbabilityDistribution[_XT_co], Generic[_XT_co, _Shape # @overload - def mean(self: _Self0, /, *, method: _RMomentMethod = None) -> _Float: ... + def mean(self: _Self0[_XT], /, *, method: _RMomentMethod = None) -> _XT: ... @overload - def mean(self: _Self[Any, _ShapeT], /, *, method: _RMomentMethod = None) -> _FloatND[_ShapeT]: ... + def mean(self: _Self[_XT, _ShapeT], /, *, method: _RMomentMethod = None) -> onp.ArrayND[_XT, _ShapeT]: ... # @overload - def variance(self: _Self0, /, *, method: _CMomentMethod = None) -> _Float: ... + def variance(self: _Self0[_XT], /, *, method: _CMomentMethod = None) -> _XT: ... @overload - def variance(self: _Self[Any, _ShapeT], /, *, method: _CMomentMethod = None) -> _FloatND[_ShapeT]: ... + def variance(self: _Self[_XT, _ShapeT], /, *, method: _CMomentMethod = None) -> onp.ArrayND[_XT, _ShapeT]: ... # @overload - def standard_deviation(self: _Self0, /, *, method: _CMomentMethod = None) -> _Float: ... + def standard_deviation(self: _Self0[_XT], /, *, method: _CMomentMethod = None) -> _XT: ... @overload - def standard_deviation(self: _Self[Any, _ShapeT], /, *, method: _CMomentMethod = None) -> _FloatND[_ShapeT]: ... + def standard_deviation(self: _Self[_XT, _ShapeT], /, *, method: _CMomentMethod = None) -> onp.ArrayND[_XT, _ShapeT]: ... # @overload - def skewness(self: _Self0, /, *, method: _SMomentMethod = None) -> _Float: ... + def skewness(self: _Self0[_XT], /, *, method: _SMomentMethod = None) -> _XT: ... @overload - def skewness(self: _Self[Any, _ShapeT], /, *, method: _SMomentMethod = None) -> _FloatND[_ShapeT]: ... + def skewness(self: _Self[_XT, _ShapeT], /, *, method: _SMomentMethod = None) -> onp.ArrayND[_XT, _ShapeT]: ... # @overload def kurtosis( - self: _Self0, - /, - *, - method: _SMomentMethod = None, - convention: _KurtosisConvention = "non-excess", - ) -> _Float: ... + self: _Self0[_XT], /, *, method: _SMomentMethod = None, convention: _KurtosisConvention = "non-excess" + ) -> _XT: ... @overload def kurtosis( - self: _Self[Any, _ShapeT], - /, - *, - method: _SMomentMethod = None, - convention: _KurtosisConvention = "non-excess", - ) -> _FloatND[_ShapeT]: ... + self: _Self[_XT, _ShapeT], /, *, method: _SMomentMethod = None, convention: _KurtosisConvention = "non-excess" + ) -> onp.ArrayND[_XT, _ShapeT]: ... # @overload @@ -256,48 +243,23 @@ class _BaseDistribution(_ProbabilityDistribution[_XT_co], Generic[_XT_co, _Shape def moment(self: _Self0, /, order: onp.ToInt = 1, *, kind: L["standardized"], method: _SMomentMethod = None) -> _Float: ... @overload def moment( - self: _Self[Any, _ShapeT], - /, - order: onp.ToInt = 1, - kind: L["raw"] = "raw", - *, - method: _RMomentMethod = None, + self: _Self[Any, _ShapeT], /, order: onp.ToInt = 1, kind: L["raw"] = "raw", *, method: _RMomentMethod = None ) -> _FloatND[_ShapeT]: ... @overload def moment( - self: _Self[Any, _ShapeT], - /, - order: onp.ToInt, - kind: L["central"], - *, - method: _CMomentMethod = None, + self: _Self[Any, _ShapeT], /, order: onp.ToInt, kind: L["central"], *, method: _CMomentMethod = None ) -> _FloatND[_ShapeT]: ... @overload def moment( - self: _Self[Any, _ShapeT], - /, - order: onp.ToInt = 1, - *, - kind: L["central"], - method: _CMomentMethod = None, + self: _Self[Any, _ShapeT], /, order: onp.ToInt = 1, *, kind: L["central"], method: _CMomentMethod = None ) -> _FloatND[_ShapeT]: ... @overload def moment( - self: _Self[Any, _ShapeT], - /, - order: onp.ToInt, - kind: L["standardized"], - *, - method: _SMomentMethod = None, + self: _Self[Any, _ShapeT], /, order: onp.ToInt, kind: L["standardized"], *, method: _SMomentMethod = None ) -> _FloatND[_ShapeT]: ... @overload def moment( # pyright: ignore[reportIncompatibleMethodOverride] # pyright false positive bug - self: _Self[Any, _ShapeT], - /, - order: onp.ToInt = 1, - *, - kind: L["standardized"], - method: _SMomentMethod = None, + self: _Self[Any, _ShapeT], /, order: onp.ToInt = 1, *, kind: L["standardized"], method: _SMomentMethod = None ) -> _FloatND[_ShapeT]: ... # From 7e9be920d5c4cd4558cfedeaec6f22b2f009862b Mon Sep 17 00:00:00 2001 From: jorenham Date: Sat, 21 Dec 2024 04:21:58 +0100 Subject: [PATCH 14/16] =?UTF-8?q?=F0=9F=8E=A8=20`stats`:=201.15.0=20new=20?= =?UTF-8?q?disribution=20infrastructure=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../stats/_distribution_infrastructure.pyi | 689 +++++++----------- 1 file changed, 264 insertions(+), 425 deletions(-) diff --git a/scipy-stubs/stats/_distribution_infrastructure.pyi b/scipy-stubs/stats/_distribution_infrastructure.pyi index a97dcef2..8d305e5e 100644 --- a/scipy-stubs/stats/_distribution_infrastructure.pyi +++ b/scipy-stubs/stats/_distribution_infrastructure.pyi @@ -3,8 +3,8 @@ import abc from collections.abc import Callable, Mapping, Sequence, Set as AbstractSet -from typing import Any, ClassVar, Final, Generic, Literal as L, Protocol, TypeAlias, overload, type_check_only -from typing_extensions import LiteralString, Never, Self, TypeIs, TypeVar, override +from typing import Any, ClassVar, Final, Generic, Literal as L, Protocol, TypeAlias, TypedDict, overload, type_check_only +from typing_extensions import LiteralString, Never, Self, TypeIs, TypeVar, Unpack, override import numpy as np import optype as op @@ -14,42 +14,62 @@ from scipy._typing import AnyShape, ToRNG from ._distn_infrastructure import rv_continuous from ._probability_distribution import _BaseDistribution -# TODO: -# `__all__ = ["Mixture", "abs", "exp", "log", "make_distribution", "order_statistic", "truncate"] - -_Float: TypeAlias = np.float64 | np.longdouble -_FloatingT = TypeVar("_FloatingT", bound=np.floating[Any], default=np.floating[Any]) -_FloatingT_co = TypeVar("_FloatingT_co", bound=np.floating[Any], default=np.floating[Any], covariant=True) -_RealT = TypeVar("_RealT", bound=np.floating[Any] | np.integer[Any], default=np.floating[Any] | np.integer[Any]) -_RealT_co = TypeVar( - "_RealT_co", - bound=np.floating[Any] | np.integer[Any], - default=np.floating[Any] | np.integer[Any], - covariant=True, -) - -_ShapeT0 = TypeVar("_ShapeT0", bound=tuple[int, ...], default=tuple[int, ...]) +__all__ = ["Mixture", "abs", "exp", "log", "make_distribution", "order_statistic", "truncate"] + +### + +_FloatT = TypeVar("_FloatT", bound=_Float, default=_Float) +_FloatT_co = TypeVar("_FloatT_co", bound=_Float, default=_Float, covariant=True) + +_RealT = TypeVar("_RealT", bound=_Float | _Int, default=_Float | _Int) +_RealT_co = TypeVar("_RealT_co", bound=_Float | _Int, default=_Float | _Int, covariant=True) + _ShapeT1 = TypeVar("_ShapeT1", bound=onp.AtLeast1D, default=onp.AtLeast1D) -_ShapeT0_co = TypeVar("_ShapeT0_co", bound=tuple[int, ...], default=tuple[int, ...], covariant=True) - -_CDistT0 = TypeVar("_CDistT0", bound=_CDist0) -_CDistT1 = TypeVar("_CDistT1", bound=_CDist[tuple[int]]) -_CDistT_1 = TypeVar("_CDistT_1", bound=_CDist[onp.AtMost1D]) -_CDistT2 = TypeVar("_CDistT2", bound=_CDist[tuple[int, int]]) -_CDistT_2 = TypeVar("_CDistT_2", bound=_CDist[onp.AtMost2D]) -_CDistT3 = TypeVar("_CDistT3", bound=_CDist[tuple[int, int, int]]) -_CDistT_3 = TypeVar("_CDistT_3", bound=_CDist[onp.AtMost3D]) -_CDistT = TypeVar("_CDistT", bound=ContinuousDistribution) -_CDistT_co = TypeVar("_CDistT_co", bound=ContinuousDistribution, default=ContinuousDistribution, covariant=True) - -# placeholder for `matplotlib.axes.Axes` -_Axes: TypeAlias = object +_ShapeT = TypeVar("_ShapeT", bound=_ND, default=_ND) +_ShapeT_co = TypeVar("_ShapeT_co", bound=_ND, default=_ND, covariant=True) + +_DistT0 = TypeVar("_DistT0", bound=_CDist0) +_DistT1 = TypeVar("_DistT1", bound=_CDist[_1D]) +_DistT_1 = TypeVar("_DistT_1", bound=_CDist[onp.AtMost1D]) +_DistT2 = TypeVar("_DistT2", bound=_CDist[_2D]) +_DistT_2 = TypeVar("_DistT_2", bound=_CDist[onp.AtMost2D]) +_DistT3 = TypeVar("_DistT3", bound=_CDist[_3D]) +_DistT_3 = TypeVar("_DistT_3", bound=_CDist[onp.AtMost3D]) +_DistT = TypeVar("_DistT", bound=ContinuousDistribution) +_DistT_co = TypeVar("_DistT_co", bound=ContinuousDistribution, default=ContinuousDistribution, covariant=True) + _AxesT = TypeVar("_AxesT", bound=_Axes, default=Any) ### -_JustFloat: TypeAlias = opt.Just[float] | np.floating[Any] +_Int: TypeAlias = np.integer[Any] +_Float: TypeAlias = np.floating[Any] +_OutFloat: TypeAlias = np.float64 | np.longdouble + +_NT = TypeVar("_NT", default=int) +_0D: TypeAlias = tuple[()] # noqa: PYI042 +_1D: TypeAlias = tuple[_NT] # noqa: PYI042 +_2D: TypeAlias = tuple[_NT, _NT] # noqa: PYI042 +_3D: TypeAlias = tuple[_NT, _NT, _NT] # noqa: PYI042 +_ND: TypeAlias = tuple[_NT, ...] + +_To1D: TypeAlias = op.CanIndex | _1D[op.CanIndex] +_To2D: TypeAlias = _2D[op.CanIndex] +_To3D: TypeAlias = _3D[op.CanIndex] + +_ToFloatMax1D: TypeAlias = onp.ToFloatStrict1D | onp.ToFloat +_ToFloatMax2D: TypeAlias = onp.ToFloatStrict2D | _ToFloatMax1D +_ToFloatMax3D: TypeAlias = onp.ToFloatStrict3D | _ToFloatMax2D +_ToFloatMaxND: TypeAlias = onp.ToFloatND | onp.ToFloat + +_ToJustIntMax1D: TypeAlias = onp.ToJustIntStrict1D | onp.ToJustInt +_ToJustIntMax2D: TypeAlias = onp.ToJustIntStrict2D | _ToJustIntMax1D +_ToJustIntMax3D: TypeAlias = onp.ToJustIntStrict3D | _ToJustIntMax2D +_ToJustIntMaxND: TypeAlias = onp.ToJustIntND | onp.ToJustInt + +_JustFloat: TypeAlias = opt.Just[float] | _Float _Null: TypeAlias = opt.Just[object] +_Axes: TypeAlias = object # placeholder for `matplotlib.axes.Axes` _DomainRegion: TypeAlias = L["domain", "typical"] _DomainDrawType: TypeAlias = L["in", "out", "on", "nan"] @@ -58,30 +78,32 @@ _CachePolicy: TypeAlias = L["no_cache"] | None _PlotQuantity: TypeAlias = L["x", "pdf", "cdf", "ccdf", "icdf", "iccdf", "logpdf", "logcdf", "logccdf", "ilogcdf", "ilogccdf"] _SMomentMethod: TypeAlias = L["formula", "general", "transform", "normalize", "cache"] -_ParamValues: TypeAlias = Mapping[str, onp.ToFloat | onp.ToFloatND] -_ToDomain: TypeAlias = _Domain | tuple[onp.ToFloat | str, onp.ToFloat | str] +_ParamValues: TypeAlias = Mapping[str, _ToFloatMaxND] +_ToDomain: TypeAlias = tuple[onp.ToFloat | str, onp.ToFloat | str] +_ToTol: TypeAlias = opt.Just[float] | _Null _DrawProportions: TypeAlias = tuple[onp.ToFloat, onp.ToFloat, onp.ToFloat, onp.ToFloat] +_Elementwise: TypeAlias = Callable[[onp.ArrayND[np.float64]], onp.ArrayND[_FloatT]] -_CDist: TypeAlias = ContinuousDistribution[np.floating[Any], _ShapeT0] -_CDist0: TypeAlias = ContinuousDistribution[_FloatingT, tuple[()]] +_CDist: TypeAlias = ContinuousDistribution[_Float, _ShapeT] +_CDist0: TypeAlias = ContinuousDistribution[_FloatT, _0D] +_TransDist: TypeAlias = TransformedDistribution[_DistT, _FloatT, _ShapeT] +_LinDist: TypeAlias = ShiftedScaledDistribution[_DistT, _FloatT, _ShapeT] +_FoldDist: TypeAlias = FoldedDistribution[_DistT, _FloatT, _ShapeT] +_TruncDist: TypeAlias = TruncatedDistribution[_DistT, _ShapeT] @type_check_only -class _ParameterField(Protocol[_FloatingT_co, _ShapeT0_co]): +class _ParamField(Protocol[_FloatT_co, _ShapeT_co]): # This actually works (even on mypy)! @overload - def __get__( - self: _ParameterField[_FloatingT, tuple[()]], - instance: object, - owner: type | None = None, - /, - ) -> _FloatingT: ... + def __get__(self: _ParamField[_FloatT, _0D], obj: object, tp: type | None = None, /) -> _FloatT: ... @overload - def __get__( - self: _ParameterField[_FloatingT, _ShapeT1], - instance: object, - owner: type | None = None, - /, - ) -> onp.ArrayND[_FloatingT, _ShapeT1]: ... + def __get__(self: _ParamField[_FloatT, _ShapeT1], obj: object, tp: type | None = None, /) -> onp.Array[_ShapeT1, _FloatT]: ... + +@type_check_only +class _DistOpts(TypedDict, total=False): + tol: _ToTol + validation_policy: _ValidationPolicy + cache_policy: _CachePolicy ### @@ -101,33 +123,22 @@ class _Domain(abc.ABC): @abc.abstractmethod def contains(self, /, x: onp.ArrayND[Any]) -> onp.ArrayND[np.bool_]: ... @abc.abstractmethod - def draw(self, /, n: int) -> onp.ArrayND[_FloatingT]: ... + def draw(self, /, n: int) -> onp.ArrayND[_FloatT]: ... @abc.abstractmethod - def get_numerical_endpoints(self, /, x: _ParamValues) -> tuple[onp.ArrayND[_Float], onp.ArrayND[_Float]]: ... + def get_numerical_endpoints(self, /, x: _ParamValues) -> tuple[onp.ArrayND[_OutFloat], onp.ArrayND[_OutFloat]]: ... # TODO(jorenham): Generic dtype class _SimpleDomain(_Domain, metaclass=abc.ABCMeta): - def __init__( - self, - /, - endpoints: tuple[onp.ToFloat | str, onp.ToFloat | str] = ..., - inclusive: tuple[bool, bool] = (False, False), - ) -> None: ... - - # + def __init__(self, /, endpoints: _ToDomain = ..., inclusive: tuple[bool, bool] = (False, False)) -> None: ... @override def __str__(self, /) -> str: ... # noqa: PYI029 @override - def get_numerical_endpoints( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] - self, - /, - parameter_values: _ParamValues, - ) -> tuple[onp.ArrayND[_Float], onp.ArrayND[_Float]]: ... + def get_numerical_endpoints(self, /, parameter_values: _ParamValues) -> _2D[onp.ArrayND[_OutFloat]]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] @override def contains( # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] self, /, - item: onp.ArrayND[np.integer[Any] | np.floating[Any]], + item: onp.ArrayND[_Int | _Float], parameter_values: _ParamValues | None = None, ) -> onp.ArrayND[np.bool_]: ... @@ -141,32 +152,38 @@ class _RealDomain(_SimpleDomain): /, n: int, type_: _DomainDrawType, - min: onp.ArrayND[np.floating[Any] | np.integer[Any]], - max: onp.ArrayND[np.floating[Any] | np.integer[Any]], - squeezed_base_shape: tuple[int, ...], + min: onp.ArrayND[_Float | _Int], + max: onp.ArrayND[_Float | _Int], + squeezed_base_shape: _ND, rng: ToRNG = None, ) -> onp.ArrayND[np.float64]: ... -_ParamValidated0D: TypeAlias = tuple[_RealT, np.dtype[_RealT], onp.Array0D[np.bool_]] -_ParamValidatedND: TypeAlias = tuple[onp.ArrayND[_RealT, _ShapeT1], np.dtype[_RealT], onp.ArrayND[np.bool_, _ShapeT1]] +_ValidateOut0D: TypeAlias = tuple[_RealT, np.dtype[_RealT], onp.Array0D[np.bool_]] +_ValidateOutND: TypeAlias = tuple[onp.ArrayND[_RealT, _ShapeT1], np.dtype[_RealT], onp.ArrayND[np.bool_, _ShapeT1]] # class _Parameter(abc.ABC, Generic[_RealT_co]): - def __init__(self, /, name: str, *, domain: _Domain, symbol: str | None = None, typical: _ToDomain | None = None) -> None: ... - + def __init__( + self, + /, + name: str, + *, + domain: _Domain, + symbol: str | None = None, + typical: _Domain | _ToDomain | None = None, + ) -> None: ... # @overload @abc.abstractmethod - def validate(self, /, arr: onp.ToFloat) -> _ParamValidated0D[_RealT_co]: ... + def validate(self, /, arr: onp.ToFloat) -> _ValidateOut0D[_RealT_co]: ... @overload @abc.abstractmethod - def validate(self, /, arr: onp.ToFloatND) -> _ParamValidatedND[_RealT_co]: ... - + def validate(self, /, arr: onp.ToFloatND) -> _ValidateOutND[_RealT_co]: ... # def draw( self, /, - size: tuple[int, ...] | None = None, + size: _ND | None = None, *, rng: ToRNG = None, region: _DomainRegion = "domain", @@ -174,11 +191,11 @@ class _Parameter(abc.ABC, Generic[_RealT_co]): parameter_values: _ParamValues | None = None, ) -> onp.ArrayND[_RealT_co]: ... -class _RealParameter(_Parameter[_FloatingT_co], Generic[_FloatingT_co]): +class _RealParameter(_Parameter[_FloatT_co], Generic[_FloatT_co]): @overload # type: ignore[override] - def validate(self, /, arr: onp.ToFloat, parameter_values: _ParamValues) -> _ParamValidated0D[_FloatingT_co]: ... + def validate(self, /, arr: onp.ToFloat, parameter_values: _ParamValues) -> _ValidateOut0D[_FloatT_co]: ... @overload - def validate(self, /, arr: onp.ToFloatND, parameter_values: _ParamValues) -> _ParamValidatedND[_FloatingT_co]: ... # pyright: ignore[reportIncompatibleMethodOverride] + def validate(self, /, arr: onp.ToFloatND, parameter_values: _ParamValues) -> _ValidateOutND[_FloatT_co]: ... # pyright: ignore[reportIncompatibleMethodOverride] class _Parameterization: parameters: Final[Mapping[str, _Parameter]] @@ -187,26 +204,24 @@ class _Parameterization: def __len__(self, /) -> int: ... def copy(self, /) -> Self: ... def matches(self, /, parameters: AbstractSet[str]) -> bool: ... - def validation( - self, /, parameter_values: Mapping[str, _Parameter] - ) -> tuple[onp.ArrayND[np.bool_], np.dtype[np.floating[Any]]]: ... + def validation(self, /, parameter_values: Mapping[str, _Parameter]) -> tuple[onp.ArrayND[np.bool_], np.dtype[_Float]]: ... def draw( self, /, - sizes: tuple[int, ...] | Sequence[tuple[int, ...]] | None = None, + sizes: _ND | Sequence[_ND] | None = None, rng: ToRNG = None, proportions: _DrawProportions | None = None, region: _DomainRegion = "domain", - ) -> dict[str, onp.ArrayND[np.floating[Any]]]: ... + ) -> dict[str, onp.ArrayND[_Float]]: ... ### -class ContinuousDistribution(_BaseDistribution[_FloatingT_co, _ShapeT0_co], Generic[_FloatingT_co, _ShapeT0_co]): +class ContinuousDistribution(_BaseDistribution[_FloatT_co, _ShapeT_co], Generic[_FloatT_co, _ShapeT_co]): __array_priority__: ClassVar[float] = 1 _parameterizations: ClassVar[Sequence[_Parameterization]] _not_implemented: Final[str] - _original_parameters: dict[str, _FloatingT_co | onp.ArrayND[_FloatingT_co, _ShapeT0_co]] + _original_parameters: dict[str, _FloatT_co | onp.ArrayND[_FloatT_co, _ShapeT_co]] _variable: _Parameter @@ -224,139 +239,102 @@ class ContinuousDistribution(_BaseDistribution[_FloatingT_co, _ShapeT0_co], Gene def cache_policy(self, /) -> _CachePolicy: ... @cache_policy.setter def cache_policy(self, cache_policy: _CachePolicy, /) -> None: ... - # def __init__( self, /, *, - tol: opt.Just[float] | _Null = ..., + tol: _ToTol = ..., validation_policy: _ValidationPolicy = None, cache_policy: _CachePolicy = None, ) -> None: ... - - # - def __neg__(self, /) -> ShiftedScaledDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... - def __abs__(self, /) -> FoldedDistribution[Self, _FloatingT_co, _ShapeT0_co]: ... + def __neg__(self, /) -> _LinDist[Self, _FloatT_co, _ShapeT_co]: ... + def __abs__(self, /) -> _FoldDist[Self, _FloatT_co, _ShapeT_co]: ... # @overload - def __add__( - self, rshift: float | np.integer[Any] | np.bool_, / - ) -> ShiftedScaledDistribution[Self, np.float64 | _FloatingT_co, _ShapeT0_co]: ... + def __add__(self, x: float | _Int | np.bool_, /) -> _LinDist[Self, np.float64 | _FloatT_co, _ShapeT_co]: ... @overload - def __add__(self, rshift: _FloatingT, /) -> ShiftedScaledDistribution[Self, _FloatingT | _FloatingT_co, _ShapeT0_co]: ... + def __add__(self, x: _FloatT, /) -> _LinDist[Self, _FloatT | _FloatT_co, _ShapeT_co]: ... @overload - def __add__(self, rshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, np.floating[Any], _ShapeT0_co]: ... + def __add__(self, x: onp.ToFloat, /) -> _LinDist[Self, _Float, _ShapeT_co]: ... @overload - def __add__( - self: _CDistT0, rshift: onp.CanArrayND[_FloatingT, _ShapeT0], / - ) -> ShiftedScaledDistribution[_CDistT0, _FloatingT | _FloatingT_co, _ShapeT0]: ... + def __add__(self: _DistT0, x: onp.CanArrayND[_FloatT, _ShapeT], /) -> _LinDist[_DistT0, _FloatT | _FloatT_co, _ShapeT]: ... @overload - def __add__( - self: _CDistT_1, rshift: onp.ToFloatStrict1D, / - ) -> ShiftedScaledDistribution[_CDistT_1, np.floating[Any], tuple[int]]: ... + def __add__(self: _DistT_1, x: onp.ToFloatStrict1D, /) -> _LinDist[_DistT_1, _Float, _1D]: ... @overload - def __add__( - self: _CDistT_2, rshift: onp.ToFloatStrict2D, / - ) -> ShiftedScaledDistribution[_CDistT_2, np.floating[Any], tuple[int, int]]: ... + def __add__(self: _DistT_2, x: onp.ToFloatStrict2D, /) -> _LinDist[_DistT_2, _Float, _2D]: ... @overload - def __add__( - self: _CDistT_3, rshift: onp.ToFloatStrict3D, / - ) -> ShiftedScaledDistribution[_CDistT_3, np.floating[Any], tuple[int, int, int]]: ... + def __add__(self: _DistT_3, x: onp.ToFloatStrict3D, /) -> _LinDist[_DistT_3, _Float, _3D]: ... @overload - def __add__(self, rshift: onp.ToFloatND, /) -> ShiftedScaledDistribution[Self]: ... + def __add__(self, x: onp.ToFloatND, /) -> _LinDist[Self]: ... __radd__ = __add__ # @overload - def __sub__( - self, lshift: float | np.integer[Any] | np.bool_, / - ) -> ShiftedScaledDistribution[Self, np.float64 | _FloatingT_co, _ShapeT0_co]: ... + def __sub__(self, lshift: float | _Int | np.bool_, /) -> _LinDist[Self, np.float64 | _FloatT_co, _ShapeT_co]: ... @overload - def __sub__(self, lshift: _FloatingT, /) -> ShiftedScaledDistribution[Self, _FloatingT | _FloatingT_co, _ShapeT0_co]: ... + def __sub__(self, lshift: _FloatT, /) -> _LinDist[Self, _FloatT | _FloatT_co, _ShapeT_co]: ... @overload - def __sub__(self, lshift: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, np.floating[Any], _ShapeT0_co]: ... + def __sub__(self, lshift: onp.ToFloat, /) -> _LinDist[Self, _Float, _ShapeT_co]: ... @overload def __sub__( - self: _CDistT0, lshift: onp.CanArrayND[_FloatingT, _ShapeT0], / - ) -> ShiftedScaledDistribution[_CDistT0, _FloatingT | _FloatingT_co, _ShapeT0]: ... + self: _DistT0, lshift: onp.CanArrayND[_FloatT, _ShapeT], / + ) -> _LinDist[_DistT0, _FloatT | _FloatT_co, _ShapeT]: ... @overload - def __sub__( - self: _CDistT_1, lshift: onp.ToFloatStrict1D, / - ) -> ShiftedScaledDistribution[_CDistT_1, np.floating[Any], tuple[int]]: ... + def __sub__(self: _DistT_1, lshift: onp.ToFloatStrict1D, /) -> _LinDist[_DistT_1, _Float, _1D]: ... @overload - def __sub__( - self: _CDistT_2, lshift: onp.ToFloatStrict2D, / - ) -> ShiftedScaledDistribution[_CDistT_2, np.floating[Any], tuple[int, int]]: ... + def __sub__(self: _DistT_2, lshift: onp.ToFloatStrict2D, /) -> _LinDist[_DistT_2, _Float, _2D]: ... @overload - def __sub__( - self: _CDistT_3, lshift: onp.ToFloatStrict3D, / - ) -> ShiftedScaledDistribution[_CDistT_3, np.floating[Any], tuple[int, int, int]]: ... + def __sub__(self: _DistT_3, lshift: onp.ToFloatStrict3D, /) -> _LinDist[_DistT_3, _Float, _3D]: ... @overload - def __sub__(self, lshift: onp.ToFloatND, /) -> ShiftedScaledDistribution[Self]: ... + def __sub__(self, lshift: onp.ToFloatND, /) -> _LinDist[Self]: ... __rsub__ = __sub__ # @overload - def __mul__( - self, scale: float | np.integer[Any] | np.bool_, / - ) -> ShiftedScaledDistribution[Self, np.float64 | _FloatingT_co, _ShapeT0_co]: ... + def __mul__(self, scale: float | _Int | np.bool_, /) -> _LinDist[Self, np.float64 | _FloatT_co, _ShapeT_co]: ... @overload - def __mul__(self, scale: _FloatingT, /) -> ShiftedScaledDistribution[Self, _FloatingT | _FloatingT_co, _ShapeT0_co]: ... + def __mul__(self, scale: _FloatT, /) -> _LinDist[Self, _FloatT | _FloatT_co, _ShapeT_co]: ... @overload - def __mul__(self, scale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, np.floating[Any], _ShapeT0_co]: ... + def __mul__(self, scale: onp.ToFloat, /) -> _LinDist[Self, _Float, _ShapeT_co]: ... @overload def __mul__( - self: _CDistT0, scale: onp.CanArrayND[_FloatingT, _ShapeT0], / - ) -> ShiftedScaledDistribution[_CDistT0, _FloatingT | _FloatingT_co, _ShapeT0]: ... + self: _DistT0, scale: onp.CanArrayND[_FloatT, _ShapeT], / + ) -> _LinDist[_DistT0, _FloatT | _FloatT_co, _ShapeT]: ... @overload - def __mul__( - self: _CDistT_1, scale: onp.ToFloatStrict1D, / - ) -> ShiftedScaledDistribution[_CDistT_1, np.floating[Any], tuple[int]]: ... + def __mul__(self: _DistT_1, scale: onp.ToFloatStrict1D, /) -> _LinDist[_DistT_1, _Float, _1D]: ... @overload - def __mul__( - self: _CDistT_2, scale: onp.ToFloatStrict2D, / - ) -> ShiftedScaledDistribution[_CDistT_2, np.floating[Any], tuple[int, int]]: ... + def __mul__(self: _DistT_2, scale: onp.ToFloatStrict2D, /) -> _LinDist[_DistT_2, _Float, _2D]: ... @overload - def __mul__( - self: _CDistT_3, scale: onp.ToFloatStrict3D, / - ) -> ShiftedScaledDistribution[_CDistT_3, np.floating[Any], tuple[int, int, int]]: ... + def __mul__(self: _DistT_3, scale: onp.ToFloatStrict3D, /) -> _LinDist[_DistT_3, _Float, _3D]: ... @overload - def __mul__(self, scale: onp.ToFloatND, /) -> ShiftedScaledDistribution[Self]: ... + def __mul__(self, scale: onp.ToFloatND, /) -> _LinDist[Self]: ... __rmul__ = __mul__ # @overload - def __truediv__( - self, iscale: float | np.integer[Any] | np.bool_, / - ) -> ShiftedScaledDistribution[Self, np.float64 | _FloatingT_co, _ShapeT0_co]: ... + def __truediv__(self, iscale: float | _Int | np.bool_, /) -> _LinDist[Self, np.float64 | _FloatT_co, _ShapeT_co]: ... @overload - def __truediv__(self, iscale: _FloatingT, /) -> ShiftedScaledDistribution[Self, _FloatingT | _FloatingT_co, _ShapeT0_co]: ... + def __truediv__(self, iscale: _FloatT, /) -> _LinDist[Self, _FloatT | _FloatT_co, _ShapeT_co]: ... @overload - def __truediv__(self, iscale: onp.ToFloat, /) -> ShiftedScaledDistribution[Self, np.floating[Any], _ShapeT0_co]: ... + def __truediv__(self, iscale: onp.ToFloat, /) -> _LinDist[Self, _Float, _ShapeT_co]: ... @overload def __truediv__( - self: _CDistT0, iscale: onp.CanArrayND[_FloatingT, _ShapeT0], / - ) -> ShiftedScaledDistribution[_CDistT0, _FloatingT | _FloatingT_co, _ShapeT0]: ... + self: _DistT0, iscale: onp.CanArrayND[_FloatT, _ShapeT], / + ) -> _LinDist[_DistT0, _FloatT | _FloatT_co, _ShapeT]: ... @overload - def __truediv__( - self: _CDistT_1, iscale: onp.ToFloatStrict1D, / - ) -> ShiftedScaledDistribution[_CDistT_1, np.floating[Any], tuple[int]]: ... + def __truediv__(self: _DistT_1, iscale: onp.ToFloatStrict1D, /) -> _LinDist[_DistT_1, _Float, _1D]: ... @overload - def __truediv__( - self: _CDistT_2, iscale: onp.ToFloatStrict2D, / - ) -> ShiftedScaledDistribution[_CDistT_2, np.floating[Any], tuple[int, int]]: ... + def __truediv__(self: _DistT_2, iscale: onp.ToFloatStrict2D, /) -> _LinDist[_DistT_2, _Float, _2D]: ... @overload - def __truediv__( - self: _CDistT_3, iscale: onp.ToFloatStrict3D, / - ) -> ShiftedScaledDistribution[_CDistT_3, np.floating[Any], tuple[int, int, int]]: ... + def __truediv__(self: _DistT_3, iscale: onp.ToFloatStrict3D, /) -> _LinDist[_DistT_3, _Float, _3D]: ... @overload - def __truediv__(self, iscale: onp.ToFloatND, /) -> ShiftedScaledDistribution[Self]: ... + def __truediv__(self, iscale: onp.ToFloatND, /) -> _LinDist[Self]: ... __rtruediv__ = __truediv__ # - def __pow__(self, exp: onp.ToInt, /) -> MonotonicTransformedDistribution[Self, _ShapeT0_co]: ... + def __pow__(self, exp: onp.ToInt, /) -> MonotonicTransformedDistribution[Self, _ShapeT_co]: ... __rpow__ = __pow__ # @@ -373,427 +351,288 @@ class ContinuousDistribution(_BaseDistribution[_FloatingT_co, _ShapeT0_co], Gene # # NOTE: This will be removed in 1.15.0rc2, see https://github.com/scipy/scipy/pull/22149 @overload - def llf(self, sample: onp.ToFloat | onp.ToFloatND, /, *, axis: None) -> _Float: ... + def llf(self, sample: _ToFloatMaxND, /, *, axis: None) -> _OutFloat: ... @overload - def llf(self: _CDist0, sample: onp.ToFloat | onp.ToFloatStrict1D, /, *, axis: AnyShape | None = -1) -> _Float: ... + def llf(self: _CDist0, sample: _ToFloatMax1D, /, *, axis: AnyShape | None = -1) -> _OutFloat: ... @overload - def llf( - self: _CDist[_ShapeT1], sample: onp.ToFloat | onp.ToFloatStrict1D, /, *, axis: AnyShape = -1 - ) -> onp.ArrayND[_Float, _ShapeT1]: ... + def llf(self: _CDist[_ShapeT1], sample: _ToFloatMax1D, /, *, axis: AnyShape = -1) -> onp.ArrayND[_OutFloat, _ShapeT1]: ... @overload - def llf( - self: _CDist0, sample: onp.ToFloatStrict2D, /, *, axis: op.CanIndex | tuple[op.CanIndex] = -1 - ) -> onp.Array1D[_Float]: ... + def llf(self: _CDist0, sample: onp.ToFloatStrict2D, /, *, axis: _To1D = -1) -> onp.Array1D[_OutFloat]: ... @overload - def llf(self: _CDist0, sample: onp.ToFloatStrict2D, /, *, axis: tuple[op.CanIndex, op.CanIndex]) -> _Float: ... + def llf(self: _CDist0, sample: onp.ToFloatStrict2D, /, *, axis: _To2D) -> _OutFloat: ... @overload - def llf( - self: _CDist0, sample: onp.ToFloatStrict3D, /, *, axis: op.CanIndex | tuple[op.CanIndex] = -1 - ) -> onp.Array2D[_Float]: ... + def llf(self: _CDist0, sample: onp.ToFloatStrict3D, /, *, axis: _To1D = -1) -> onp.Array2D[_OutFloat]: ... @overload - def llf(self: _CDist0, sample: onp.ToFloatStrict3D, /, *, axis: tuple[op.CanIndex, op.CanIndex]) -> onp.Array1D[_Float]: ... + def llf(self: _CDist0, sample: onp.ToFloatStrict3D, /, *, axis: _To2D) -> onp.Array1D[_OutFloat]: ... @overload - def llf(self: _CDist0, sample: onp.ToFloatStrict3D, /, *, axis: tuple[op.CanIndex, op.CanIndex, op.CanIndex]) -> _Float: ... + def llf(self: _CDist0, sample: onp.ToFloatStrict3D, /, *, axis: _To3D) -> _OutFloat: ... @overload def llf( - self: _CDist[_ShapeT1], sample: onp.ToFloat | onp.ToFloatND, /, *, axis: AnyShape = -1 - ) -> onp.Array[_ShapeT1, _Float] | onp.ArrayND[_Float]: ... # the first union type is needed on numpy <2.1 + self: _CDist[_ShapeT1], sample: _ToFloatMaxND, /, *, axis: AnyShape = -1 + ) -> onp.Array[_ShapeT1, _OutFloat] | onp.ArrayND[_OutFloat]: ... # the first union type is needed on numpy <2.1 @overload - def llf(self, sample: onp.ToFloat | onp.ToFloatND, /, *, axis: AnyShape | None = -1) -> _Float | onp.ArrayND[_Float]: ... - -_ElementwiseFunction: TypeAlias = Callable[[onp.ArrayND[np.float64]], onp.ArrayND[_FloatingT]] + def llf(self, sample: _ToFloatMaxND, /, *, axis: AnyShape | None = -1) -> _OutFloat | onp.ArrayND[_OutFloat]: ... # 7 years of asking and >400 upvotes, but still no higher-kinded typing support: https://github.com/python/typing/issues/548 -class TransformedDistribution( - ContinuousDistribution[_FloatingT_co, _ShapeT0_co], - Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], -): - _dist: _CDistT_co # readonly +class TransformedDistribution(ContinuousDistribution[_FloatT_co, _ShapeT_co], Generic[_DistT_co, _FloatT_co, _ShapeT_co]): + _dist: _DistT_co # readonly def __init__( - self: TransformedDistribution[ContinuousDistribution[_FloatingT, _ShapeT0], _FloatingT, _ShapeT0], # nice trick, eh? - X: _CDistT_co, + self: _TransDist[ContinuousDistribution[_FloatT, _ShapeT], _FloatT, _ShapeT], # nice trick, eh? + X: _DistT_co, /, *args: Never, - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, + **kwargs: Unpack[_DistOpts], ) -> None: ... -class ShiftedScaledDistribution( - TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], - Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], -): +class ShiftedScaledDistribution(_TransDist[_DistT_co, _FloatT_co, _ShapeT_co], Generic[_DistT_co, _FloatT_co, _ShapeT_co]): _loc_domain: ClassVar[_RealDomain] = ... _loc_param: ClassVar[_RealParameter] = ... - _scale_domain: ClassVar[_RealDomain] = ... _scale_param: ClassVar[_RealParameter] = ... - loc: _ParameterField[_FloatingT_co, _ShapeT0_co] - scale: _ParameterField[_FloatingT_co, _ShapeT0_co] + loc: _ParamField[_FloatT_co, _ShapeT_co] + scale: _ParamField[_FloatT_co, _ShapeT_co] # TODO(jorenham): override `__[r]{add,sub,mul,truediv}__` so that it returns a `Self` (but maybe with different shape) -class FoldedDistribution( - TransformedDistribution[_CDistT_co, _FloatingT_co, _ShapeT0_co], - Generic[_CDistT_co, _FloatingT_co, _ShapeT0_co], -): +class FoldedDistribution(_TransDist[_DistT_co, _FloatT_co, _ShapeT_co], Generic[_DistT_co, _FloatT_co, _ShapeT_co]): @overload - def __init__( - self: FoldedDistribution[_CDistT0, np.floating[Any], tuple[()]], - X: _CDistT0, - /, - *args: Never, - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, - ) -> None: ... + def __init__(self: _FoldDist[_DistT0, _Float, _0D], X: _DistT0, /, *args: Never, **kwargs: Unpack[_DistOpts]) -> None: ... @overload - def __init__( - self: FoldedDistribution[_CDistT1, np.floating[Any], tuple[int]], - X: _CDistT1, - /, - *args: Never, - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, - ) -> None: ... + def __init__(self: _FoldDist[_DistT1, _Float, _1D], X: _DistT1, /, *args: Never, **kwargs: Unpack[_DistOpts]) -> None: ... @overload - def __init__( - self: FoldedDistribution[_CDistT2, np.floating[Any], tuple[int, int]], - X: _CDistT2, - /, - *args: Never, - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, - ) -> None: ... + def __init__(self: _FoldDist[_DistT2, _Float, _2D], X: _DistT2, /, *args: Never, **kwargs: Unpack[_DistOpts]) -> None: ... @overload - def __init__( - self: FoldedDistribution[_CDistT3, np.floating[Any], tuple[int, int, int]], - X: _CDistT3, - /, - *args: Never, - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, - ) -> None: ... + def __init__(self: _FoldDist[_DistT3, _Float, _3D], X: _DistT3, /, *args: Never, **kwargs: Unpack[_DistOpts]) -> None: ... @overload - def __init__( - self: FoldedDistribution[_CDistT, np.floating[Any], tuple[int, ...]], - X: _CDistT, - /, - *args: Never, - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, - ) -> None: ... + def __init__(self: _FoldDist[_DistT, _Float, _ND], X: _DistT, /, *args: Never, **kwargs: Unpack[_DistOpts]) -> None: ... -class TruncatedDistribution( - TransformedDistribution[_CDistT_co, np.floating[Any], _ShapeT0_co], - Generic[_CDistT_co, _ShapeT0_co], -): +class TruncatedDistribution(_TransDist[_DistT_co, _Float, _ShapeT_co], Generic[_DistT_co, _ShapeT_co]): _lb_domain: ClassVar[_RealDomain] = ... _lb_param: ClassVar[_RealParameter] = ... - _ub_domain: ClassVar[_RealDomain] = ... _ub_param: ClassVar[_RealParameter] = ... - lb: _ParameterField[np.floating[Any], _ShapeT0_co] - ub: _ParameterField[np.floating[Any], _ShapeT0_co] + lb: _ParamField[_Float, _ShapeT_co] + ub: _ParamField[_Float, _ShapeT_co] @overload def __init__( - self: TruncatedDistribution[_CDistT0, tuple[()]], - X: _CDistT0, + self: _TruncDist[_DistT0, _0D], + X: _DistT0, /, *args: Never, lb: onp.ToFloat = ..., ub: onp.ToFloat = ..., - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, + **kwargs: Unpack[_DistOpts], ) -> None: ... @overload def __init__( - self: TruncatedDistribution[_CDistT1, tuple[int]], - X: _CDistT1, + self: _TruncDist[_DistT1, _1D], + X: _DistT1, /, *args: Never, - lb: onp.ToFloat | onp.ToFloatStrict1D = ..., - ub: onp.ToFloat | onp.ToFloatStrict1D = ..., - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, + lb: _ToFloatMax1D = ..., + ub: _ToFloatMax1D = ..., + **kwargs: Unpack[_DistOpts], ) -> None: ... @overload def __init__( - self: TruncatedDistribution[_CDistT2, tuple[int, int]], - X: _CDistT2, + self: _TruncDist[_DistT2, _2D], + X: _DistT2, /, *args: Never, - lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., - ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, + lb: _ToFloatMax2D = ..., + ub: _ToFloatMax2D = ..., + **kwargs: Unpack[_DistOpts], ) -> None: ... @overload def __init__( - self: TruncatedDistribution[_CDistT3, tuple[int, int, int]], - X: _CDistT3, + self: _TruncDist[_DistT3, _3D], + X: _DistT3, /, *args: Never, - lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., - ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, + lb: _ToFloatMax3D = ..., + ub: _ToFloatMax3D = ..., + **kwargs: Unpack[_DistOpts], ) -> None: ... @overload def __init__( - self: TruncatedDistribution[_CDistT, tuple[int, ...]], - X: _CDistT, + self: _TruncDist[_DistT, _ND], + X: _DistT, /, *args: Never, - lb: onp.ToFloat | onp.ToFloatND = ..., - ub: onp.ToFloat | onp.ToFloatND = ..., - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, + lb: _ToFloatMaxND = ..., + ub: _ToFloatMaxND = ..., + **kwargs: Unpack[_DistOpts], ) -> None: ... # always float64 or longdouble -class OrderStatisticDistribution(TransformedDistribution[_CDistT_co, _Float, _ShapeT0_co], Generic[_CDistT_co, _ShapeT0_co]): +class OrderStatisticDistribution(_TransDist[_DistT_co, _OutFloat, _ShapeT_co], Generic[_DistT_co, _ShapeT_co]): # these should actually be integral; but the `_IntegerDomain` isn't finished yet _r_domain: ClassVar[_RealDomain] = ... _r_param: ClassVar[_RealParameter] = ... - _n_domain: ClassVar[_RealDomain] = ... _n_param: ClassVar[_RealParameter] = ... @overload def __init__( - self: OrderStatisticDistribution[_CDistT0, tuple[()]], - dist: _CDistT0, + self: OrderStatisticDistribution[_DistT0, _0D], + dist: _DistT0, /, *args: Never, r: onp.ToJustInt, n: onp.ToJustInt, - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, + **kwargs: Unpack[_DistOpts], ) -> None: ... @overload def __init__( - self: OrderStatisticDistribution[_CDistT1, tuple[int]], - dist: _CDistT1, + self: OrderStatisticDistribution[_DistT1, _1D], + dist: _DistT1, /, *args: Never, - r: onp.ToJustInt | onp.ToJustIntStrict1D, - n: onp.ToJustInt | onp.ToJustIntStrict1D, - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, + r: _ToJustIntMax1D, + n: _ToJustIntMax1D, + **kwargs: Unpack[_DistOpts], ) -> None: ... @overload def __init__( - self: OrderStatisticDistribution[_CDistT2, tuple[int, int]], - dist: _CDistT2, + self: OrderStatisticDistribution[_DistT2, _2D], + dist: _DistT2, /, *args: Never, - r: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D, - n: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D, - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, + r: _ToJustIntMax2D, + n: _ToJustIntMax2D, + **kwargs: Unpack[_DistOpts], ) -> None: ... @overload def __init__( - self: OrderStatisticDistribution[_CDistT3, tuple[int, int, int]], - dist: _CDistT3, + self: OrderStatisticDistribution[_DistT3, _3D], + dist: _DistT3, /, *args: Never, - r: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D | onp.ToJustIntStrict3D, - n: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D | onp.ToJustIntStrict3D, - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, + r: _ToJustIntMax3D, + n: _ToJustIntMax3D, + **kwargs: Unpack[_DistOpts], ) -> None: ... @overload def __init__( - self: OrderStatisticDistribution[_CDistT, tuple[int, ...]], - X: _CDistT, + self: OrderStatisticDistribution[_DistT, _ND], + X: _DistT, /, *args: Never, - r: onp.ToJustInt | onp.ToJustIntND, - n: onp.ToJustInt | onp.ToJustIntND, - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, + r: _ToJustIntMaxND, + n: _ToJustIntMaxND, + **kwargs: Unpack[_DistOpts], ) -> None: ... # without HKT there's no reasonable way tot determine the floating scalar type -class MonotonicTransformedDistribution( - TransformedDistribution[_CDistT_co, np.floating[Any], _ShapeT0_co], - Generic[_CDistT_co, _ShapeT0_co], -): - _g: Final[_ElementwiseFunction] - _h: Final[_ElementwiseFunction] - _dh: Final[_ElementwiseFunction] - _logdh: Final[_ElementwiseFunction] +class MonotonicTransformedDistribution(_TransDist[_DistT_co, _Float, _ShapeT_co], Generic[_DistT_co, _ShapeT_co]): + _g: Final[_Elementwise] + _h: Final[_Elementwise] + _dh: Final[_Elementwise] + _logdh: Final[_Elementwise] _increasing: Final[bool] _repr_pattern: Final[str] def __init__( - self: MonotonicTransformedDistribution[_CDist[_ShapeT0], _ShapeT0], - X: _CDistT_co, + self: MonotonicTransformedDistribution[_CDist[_ShapeT], _ShapeT], + X: _DistT_co, /, *args: Never, - g: _ElementwiseFunction, - h: _ElementwiseFunction, - dh: _ElementwiseFunction, - logdh: _ElementwiseFunction | None = None, + g: _Elementwise, + h: _Elementwise, + dh: _Elementwise, + logdh: _Elementwise | None = None, increasing: bool = True, repr_pattern: str | None = None, - tol: opt.Just[float] | _Null = ..., - validation_policy: _ValidationPolicy = None, - cache_policy: _CachePolicy = None, + **kwargs: Unpack[_DistOpts], ) -> None: ... -class Mixture(_BaseDistribution[_FloatingT_co, tuple[()]], Generic[_FloatingT_co]): - _shape: tuple[()] - _dtype: np.dtype[_FloatingT_co] - _components: Sequence[_CDist0[_FloatingT_co]] - _weights: onp.Array1D[_FloatingT_co] +class Mixture(_BaseDistribution[_FloatT_co, _0D], Generic[_FloatT_co]): + _shape: _0D + _dtype: np.dtype[_FloatT_co] + _components: Sequence[_CDist0[_FloatT_co]] + _weights: onp.Array1D[_FloatT_co] validation_policy: None @property - def components(self, /) -> list[_CDist0[_FloatingT_co]]: ... + def components(self, /) -> list[_CDist0[_FloatT_co]]: ... @property - def weights(self, /) -> onp.Array1D[_FloatingT_co]: ... + def weights(self, /) -> onp.Array1D[_FloatT_co]: ... # - def __init__(self, /, components: Sequence[_CDist0[_FloatingT_co]], *, weights: onp.ToFloat1D | None = None) -> None: ... + def __init__(self, /, components: Sequence[_CDist0[_FloatT_co]], *, weights: onp.ToFloat1D | None = None) -> None: ... # @override - def kurtosis(self, /, *, method: _SMomentMethod | None = None) -> _Float: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + def kurtosis(self, /, *, method: _SMomentMethod | None = None) -> _OutFloat: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] ### # still waiting on the intersection type PEP... + @overload -def truncate( - X: _CDistT0, - lb: onp.ToFloat = ..., - ub: onp.ToFloat = ..., -) -> TruncatedDistribution[_CDistT0, tuple[()]]: ... +def truncate(X: _DistT0, lb: onp.ToFloat = ..., ub: onp.ToFloat = ...) -> _TruncDist[_DistT0, _0D]: ... @overload -def truncate( - X: _CDistT1, - lb: onp.ToFloat | onp.ToFloatStrict1D = ..., - ub: onp.ToFloat | onp.ToFloatStrict1D = ..., -) -> TruncatedDistribution[_CDistT1, tuple[int]]: ... +def truncate(X: _DistT1, lb: _ToFloatMax1D = ..., ub: _ToFloatMax1D = ...) -> _TruncDist[_DistT1, _1D]: ... @overload -def truncate( - X: _CDistT2, - lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., - ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D = ..., -) -> TruncatedDistribution[_CDistT2, tuple[int, int]]: ... +def truncate(X: _DistT2, lb: _ToFloatMax2D = ..., ub: _ToFloatMax2D = ...) -> _TruncDist[_DistT2, _2D]: ... @overload -def truncate( - X: _CDistT3, - lb: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., - ub: onp.ToFloat | onp.ToFloatStrict1D | onp.ToFloatStrict2D | onp.ToFloatStrict3D = ..., -) -> TruncatedDistribution[_CDistT3, tuple[int, int, int]]: ... +def truncate(X: _DistT3, lb: _ToFloatMax3D = ..., ub: _ToFloatMax3D = ...) -> _TruncDist[_DistT3, _3D]: ... @overload -def truncate( - X: _CDistT, - lb: onp.ToFloat | onp.ToFloatND = ..., - ub: onp.ToFloat | onp.ToFloatND = ..., -) -> TruncatedDistribution[_CDistT, tuple[int, ...]]: ... +def truncate(X: _DistT, lb: _ToFloatMaxND = ..., ub: _ToFloatMaxND = ...) -> _TruncDist[_DistT, _ND]: ... # @overload -def order_statistic( - X: _CDistT0, - /, - *, - r: onp.ToJustInt, - n: onp.ToJustInt, -) -> OrderStatisticDistribution[_CDistT0, tuple[()]]: ... +def order_statistic(X: _DistT0, /, *, r: onp.ToJustInt, n: onp.ToJustInt) -> OrderStatisticDistribution[_DistT0, _0D]: ... @overload -def order_statistic( - X: _CDistT1, - /, - *, - r: onp.ToJustInt | onp.ToJustIntStrict1D, - n: onp.ToJustInt | onp.ToJustIntStrict1D, -) -> OrderStatisticDistribution[_CDistT1, tuple[int]]: ... +def order_statistic(X: _DistT1, /, *, r: _ToJustIntMax1D, n: _ToJustIntMax1D) -> OrderStatisticDistribution[_DistT1, _1D]: ... @overload -def order_statistic( - X: _CDistT2, - /, - *, - r: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D, - n: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D, -) -> OrderStatisticDistribution[_CDistT2, tuple[int, int]]: ... +def order_statistic(X: _DistT2, /, *, r: _ToJustIntMax2D, n: _ToJustIntMax2D) -> OrderStatisticDistribution[_DistT2, _2D]: ... @overload -def order_statistic( - X: _CDistT3, - /, - *, - r: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D | onp.ToJustIntStrict3D, - n: onp.ToJustInt | onp.ToJustIntStrict1D | onp.ToJustIntStrict2D | onp.ToJustIntStrict3D, -) -> OrderStatisticDistribution[_CDistT3, tuple[int, int, int]]: ... +def order_statistic(X: _DistT3, /, *, r: _ToJustIntMax3D, n: _ToJustIntMax3D) -> OrderStatisticDistribution[_DistT3, _3D]: ... @overload -def order_statistic( - X: _CDistT, - /, - *, - r: onp.ToJustInt | onp.ToJustIntND, - n: onp.ToJustInt | onp.ToJustIntND, -) -> OrderStatisticDistribution[_CDistT, tuple[int, ...]]: ... +def order_statistic(X: _DistT, /, *, r: _ToJustIntMaxND, n: _ToJustIntMaxND) -> OrderStatisticDistribution[_DistT, _ND]: ... # @overload -def abs(X: _CDistT0, /) -> FoldedDistribution[_CDistT0, np.floating[Any], tuple[()]]: ... +def abs(X: _DistT0, /) -> _FoldDist[_DistT0, _Float, _0D]: ... @overload -def abs(X: _CDistT1, /) -> FoldedDistribution[_CDistT1, np.floating[Any], tuple[int]]: ... +def abs(X: _DistT1, /) -> _FoldDist[_DistT1, _Float, _1D]: ... @overload -def abs(X: _CDistT2, /) -> FoldedDistribution[_CDistT2, np.floating[Any], tuple[int, int]]: ... +def abs(X: _DistT2, /) -> _FoldDist[_DistT2, _Float, _2D]: ... @overload -def abs(X: _CDistT3, /) -> FoldedDistribution[_CDistT3, np.floating[Any], tuple[int, int, int]]: ... +def abs(X: _DistT3, /) -> _FoldDist[_DistT3, _Float, _3D]: ... @overload -def abs(X: _CDistT, /) -> FoldedDistribution[_CDistT, np.floating[Any], tuple[int, ...]]: ... +def abs(X: _DistT, /) -> _FoldDist[_DistT, _Float, _ND]: ... # @overload -def exp(X: _CDistT0, /) -> MonotonicTransformedDistribution[_CDistT0, tuple[()]]: ... +def exp(X: _DistT0, /) -> MonotonicTransformedDistribution[_DistT0, _0D]: ... @overload -def exp(X: _CDistT1, /) -> MonotonicTransformedDistribution[_CDistT1, tuple[int]]: ... +def exp(X: _DistT1, /) -> MonotonicTransformedDistribution[_DistT1, _1D]: ... @overload -def exp(X: _CDistT2, /) -> MonotonicTransformedDistribution[_CDistT2, tuple[int, int]]: ... +def exp(X: _DistT2, /) -> MonotonicTransformedDistribution[_DistT2, _2D]: ... @overload -def exp(X: _CDistT3, /) -> MonotonicTransformedDistribution[_CDistT3, tuple[int, int, int]]: ... +def exp(X: _DistT3, /) -> MonotonicTransformedDistribution[_DistT3, _3D]: ... @overload -def exp(X: _CDistT, /) -> MonotonicTransformedDistribution[_CDistT, tuple[int, ...]]: ... +def exp(X: _DistT, /) -> MonotonicTransformedDistribution[_DistT, _ND]: ... # @overload -def log(X: _CDistT0, /) -> MonotonicTransformedDistribution[_CDistT0, tuple[()]]: ... +def log(X: _DistT0, /) -> MonotonicTransformedDistribution[_DistT0, _0D]: ... @overload -def log(X: _CDistT1, /) -> MonotonicTransformedDistribution[_CDistT1, tuple[int]]: ... +def log(X: _DistT1, /) -> MonotonicTransformedDistribution[_DistT1, _1D]: ... @overload -def log(X: _CDistT2, /) -> MonotonicTransformedDistribution[_CDistT2, tuple[int, int]]: ... +def log(X: _DistT2, /) -> MonotonicTransformedDistribution[_DistT2, _2D]: ... @overload -def log(X: _CDistT3, /) -> MonotonicTransformedDistribution[_CDistT3, tuple[int, int, int]]: ... +def log(X: _DistT3, /) -> MonotonicTransformedDistribution[_DistT3, _3D]: ... @overload -def log(X: _CDistT, /) -> MonotonicTransformedDistribution[_CDistT, tuple[int, ...]]: ... +def log(X: _DistT, /) -> MonotonicTransformedDistribution[_DistT, _ND]: ... # NOTE: These currently don't support >0-d parameters, and it looks like they always return float64, regardless of dtype @type_check_only -class CustomDistribution(ContinuousDistribution[np.float64, tuple[()]]): - _dtype: np.dtype[np.floating[Any]] # ignored +class CustomDistribution(ContinuousDistribution[np.float64, _0D]): + _dtype: np.dtype[_Float] # ignored def make_distribution(dist: rv_continuous) -> type[CustomDistribution]: ... From 02393e1e059842769a910a812317db83a28f04d6 Mon Sep 17 00:00:00 2001 From: jorenham Date: Sat, 21 Dec 2024 05:54:20 +0100 Subject: [PATCH 15/16] =?UTF-8?q?=F0=9F=91=BD=EF=B8=8F=20`stats`:=201.15.0?= =?UTF-8?q?=20annotate=20`Normal`=20and=20`Uniform`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .mypyignore | 3 + scipy-stubs/stats/__init__.pyi | 8 +- scipy-stubs/stats/_new_distributions.pyi | 164 +++++++++++++++++++++++ 3 files changed, 170 insertions(+), 5 deletions(-) create mode 100644 scipy-stubs/stats/_new_distributions.pyi diff --git a/.mypyignore b/.mypyignore index 2d44636f..34f3d08f 100644 --- a/.mypyignore +++ b/.mypyignore @@ -28,6 +28,9 @@ scipy\.(_lib|integrate|stats)\.((_|\w)+\.)+__replace__ # `NamedTuple` on `pytho # stubtest doesn't understand `if sys.version_info >= _: ...` blocks scipy\.sparse\.(\w+)\.warn +# annoying and useless __new__ +scipy\.stats\.(_new_distributions\.)?Normal\.__new__ + # mypy fails recognize type-check-only ufunc subtypes as ufuncs # https://github.com/KotlinIsland/basedmypy/issues/816 scipy\.special\._basic\.digamma diff --git a/scipy-stubs/stats/__init__.pyi b/scipy-stubs/stats/__init__.pyi index 44388cd1..811505d5 100644 --- a/scipy-stubs/stats/__init__.pyi +++ b/scipy-stubs/stats/__init__.pyi @@ -73,9 +73,7 @@ from ._multivariate import ( vonmises_fisher, wishart, ) - -# TODO(jorenham) -# `from ._new_distributions import Normal, Uniform +from ._new_distributions import Normal, Uniform from ._page_trend_test import page_trend_test from ._resampling import ( BootstrapMethod, @@ -309,9 +307,9 @@ __all__ = [ "Mixture", "MonteCarloMethod", "NearConstantInputWarning", - # "Normal", + "Normal", "PermutationMethod", - # "Uniform", + "Uniform", "abs", "alexandergovern", "alpha", diff --git a/scipy-stubs/stats/_new_distributions.pyi b/scipy-stubs/stats/_new_distributions.pyi new file mode 100644 index 00000000..e2750571 --- /dev/null +++ b/scipy-stubs/stats/_new_distributions.pyi @@ -0,0 +1,164 @@ +from typing import Any, ClassVar, Generic, TypeAlias, overload +from typing_extensions import Never, TypeVar, Unpack + +import numpy as np +import optype.numpy as onp +from ._distribution_infrastructure import ContinuousDistribution, _DistOpts, _RealDomain, _RealParameter + +__all__ = ["Normal", "Uniform"] + +### + +_Float: TypeAlias = np.floating[Any] + +_NT = TypeVar("_NT", default=int) +_0D: TypeAlias = tuple[()] # noqa: PYI042 +_1D: TypeAlias = tuple[_NT] # noqa: PYI042 +_2D: TypeAlias = tuple[_NT, _NT] # noqa: PYI042 +_3D: TypeAlias = tuple[_NT, _NT, _NT] # noqa: PYI042 +_ND: TypeAlias = tuple[_NT, ...] + +_ToFloat_1D: TypeAlias = onp.ToFloatStrict1D | onp.ToFloat +_ToFloat_2D: TypeAlias = onp.ToFloatStrict2D | _ToFloat_1D +_ToFloat_3D: TypeAlias = onp.ToFloatStrict3D | _ToFloat_2D +_ToFloat_ND: TypeAlias = onp.ToFloatND | onp.ToFloat + +_FloatT = TypeVar("_FloatT", bound=_Float, default=_Float) +_FloatT_co = TypeVar("_FloatT_co", bound=_Float, default=_Float, covariant=True) + +_ShapeT = TypeVar("_ShapeT", bound=_ND, default=_ND) +_ShapeT_co = TypeVar("_ShapeT_co", bound=_ND, default=_ND, covariant=True) + +### + +class Normal(ContinuousDistribution[_FloatT_co, _ShapeT_co], Generic[_ShapeT_co, _FloatT_co]): + _mu_domain: ClassVar[_RealDomain] = ... + _mu_param: ClassVar[_RealParameter] = ... + _sigma_domain: ClassVar[_RealDomain] = ... + _sigma_param: ClassVar[_RealParameter] = ... + _x_support: ClassVar[_RealDomain] = ... + _x_param: ClassVar[_RealParameter] = ... + _normalization: ClassVar[np.float64] = ... + _log_normalization: ClassVar[np.float64] = ... + + @property + def mu(self, /) -> _FloatT_co | onp.Array[_ShapeT_co, _FloatT_co]: ... + @property + def sigma(self, /) -> _FloatT_co | onp.Array[_ShapeT_co, _FloatT_co]: ... + + # TODO(jorenham): __new__ + + # + @overload # default + def __init__(self: Normal[tuple[()], np.float64], /, **kw: Unpack[_DistOpts]) -> None: ... + @overload # mu: N-d + def __init__( + self: Normal[_ShapeT, _FloatT], + /, + *, + mu: onp.CanArrayND[_FloatT, _ShapeT], + sigma: onp.CanArrayND[_FloatT | np.integer[Any] | np.bool_, _ShapeT] | onp.ToInt, + **kw: Unpack[_DistOpts], + ) -> None: ... + @overload # sigma: N-d + def __init__( + self: Normal[_ShapeT, _FloatT], + /, + *, + mu: onp.CanArrayND[_FloatT | np.integer[Any] | np.bool_, _ShapeT] | onp.ToInt, + sigma: onp.CanArrayND[_FloatT, _ShapeT], + **kw: Unpack[_DistOpts], + ) -> None: ... + @overload # mu, sigma: 0-d float + def __init__(self: Normal[_0D, np.float64], /, *, mu: float, sigma: float | onp.ToInt, **kw: Unpack[_DistOpts]) -> None: ... + @overload # mu, sigma: 0-d float + def __init__(self: Normal[_0D, np.float64], /, *, mu: float | onp.ToInt, sigma: float, **kw: Unpack[_DistOpts]) -> None: ... + @overload # mu: 0-d , sigma: 0-d + def __init__(self: Normal[_0D, _FloatT], /, *, mu: _FloatT, sigma: _FloatT | onp.ToInt, **kw: Unpack[_DistOpts]) -> None: ... + @overload # a, sigma: 0-d + def __init__(self: Normal[_0D, _FloatT], /, *, mu: _FloatT | onp.ToInt, sigma: _FloatT, **kw: Unpack[_DistOpts]) -> None: ... + @overload # a, sigma: 0-d + def __init__(self: Normal[_0D], /, *, mu: onp.ToFloat = 0.0, sigma: onp.ToFloat = 1.0, **kw: Unpack[_DistOpts]) -> None: ... + @overload # mu: 1-d + def __init__(self: Normal[_1D], /, *, mu: onp.ToFloatStrict1D, sigma: _ToFloat_1D = 1.0, **kw: Unpack[_DistOpts]) -> None: ... + @overload # sigma: 1-d + def __init__(self: Normal[_1D], /, *, mu: _ToFloat_1D = 0.0, sigma: onp.ToFloatStrict1D, **kw: Unpack[_DistOpts]) -> None: ... + @overload # mu: 2-d + def __init__(self: Normal[_2D], /, *, mu: onp.ToFloatStrict2D, sigma: _ToFloat_2D = 1.0, **kw: Unpack[_DistOpts]) -> None: ... + @overload # sigma: 2-d + def __init__(self: Normal[_2D], /, *, mu: _ToFloat_2D = 0.0, sigma: onp.ToFloatStrict2D, **kw: Unpack[_DistOpts]) -> None: ... + @overload # mu: 3-d + def __init__(self: Normal[_2D], /, *, mu: onp.ToFloatStrict3D, sigma: _ToFloat_3D = 1.0, **kw: Unpack[_DistOpts]) -> None: ... + @overload # sigma: 3-d + def __init__(self: Normal[_3D], /, *, mu: _ToFloat_3D = 0.0, sigma: onp.ToFloatStrict3D, **kw: Unpack[_DistOpts]) -> None: ... + @overload # mu: >=1-d + def __init__( + self: Normal[onp.AtLeast1D], + /, + *, + mu: onp.ToFloatND, + sigma: _ToFloat_ND = 1.0, + **kw: Unpack[_DistOpts], + ) -> None: ... + @overload # sigma: >=1-d + def __init__( + self: Normal[onp.AtLeast1D], + /, + *, + mu: _ToFloat_ND = 0.0, + sigma: onp.ToFloatND, + **kw: Unpack[_DistOpts], + ) -> None: ... + +class StandardNormal(Normal[tuple[()], np.float64]): # undocumented + mu: ClassVar[np.float64] = ... # pyright: ignore[reportIncompatibleMethodOverride] + sigma: ClassVar[np.float64] = ... # pyright: ignore[reportIncompatibleMethodOverride] + + def __init__(self, /, **kw: Unpack[_DistOpts]) -> None: ... + +class Uniform(ContinuousDistribution[_FloatT_co, _ShapeT_co], Generic[_ShapeT_co, _FloatT_co]): + _a_domain: ClassVar[_RealDomain] = ... + _a_param: ClassVar[_RealParameter] = ... + _b_domain: ClassVar[_RealDomain] = ... + _b_param: ClassVar[_RealParameter] = ... + _x_support: ClassVar[_RealDomain] = ... + _x_param: ClassVar[_RealParameter] = ... + + @property + def a(self, /) -> _FloatT_co | onp.Array[_ShapeT_co, _FloatT_co]: ... + @property + def b(self, /) -> _FloatT_co | onp.Array[_ShapeT_co, _FloatT_co]: ... + @property + def ab(self, /) -> _FloatT_co | onp.Array[_ShapeT_co, _FloatT_co]: ... # b - a + + # NOTE: `a` and `b` are both required; the defaults are just there to confuse you or something... + @overload # a: 0-d float, b: 0-d + def __init__(self: Uniform[_0D, np.float64], /, *, a: float, b: float | onp.ToInt, **kw: Unpack[_DistOpts]) -> None: ... + @overload # a, b: 0-d float + def __init__(self: Uniform[_0D, np.float64], /, *, a: float | onp.ToInt, b: float, **kw: Unpack[_DistOpts]) -> None: ... + @overload # a: 0-d , b: 0-d + def __init__(self: Uniform[_0D, _FloatT], /, *, a: _FloatT, b: _FloatT | onp.ToInt, **kw: Unpack[_DistOpts]) -> None: ... + @overload # a, b: 0-d + def __init__(self: Uniform[_0D, _FloatT], /, *, a: _FloatT | onp.ToInt, b: _FloatT, **kw: Unpack[_DistOpts]) -> None: ... + @overload # a, b: 0-d + def __init__(self: Uniform[_0D], /, *, a: onp.ToFloat, b: onp.ToFloat, **kw: Unpack[_DistOpts]) -> None: ... + @overload # a: 1-d + def __init__(self: Uniform[_1D], /, *, a: onp.ToFloatStrict1D, b: _ToFloat_1D, **kw: Unpack[_DistOpts]) -> None: ... + @overload # b: 1-d + def __init__(self: Uniform[_1D], /, *, a: _ToFloat_1D, b: onp.ToFloatStrict1D, **kw: Unpack[_DistOpts]) -> None: ... + @overload # a: 2-d + def __init__(self: Uniform[_2D], /, *, a: onp.ToFloatStrict2D, b: _ToFloat_2D, **kw: Unpack[_DistOpts]) -> None: ... + @overload # b: 2-d + def __init__(self: Uniform[_2D], /, *, a: _ToFloat_2D, b: onp.ToFloatStrict2D, **kw: Unpack[_DistOpts]) -> None: ... + @overload # a: 3-d + def __init__(self: Uniform[_2D], /, *, a: onp.ToFloatStrict3D, b: _ToFloat_3D, **kw: Unpack[_DistOpts]) -> None: ... + @overload # b: 3-d + def __init__(self: Uniform[_3D], /, *, a: _ToFloat_3D, b: onp.ToFloatStrict3D, **kw: Unpack[_DistOpts]) -> None: ... + @overload # a: >=1-d + def __init__(self: Uniform[onp.AtLeast1D], /, *, a: onp.ToFloatND, b: _ToFloat_ND, **kw: Unpack[_DistOpts]) -> None: ... + @overload # b: >=1-d + def __init__(self: Uniform[onp.AtLeast1D], /, *, a: _ToFloat_ND, b: onp.ToFloatND, **kw: Unpack[_DistOpts]) -> None: ... + @overload # a: None -> ValueError + def __init__(self, /, *, a: None = None, b: _ToFloat_ND | None = None, **kw: Unpack[_DistOpts]) -> Never: ... + @overload # b: None -> ValueError + def __init__(self, /, *, a: _ToFloat_ND | None = None, b: None = None, **kw: Unpack[_DistOpts]) -> Never: ... From 159c65747395cb834d94d2db29e753d3cdda8423 Mon Sep 17 00:00:00 2001 From: jorenham Date: Sat, 21 Dec 2024 05:55:30 +0100 Subject: [PATCH 16/16] =?UTF-8?q?=F0=9F=94=A5=20remove=20the=20temporary?= =?UTF-8?q?=20`1.15.0`=20allowlist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .mypyignore-todo | 2 -- pyproject.toml | 1 - tox.toml | 28 ++-------------------------- 3 files changed, 2 insertions(+), 29 deletions(-) delete mode 100644 .mypyignore-todo diff --git a/.mypyignore-todo b/.mypyignore-todo deleted file mode 100644 index fe71ef66..00000000 --- a/.mypyignore-todo +++ /dev/null @@ -1,2 +0,0 @@ -scipy\.stats\.__all__ -scipy\.stats\.(Normal|Uniform) diff --git a/pyproject.toml b/pyproject.toml index c1ca53a4..0235c423 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -139,7 +139,6 @@ uv run --frozen --no-editable --isolated --refresh-package=scipy-stubs stubtest --mypy-config-file=pyproject.toml --allowlist=.mypyignore - --allowlist=.mypyignore-todo --ignore-unused-allowlist $modules """ diff --git a/tox.toml b/tox.toml index c1613b21..a56c20ee 100644 --- a/tox.toml +++ b/tox.toml @@ -75,18 +75,7 @@ commands = [ [env.basedpyright] description = "basedpyright" dependency_groups = ["typecheck"] -commands = [ - [ - "uv", - "pip", - "freeze", - ], - [ - "basedpyright", - "scipy-stubs", - "codegen", - ], -] +commands = [["uv", "pip", "freeze"], ["basedpyright", "scipy-stubs", "codegen"]] [env.min-versions-test] description = "min versions tests" @@ -140,7 +129,6 @@ commands = [ "stubtest", "--mypy-config-file=pyproject.toml", "--allowlist=.mypyignore", - "--allowlist=.mypyignore-todo", "--ignore-unused-allowlist", "scipy", ], @@ -168,19 +156,7 @@ commands = [ [env.pyright] description = "Run pyright" dependency_groups = ["typecheck"] -commands = [ - [ - "uv", - "pip", - "freeze", - ], - [ - "uv", - "run", - "--no-sync", - "basedpyright", - ], -] +commands = [["uv", "pip", "freeze"], ["uv", "run", "--no-sync", "basedpyright"]] [env.typetest] description = "Run all type tests"