double bayestar_log_posterior_toa_phoa_snr(
    double ra,
    double sin_dec,
    double distance,
    double u,
    double twopsi,
    double t,
    double gmst, /* Greenwich mean sidereal time in radians. */
    int nifos, /* Input: number of detectors. */
    const float (**responses)[3], /* Pointers to detector responses. */
    const double **locations, /* Pointers to locations of detectors in Cartesian geographic coordinates. */
    const double *toas, /* Input: array of times of arrival with arbitrary relative offset. (Make toas[0] == 0.) */
    const double *phoas, /* Input: array of times of arrival with arbitrary relative offset. (Make toas[0] == 0.) */
    const double *snrs, /* Input: array of SNRs. */
    const double *w_toas, /* Input: sum-of-squares weights, (1/TOA variance)^2. */
    const double *w1s, /* Input: first moments of angular frequency. */
    const double *w2s, /* Input: second moments of angular frequency. */
    const double *horizons, /* Distances at which a source would produce an SNR of 1 in each detector. */
    int prior_distance_power) /* Use a prior of (distance)^(prior_distance_power) */
{
    int iifo;
    const double dec = asin(sin_dec);
    const double u2 = gsl_pow_2(u);
    const double complex exp_i_twopsi = exp_i(twopsi);

    (void)w2s; /* FIXME: remove unused parameter */

    /* Compute time of arrival errors */
    double dt[nifos];
    toa_errors(dt, M_PI_2 - dec, ra, gmst, nifos, locations, toas);

    {
        double mean_dt = gsl_stats_wmean(w_toas, 1, dt, 1, nifos);
        for (iifo = 0; iifo < nifos; iifo++)
            dt[iifo] += t - mean_dt;
    }

    /* Rescale distances so that furthest horizon distance is 1. */
    double d1[nifos];
    {
        const double d1max = gsl_stats_max(horizons, 1, nifos);
        for (iifo = 0; iifo < nifos; iifo ++)
            d1[iifo] = horizons[iifo] / d1max;
        distance /= d1max;
    }

    double logp = 0;
    double complex i0arg_complex = 0;
    double A = 0;
    double B = 0;

    /* Loop over detectors */
    for (iifo = 0; iifo < nifos; iifo++)
    {
        double complex F;
        XLALComputeDetAMResponse(
            (double *)&F,     /* Type-punned real part */
            1 + (double *)&F, /* Type-punned imag part */
            responses[iifo], ra, dec, 0, gmst);
        F *= d1[iifo];

        const double complex tmp = F * exp_i_twopsi;
        double complex phase_rhotimesr = 0.5 * (1 + u2) * creal(tmp) + I * u * cimag(tmp);
        const double abs_rhotimesr_2 = cabs2(phase_rhotimesr);
        const double abs_rhotimesr = sqrt(abs_rhotimesr_2);
        phase_rhotimesr /= abs_rhotimesr;
        i0arg_complex += exp_i(phoas[iifo] + w1s[iifo] * dt[iifo]) * phase_rhotimesr * gsl_pow_2(snrs[iifo]);
        logp += -0.5 * w_toas[iifo] * gsl_pow_2(dt[iifo]);

        A += abs_rhotimesr_2;
        B += abs_rhotimesr * snrs[iifo];
    }
    A *= -0.5;

    const double i0arg = cabs(i0arg_complex);

    /* Should be equivalent to, but more accurate than:
         logp += log(gsl_sf_bessel_I0(i0arg))
     */
    logp += log(gsl_sf_bessel_I0_scaled(i0arg)) + i0arg;

    logp += log_radial_integrand(distance, A, B, prior_distance_power);

    return logp;
}
double *bayestar_sky_map_toa_phoa_snr(
    long *npix, /* Input: number of HEALPix pixels. */
    double gmst, /* Greenwich mean sidereal time in radians. */
    int nifos, /* Input: number of detectors. */
    const float (**responses)[3], /* Pointers to detector responses. */
    const double **locations, /* Pointers to locations of detectors in Cartesian geographic coordinates. */
    const double *toas, /* Input: array of times of arrival with arbitrary relative offset. (Make toas[0] == 0.) */
    const double *phoas, /* Input: array of phases of arrival with arbitrary relative offset. (Make phoas[0] == 0.) */
    const double *snrs, /* Input: array of SNRs. */
    const double *w_toas, /* Input: sum-of-squares weights, (1/TOA variance)^2. */
    const double *w1s, /* Input: first moments of angular frequency. */
    const double *w2s, /* Input: second moments of angular frequency. */
    const double *horizons, /* Distances at which a source would produce an SNR of 1 in each detector. */
    double min_distance,
    double max_distance,
    int prior_distance_power) /* Use a prior of (distance)^(prior_distance_power) */
{
    long nside;
    long maxpix;
    long i;
    double d1[nifos];
    double *P;
    gsl_permutation *pix_perm;
    double complex exp_i_phoas[nifos];

    /* Hold GSL return values for any thread that fails. */
    int gsl_errno = GSL_SUCCESS;

    /* Storage for old GSL error handler. */
    gsl_error_handler_t *old_handler;

    /* Maximum number of subdivisions for adaptive integration. */
    static const size_t subdivision_limit = 64;

    /* Subdivide radial integral where likelihood is this fraction of the maximum,
     * will be used in solving the quadratic to find the breakpoints */
    static const double eta = 0.01;

    /* Use this many integration steps in 2*psi  */
    static const int ntwopsi = 16;

    /* Number of integration steps in cos(inclination) */
    static const int nu = 16;

    /* Number of integration steps in arrival time */
    static const int nt = 16;

    /* Rescale distances so that furthest horizon distance is 1. */
    {
        double d1max;
        memcpy(d1, horizons, sizeof(d1));
        for (d1max = d1[0], i = 1; i < nifos; i ++)
            if (d1[i] > d1max)
                d1max = d1[i];
        for (i = 0; i < nifos; i ++)
            d1[i] /= d1max;
        min_distance /= d1max;
        max_distance /= d1max;
    }

    (void)w2s; /* FIXME: remove unused parameter */

    for (i = 0; i < nifos; i ++)
        exp_i_phoas[i] = exp_i(phoas[i]);

    /* Evaluate posterior term only first. */
    P = bayestar_sky_map_toa_adapt_resolution(&pix_perm, &maxpix, npix, gmst, nifos, locations, toas, w_toas, autoresolution_count_pix_toa_phoa_snr);
    if (!P)
        return NULL;

    /* Determine the lateral HEALPix resolution. */
    nside = npix2nside(*npix);

    /* Zero all pixels that didn't meet the TDOA cut. */
    for (i = maxpix; i < *npix; i ++)
    {
        long ipix = gsl_permutation_get(pix_perm, i);
        P[ipix] = -INFINITY;
    }

    /* Use our own error handler while in parallel section to avoid concurrent
     * calls to the GSL error handler, which if provided by the user may not
     * be threadsafe. */
    old_handler = gsl_set_error_handler(my_gsl_error);

    /* Compute posterior factor for amplitude consistency. */
    #pragma omp parallel for firstprivate(gsl_errno) lastprivate(gsl_errno)
    for (i = 0; i < maxpix; i ++)
    {
       /* Cancel further computation if a GSL error condition has occurred.
        *
        * Note: if one thread sets gsl_errno, not necessarily all thread will
        * get the updated value. That's OK, because most failure modes will
        * cause GSL error conditions on all threads. If we cared to have any
        * failure on any thread terminate all of the other threads as quickly
        * as possible, then we would want to insert the following pragma here:
        *
        *     #pragma omp flush(gsl_errno)
        *
        * and likewise before any point where we set gsl_errno.
        */

        if (gsl_errno != GSL_SUCCESS)
            goto skip;

        {
            long ipix = gsl_permutation_get(pix_perm, i);
            double complex F[nifos];
            double theta, phi;
            int itwopsi, iu, it, iifo;
            double accum = -INFINITY;
            double complex exp_i_toaphoa[nifos];
            double dtau[nifos], mean_dtau;

            /* Prepare workspace for adaptive integrator. */
            gsl_integration_workspace *workspace = gsl_integration_workspace_alloc(subdivision_limit);

            /* If the workspace could not be allocated, then record the GSL
             * error value for later reporting when we leave the parallel
             * section. Then, skip to the next loop iteration. */
            if (!workspace)
            {
               gsl_errno = GSL_ENOMEM;
               goto skip;
            }

            /* Look up polar coordinates of this pixel */
            pix2ang_ring(nside, ipix, &theta, &phi);

            toa_errors(dtau, theta, phi, gmst, nifos, locations, toas);
            for (iifo = 0; iifo < nifos; iifo ++)
                exp_i_toaphoa[iifo] = exp_i_phoas[iifo] * exp_i(w1s[iifo] * dtau[iifo]);

            /* Find mean arrival time error */
            mean_dtau = gsl_stats_wmean(w_toas, 1, dtau, 1, nifos);

            /* Look up antenna factors */
            for (iifo = 0; iifo < nifos; iifo++)
            {
                XLALComputeDetAMResponse(
                    (double *)&F[iifo],     /* Type-punned real part */
                    1 + (double *)&F[iifo], /* Type-punned imag part */
                    responses[iifo], phi, M_PI_2 - theta, 0, gmst);
                F[iifo] *= d1[iifo];
            }

            /* Integrate over 2*psi */
            for (itwopsi = 0; itwopsi < ntwopsi; itwopsi++)
            {
                const double twopsi = (2 * M_PI / ntwopsi) * itwopsi;
                const double complex exp_i_twopsi = exp_i(twopsi);

                /* Integrate over u from u=-1 to u=1. */
                for (iu = -nu; iu <= nu; iu++)
                {
                    const double u = (double)iu / nu;
                    const double u2 = gsl_pow_2(u);

                    double A = 0, B = 0;
                    double breakpoints[5];
                    int num_breakpoints = 0;
                    double log_offset = -INFINITY;

                    /* The log-likelihood is quadratic in the estimated and true
                     * values of the SNR, and in 1/r. It is of the form A/r^2 + B/r,
                     * where A depends only on the true values of the SNR and is
                     * strictly negative and B depends on both the true values and
                     * the estimates and is strictly positive.
                     *
                     * The middle breakpoint is at the maximum of the log-likelihood,
                     * occurring at 1/r=-B/2A. The lower and upper breakpoints occur
                     * when the likelihood becomes eta times its maximum value. This
                     * occurs when
                     *
                     *   A/r^2 + B/r = log(eta) - B^2/4A.
                     *
                     */

                    /* Perform arrival time integral */
                    double accum1 = -INFINITY;
                    for (it = -nt/2; it <= nt/2; it++)
                    {
                        const double t = mean_dtau + LAL_REARTH_SI / LAL_C_SI * it / nt;
                        double complex i0arg_complex = 0;
                        for (iifo = 0; iifo < nifos; iifo++)
                        {
                            const double complex tmp = F[iifo] * exp_i_twopsi;
                            /* FIXME: could use - sign here to avoid conj below, but
                             * this probably just sets our sign convention relative to
                             * detection pipeline */
                            double complex phase_rhotimesr = 0.5 * (1 + u2) * creal(tmp) + I * u * cimag(tmp);
                            const double abs_rhotimesr_2 = cabs2(phase_rhotimesr);
                            const double abs_rhotimesr = sqrt(abs_rhotimesr_2);
                            phase_rhotimesr /= abs_rhotimesr;
                            i0arg_complex += exp_i_toaphoa[iifo] * exp_i(-w1s[iifo] * t) * phase_rhotimesr * gsl_pow_2(snrs[iifo]);
                        }
                        const double i0arg = cabs(i0arg_complex);
                        accum1 = logaddexp(accum1, log(gsl_sf_bessel_I0_scaled(i0arg)) + i0arg - 0.5 * gsl_stats_wtss_m(w_toas, 1, dtau, 1, nifos, t));
                    }

                    /* Loop over detectors */
                    for (iifo = 0; iifo < nifos; iifo++)
                    {
                        const double complex tmp = F[iifo] * exp_i_twopsi;
                        /* FIXME: could use - sign here to avoid conj below, but
                         * this probably just sets our sign convention relative to
                         * detection pipeline */
                        double complex phase_rhotimesr = 0.5 * (1 + u2) * creal(tmp) + I * u * cimag(tmp);
                        const double abs_rhotimesr_2 = cabs2(phase_rhotimesr);
                        const double abs_rhotimesr = sqrt(abs_rhotimesr_2);

                        A += abs_rhotimesr_2;
                        B += abs_rhotimesr * snrs[iifo];
                    }
                    A *= -0.5;

                    {
                        const double middle_breakpoint = -2 * A / B;
                        const double lower_breakpoint = 1 / (1 / middle_breakpoint + sqrt(log(eta) / A));
                        const double upper_breakpoint = 1 / (1 / middle_breakpoint - sqrt(log(eta) / A));
                        breakpoints[num_breakpoints++] = min_distance;
                        if(lower_breakpoint > breakpoints[num_breakpoints-1] && lower_breakpoint < max_distance)
                            breakpoints[num_breakpoints++] = lower_breakpoint;
                        if(middle_breakpoint > breakpoints[num_breakpoints-1] && middle_breakpoint < max_distance)
                            breakpoints[num_breakpoints++] = middle_breakpoint;
                        if(upper_breakpoint > breakpoints[num_breakpoints-1] && upper_breakpoint < max_distance)
                            breakpoints[num_breakpoints++] = upper_breakpoint;
                        breakpoints[num_breakpoints++] = max_distance;
                    }

                    {
                        /*
                         * Set log_offset to the maximum of the logarithm of the
                         * radial integrand evaluated at all of the breakpoints. */
                        int ibreakpoint;
                        for (ibreakpoint = 0; ibreakpoint < num_breakpoints; ibreakpoint++)
                        {
                            const double new_log_offset = log_radial_integrand(
                                breakpoints[ibreakpoint], A, B, prior_distance_power);
                            if (new_log_offset < INFINITY && new_log_offset > log_offset)
                                log_offset = new_log_offset;
                        }
                    }

                    {
                        /* Perform adaptive integration. Stop when a relative
                         * accuracy of 0.05 has been reached. */
                        inner_integrand_params integrand_params = {A, B, log_offset, prior_distance_power};
                        const gsl_function func = {radial_integrand, &integrand_params};
                        double result, abserr;
                        int ret = gsl_integration_qagp(&func, &breakpoints[0], num_breakpoints, DBL_MIN, 0.05, subdivision_limit, workspace, &result, &abserr);

                        /* If the integrator failed, then record the GSL error
                         * value for later reporting when we leave the parallel
                         * section. Then, break out of the loop. */
                        if (ret != GSL_SUCCESS)
                        {
                            gsl_errno = ret;
                            gsl_integration_workspace_free(workspace);
                            goto skip;
                        }

                        /* Take the logarithm and put the log-normalization back in. */
                        result = log(result) + integrand_params.log_offset + accum1;

                        /* Accumulate result. */
                        accum = logaddexp(accum, result);
                    }
                }
            }
            /* Discard workspace for adaptive integrator. */
            gsl_integration_workspace_free(workspace);

            /* Store log posterior. */
            P[ipix] = accum;
        }

        skip: /* this statement intentionally left blank */;
    }

    /* Restore old error handler. */
    gsl_set_error_handler(old_handler);

    /* Free permutation. */
    gsl_permutation_free(pix_perm);

    /* Check if there was an error in any thread evaluating any pixel. If there
     * was, raise the error and return. */
    if (gsl_errno != GSL_SUCCESS)
    {
        free(P);
        GSL_ERROR_NULL(gsl_strerror(gsl_errno), gsl_errno);
    }

    /* Exponentiate and normalize posterior. */
    pix_perm = get_pixel_ranks(*npix, P);
    if (!pix_perm)
    {
        free(P);
        return NULL;
    }
    exp_normalize(*npix, P, pix_perm);
    gsl_permutation_free(pix_perm);

    return P;
}
void Automata::loadFromXML(string archivo,string archivo_default)
{
    TiXmlDocument doc_t(archivo.c_str());
    bool loadOkay = doc_t.LoadFile();
    if(!loadOkay)
    {
        doc_t=TiXmlDocument(archivo_default.c_str());
        loadOkay=doc_t.LoadFile();
        cout.flush();
    }
    TiXmlDocument *doc;
    doc=&doc_t;

    for(TiXmlNode* nodo=doc->FirstChild("State");
            nodo!=NULL;
            nodo=nodo->NextSibling("State"))
    {
        std::vector<Transicion*> transiciones;
        for(TiXmlElement *e_action=nodo->FirstChild("Action")->ToElement();
                e_action!=NULL;
                e_action=e_action->NextSiblingElement("Action"))
        {
            Transicion *transicion;
            if(e_action->Attribute("rewardable")!=NULL)
                transicion=new Transicion(e_action->Attribute("input"),e_action->Attribute("destination"),strcmp(e_action->Attribute("rewardable"),"yes")==0);
            else
                transicion=new Transicion(e_action->Attribute("input"),e_action->Attribute("destination"),false);
            if(e_action->Attribute("reward")!=NULL)
                transicion->setRecompensa(atoi(e_action->Attribute("reward")));
            if(e_action->Attribute("wait")!=NULL)
                transicion->setWait(atoi(e_action->Attribute("wait")));




            if(e_action->FirstChild("condition")!=NULL)
            {
                for(TiXmlElement *elemento_condicion=e_action->FirstChild("condition")->ToElement();
                        elemento_condicion!=NULL;
                        elemento_condicion=elemento_condicion->NextSiblingElement("condition"))
                {
                    std::string exp_i(elemento_condicion->Attribute("left_exp"));
                    std::string op(elemento_condicion->Attribute("relational_op"));
                    std::string exp_d(elemento_condicion->Attribute("right_exp"));
                    std::string str_contrario(elemento_condicion->Attribute("to_opponent"));
                    bool contrario=(str_contrario=="yes");
                    transicion->agregarCondicion(Condicion2(exp_i,op,exp_d,contrario));
                }
            }

            if(e_action->FirstChild("condition_integer")!=NULL)
            {
                for(TiXmlElement *elemento_condicion=e_action->FirstChild("condition_integer")->ToElement();
                        elemento_condicion!=NULL;
                        elemento_condicion=elemento_condicion->NextSiblingElement("condition_integer"))
                {
                    std::string exp_i(elemento_condicion->Attribute("left_exp"));
                    std::string op(elemento_condicion->Attribute("relational_op"));
                    int exp_d=atoi(elemento_condicion->Attribute("right_exp"));
                    std::string str_contrario(elemento_condicion->Attribute("to_opponent"));
                    bool contrario=(str_contrario=="yes");
                    transicion->agregarCondicion(Condicion2(exp_i,op,exp_d,contrario));
                }
            }
            transiciones.push_back(transicion);
        }
        estados[std::string(nodo->ToElement()->Attribute("name"))]=new Estado(transiciones);
    }
}