Source code for pysatl_core.families.distribution

"""
Concrete distribution instances with specific parameter values.

This module provides the implementation for individual distribution instances
created from parametric families.
"""

from __future__ import annotations

__author__ = "Leonid Elkin, Mikhail Mikhailov"
__copyright__ = "Copyright (c) 2025 PySATL project"
__license__ = "SPDX-License-Identifier: MIT"


from dataclasses import dataclass
from typing import TYPE_CHECKING, cast

from pysatl_core.distributions.distribution import Distribution
from pysatl_core.families.registry import ParametricFamilyRegister
from pysatl_core.types import NumericArray

if TYPE_CHECKING:
    from collections.abc import Mapping
    from typing import Any

    from pysatl_core.distributions.computation import AnalyticalComputation
    from pysatl_core.distributions.strategies import (
        ComputationStrategy,
        SamplingStrategy,
    )
    from pysatl_core.distributions.support import Support
    from pysatl_core.families.parametric_family import ParametricFamily
    from pysatl_core.families.parametrizations import (
        Parametrization,
        ParametrizationConstraint,
    )
    from pysatl_core.types import (
        DistributionType,
        GenericCharacteristicName,
        ParametrizationName,
    )


[docs] @dataclass(slots=True) class ParametricFamilyDistribution(Distribution): """ A specific distribution instance from a parametric family. Represents a concrete distribution with specific parameter values, providing methods for computation and sampling. Parameters ---------- family_name : str Name of the distribution family. _distribution_type : DistributionType Type of this distribution. _parametrization : Parametrization Parameter values for this distribution. _support : Support or None Support of this distribution. """ family_name: str _distribution_type: DistributionType _parametrization: Parametrization _support: Support | None @property def distribution_type(self) -> DistributionType: """Get the distribution type.""" return self._distribution_type @property def parametrization(self) -> Parametrization: """ Get the parametrization object containing distribution parameters. Returns ------- Parametrization Parametrization instance with all parameter values. """ return self._parametrization @property def parameters(self) -> dict[str, Any]: """ Get distribution parameters as a dictionary (shortcut). Returns ------- dict[str, Any] Dictionary mapping parameter names to their values. """ return self._parametrization.parameters @property def parametrization_name(self) -> ParametrizationName: """ Get the name of the parametrization used by this distribution. Returns ------- ParametrizationName Name of the parameterization format (e.g., 'meanStd'). """ return self._parametrization.name @property def parameters_constraints(self) -> list[ParametrizationConstraint]: """ Get constraints that apply to the distribution's parameters. Returns ------- list[ParametrizationConstraint] List of parameter constraints for validation. """ return self._parametrization.constraints @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.family_name) @property def analytical_computations( self, ) -> Mapping[GenericCharacteristicName, AnalyticalComputation[Any, Any]]: """ Get analytical computations for this distribution. Lazily computed and cached per instance. Cache invalidates when parametrization object or name changes. """ key = (id(self.parametrization), self.parametrization_name) cache_key = getattr(self, "_analytical_cache_key", None) cache_val = getattr(self, "_analytical_cache_val", None) if cache_key != key or cache_val is None: cache_val = self.family._build_analytical_computations(self.parametrization) self._analytical_cache_key = key self._analytical_cache_val = cache_val return cache_val @property def sampling_strategy(self) -> SamplingStrategy: """Get the sampling strategy for this distribution.""" return self.family.sampling_strategy @property def computation_strategy(self) -> ComputationStrategy[Any, Any]: """Get the computation strategy for this distribution.""" return self.family.computation_strategy @property def support(self) -> Support | None: """Get the support of this distribution.""" return self._support
[docs] def sample(self, n: int, **options: Any) -> NumericArray: """ Generate random samples from the distribution. Parameters ---------- n : int Number of samples to generate. **options : Any Additional sampling options forwarded to the underlying sampling strategy. Returns ------- NumericArray NumPy array containing ``n`` generated samples. The exact array shape depends on the distribution and the sampling strategy. """ return cast(NumericArray, self.sampling_strategy.sample(n, distr=self, **options))