22from typing import Any
33
44import numpy as np
5- from scipy .integrate import quad
65from scipy .special import binom
76from scipy .stats import norm , rv_continuous
87from scipy .stats .distributions import rv_frozen
98
109from src .algorithms .support_algorithms .log_rqmc import LogRQMC
11- from src .algorithms .support_algorithms .rqmc import RQMC
10+ from src .algorithms .support_algorithms .integrator import Integrator
11+ from src .algorithms .support_algorithms .rqmc import RQMCIntegrator
12+ from src .algorithms .support_algorithms .quad_integrator import QuadIntegrator
1213from src .mixtures .abstract_mixture import AbstractMixtures
1314
1415
@@ -59,156 +60,175 @@ def _params_validation(self, data_collector: Any, params: dict[str, float | rv_c
5960 raise ValueError ("Gamma cant be zero" )
6061 return data_class
6162
62- def _classical_moment (self , n : int , params : dict ) -> tuple [float , float ]:
63+ def _classical_moment (self , n : int , params : dict , integrator : Integrator = None ) -> tuple [float , float ]:
6364 """
6465 Compute n-th moment of classical NMM
6566
6667 Args:
6768 n (): Moment ordinal
6869 params (): Parameters of integration algorithm
70+ integrator (): type of integrator to computing
6971
7072 Returns: moment approximation and error tolerance
7173
7274 """
7375 mixture_moment = 0
7476 error_tolerance = 0
77+ integrator = integrator or QuadIntegrator ()
7578 for k in range (0 , n + 1 ):
7679 for l in range (0 , k + 1 ):
77- coefficient = binom (n , n - k ) * binom (k , k - l ) * (self .params .beta ** (k - l )) * (self .params .gamma ** l )
78- mixing_moment = quad (lambda u : self .params .distribution .ppf (u ) ** (k - l ), 0 , 1 , ** params )
79- error_tolerance += (self .params .beta ** (k - l )) * mixing_moment [1 ]
80- mixture_moment += coefficient * (self .params .alpha ** (n - k )) * mixing_moment [0 ] * norm .moment (l )
81- return mixture_moment , error_tolerance
80+ coefficient = binom (n , n - k ) * binom (k , k - l ) * (self .params .beta ** (k - l )) * (
81+ self .params .gamma ** l )
82+ mixing_moment = integrator .compute_integral (lambda u : self .params .distribution .ppf (u ) ** (k - l ),
83+ {"a" : 0 , "b" : 1 , ** params })
84+ error_tolerance += (self .params .beta ** (k - l )) * mixing_moment .error
85+ mixture_moment += coefficient * (self .params .alpha ** (n - k )) * mixing_moment .value * norm .moment (l )
86+ return mixture_moment , error_tolerance
87+
8288
83- def _canonical_moment (self , n : int , params : dict ) -> tuple [float , float ]:
89+ def _canonical_moment (self , n : int , params : dict , integrator : Integrator = None ) -> tuple [float , float ]:
8490 """
8591 Compute n-th moment of canonical NMM
8692
8793 Args:
8894 n (): Moment ordinal
8995 params (): Parameters of integration algorithm
96+ integrator (): type of integrator to computing
9097
9198 Returns: moment approximation and error tolerance
9299
93100 """
94101 mixture_moment = 0
95102 error_tolerance = 0
103+ integrator = integrator or QuadIntegrator ()
96104 for k in range (0 , n + 1 ):
97- coefficient = binom (n , n - k ) * (self .params .sigma ** k )
98- mixing_moment = quad (lambda u : self .params .distribution .ppf (u ) ** (n - k ), 0 , 1 , ** params )
99- error_tolerance += mixing_moment [1 ]
100- mixture_moment += coefficient * mixing_moment [0 ] * norm .moment (k )
105+ coefficient = binom (n , n - k ) * (self .params .sigma ** k )
106+ mixing_moment = integrator .compute_integral (lambda u : self .params .distribution .ppf (u ) ** (n - k ),
107+ {"a" : 0 , "b" : 1 , ** params })
108+ error_tolerance += mixing_moment .error
109+ mixture_moment += coefficient * mixing_moment .value * norm .moment (k )
101110 return mixture_moment , error_tolerance
102111
103- def compute_moment (self , n : int , params : dict ) -> tuple [float , float ]:
112+ def compute_moment (self , n : int , params : dict , integrator : Integrator = None ) -> tuple [float , float ]:
104113 """
105114 Compute n-th moment of NMM
106115
107116 Args:
108117 n (): Moment ordinal
109118 params (): Parameters of integration algorithm
119+ integrator (): type of integrator to computing
110120
111121 Returns: moment approximation and error tolerance
112122
113123 """
114124 if isinstance (self .params , _NMMClassicDataCollector ):
115- return self ._classical_moment (n , params )
116- return self ._canonical_moment (n , params )
125+ return self ._classical_moment (n , params , integrator )
126+ return self ._canonical_moment (n , params , integrator )
117127
118- def _canonical_compute_cdf (self , x : float , params : dict ) -> tuple [float , float ]:
128+ def _canonical_compute_cdf (self , x : float , params : dict , integrator : Integrator = None ) -> tuple [float , float ]:
119129 """
120130 Equation for canonical cdf
121131 Args:
122132 x (): point
123133 params (): parameters of RQMC algorithm
134+ integrator (): type of integrator to computing
124135
125136 Returns: computed cdf and error tolerance
126137
127138 """
128- rqmc = RQMC (lambda u : norm .cdf ((x - self .params .distribution .ppf (u )) / np .abs (self .params .sigma )), ** params )
129- return rqmc ()
139+ integrator = integrator or RQMCIntegrator ()
140+ rqmc = integrator .compute_integral (func = lambda u : norm .cdf ((x - self .params .distribution .ppf (u )) / np .abs (self .params .sigma )), ** params )
141+ return rqmc .value , rqmc .error
130142
131- def _classical_compute_cdf (self , x : float , params : dict ) -> tuple [float , float ]:
143+ def _classical_compute_cdf (self , x : float , params : dict , integrator : Integrator = None ) -> tuple [float , float ]:
132144 """
133145 Equation for classic cdf
134146 Args:
135147 x (): point
136148 params (): parameters of RQMC algorithm
149+ integrator (): type of integrator to computing
137150
138151 Returns: computed cdf and error tolerance
139152
140153 """
141- rqmc = RQMC (
154+ integrator = integrator or RQMCIntegrator ()
155+ rqmc = integrator .compute_integral (func =
142156 lambda u : norm .cdf (
143157 (x - self .params .alpha - self .params .beta * self .params .distribution .ppf (u )) / np .abs (self .params .gamma )
144158 ),
145159 ** params
146160 )
147- return rqmc ()
161+ return rqmc . value , rqmc . error
148162
149- def compute_cdf (self , x : float , params : dict ) -> tuple [float , float ]:
163+ def compute_cdf (self , x : float , params : dict , integrator : Integrator = None ) -> tuple [float , float ]:
150164 """
151165 Choose equation for cdf estimation depends on Mixture form
152166 Args:
153167 x (): point
154168 params (): parameters of RQMC algorithm
169+ integrator (): type of integrator to computing
155170
156171 Returns: Computed pdf and error tolerance
157172
158173 """
159174 if isinstance (self .params , _NMMCanonicalDataCollector ):
160- return self ._canonical_compute_cdf (x , params )
161- return self ._classical_compute_cdf (x , params )
175+ return self ._canonical_compute_cdf (x , params , integrator )
176+ return self ._classical_compute_cdf (x , params , integrator )
162177
163- def _canonical_compute_pdf (self , x : float , params : dict ) -> tuple [float , float ]:
178+ def _canonical_compute_pdf (self , x : float , params : dict , integrator : Integrator = None ) -> tuple [float , float ]:
164179 """
165180 Equation for canonical pdf
166181 Args:
167182 x (): point
168183 params (): parameters of RQMC algorithm
184+ integrator (): type of integrator to computing
169185
170186 Returns: computed pdf and error tolerance
171187
172188 """
173- rqmc = RQMC (
189+ integrator = integrator or RQMCIntegrator ()
190+ rqmc = integrator .compute_integral (func =
174191 lambda u : (1 / np .abs (self .params .sigma ))
175192 * norm .pdf ((x - self .params .distribution .ppf (u )) / np .abs (self .params .sigma )),
176193 ** params
177194 )
178- return rqmc ()
195+ return rqmc . value , rqmc . error
179196
180- def _classical_compute_pdf (self , x : float , params : dict ) -> tuple [float , float ]:
197+ def _classical_compute_pdf (self , x : float , params : dict , integrator : Integrator = None ) -> tuple [float , float ]:
181198 """
182199 Equation for classic pdf
183200 Args:
184201 x (): point
185202 params (): parameters of RQMC algorithm
203+ integrator (): type of integrator to computing
186204
187205 Returns: computed pdf and error tolerance
188206
189207 """
190- rqmc = RQMC (
208+ integrator = integrator or RQMCIntegrator ()
209+ rqmc = integrator .compute_integral (func =
191210 lambda u : (1 / np .abs (self .params .gamma ))
192211 * norm .pdf (
193212 (x - self .params .alpha - self .params .beta * self .params .distribution .ppf (u )) / np .abs (self .params .gamma )
194213 ),
195214 ** params
196215 )
197- return rqmc ()
216+ return rqmc . value , rqmc . error
198217
199- def compute_pdf (self , x : float , params : dict ) -> tuple [float , float ]:
218+ def compute_pdf (self , x : float , params : dict , integrator : Integrator = None ) -> tuple [float , float ]:
200219 """
201220 Choose equation for pdf estimation depends on Mixture form
202221 Args:
203222 x (): point
204223 params (): parameters of RQMC algorithm
224+ integrator (): type of integrator to computing
205225
206226 Returns: Computed pdf and error tolerance
207227
208228 """
209229 if isinstance (self .params , _NMMCanonicalDataCollector ):
210- return self ._canonical_compute_pdf (x , params )
211- return self ._classical_compute_pdf (x , params )
230+ return self ._canonical_compute_pdf (x , params , integrator )
231+ return self ._classical_compute_pdf (x , params , integrator )
212232
213233 def _classical_compute_log_pdf (self , x : float , params : dict ) -> tuple [float , float ]:
214234 """
@@ -258,4 +278,4 @@ def compute_logpdf(self, x: float, params: dict) -> tuple[float, float]:
258278 """
259279 if isinstance (self .params , _NMMCanonicalDataCollector ):
260280 return self ._canonical_compute_log_pdf (x , params )
261- return self ._classical_compute_log_pdf (x , params )
281+ return self ._classical_compute_log_pdf (x , params )
0 commit comments