1111__copyright__ = "Copyright (c) 2025 PySATL project"
1212__license__ = "SPDX-License-Identifier: MIT"
1313
14-
15- from dataclasses import dataclass
1614from typing import TYPE_CHECKING , cast
1715
1816from pysatl_core .distributions .distribution import Distribution
17+ from pysatl_core .distributions .strategies import (
18+ DefaultComputationStrategy ,
19+ DefaultSamplingUnivariateStrategy ,
20+ )
1921from pysatl_core .families .registry import ParametricFamilyRegister
2022from pysatl_core .types import NumericArray
2123
4042 ParametrizationName ,
4143 )
4244
45+ _KEEP : object = object ()
46+
4347
44- @dataclass (slots = True )
4548class 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