Skip to content

Commit 17a2ecb

Browse files
author
Леонид Елкин
committed
refactor: strategies now is one per distribution
1 parent 5417c30 commit 17a2ecb

4 files changed

Lines changed: 193 additions & 69 deletions

File tree

src/pysatl_core/families/distribution.py

Lines changed: 135 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111
__copyright__ = "Copyright (c) 2025 PySATL project"
1212
__license__ = "SPDX-License-Identifier: MIT"
1313

14-
15-
from dataclasses import dataclass
1614
from typing import TYPE_CHECKING, cast
1715

1816
from pysatl_core.distributions.distribution import Distribution
17+
from pysatl_core.distributions.strategies import (
18+
DefaultComputationStrategy,
19+
DefaultSamplingUnivariateStrategy,
20+
)
1921
from pysatl_core.families.registry import ParametricFamilyRegister
2022
from pysatl_core.types import NumericArray
2123

@@ -40,8 +42,9 @@
4042
ParametrizationName,
4143
)
4244

45+
_KEEP: object = object()
46+
4347

44-
@dataclass(slots=True)
4548
class ParametricFamilyDistribution(Distribution):
4649
"""
4750
A specific distribution instance from a parametric family.
@@ -53,18 +56,43 @@ class ParametricFamilyDistribution(Distribution):
5356
----------
5457
family_name : str
5558
Name of the distribution family.
56-
_distribution_type : DistributionType
59+
distribution_type : DistributionType
5760
Type of this distribution.
58-
_parametrization : Parametrization
61+
parametrization : Parametrization
5962
Parameter values for this distribution.
60-
_support : Support or None
63+
support : Support or None
6164
Support of this distribution.
65+
sampling_strategy : SamplingStrategy
66+
Strategy for generating random samples.
67+
computation_strategy : ComputationStrategy
68+
Strategy for computing characteristics and conversions.
6269
"""
6370

64-
family_name: str
65-
_distribution_type: DistributionType
66-
_parametrization: Parametrization
67-
_support: Support | None
71+
def __init__(
72+
self,
73+
family_name: str,
74+
distribution_type: DistributionType,
75+
parametrization: Parametrization,
76+
support: Support | None,
77+
sampling_strategy: SamplingStrategy | None = None,
78+
computation_strategy: ComputationStrategy[Any, Any] | None = None,
79+
):
80+
self._distribution_type = distribution_type
81+
self._family_name = family_name
82+
self._parametrization = parametrization
83+
self._support = support
84+
85+
self._computation_strategy = computation_strategy or DefaultComputationStrategy()
86+
self._sampling_strategy = sampling_strategy or DefaultSamplingUnivariateStrategy()
87+
88+
self._analytical_cache_key: tuple[int, GenericCharacteristicName] | None = None
89+
self._analytical_cache_val: (
90+
Mapping[GenericCharacteristicName, AnalyticalComputation[Any, Any]] | None
91+
) = None
92+
93+
@property
94+
def family_name(self) -> str:
95+
return self._family_name
6896

6997
@property
7098
def distribution_type(self) -> DistributionType:
@@ -142,25 +170,114 @@ def analytical_computations(
142170
parametrization object or name changes.
143171
"""
144172
key = (id(self.parametrization), self.parametrization_name)
145-
cache_key = getattr(self, "_analytical_cache_key", None)
146-
cache_val = getattr(self, "_analytical_cache_val", None)
147173

148-
if cache_key != key or cache_val is None:
149-
cache_val = self.family._build_analytical_computations(self.parametrization)
174+
if self._analytical_cache_key != key or self._analytical_cache_val is None:
175+
self._analytical_cache_val = self.family.build_analytical_computations(
176+
self.parametrization
177+
)
150178
self._analytical_cache_key = key
151-
self._analytical_cache_val = cache_val
152179

153-
return cache_val
180+
return self._analytical_cache_val
154181

155182
@property
156183
def sampling_strategy(self) -> SamplingStrategy:
157184
"""Get the sampling strategy for this distribution."""
158-
return self.family.sampling_strategy
185+
return self._sampling_strategy
159186

160187
@property
161188
def computation_strategy(self) -> ComputationStrategy[Any, Any]:
162189
"""Get the computation strategy for this distribution."""
163-
return self.family.computation_strategy
190+
return self._computation_strategy
191+
192+
def with_sampling_strategy(
193+
self, sampling_strategy: SamplingStrategy | None
194+
) -> ParametricFamilyDistribution:
195+
"""
196+
Return a copy of this distribution with an updated sampling strategy.
197+
198+
Parameters
199+
----------
200+
sampling_strategy : SamplingStrategy | None
201+
New sampling strategy. If ``None``, the default sampling strategy is used.
202+
203+
Returns
204+
-------
205+
ParametricFamilyDistribution
206+
New distribution instance with the same parameters and updated strategy.
207+
"""
208+
return ParametricFamilyDistribution(
209+
family_name=self._family_name,
210+
distribution_type=self._distribution_type,
211+
parametrization=self._parametrization,
212+
support=self._support,
213+
sampling_strategy=sampling_strategy,
214+
computation_strategy=self._computation_strategy,
215+
)
216+
217+
def with_computation_strategy(
218+
self, computation_strategy: ComputationStrategy[Any, Any] | None
219+
) -> ParametricFamilyDistribution:
220+
"""
221+
Return a copy of this distribution with an updated computation strategy.
222+
223+
Parameters
224+
----------
225+
computation_strategy : ComputationStrategy[Any, Any] | None
226+
New computation strategy. If ``None``, the default computation strategy is used.
227+
228+
Returns
229+
-------
230+
ParametricFamilyDistribution
231+
New distribution instance with the same parameters and updated strategy.
232+
"""
233+
return ParametricFamilyDistribution(
234+
family_name=self._family_name,
235+
distribution_type=self._distribution_type,
236+
parametrization=self._parametrization,
237+
support=self._support,
238+
sampling_strategy=self._sampling_strategy,
239+
computation_strategy=computation_strategy,
240+
)
241+
242+
def with_strategies(
243+
self,
244+
*,
245+
sampling_strategy: SamplingStrategy | None = None,
246+
computation_strategy: ComputationStrategy[Any, Any] | None = None,
247+
) -> ParametricFamilyDistribution:
248+
"""
249+
Return a copy of this distribution with updated strategies.
250+
251+
Parameters
252+
----------
253+
sampling_strategy : SamplingStrategy | None | object, optional
254+
New sampling strategy. If not provided, the current strategy is preserved.
255+
If explicitly set to ``None``, the default sampling strategy is used.
256+
computation_strategy : ComputationStrategy[Any, Any] | None | object, optional
257+
New computation strategy. If not provided, the current strategy is preserved.
258+
If explicitly set to ``None``, the default computation strategy is used.
259+
260+
Returns
261+
-------
262+
ParametricFamilyDistribution
263+
New distribution instance with the same parameters and updated strategies.
264+
"""
265+
new_sampling = (
266+
self._sampling_strategy if sampling_strategy is _KEEP else cast(Any, sampling_strategy)
267+
)
268+
new_computation = (
269+
self._computation_strategy
270+
if computation_strategy is _KEEP
271+
else cast(Any, computation_strategy)
272+
)
273+
return ParametricFamilyDistribution(
274+
family_name=self._family_name,
275+
distribution_type=self._distribution_type,
276+
parametrization=self._parametrization,
277+
support=self._support,
278+
sampling_strategy=new_sampling,
279+
computation_strategy=new_computation,
280+
)
164281

165282
@property
166283
def support(self) -> Support | None:

0 commit comments

Comments
 (0)