Quiero integrar una función de densidad de probabilidad de (-\infty, a]
porque el cdf no está disponible en forma cerrada. Pero no estoy seguro de cómo hacer esto en C++.Rutinas de cuadratura para densidades de probabilidad
Esta tarea es bastante simple en Mathematica; Todo lo que necesito hacer es definir la función,
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))
];
y luego llamar a la rutina NIntegrate
para integrar numéricamente.
F[x_, lambda_, alpha_, beta_, mu_] :=
NIntegrate[f[t, lambda, alpha, beta, mu], {t, -\[Infinity], x}]
Ahora quiero lograr lo mismo en C++. Utilizo la rutina gsl_integration_qagil
de la biblioteca de gsl numerics. Está diseñado para integrar funciones en los intervalos semi infinitos (-\infty, a]
que es justo lo que quiero. Pero desafortunadamente no puedo hacer que funcione.
Ésta es la función de densidad en 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));
}
entonces trato e integrar para obtener el CDF llamando a la rutina 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;
}
Sin embargo gsl_integration_qagil
devuelve un error, 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;
Si aumento el tamaño del espacio de trabajo, la función bessel no se evaluará.
Me preguntaba si había alguien que pudiera darme una idea de mi problema. Una llamada a la función F correspondiente de Mathematica con x = 0.01
devuelve 0.904384
.
Podría ser que la densidad se concentre en un intervalo muy pequeño (es decir, fuera de [-0.05, 0.05]
, la densidad es casi 0
, se proporciona un gráfico a continuación). Si es así, ¿qué se puede hacer al respecto? Gracias por leer.
Esta función tiene un aspecto simétrico, lo que significa que 'cdf (0) = 1/2'.Recuerde que el cdf evaluado en x es el mismo que el integral de 0 a x más el cdf evaluado en 0. Por supuesto, estoy pasando de la forma del gráfico, puede que en realidad no sea exactamente simétrico. –
Hola @Ben, ¡ojalá fuera ese el caso! – mark