反蒙特卡罗积分的逆累积正态分布

时间:2017-07-17 17:33:02

标签: c++ integration

我正在尝试集成函数,包括使用ICDF函数(gsl_cdf_gaussian_Pinv(x[1], 1))更改变量,但结果总是错误的:

#include <fstream>
#include <iostream>
#include <memory>
#include <cmath>
#include <iomanip>
#include <ctime>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <math.h>
#include <stdio.h>
#include <gaussinv.c>

#define _USE_MATH_DEFINES
using namespace std;


double f(double[], int);

double int_mcnd(double(*)(double[], int), double[], double[], int, int);


double varr[100];
int k = 0;
double hj = 0;
double mj = 1;

# include "sobol.hpp"

int DIM_NUM = 10;


int main() {


    const int n = 10;       /* define how many integrals */
//    const int m = 1000000; /* define how many points */
    double a[n] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* left end-points */
    double b[n] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; /* right end-points */
    double result;
    int i, m;
    int ntimes;

    cout.setf(ios::fixed | ios::showpoint);
// current time in seconds (begin calculations)
    time_t seconds_i;
    seconds_i = time(NULL);

    m = 1;                // initial number of intervals
    ntimes = 20;          // number of interval doublings with nmax=2^ntimes
    cout << setw(12) << n << "D Integral" << endl;
    for (i = 0; i <= ntimes; i = i + 1) {
        result = int_mcnd(f, a, b, n, m);
        cout << setw(10) << m << "      " << setprecision(30) << result << endl;
        m = m * 2;
    }
    // current time in seconds (end of calculations)
    time_t seconds_f;
    seconds_f = time(NULL);
    cout << endl << "total elapsed time = " << seconds_f - seconds_i << " seconds" << endl << endl;
    return 0;
}

double f(double x[], int n) {
    double y;
    int j;
    y = 0.0;
    /* define Multidimensional Gaussian distribution and covariance */
    /* X=(x1, k=2, mu = (0,  covariance matrix = (v  0  0  0
     *    x2             0                        0  v  0  0
     *    x3             0                        0  0  v  0
     *    x4)            0)                       0  0  0  v) */

    double v = 1;
    double determinant = pow(v, 10);
    double inverse = 1 / v;
    double rang = gsl_cdf_gaussian_Pinv(0.99999904632568359375, 1) - gsl_cdf_gaussian_Pinv(0.00000095367431640625, 1) +
                  gsl_cdf_gaussian_Pinv(0.00000095367431640625, 1);
    y = (1 / sqrt(pow(2 * M_PI, 10) * determinant) * exp(-0.5 * (inverse * pow(gsl_cdf_gaussian_Pinv(x[0], 1), 2) +
                                                                 inverse * pow(gsl_cdf_gaussian_Pinv(x[1], 1), 2) +
                                                                 inverse * pow(gsl_cdf_gaussian_Pinv(x[2], 1), 2) +
                                                                 inverse * pow(gsl_cdf_gaussian_Pinv(x[3], 1), 2) +
                                                                 inverse * pow(gsl_cdf_gaussian_Pinv(x[4], 1), 2) +
                                                                 inverse * pow(gsl_cdf_gaussian_Pinv(x[5], 1), 2) +
                                                                 inverse * pow(gsl_cdf_gaussian_Pinv(x[6], 1), 2) +
                                                                 inverse * pow(gsl_cdf_gaussian_Pinv(x[7], 1), 2) +
                                                                 inverse * pow(gsl_cdf_gaussian_Pinv(x[8], 1), 2) +
                                                                 inverse * pow(gsl_cdf_gaussian_Pinv(x[9], 1), 2))));

    return y;
}

/*==============================================================

input:
    fn  - a multiple argument real function (supplied by the user)
    a[] - left end-points of the interval of integration
    b[] - right end-points of the interval of integration
    n  - dimension of integral
    m  - number of random points
output:
    r      - result of integration

================================================================*/

double int_mcnd(double(*fn)(double[], int), double a[], double b[], int n, int m) {
    double r, x[n], p;
    int i, j;
    double rarr[DIM_NUM];
    long long int seed;
    seed = 1;
    long long int seed_in;
    long long int seed_out;

    srand(time(NULL));  /* initial seed value (use system time) */

    r = 0.0;
    p = 1.0;

// step 1: calculate the common factor p
    for (j = 0; j < n; j = j + 1) {
       // p = p * (b[j] - a[j]);
        p=p*(gsl_cdf_gaussian_Pinv(0.99999904632568359375, 1)-gsl_cdf_gaussian_Pinv(0.00000095367431640625, 1));
    }


// step 2: integration
    for (i = 1; i <= m; i = i + 1) {
        seed_in = seed;
        i8_sobol(DIM_NUM, &seed, rarr);
        seed_out = seed;
//      calculate random x[] points
        for (j = 0; j < n; j = j + 1) {
            x[j] = a[j] + (b[j] - a[j]) * rarr[j];
        }
        r = r + fn(x, n);
    }

    cout << endl << "p = " << p << " seconds" << endl << endl;

    r = r * p / m;

    return r;
}

问题出在参数化参数p中,我建议

p=p*(gsl_cdf_gaussian_Pinv(0.99999904632568359375, 1)-gsl_cdf_gaussian_Pinv(0.00000095367431640625, 1))

而不是标准 - p = p * (b[j] - a[j]); 我想不仅要在[0,1] ^ N区间内进行整合,还要在[-20; 20]进行整合。

我无法定义我的错误。有人可以帮帮忙吗?

0 个答案:

没有答案