-
Notifications
You must be signed in to change notification settings - Fork 0
families/developing: prototype implementation #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
6593cc6
feat: add base for parametric families
Desiment f143b38
feat: add more enhanced support for multiple parametrizations
Desiment 03f2e33
test: add tests for parametric families
Desiment 14b4c95
chore: move matplotlib to docs group
Desiment 223fcb9
feat: make multiple parametrizations api consistent
Desiment File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| """ | ||
| Parametric Families module for working with statistical distribution families. | ||
|
|
||
| This package provides a comprehensive framework for defining, managing, and | ||
| working with parametric families of statistical distributions. It supports | ||
| multiple parameterizations, constraint validation, and automatic conversion | ||
| between different parameter formats. | ||
| """ | ||
|
|
||
| __author__ = "Leonid Elkin, Mikhail, Mikhailov" | ||
| __copyright__ = "Copyright (c) 2025 PySATL project" | ||
| __license__ = "SPDX-License-Identifier: MIT" | ||
|
|
||
|
|
||
| from pysatl_core.families.distribution import ParametricFamilyDistribution | ||
| from pysatl_core.families.parametric_family import ParametricFamily | ||
| from pysatl_core.families.parametrizations import ( | ||
| Parametrization, | ||
| ParametrizationConstraint, | ||
| ParametrizationSpec, | ||
| constraint, | ||
| parametrization, | ||
| ) | ||
| from pysatl_core.families.registry import ParametricFamilyRegister | ||
|
|
||
| __all__ = [ | ||
| "ParametricFamilyRegister", | ||
| "ParametrizationConstraint", | ||
| "Parametrization", | ||
| "ParametrizationSpec", | ||
| "ParametricFamily", | ||
| "ParametricFamilyDistribution", | ||
| "constraint", | ||
| "parametrization", | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,151 @@ | ||
| """ | ||
| Concrete distribution instances with specific parameter values. | ||
|
|
||
| This module provides the implementation for individual distribution instances | ||
| created from parametric families. It handles distribution characteristics | ||
| computation, sampling, and provides access to analytical methods for | ||
| specific parameter sets. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| __author__ = "Leonid Elkin, Mikhail, Mikhailov" | ||
| __copyright__ = "Copyright (c) 2025 PySATL project" | ||
| __license__ = "SPDX-License-Identifier: MIT" | ||
|
|
||
| from collections.abc import Mapping | ||
| from dataclasses import dataclass | ||
| from functools import partial | ||
| from typing import TYPE_CHECKING, Any | ||
|
|
||
| from pysatl_core.distributions import ( | ||
| AnalyticalComputation, | ||
| ComputationStrategy, | ||
| Sample, | ||
| SamplingStrategy, | ||
| ) | ||
| from pysatl_core.families.parametrizations import Parametrization | ||
| from pysatl_core.families.registry import ParametricFamilyRegister | ||
| from pysatl_core.types import ( | ||
| DistributionType, | ||
| GenericCharacteristicName, | ||
| ) | ||
|
|
||
| if TYPE_CHECKING: | ||
| from pysatl_core.families.parametric_family import ParametricFamily | ||
|
|
||
|
|
||
| @dataclass | ||
Desiment marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| class ParametricFamilyDistribution: | ||
Desiment marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| """ | ||
| A specific distribution instance from a parametric family. | ||
|
|
||
| This class represents a concrete distribution with specific parameter | ||
| values, providing methods for computation and sampling. | ||
|
|
||
| Attributes | ||
| ---------- | ||
| distr_name : str | ||
| Name of the distribution family. | ||
| distribution_type : DistributionType | ||
| Type of this distribution. | ||
| parameters : Parametrization | ||
| Parameter values for this distribution. | ||
| """ | ||
|
|
||
| distr_name: str | ||
| distribution_type: DistributionType | ||
| parameters: Parametrization | ||
|
|
||
| @property | ||
| def family(self) -> ParametricFamily: | ||
| """ | ||
| Get the parametric family this distribution belongs to. | ||
|
|
||
| Returns | ||
| ------- | ||
| ParametricFamily | ||
| The parametric family of this distribution. | ||
| """ | ||
| return ParametricFamilyRegister.get(self.distr_name) | ||
|
|
||
| @property | ||
| def analytical_computations( | ||
| self, | ||
| ) -> Mapping[GenericCharacteristicName, AnalyticalComputation[Any, Any]]: | ||
| """ | ||
| Get analytical computation functions for this distribution. | ||
|
|
||
| Returns | ||
| ------- | ||
| Mapping[GenericCharacteristicName, AnalyticalComputation] | ||
| Mapping from characteristic names to computation functions. | ||
| """ | ||
| analytical_computations = {} | ||
|
|
||
| # First form list of all characteristics, available from current parametrization | ||
| for characteristic, forms in self.family.distr_characteristics.items(): | ||
| if self.parameters.name in forms: | ||
| analytical_computations[characteristic] = AnalyticalComputation( | ||
| target=characteristic, | ||
| func=partial(forms[self.parameters.name], self.parameters), | ||
| ) | ||
| # TODO: Second, apply rule set, for, e.g. approximations | ||
|
|
||
| # Finally, fill other chacteristics | ||
| base_name = self.family.parametrizations.base_parametrization_name | ||
| base_parameters = self.family.parametrizations.get_base_parameters(self.parameters) | ||
| for characteristic, forms in self.family.distr_characteristics.items(): | ||
| if characteristic in analytical_computations: | ||
| continue | ||
| if base_name in forms: | ||
| analytical_computations[characteristic] = AnalyticalComputation( | ||
| target=characteristic, func=partial(forms[base_name], base_parameters) | ||
| ) | ||
|
|
||
| return analytical_computations | ||
|
|
||
| @property | ||
| def sampling_strategy(self) -> SamplingStrategy: | ||
| """ | ||
| Get the sampling strategy for this distribution. | ||
|
|
||
| Returns | ||
| ------- | ||
| SamplingStrategy | ||
| Strategy for sampling from this distribution. | ||
| """ | ||
| return self.family.sampling_strategy | ||
|
|
||
| @property | ||
| def computation_strategy(self) -> ComputationStrategy[Any, Any]: | ||
| """ | ||
| Get the computation strategy for this distribution. | ||
|
|
||
| Returns | ||
| ------- | ||
| ComputationStrategy | ||
| Strategy for computing characteristics of this distribution. | ||
| """ | ||
| return self.family.computation_strategy | ||
|
|
||
| def log_likelihood(self, batch: Sample) -> float: | ||
| raise NotImplementedError | ||
|
|
||
| def sample(self, n: int, **options: Any) -> Sample: | ||
| """ | ||
| Generate samples from this distribution. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| n : int | ||
| Number of samples to generate. | ||
| **options : Any | ||
| Additional options for the sampling algorithm. | ||
|
|
||
| Returns | ||
| ------- | ||
| Sample | ||
| The generated samples. | ||
| """ | ||
| return self.sampling_strategy.sample(n, distr=self, **options) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,157 @@ | ||
| """ | ||
| Parametric family definitions and management infrastructure. | ||
|
|
||
| This module contains the main class for defining parametric families of | ||
| distributions, including support for multiple parameterizations, distribution | ||
| characteristics, sampling strategies, and computation methods. It serves as | ||
| the central definition point for statistical distribution families. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| __author__ = "Leonid Elkin, Mikhail, Mikhailov" | ||
| __copyright__ = "Copyright (c) 2025 PySATL project" | ||
| __license__ = "SPDX-License-Identifier: MIT" | ||
|
|
||
| from collections.abc import Callable | ||
| from typing import Any | ||
|
|
||
| from pysatl_core.distributions import ( | ||
| ComputationStrategy, | ||
| SamplingStrategy, | ||
| ) | ||
| from pysatl_core.families.distribution import ParametricFamilyDistribution | ||
| from pysatl_core.families.parametrizations import Parametrization, ParametrizationSpec | ||
| from pysatl_core.types import ( | ||
| DistributionType, | ||
| GenericCharacteristicName, | ||
| ParametrizationName, | ||
| ) | ||
|
|
||
| type ParametrizedFunction = Callable[[Parametrization, Any], Any] | ||
|
|
||
|
|
||
| class ParametricFamily: | ||
| """ | ||
| A family of distributions with multiple parametrizations. | ||
|
|
||
| This class represents a parametric family of distributions, such as | ||
| the normal or lognormal family, which can be parameterized in different | ||
| ways (e.g., mean-variance or canonical parametrization). | ||
|
|
||
| Attributes | ||
| ---------- | ||
| name : str | ||
| Name of the distribution family. | ||
| distr_type : DistributionType | Callable[[Parametrization] | DistributionType] | ||
| Type of distributions in this family. | ||
| parametrizations : ParametrizationSpec | ||
| Specification of available parametrizations. | ||
| distr_parametrizations : | ||
|
|
||
| distr_characteristics : Dict[GenericCharacteristicName, Callable[[Any, Any], Any]] | ||
| Mapping from characteristic names to computation functions. | ||
| sampling_strategy : SamplingStrategy | ||
| Strategy for sampling from distributions in this family. | ||
| computation_strategy : ComputationStrategy | ||
| Strategy for computing distribution characteristics. | ||
| """ | ||
|
|
||
| def __init__( | ||
| self, | ||
| name: str, | ||
| distr_type: DistributionType | Callable[[Parametrization], DistributionType], | ||
| distr_parametrizations: list[ParametrizationName], | ||
| distr_characteristics: dict[ | ||
| GenericCharacteristicName, | ||
| dict[ParametrizationName, ParametrizedFunction] | ParametrizedFunction, | ||
| ], | ||
| sampling_strategy: SamplingStrategy, | ||
| computation_strategy: ComputationStrategy[Any, Any], | ||
| ): | ||
| """ | ||
| Initialize a new parametric family. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| name : str | ||
| Name of the distribution family. | ||
|
|
||
| distr_type : DistributionType | Callable[[Parametrization], DistributionType] | ||
| Type of distributions in this family or, if type is parameter-depended, function | ||
| that takes as input *base* parametrization and inferes type based on it. | ||
|
|
||
| distr_parametrizations : List[ParametrizationName] | ||
| List of parametrizations for this distribution. *First parametrization is always | ||
| base parametrization*. | ||
|
|
||
| distr_characteristics: | ||
| Mapping from characteristics names to computation functions or dictionary of those, | ||
| if for multiple parametrizations same characteristic available. | ||
|
|
||
| sampling_strategy : SamplingStrategy | ||
| Strategy for sampling from distributions in this family. | ||
|
|
||
| computation_strategy : ComputationStrategy | ||
| Strategy for computing distribution characteristics. | ||
| """ | ||
| self._name = name | ||
| self._distr_type: Callable[[Parametrization], DistributionType] = ( | ||
| (lambda params: distr_type) if isinstance(distr_type, DistributionType) else distr_type | ||
| ) | ||
|
|
||
| # Parametrizations must be built by user | ||
| self.parametrization_names = distr_parametrizations | ||
| self.parametrizations = ParametrizationSpec(self.parametrization_names[0]) | ||
|
|
||
| self.sampling_strategy = sampling_strategy | ||
| self.computation_strategy = computation_strategy | ||
|
|
||
| def _process_char_val( | ||
| value: dict[ParametrizationName, ParametrizedFunction] | ParametrizedFunction, | ||
| ) -> dict[ParametrizationName, ParametrizedFunction]: | ||
| return value if isinstance(value, dict) else {self.parametrization_names[0]: value} | ||
|
|
||
| self.distr_characteristics = { | ||
| key: _process_char_val(value) for key, value in distr_characteristics.items() | ||
| } | ||
|
|
||
| @property | ||
| def name(self) -> str: | ||
| return self._name | ||
|
|
||
| def distribution( | ||
| self, parametrization_name: str | None = None, **parameters_values: Any | ||
| ) -> ParametricFamilyDistribution: | ||
| """ | ||
| Create a distribution instance with the given parameters. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| parametrization_name : str | None, optional | ||
| Name of the parametrization to use, or None for base parametrization. | ||
| **parameters_values | ||
| Parameter values for the distribution. | ||
|
|
||
| Returns | ||
| ------- | ||
| ParametricFamilyDistribution | ||
| A distribution instance with the specified parameters. | ||
|
|
||
| Raises | ||
| ------ | ||
| ValueError | ||
| If the parameters don't satisfy the parametrization constraints. | ||
| """ | ||
| if parametrization_name is None: | ||
| parametrization_class = self.parametrizations.base | ||
| else: | ||
| parametrization_class = self.parametrizations.parametrizations[parametrization_name] | ||
|
|
||
| parameters = parametrization_class(**parameters_values) | ||
| base_parameters = self.parametrizations.get_base_parameters(parameters) | ||
| parameters.validate() | ||
| distribution_type = self._distr_type(base_parameters) | ||
| return ParametricFamilyDistribution(self.name, distribution_type, parameters) | ||
|
|
||
| __call__ = distribution |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.