Desidero integrare una funzione di densità di probabilità da (-\infty, a]
perché il cdf non è disponibile in forma chiusa. Ma non sono sicuro di come farlo in C++.Routine di quadratura per densità di probabilità
Questo compito è piuttosto semplice in Mathematica; Tutto quello che devi fare è definire la funzione,
f[x_, lambda_, alpha_, beta_, mu_] :=
Module[{gamma},
gamma = Sqrt[alpha^2 - beta^2];
(gamma^(2*lambda)/((2*alpha)^(lambda - 1/2)*Sqrt[Pi]*Gamma[lambda]))*
Abs[x - mu]^(lambda - 1/2)*
BesselK[lambda - 1/2, alpha Abs[x - mu]] E^(beta (x - mu))
];
e quindi chiamare il NIntegrate
Routine di integrare numericamente esso.
F[x_, lambda_, alpha_, beta_, mu_] :=
NIntegrate[f[t, lambda, alpha, beta, mu], {t, -\[Infinity], x}]
Ora voglio ottenere la stessa cosa in C++. Io uso la routine gsl_integration_qagil
dalla libreria numerica di gsl. È progettato per integrare le funzioni sugli intervalli semi infiniti (-\infty, a]
che è proprio quello che voglio. Ma sfortunatamente non riesco a farlo funzionare.
Questa è la funzione di densità in C++,
density(double x)
{
using namespace boost::math;
if(x == _mu)
return std::numeric_limits<double>::infinity();
return pow(_gamma, 2*_lambda)/(pow(2*_alpha, _lambda-0.5)*sqrt(_pi)*tgamma(_lambda))* pow(abs(x-_mu), _lambda - 0.5) * cyl_bessel_k(_lambda-0.5, _alpha*abs(x - _mu)) * exp(_beta*(x - _mu));
}
Poi cerco di integrare per ottenere il CDF chiamando la routine di GSL.
cdf(double x)
{
gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000);
double result, error;
gsl_function F;
F.function = &density;
double epsabs = 0;
double epsrel = 1e-12;
gsl_integration_qagil (&F, x, epsabs, epsrel, 1000, w, &result, &error);
printf("result = % .18f\n", result);
printf ("estimated error = % .18f\n", error);
printf ("intervals = %d\n", w->size);
gsl_integration_workspace_free (w);
return result;
}
Tuttavia gsl_integration_qagil
restituisce un errore, number of iterations was insufficient
.
double mu = 0.0f;
double lambda = 3.0f;
double alpha = 265.0f;
double beta = -5.0f;
cout << cdf(0.01) << endl;
Se si aumenta la dimensione dell'area di lavoro, la funzione di bessel non verrà valutata.
Mi chiedevo se c'era qualcuno che potesse darmi qualche idea del mio problema. Una chiamata alla corrispondente funzione Mathematica F sopra con x = 0.01
restituisce 0.904384
.
Potrebbe essere che la densità si concentra su un intervallo molto piccolo (ad esempio all'esterno di [-0.05, 0.05]
la densità è quasi 0
, un grafico è riportato di seguito). In tal caso, cosa si può fare al riguardo. Grazie per aver letto.
Questa funzione ha un aspetto simmetrico, ovvero 'cdf (0) = 1/2'.Ricorda che il cdf valutato in x è lo stesso dell'integrale da 0 a x più il cdf valutato a 0. Naturalmente, sto andando dalla forma del grafico, potrebbe non essere esattamente esattamente simmetrico. –
Ciao @ Ben, vorrei che fosse così! – mark