55This module defines and configures parametric distribution families for the PySATL library:
66
77- :class:`Normal Family` — Gaussian distribution with multiple parameterizations.
8+ - :class:`Uniform Family` — Gaussian distribution with multiple parameterizations.
89
910Notes
1011-----
@@ -69,6 +70,7 @@ def configure_families_register() -> ParametricFamilyRegister:
6970 The global registry of parametric families.
7071 """
7172 _configure_normal_family ()
73+ _configure_uniform_family ()
7274 return ParametricFamilyRegister ()
7375
7476
@@ -323,7 +325,7 @@ def skew_func(_1: Parametrization, _2: Any) -> int:
323325 return 0
324326
325327 def kurt_func (_1 : Parametrization , _2 : Any , excess : bool = False ) -> int :
326- """Raw or excess kurtosis of normal distribution (always 3) .
328+ """Raw or excess kurtosis of normal distribution.
327329
328330 Parameters
329331 ----------
@@ -344,10 +346,11 @@ def kurt_func(_1: Parametrization, _2: Any, excess: bool = False) -> int:
344346 return 0
345347
346348 def _normal_support (_ : Parametrization ) -> ContinuousSupport :
349+ """Support of normal distribution"""
347350 return ContinuousSupport ()
348351
349352 Normal = ParametricFamily (
350- name = "Normal Family " ,
353+ name = "Normal" ,
351354 distr_type = UnivariateContinuous ,
352355 distr_parametrizations = ["meanStd" , "meanPrec" , "exponential" ],
353356 distr_characteristics = {
@@ -372,6 +375,332 @@ def _normal_support(_: Parametrization) -> ContinuousSupport:
372375 ParametricFamilyRegister .register (Normal )
373376
374377
378+ @dataclass
379+ class UniformStandardParametrization (Parametrization ):
380+ """
381+ Standard parametrization of uniform distribution.
382+
383+ Parameters
384+ ----------
385+ lower_bound : float
386+ Lower bound of the distribution
387+ upper_bound : float
388+ Upper bound of the distribution
389+ """
390+
391+ lower_bound : float
392+ upper_bound : float
393+
394+ @constraint (description = "lower_bound < upper_bound" )
395+ def check_lower_less_than_upper (self ) -> bool :
396+ """Check that lower bound is less than upper bound."""
397+ return self .lower_bound < self .upper_bound
398+
399+
400+ @dataclass
401+ class UniformMeanWidthParametrization (Parametrization ):
402+ """
403+ Mean-width parametrization of uniform distribution.
404+
405+ Parameters
406+ ----------
407+ mean : float
408+ Mean (center) of the distribution
409+ width : float
410+ Width of the distribution (upper_bound - lower_bound)
411+ """
412+
413+ mean : float
414+ width : float
415+
416+ @constraint (description = "width > 0" )
417+ def check_width_positive (self ) -> bool :
418+ """Check that width is positive."""
419+ return self .width > 0
420+
421+ def transform_to_base_parametrization (self ) -> Parametrization :
422+ """
423+ Transform to Standard parametrization.
424+
425+ Returns
426+ -------
427+ Parametrization
428+ Standard parametrization instance
429+ """
430+ half_width = self .width / 2
431+ return UniformStandardParametrization (
432+ lower_bound = self .mean - half_width , upper_bound = self .mean + half_width
433+ )
434+
435+
436+ @dataclass
437+ class UniformMinRangeParametrization (Parametrization ):
438+ """
439+ Minimum-range parametrization of uniform distribution.
440+
441+ Parameters
442+ ----------
443+ minimum : float
444+ Minimum value (lower bound)
445+ range_val : float
446+ Range of the distribution (upper_bound - lower_bound)
447+ """
448+
449+ minimum : float
450+ range_val : float
451+
452+ @constraint (description = "range_val > 0" )
453+ def check_range_positive (self ) -> bool :
454+ """Check that range is positive."""
455+ return self .range_val > 0
456+
457+ def transform_to_base_parametrization (self ) -> Parametrization :
458+ """
459+ Transform to Standard parametrization.
460+
461+ Returns
462+ -------
463+ Parametrization
464+ Standard parametrization instance
465+ """
466+ return UniformStandardParametrization (
467+ lower_bound = self .minimum , upper_bound = self .minimum + self .range_val
468+ )
469+
470+
471+ def _configure_uniform_family () -> None :
472+ UNIFORM_DOC = """
473+ Uniform (continuous) distribution.
474+
475+ The uniform distribution is a continuous probability distribution where
476+ all intervals of the same length are equally probable. It is defined by
477+ two parameters: lower bound and upper bound.
478+
479+ Probability density function:
480+ f(x) = 1/(upper_bound - lower_bound) for x in [lower_bound, upper_bound], 0 otherwise
481+
482+ The uniform distribution is often used when there is no prior knowledge
483+ about the possible values of a variable, representing maximum uncertainty.
484+ """
485+
486+ def uniform_pdf (
487+ parameters : Parametrization , x : npt .NDArray [np .float64 ]
488+ ) -> npt .NDArray [np .float64 ]:
489+ """
490+ Probability density function for uniform distribution.
491+ Uses np.clip for vectorized computation:
492+ - For x < lower_bound: returns 0
493+ - For x > upper_bound: returns 1
494+ - Otherwise: returns (x - lower_bound) / (upper_bound - lower_bound)
495+
496+ Parameters
497+ ----------
498+ parameters : Parametrization
499+ Distribution parameters object with fields:
500+ - lower_bound: float (lower bound)
501+ - upper_bound: float (upper bound)
502+ x : npt.NDArray[np.float64]
503+ Points at which to evaluate the probability density function
504+
505+ Returns
506+ -------
507+ npt.NDArray[np.float64]
508+ Probability density values at points x
509+ """
510+ parameters = cast (UniformStandardParametrization , parameters )
511+
512+ lower_bound = parameters .lower_bound
513+ upper_bound = parameters .upper_bound
514+
515+ return np .where (
516+ (x >= lower_bound ) & (x <= upper_bound ), 1.0 / (upper_bound - lower_bound ), 0.0
517+ )
518+
519+ def uniform_cdf (
520+ parameters : Parametrization , x : npt .NDArray [np .float64 ]
521+ ) -> npt .NDArray [np .float64 ]:
522+ """
523+ Cumulative distribution function for uniform distribution.
524+ Uses np.clip for vectorized computation:
525+ - For x < lower_bound: returns 0
526+ - For x > upper_bound: returns 1
527+
528+ Parameters
529+ ----------
530+ parameters : Parametrization
531+ Distribution parameters object with fields:
532+ - lower_bound: float (lower bound)
533+ - upper_bound: float (upper bound)
534+ x : npt.NDArray[np.float64]
535+ Points at which to evaluate the cumulative distribution function
536+
537+ Returns
538+ -------
539+ npt.NDArray[np.float64]
540+ Probabilities P(X ≤ x) for each point x
541+ """
542+ parameters = cast (UniformStandardParametrization , parameters )
543+
544+ lower_bound = parameters .lower_bound
545+ upper_bound = parameters .upper_bound
546+
547+ return np .clip ((x - lower_bound ) / (upper_bound - lower_bound ), 0.0 , 1.0 )
548+
549+ def uniform_ppf (
550+ parameters : Parametrization , p : npt .NDArray [np .float64 ]
551+ ) -> npt .NDArray [np .float64 ]:
552+ """
553+ Percent point function (inverse CDF) for uniform distribution.
554+
555+ For uniform distribution on [lower_bound, upper_bound]:
556+ - For p = 0: returns lower_bound
557+ - For p = 1: returns upper_bound
558+ - For p in (0, 1): returns lower_bound + p × (upper_bound - lower_bound)
559+
560+ Parameters
561+ ----------
562+ parameters : Parametrization
563+ Distribution parameters object with fields:
564+ - lower_bound: float (lower bound)
565+ - upper_bound: float (upper bound)
566+ p : npt.NDArray[np.float64]
567+ Probability from [0, 1]
568+
569+ Returns
570+ -------
571+ npt.NDArray[np.float64]
572+ Quantiles corresponding to probabilities p
573+
574+ Raises
575+ ------
576+ ValueError
577+ If probability is outside [0, 1]
578+ """
579+ if np .any ((p < 0 ) | (p > 1 )):
580+ raise ValueError ("Probability must be in [0, 1]" )
581+
582+ parameters = cast (UniformStandardParametrization , parameters )
583+ lower_bound = parameters .lower_bound
584+ upper_bound = parameters .upper_bound
585+
586+ return cast (npt .NDArray [np .float64 ], lower_bound + p * (upper_bound - lower_bound ))
587+
588+ def uniform_char_func (
589+ parameters : Parametrization , t : npt .NDArray [np .float64 ]
590+ ) -> npt .NDArray [np .complex128 ]:
591+ """
592+ Characteristic function of uniform distribution.
593+
594+ Characteristic function formula for uniform distribution on [lower_bound, upper bound]:
595+ φ(t) = sinc((upper bound - lower_bound) * t / 2) *
596+ * exp(i * (lower_bound + upper bound) * t / 2)
597+ where sinc(x) = sin(πx)/(πx) as defined by numpy.
598+
599+ Parameters
600+ ----------
601+ parameters : Parametrization
602+ Distribution parameters object with fields:
603+ - lower_bound: float (lower bound)
604+ - upper_bound: float (upper bound)
605+ t : npt.NDArray[np.float64]
606+ Points at which to evaluate the characteristic function
607+
608+ Returns
609+ -------
610+ npt.NDArray[np.complex128]
611+ Characteristic function values at points t
612+ """
613+ parameters = cast (UniformStandardParametrization , parameters )
614+
615+ lower_bound = parameters .lower_bound
616+ upper_bound = parameters .upper_bound
617+
618+ width = upper_bound - lower_bound
619+ center = (lower_bound + upper_bound ) / 2
620+
621+ t_arr = np .asarray (t , dtype = np .float64 )
622+
623+ x = width * t_arr / (2 * np .pi )
624+ sinc_val = np .sinc (x )
625+
626+ return cast (npt .NDArray [np .complex128 ], sinc_val * np .exp (1j * center * t_arr ))
627+
628+ def mean_func (parameters : Parametrization , _ : Any ) -> float :
629+ """Mean of uniform distribution."""
630+ parameters = cast (UniformStandardParametrization , parameters )
631+ return (parameters .lower_bound + parameters .upper_bound ) / 2
632+
633+ def var_func (parameters : Parametrization , _ : Any ) -> float :
634+ """Variance of uniform distribution."""
635+ parameters = cast (UniformStandardParametrization , parameters )
636+ width = parameters .upper_bound - parameters .lower_bound
637+ return width ** 2 / 12
638+
639+ def skew_func (_1 : Parametrization , _2 : Any ) -> int :
640+ """Skewness of uniform distribution (always 0)."""
641+ return 0
642+
643+ def kurt_func (_1 : Parametrization , _2 : Any , excess : bool = False ) -> float :
644+ """Raw or excess kurtosis of uniform distribution.
645+
646+ Parameters
647+ ----------
648+ _1 : Parametrization
649+ Needed by architecture parameter
650+ _2 : Any
651+ Needed by architecture parameter
652+ excess : bool
653+ A value defines if there will be raw or excess kurtosis
654+ default is False
655+
656+ Returns
657+ -------
658+ float
659+ Kurtosis value
660+ """
661+ if not excess :
662+ return 1.8
663+ else :
664+ return - 1.2
665+
666+ def _uniform_support (parameters : Parametrization ) -> ContinuousSupport :
667+ """Support of uniform distribution"""
668+ parameters = cast (
669+ UniformStandardParametrization , parameters .transform_to_base_parametrization ()
670+ )
671+ return ContinuousSupport (
672+ left = parameters .lower_bound ,
673+ right = parameters .upper_bound ,
674+ left_closed = True ,
675+ right_closed = True ,
676+ )
677+
678+ Uniform = ParametricFamily (
679+ name = "ContinuousUniform" ,
680+ distr_type = UnivariateContinuous ,
681+ distr_parametrizations = ["standard" , "meanWidth" , "minRange" ],
682+ distr_characteristics = {
683+ PDF : uniform_pdf ,
684+ CDF : uniform_cdf ,
685+ PPF : uniform_ppf ,
686+ CF : uniform_char_func ,
687+ MEAN : mean_func ,
688+ VAR : var_func ,
689+ SKEW : skew_func ,
690+ KURT : kurt_func ,
691+ },
692+ sampling_strategy = DefaultSamplingUnivariateStrategy (),
693+ support_by_parametrization = _uniform_support ,
694+ )
695+ Uniform .__doc__ = UNIFORM_DOC
696+
697+ parametrization (family = Uniform , name = "standard" )(UniformStandardParametrization )
698+ parametrization (family = Uniform , name = "meanWidth" )(UniformMeanWidthParametrization )
699+ parametrization (family = Uniform , name = "minRange" )(UniformMinRangeParametrization )
700+
701+ ParametricFamilyRegister .register (Uniform )
702+
703+
375704def reset_families_register () -> None :
376705 configure_families_register .cache_clear ()
377706 ParametricFamilyRegister ._reset ()
0 commit comments