Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
87bd31a
feat(generator): unify mixture generators and support canonical forms
plidan123 May 10, 2025
08756db
refactor: Rename folder algorithms to procedures
May 13, 2025
1062e1c
refactor: Rename member functions algorithm to compute
May 24, 2025
bfdf571
refactor: Fix naming of estimators
May 24, 2025
76838d6
refactor: Update register names
May 25, 2025
7e47e63
refactor: Update register names
May 25, 2025
78a7b35
refactor: Update procedures class names
May 25, 2025
9fa4aad
refactor: update tests
May 28, 2025
3c5c1b2
feat: Add general interface StatisticalProcedure
May 31, 2025
1280bdf
feat: Implement dynamic integrator selection, enabling the use of cus…
Amellgo May 12, 2025
51a7303
feat: integration parameters are now part of the constructor
Amellgo Jun 1, 2025
947f956
refactor: Rename algorithm classes and folders
Jun 5, 2025
0d635b3
fix: Fixing errors from the previous commit
Jun 7, 2025
a2789f7
feat: add batch support and refactor mixture evaluation logic
plidan123 May 25, 2025
476758e
Merge pull request #40 from PySATL/api/abstract-integrator
plidan123 Jun 25, 2025
8ec30a0
Merge pull request #38 from PySATL/feat/unify-mixture-generators
plidan123 Jun 25, 2025
d29b60e
Merge branch 'update' into feat/unify-mixture
plidan123 Jun 25, 2025
4296e34
fixed
plidan123 Jun 25, 2025
12b3205
fixed
plidan123 Jun 25, 2025
1b5138d
fixed
plidan123 Jun 25, 2025
5f7295c
fixed
plidan123 Jun 25, 2025
1cebc58
Merge pull request #46 from PySATL/feat/unify-mixture
plidan123 Jun 25, 2025
2727050
fixed
plidan123 Jun 26, 2025
8d481af
fixed
plidan123 Jun 26, 2025
b1c944c
fixed
plidan123 Jun 26, 2025
d4e7c06
fixed
plidan123 Jun 26, 2025
cb90a63
fixed
plidan123 Jun 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 0 additions & 46 deletions src/algorithms/__init__.py

This file was deleted.

2 changes: 1 addition & 1 deletion src/estimators/abstract_estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from numpy import _typing

from src.algorithms import ALGORITHM_REGISTRY
from src.procedures import ALGORITHM_REGISTRY
from src.estimators.estimate_result import EstimateResult
from src.register.algorithm_purpose import AlgorithmPurpose

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from src.estimators.estimate_result import EstimateResult


class AbstractSemiParametricEstimator(AbstractEstimator):
class AbstractSemiparEstim(AbstractEstimator):
def __init__(self, algorithm_name: str, params: dict | None = None) -> None:
super().__init__(algorithm_name, params)

Expand Down
4 changes: 2 additions & 2 deletions src/estimators/semiparametric/nm_semiparametric_estimator.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from numpy import _typing

from src.estimators.estimate_result import EstimateResult
from src.estimators.semiparametric.abstract_semiparametric_estimator import AbstractSemiParametricEstimator
from src.estimators.semiparametric.abstract_semiparametric_estimator import AbstractSemiparEstim
from src.register.algorithm_purpose import AlgorithmPurpose


class NMSemiParametricEstimator(AbstractSemiParametricEstimator):
class NMSemiparEstim(AbstractSemiparEstim):
def __init__(self, algorithm_name: str, params: dict | None = None) -> None:
super().__init__(algorithm_name, params)
self._purpose = AlgorithmPurpose.NM_SEMIPARAMETRIC
Expand Down
4 changes: 2 additions & 2 deletions src/estimators/semiparametric/nmv_semiparametric_estimator.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from numpy import _typing

from src.estimators.estimate_result import EstimateResult
from src.estimators.semiparametric.abstract_semiparametric_estimator import AbstractSemiParametricEstimator
from src.estimators.semiparametric.abstract_semiparametric_estimator import AbstractSemiparEstim
from src.register.algorithm_purpose import AlgorithmPurpose


class NMVSemiParametricEstimator(AbstractSemiParametricEstimator):
class NMVSemiparEstim(AbstractSemiparEstim):
def __init__(self, algorithm_name: str, params: dict | None = None) -> None:
super().__init__(algorithm_name, params)
self._purpose = AlgorithmPurpose.NMV_SEMIPARAMETRIC
Expand Down
4 changes: 2 additions & 2 deletions src/estimators/semiparametric/nv_semiparametric_estimator.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from numpy import _typing

from src.estimators.estimate_result import EstimateResult
from src.estimators.semiparametric.abstract_semiparametric_estimator import AbstractSemiParametricEstimator
from src.estimators.semiparametric.abstract_semiparametric_estimator import AbstractSemiparEstim
from src.register.algorithm_purpose import AlgorithmPurpose


class NVSemiParametricEstimator(AbstractSemiParametricEstimator):
class NVSemiparEstim(AbstractSemiparEstim):
def __init__(self, algorithm_name: str, params: dict | None = None) -> None:
super().__init__(algorithm_name, params)
self._purpose = AlgorithmPurpose.NV_SEMIPARAMETRIC
Expand Down
4 changes: 2 additions & 2 deletions src/mixtures/nm_mixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from scipy.stats import norm, rv_continuous
from scipy.stats.distributions import rv_frozen

from src.algorithms.support_algorithms.log_rqmc import LogRQMC
from src.algorithms.support_algorithms.rqmc import RQMC
from src.procedures.support.log_rqmc import LogRQMC
from src.procedures.support.rqmc import RQMC
from src.mixtures.abstract_mixture import AbstractMixtures


Expand Down
4 changes: 2 additions & 2 deletions src/mixtures/nmv_mixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from scipy.stats import geninvgauss, norm, rv_continuous
from scipy.stats.distributions import rv_frozen

from src.algorithms.support_algorithms.log_rqmc import LogRQMC
from src.algorithms.support_algorithms.rqmc import RQMC
from src.procedures.support.log_rqmc import LogRQMC
from src.procedures.support.rqmc import RQMC
from src.mixtures.abstract_mixture import AbstractMixtures


Expand Down
4 changes: 2 additions & 2 deletions src/mixtures/nv_mixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from scipy.stats import norm, rv_continuous
from scipy.stats.distributions import rv_frozen

from src.algorithms.support_algorithms.log_rqmc import LogRQMC
from src.algorithms.support_algorithms.rqmc import RQMC
from src.procedures.support.log_rqmc import LogRQMC
from src.procedures.support.rqmc import RQMC
from src.mixtures.abstract_mixture import AbstractMixtures


Expand Down
46 changes: 46 additions & 0 deletions src/procedures/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from src.procedures.semiparametric.nm_semi_param_algorithms.g_estimation_convolution import (
NMEstimationDensityInvMT,
)
from src.procedures.semiparametric.nm_semi_param_algorithms.sigma_estimation_eigenvalue_based import (
NMEstimationSigmaEigenvals,
)
from src.procedures.semiparametric.nm_semi_param_algorithms.sigma_estimation_empirical import (
NMEstimationSigmaLaplace,
)
from src.procedures.semiparametric.nv_semi_param_algorithms.g_estimation_given_mu import (
NVEstimationDensityInvMT,
)
from src.procedures.semiparametric.nv_semi_param_algorithms.g_estimation_post_widder import (
NMVEstimationDensityPW,
)
from src.procedures.semiparametric.nvm_semi_param_algorithms.g_estimation_given_mu import (
NMVEstimationDensityInvMTquad,
)
from src.procedures.semiparametric.nvm_semi_param_algorithms.g_estimation_given_mu_rqmc_based import (
NMVEstimationDensityInvMTquadRQMCBased,
)
from src.procedures.semiparametric.nvm_semi_param_algorithms.g_estimation_post_widder import (
SemiParametricGEstimationPostWidder,
)
from src.procedures.semiparametric.nvm_semi_param_algorithms.mu_estimation import (NMVEstimationMu)
from src.register.algorithm_purpose import AlgorithmPurpose
from src.register.register import Registry

ALGORITHM_REGISTRY: Registry = Registry()
ALGORITHM_REGISTRY.register("mu_estimation", AlgorithmPurpose.NMV_SEMIPARAMETRIC)(NMVEstimationMu)
ALGORITHM_REGISTRY.register("density_estim_inv_mellin_quad_int", AlgorithmPurpose.NMV_SEMIPARAMETRIC)(
NMVEstimationDensityInvMTquad
)
ALGORITHM_REGISTRY.register("density_estim_deconv", AlgorithmPurpose.NM_SEMIPARAMETRIC)(NMEstimationDensityInvMT)
ALGORITHM_REGISTRY.register("sigma_estimation_eigenvalue", AlgorithmPurpose.NM_SEMIPARAMETRIC)(
NMEstimationSigmaEigenvals
)
ALGORITHM_REGISTRY.register("sigma_estimation_laplace", AlgorithmPurpose.NM_SEMIPARAMETRIC)(
NMEstimationSigmaLaplace
)
ALGORITHM_REGISTRY.register("density_estim_inv_mellin_rqmc_int", AlgorithmPurpose.NMV_SEMIPARAMETRIC)(
NMVEstimationDensityInvMTquadRQMCBased
)
ALGORITHM_REGISTRY.register("density_estim_post_widder", AlgorithmPurpose.NMV_SEMIPARAMETRIC)(
SemiParametricGEstimationPostWidder
)
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
BOHMAN_DELTA_DEFAULT_VALUE: float = 0.0001
X_DATA_DEFAULT_VALUE: List[float] = [1.0]


class NMSemiParametricGEstimation:
class NMEstimationDensityInvMT:
"""Estimation of mixing density function g (xi density function) of NM mixture
represented in canonical form Y = xi + sigma*N.

Expand All @@ -34,8 +33,8 @@ class ParamsAnnotation(TypedDict, total=False):
bohman_n: int
bohman_delta: float

def __init__(self, sample: Optional[_typing.NDArray[np.float64]] = None, **kwargs: Unpack[ParamsAnnotation]):
self.sample: _typing.NDArray[np.float64] = np.array([]) if sample is None else sample
def __init__(self, sample: Optional[np.ndarray] = None, **kwargs: Unpack[ParamsAnnotation]):
self.sample: np.ndarray = np.array([]) if sample is None else sample
self.n: int = len(self.sample)
(
self.x_data,
Expand Down Expand Up @@ -93,7 +92,7 @@ def cdf(self, X: np.ndarray) -> np.ndarray:

return F_x.real

def algorithm(self, sample: _typing.NDArray[np.float64]) -> EstimateResult:
def compute(self, sample: np.ndarray) -> EstimateResult:
inv = self.BohmanA(N=self.bohman_n, delta=self.bohman_delta)
inv.fit(self.characteristic_function_xi)
x_data_array = np.array(self.x_data, dtype=np.float64)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
PARAMETER_KEYS = ["l", "k", "eps", "search_area", "search_density"]


class SemiParametricMeanSigmaEstimationEigenvalueBased:
class NMEstimationSigmaEigenvals:
"""Estimation of sigma parameter of NM mixture represented in canonical form Y = xi + sigma*N.

Args:
Expand Down Expand Up @@ -86,7 +86,7 @@ def _build_matrix(self, tau: float) -> np.ndarray:
matrix[i, j] = self._alpha(t[i] - t[j], tau)
return matrix

def algorithm(self, sample: np.ndarray) -> EstimateResult:
def compute(self, sample: np.ndarray) -> EstimateResult:
"""Estimate sigma.

Args:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
PARAMETER_KEYS = ["t"]


class SemiParametricMeanSigmaEstimationEmpirical:
class NMEstimationSigmaLaplace:
"""Estimation of sigma parameter of NM mixture represented in canonical form Y = xi + sigma*N.

Args:
Expand Down Expand Up @@ -51,7 +51,7 @@ def _validate_kwargs(**kwargs: ParamsAnnotation) -> float:
raise ValueError("Expected a positive float as parameter `t`.")
return t

def algorithm(self, sample: np.ndarray) -> EstimateResult:
def compute(self, sample: np.ndarray) -> EstimateResult:
"""Estimate the sigma parameter.

Args:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def v_sequence_default_value(n: float) -> float:
INTEGRATION_LIMIT_DEFAULT_VALUE: int = 50


class SemiParametricNVEstimation:
class NVEstimationDensityInvMT:
"""Estimation of mixing density function g (xi density function) of NV mixture represented in canonical form Y =
alpha + sqrt(xi)*N, where alpha = 0 and mu = 0.

Expand All @@ -49,13 +49,13 @@ class ParamsAnnotation(TypedDict, total=False):
integration_tolerance: float
integration_limit: int

def __init__(self, sample: Optional[_typing.NDArray[np.float64]] = None, **kwargs: Unpack[ParamsAnnotation]):
def __init__(self, sample: Optional[np.ndarray] = None, **kwargs: Unpack[ParamsAnnotation]):
self.x_powers: Dict[float, np.ndarray] = {}
self.second_u_integrals: np.ndarray
self.first_u_integrals: np.ndarray
self.gamma_grid: np.ndarray
self.v_grid: np.ndarray
self.sample: _typing.NDArray[np.float64] = np.array([]) if sample is None else sample
self.sample: np.ndarray = np.array([]) if sample is None else sample
self.n: int = len(self.sample)
(
self.gmm,
Expand Down Expand Up @@ -173,6 +173,6 @@ def compute_integrals_for_x(self, x: float) -> float:
total = np.sum(first_integral + second_integral) / self.denominator
return max(0.0, total.real)

def algorithm(self, sample: _typing.NDArray[np.float64]) -> EstimateResult:
def compute(self, sample: np.ndarray) -> EstimateResult:
y_data = [self.compute_integrals_for_x(x) for x in self.x_data]
return EstimateResult(list_value=y_data, success=True)
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
X_DATA_DEFAULT_VALUE = [1.0]


class NVSemiParametricGEstimationPostWidder:
class NMVEstimationDensityPW:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NV stands for Normal Variance, NMV -- for Normal Mean-Variance. I suggest renaming NVSemiParametricGEstimationPostWidder to NVEstimationDensityPW. I suppose you missed SemiParametricGEstimationPostWidder it should be renamed to NMVEstimationDensityPW. I know its messy. Thats why we refactor it : )

"""Estimation of mixing density function g (xi density function) of NVM mixture represented in classical form Y =
alpha + sigma*sqrt(xi)*N, where alpha = 0 and mu, sigma are given.

Expand Down Expand Up @@ -77,7 +77,7 @@ def p_x_estimation(self, x: float) -> float:
)
return result.real

def algorithm(self, sample: np._typing.NDArray) -> EstimateResult:
def compute(self, sample: np.ndarray) -> EstimateResult:
"""Estimate g(x)

Args:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def v_sequence_default_value(n: float) -> float:
INTEGRATION_LIMIT_DEFAULT_VALUE: int = 50


class SemiParametricGEstimationGivenMu:
class NMVEstimationDensityInvMTquad:
"""Estimation of mixing density function g (xi density function) of NVM mixture represented in canonical form Y =
alpha + mu*xi + sqrt(xi)*N, where alpha = 0 and mu is given.

Expand All @@ -51,13 +51,13 @@ class ParamsAnnotation(TypedDict, total=False):
integration_tolerance: float
integration_limit: int

def __init__(self, sample: Optional[_typing.NDArray[np.float64]] = None, **kwargs: Unpack[ParamsAnnotation]):
def __init__(self, sample: Optional[np.ndarray] = None, **kwargs: Unpack[ParamsAnnotation]):
self.x_powers: Dict[float, np.ndarray] = {}
self.second_u_integrals: np.ndarray
self.first_u_integrals: np.ndarray
self.gamma_grid: np.ndarray
self.v_grid: np.ndarray
self.sample: _typing.NDArray[np.float64] = np.array([]) if sample is None else sample
self.sample: np.ndarray= np.array([]) if sample is None else sample
self.n: int = len(self.sample)
(
self.mu,
Expand Down Expand Up @@ -179,6 +179,6 @@ def compute_integrals_for_x(self, x: float) -> float:
total = np.sum(first_integral + second_integral) / self.denominator
return max(0.0, total.real)

def algorithm(self, sample: _typing.NDArray[np.float64]) -> EstimateResult:
def compute(self, sample: np.ndarray) -> EstimateResult:
y_data = [self.compute_integrals_for_x(x) for x in self.x_data]
return EstimateResult(list_value=y_data, success=True)
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from scipy.integrate import quad_vec
from scipy.special import gamma

from src.algorithms.support_algorithms.rqmc import RQMC
from src.procedures.support.rqmc import RQMC
from src.estimators.estimate_result import EstimateResult

MU_DEFAULT_VALUE = 1.0
Expand All @@ -32,7 +32,7 @@ def v_sequence_default_value(n: float) -> float:
INTEGRATION_LIMIT_DEFAULT_VALUE: int = 50


class SemiParametricGEstimationGivenMuRQMCBased:
class NMVEstimationDensityInvMTquadRQMCBased:
"""Estimation of mixing density function g (xi density function) of NVM mixture represented in canonical form Y =
alpha + mu*xi + sqrt(xi)*N, where alpha = 0 and mu is given.

Expand All @@ -52,13 +52,13 @@ class ParamsAnnotation(TypedDict, total=False):
integration_tolerance: float
integration_limit: int

def __init__(self, sample: Optional[_typing.NDArray[np.float64]] = None, **kwargs: Unpack[ParamsAnnotation]):
def __init__(self, sample: Optional[np.ndarray] = None, **kwargs: Unpack[ParamsAnnotation]):
self.x_powers: Dict[float, np.ndarray] = {}
self.second_u_integrals: np.ndarray
self.first_u_integrals: np.ndarray
self.gamma_grid: np.ndarray
self.v_grid: np.ndarray
self.sample: _typing.NDArray[np.float64] = np.array([]) if sample is None else sample
self.sample: np.ndarray = np.array([]) if sample is None else sample
self.n: int = len(self.sample)
(
self.mu,
Expand Down Expand Up @@ -171,6 +171,6 @@ def compute_integrals_for_x(self, x: float) -> float:
total = (first_integral + second_integral) / self.denominator
return max(0.0, total.real)

def algorithm(self, sample: np._typing.NDArray) -> EstimateResult:
def compute(self, sample: np.ndarray) -> EstimateResult:
y_data = [self.compute_integrals_for_x(x) for x in self.x_data]
return EstimateResult(list_value=y_data, success=True)
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def p_x_estimation(self, x: float) -> float:
)
return result.real

def algorithm(self, sample: np._typing.NDArray) -> EstimateResult:
def compute(self, sample: np._typing.NDArray) -> EstimateResult:
"""Estimate g(x)

Args:
Expand Down
Loading
Loading