Exemplo n.º 1
0
//Simpsonregel von Blatt 1
double Simpsonregel(double (*Integrand)(double), double unten, double oben, unsigned int Intervallanzahl){
	double Intervallbreite = (oben-unten)/Intervallanzahl;
	double stuetzstelle = unten + Intervallbreite;
	double Summe = 0;
	for (int i = 1; i < Intervallanzahl/2; ++i){
		Summe += 4.0/3.0*Integrand(stuetzstelle);
		stuetzstelle += Intervallbreite;
		Summe += 2.0/3.0*Integrand(stuetzstelle);
		stuetzstelle += Intervallbreite;
	}
	Summe += 4.0/3.0*Integrand(stuetzstelle) + 1.0/3.0*(Integrand(unten) + Integrand(oben));
	Summe *= Intervallbreite;
	return Summe;
}
Exemplo n.º 2
0
void MonteCarloIntegral::Integrate(double* I, double* param, double* errorout, int* nevalout, double epsrel, double epsabs) const {
    /* Make sure error thresholds are sensible */
    if(epsrel <= 0)
        epsrel = DEFAULT_EPSREL;
    if(epsabs <= 0)
        epsabs = DEFAULT_EPSABS;

    int neval = 0;

    /* Compute Jacobian */
    double jacobian = 1;
    for(int i = 0; i < n; i++)
        jacobian *= (V[i].b - V[i].a);

    /* Initialize state */
    State state;
    state.niter = 0;
    state.nsamples = nstart;
    state.cumul.resize(m);
    state.grid.resize(n);
    for(int i = 0; i < n; i++)
        for(int bin = 0; bin < NBINS; bin++)
            state.grid[i][bin] = (bin + 1)/(double)NBINS;

    /* Initialize quasi-random number generator */
    Sobol qrng;
    rng_sobol_init(&qrng, n);

    /* Initialize sample buffer */
    int samplebufsize = nbatch*((1 + n + m)*sizeof(double) + n*sizeof(short));
    char* samplebuf = (char*)malloc(samplebufsize);

    /* Main iteration loop */
    int notdone = 1;
    while(notdone) {
        int nsamples = state.nsamples;
        Grid margsum[m][n];
        memset(margsum, 0, sizeof(margsum));
        double base_weight = 1./nsamples;

        /* Sample integrand one batch at a time */
        while(nsamples > 0) {
            int size = (nbatch < nsamples) ? nbatch : nsamples;   // size of current batch
            double* w = (double*)samplebuf;
            double* x = w + size;
            double* f = x + size*n;
            double* lastf = f + size*m;
            short* bin = (short*)lastf;

            /* Prepare positions and weights for sampling */
            while(x < f) {
                double weight = base_weight;
                rng_sobol_get(&qrng, x);
                for(int i = 0; i < n; i++) {
                    double pos = (*x)*NBINS;
                    int ipos = (int)pos;
                    double prev = (ipos == 0) ? 0 : state.grid[i][ipos-1];
                    double diff = state.grid[i][ipos] - prev;
                    *x++ = prev + (pos - ipos)*diff;
                    *bin++ = ipos;
                    weight *= diff*NBINS;
                }
                *w++ = weight;
            }

            /* Sample integrand (why does Cuba's DoSample() pass w to the integrand?) */
            f = x;
            x = w;
            double y[n];
            for(int s = 0; s < size; s++) {
                for(int i = 0; i < n; i++)
                    y[i] = V[i].a + x[i]*(V[i].b - V[i].a);
                Integrand(y, f, param);
                x += n;
                f += m;
            }
            neval += size;

            /* Adjust weights */
            f = x;
            w = (double*)samplebuf;
            bin = (short*)lastf;
            while(f < lastf) {
                double weight = *w++;
                for(int j = 0; j < m; j++) {
                    double wfun = weight * (*f++);
                    if(wfun != 0) {
                        Cumulants* c = &state.cumul[j];
                        Grid* ms = margsum[j];
                        c->sum += wfun;
                        c->sqsum += wfun*wfun;
                        for(int i = 0; i < n; i++)
                            ms[i][bin[i]] += wfun*wfun;
                    }
                }
                bin += n;
            }

            nsamples -= nbatch;
        }

        notdone = 0;

        /* Compute the integral and error values */
        for(int j = 0; j < m; j++) {
            Cumulants* c = &state.cumul[j];
            double w = Weight(c->sum, c->sqsum, state.nsamples);

            c->weightsum += w;
            c->avgsum += w*c->sum;
            double sigsq = 1/c->weightsum;
            c->avg = sigsq*c->avgsum;
            c->err = sqrt(sigsq);
            notdone |= (c->err > fmax(epsrel*fabs(c->avg), epsabs/jacobian));

            if(state.niter == 0)
                c->guess = c->sum;
            else {
                w *= (c->sum - c->guess);
                c->chisum += w;
                c->chisqsum += w*c->sum;
            }
            c->chisq = c->chisqsum - c->avg*c->chisum;

            c->sum = c->sqsum = 0;
        }

        /* Finish if we're below error thresholds */
        if(notdone == 0)
            break;

        /* Abort (with a warning) if we've reached the maximum number of evaluations */
        if(neval >= maxeval) {
            warning("MonteCarlo: maximum number of evaluations reached\n");
            break;
        }

        /* Refine the grid for the next iteration */
        if(m == 1) {
            for(int i = 0; i < n; i++)
                RefineGrid(state.grid[i], margsum[0][i]);
        }
        else {
            for(int i = 0; i < n; i++) {
                Grid wmargsum;
                memset(wmargsum, 0, sizeof(wmargsum));
                for(int j = 0; j < m; j++) {
                    double w = state.cumul[j].avg;
                    if(w != 0) {
                        double* ms = margsum[j][i];
                        for(int bin = 0; bin < NBINS; bin++)
                            wmargsum[bin] += ms[bin]/(w*w);
                    }
                }
                RefineGrid(state.grid[i], wmargsum);
            }
        }

        /* Proceed to the next iteration */
        state.niter++;
        state.nsamples += nincrease;
    }

    /* Prepare results */
    for(int j = 0; j < m; j++) {
        Cumulants* c = &state.cumul[j];
        I[j] = jacobian * c->avg;
        if(errorout)
            errorout[j] = jacobian * c->err;
    }
    if(nevalout)
        *nevalout = neval;
}