使用 GSL Monte Carlo 在 C++ 中集成多维函数
Using GSL Monte Carlo Integration in C++ for a multidimensional function
我正在尝试在我生成的 C++ 代码中使用 GSL Monte Carlo 集成。
这个想法是有一个布朗运动函数(brownian
),它在另一个函数(g
)中用于执行 4-dim 数值积分。
double brownian(const double &x,const double &x0,const double & sigma,const double & t) {
double a1 = (1/sqrt(2.0 * M_PI * sigma * t));
double b1 = exp(-((x - x0) * (x - x0))/(2.0 * sigma * t));
double res = a1 * b1;
return res;
}
double g(double *k, size_t dim, void *p[]){
const double& xA0 = *(double *)p[0];
const double& xB0 = *(double *)p[1];
const double& yA0 = *(double *)p[2];
const double& yB0 = *(double *)p[3];
const double& sigma = *(double *)p[4];
const double& t1 = *(double *)p[5];
double temp_pbxA = brownian(k[0], xA0, sigma,t1);
double temp_pbxB = brownian(k[1], xB0, sigma, t1);
double temp_pbyA = brownian(k[2], yA0, sigma,t1);
double temp_pbyB = brownian(k[3], yB0, sigma, t1);
return (temp_pbxB * temp_pbyB) * (temp_pbxA * temp_pbyA);
}
double integrate_test(const double xl, const double xu, const double& xA0, const double& xB0, const double& yA0, const double& yB0, const double& t1, const double& sigma){
double res, err;
const gsl_rng_type *T;
gsl_rng *r;
gsl_monte_function G;
G.f = &g;
G.dim = 4;
G.params = { xA0, xB0, yA0, yB0, sigma, t1};
size_t calls = 500000;
gsl_rng_env_setup ();
T = gsl_rng_default;
r = gsl_rng_alloc (T);
gsl_monte_plain_state *s = gsl_monte_plain_alloc (4);
gsl_monte_plain_integrate (&G, xl, xu, 4, calls, r, s,
&res, &err);
gsl_monte_plain_free (s);
return res;
}
但是,当我尝试编译代码时出现以下错误:
error: assigning to 'double (*)(double *, size_t, void *)' (aka 'double (*)(double *, unsigned long, void *)') from incompatible type 'double (*)(double *, size_t, void **)' (aka 'double (*)(double *, unsigned long, void **)'): type mismatch at 3rd parameter ('void *' vs 'void **')
G.f = &g;
我不明白为什么把 void *p[]
当作 void**
。
有什么建议吗?
这是您的代码与编译代码之间的差异。这并不意味着我的代码是正确的:你只能得到你所要求的——因为你没有提供完整的最小工作示例,任何试图帮助你的人都被迫猜测你的问题到底是什么。
13c13
< double g(double *k, size_t dim, void *p){
---
> double g(double *k, size_t dim, void *p[]){
15,20c15,20
< const double& xA0 = ((double *)p)[0];
< const double& xB0 = ((double *)p)[1];
< const double& yA0 = ((double *)p)[2];
< const double& yB0 = ((double *)p)[3];
< const double& sigma = ((double *)p)[4];
< const double& t1 = ((double *)p)[5];
---
> const double& xA0 = *(double *)p[0];
> const double& xB0 = *(double *)p[1];
> const double& yA0 = *(double *)p[2];
> const double& yB0 = *(double *)p[3];
> const double& sigma = *(double *)p[4];
> const double& t1 = *(double *)p[5];
31c31
< double integrate_test(const double xl[], const double xu[], const double& xA0, const double& xB0, const double& yA0, const double& yB0, const double& t1, const double& sigma){
---
> double integrate_test(const double xl, const double xu, const double& xA0, const double& xB0, const double& yA0, const double& yB0, const double& t1, const double& sigma){
41,42c41
< double params[] = { xA0, xB0, yA0, yB0, sigma, t1};
< G.params = params;
---
> G.params = { xA0, xB0, yA0, yB0, sigma, t1};
如您所见,您的编译器至少抱怨了 2 个问题。
gsl_monte_function
期望组件 f
具有签名 double (* f) (double * x, size_t dim, void * params)
,请参阅 https://www.gnu.org/software/gsl/doc/html/montecarlo.html。我必须强调,通常 GSL 中的参数是通过指向必须事先在某处定义的结构的空指针传递的,但在这里你很幸运,所有参数都只是 double
s,所以为了节省额外的代码,你可以使用旧的普通 C 数组
double params[] = { xA0, xB0, yA0, yB0, sigma, t1};
并将其地址作为 G.params
传递。然后,您将使用像这样的 C 语法 g
在
中检索它们
const double& xA0 = ((double *)p)[0];
(将void指针转换为double*
,然后将其视为C风格数组的名称)。
gsl_monte_plain_integrate
期望它的第二个和第三个参数是 C 风格的数组。请参阅 https://www.gnu.org/software/gsl/doc/html/montecarlo.html。这就是为什么你需要在 integrate_test
. 中更改 xl
和 xu
的类型
GSL 很难使用。如有疑问,请不要犹豫。
我正在尝试在我生成的 C++ 代码中使用 GSL Monte Carlo 集成。
这个想法是有一个布朗运动函数(brownian
),它在另一个函数(g
)中用于执行 4-dim 数值积分。
double brownian(const double &x,const double &x0,const double & sigma,const double & t) {
double a1 = (1/sqrt(2.0 * M_PI * sigma * t));
double b1 = exp(-((x - x0) * (x - x0))/(2.0 * sigma * t));
double res = a1 * b1;
return res;
}
double g(double *k, size_t dim, void *p[]){
const double& xA0 = *(double *)p[0];
const double& xB0 = *(double *)p[1];
const double& yA0 = *(double *)p[2];
const double& yB0 = *(double *)p[3];
const double& sigma = *(double *)p[4];
const double& t1 = *(double *)p[5];
double temp_pbxA = brownian(k[0], xA0, sigma,t1);
double temp_pbxB = brownian(k[1], xB0, sigma, t1);
double temp_pbyA = brownian(k[2], yA0, sigma,t1);
double temp_pbyB = brownian(k[3], yB0, sigma, t1);
return (temp_pbxB * temp_pbyB) * (temp_pbxA * temp_pbyA);
}
double integrate_test(const double xl, const double xu, const double& xA0, const double& xB0, const double& yA0, const double& yB0, const double& t1, const double& sigma){
double res, err;
const gsl_rng_type *T;
gsl_rng *r;
gsl_monte_function G;
G.f = &g;
G.dim = 4;
G.params = { xA0, xB0, yA0, yB0, sigma, t1};
size_t calls = 500000;
gsl_rng_env_setup ();
T = gsl_rng_default;
r = gsl_rng_alloc (T);
gsl_monte_plain_state *s = gsl_monte_plain_alloc (4);
gsl_monte_plain_integrate (&G, xl, xu, 4, calls, r, s,
&res, &err);
gsl_monte_plain_free (s);
return res;
}
但是,当我尝试编译代码时出现以下错误:
error: assigning to 'double (*)(double *, size_t, void *)' (aka 'double (*)(double *, unsigned long, void *)') from incompatible type 'double (*)(double *, size_t, void **)' (aka 'double (*)(double *, unsigned long, void **)'): type mismatch at 3rd parameter ('void *' vs 'void **')
G.f = &g;
我不明白为什么把 void *p[]
当作 void**
。
有什么建议吗?
这是您的代码与编译代码之间的差异。这并不意味着我的代码是正确的:你只能得到你所要求的——因为你没有提供完整的最小工作示例,任何试图帮助你的人都被迫猜测你的问题到底是什么。
13c13
< double g(double *k, size_t dim, void *p){
---
> double g(double *k, size_t dim, void *p[]){
15,20c15,20
< const double& xA0 = ((double *)p)[0];
< const double& xB0 = ((double *)p)[1];
< const double& yA0 = ((double *)p)[2];
< const double& yB0 = ((double *)p)[3];
< const double& sigma = ((double *)p)[4];
< const double& t1 = ((double *)p)[5];
---
> const double& xA0 = *(double *)p[0];
> const double& xB0 = *(double *)p[1];
> const double& yA0 = *(double *)p[2];
> const double& yB0 = *(double *)p[3];
> const double& sigma = *(double *)p[4];
> const double& t1 = *(double *)p[5];
31c31
< double integrate_test(const double xl[], const double xu[], const double& xA0, const double& xB0, const double& yA0, const double& yB0, const double& t1, const double& sigma){
---
> double integrate_test(const double xl, const double xu, const double& xA0, const double& xB0, const double& yA0, const double& yB0, const double& t1, const double& sigma){
41,42c41
< double params[] = { xA0, xB0, yA0, yB0, sigma, t1};
< G.params = params;
---
> G.params = { xA0, xB0, yA0, yB0, sigma, t1};
如您所见,您的编译器至少抱怨了 2 个问题。
gsl_monte_function
期望组件f
具有签名double (* f) (double * x, size_t dim, void * params)
,请参阅 https://www.gnu.org/software/gsl/doc/html/montecarlo.html。我必须强调,通常 GSL 中的参数是通过指向必须事先在某处定义的结构的空指针传递的,但在这里你很幸运,所有参数都只是double
s,所以为了节省额外的代码,你可以使用旧的普通 C 数组
double params[] = { xA0, xB0, yA0, yB0, sigma, t1};
并将其地址作为 G.params
传递。然后,您将使用像这样的 C 语法 g
在
const double& xA0 = ((double *)p)[0];
(将void指针转换为double*
,然后将其视为C风格数组的名称)。
gsl_monte_plain_integrate
期望它的第二个和第三个参数是 C 风格的数组。请参阅 https://www.gnu.org/software/gsl/doc/html/montecarlo.html。这就是为什么你需要在integrate_test
. 中更改
xl
和 xu
的类型
GSL 很难使用。如有疑问,请不要犹豫。