double AnalyticIntegral( SpkModel &model , const std::valarray<int> &N , const std::valarray<double> &y , const std::valarray<double> &alpha , const std::valarray<double> &L , const std::valarray<double> &U , size_t individual ) { double Pi = 4. * atan(1.); // set the fixed effects model.setPopPar(alpha); // set the individual model.selectIndividual(individual); // index in y where measurements for this individual starts size_t start = 0; size_t i; for(i = 0; i < individual; i++) { assert( N[i] >= 0 ); start += N[i]; } // number of measurements for this individual assert( N[individual] >= 0 ); size_t Ni = N[individual]; // data for this individual std::valarray<double> yi = y[ std::slice( start, Ni, 1 ) ]; // set the random effects = 0 std::valarray<double> b(1); b[0] = 0.; model.setIndPar(b); std::valarray<double> Fi(Ni); model.dataMean(Fi); // model for the variance of random effects std::valarray<double> D(1); model.indParVariance(D); // model for variance of the measurements given random effects std::valarray<double> Ri( Ni * Ni ); model.dataVariance(Ri); // determine bHat double residual = 0; size_t j; for(j = 0; j < Ni; j++) { assert( Ri[j * Ni + j] == Ri[0] ); residual += (yi[j] - Fi[j]); } std::valarray<double> bHat(1); bHat[0] = residual * D[0] / (Ni * D[0] + Ri[0]); // now evaluate the Map Bayesian objective at its optimal value model.setIndPar(bHat); model.dataMean(Fi); double sum = bHat[0] * bHat[0] / D[0] + log( 2. * Pi * D[0] ); for(j = 0; j < Ni; j++) { sum += (yi[j] - Fi[j]) * (yi[j] - Fi[j]) / Ri[0]; sum += log( 2. * Pi * Ri[0] ); } double GHat = .5 * sum; // square root of Hessian of the Map Bayesian objective double rootHessian = sqrt( 1. / D[0] + Ni / Ri[0]); // determine the values of beta that correspond to the limits double Gamma_L = (L[0] - bHat[0]) * rootHessian; double Gamma_U = (U[0] - bHat[0]) * rootHessian; // compute the upper tails corresponding to the standard normal double Q_L = gsl_sf_erf_Q(Gamma_L); double Q_U = gsl_sf_erf_Q(Gamma_U); // analytic value of the integral double factor = exp(-GHat) * sqrt(2. * Pi) / rootHessian; return factor * (Q_L - Q_U); }
double gaussCdf(double x) { // return 0.5*(1+gsl_sf_erf(x)*M_SQRT1_2); return 1 - gsl_sf_erf_Q(x); };
static VALUE Error_erf_Q(VALUE self, VALUE x) { return rb_float_new(gsl_sf_erf_Q(NUM2DBL(x))); }