尝试在 cpp 脚本中模仿 Python 中的 fsolve 函数以获得简单的函数
Trying to mimic the fsolve function from Python in a cpp scritp for simple functions
首先,我是 C++ 新手。老实说,我发现很难“习惯”,但由于计算时间要求,上周我一直在尝试将脚本从 Python 翻译成 C++。
我遇到的问题之一是简单一维函数的求根:
首先是 Python 中的简单 MWE:
试图解决 ax^2+bx+c = 0 :
def f(x,a,b,c):
return a*x**2+b*x+c
optimize.fsolve(f,-1.0e2,args=(1,1,-1))
这将 return -1.618
或 0.618
取决于开始的猜测符号
好的,我在网上搜索到的 C++ 有点复杂,并使用了 GSL Root finding 库。
对于简单的非多项式函数,它就像一个魅力,但是当二阶进来时,
当您简化搜索“快速”解决方案时,添加端点 似乎是个问题:
#include <stdio.h>
#include <math.h>
#include <functional>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <gsl/gsl_math.h>
#include <gsl/gsl_interp2d.h>
#include <gsl/gsl_spline2d.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_spline.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_roots.h>
struct my_f_params { double a; double b; double c; };
double
my_f (double x, void * p)
{
struct my_f_params * params = (struct my_f_params *)p;
double a = (params->a);
double b = (params->b);
double c = (params->c);
return (a * x + b) * x + c;
}
double root (struct my_f_params prms, double r)
{
int status;
int iter = 0, max_iter = 50;
const gsl_root_fsolver_type *T;
gsl_root_fsolver *s;
double x_lo= -5e0, x_hi=11e0;
gsl_function F;
F.function = &my_f;
F.params = &prms;
T = gsl_root_fsolver_falsepos;
s = gsl_root_fsolver_alloc (T);
gsl_root_fsolver_set (s, &F, x_lo, x_hi);
do
{
iter++;
gsl_set_error_handler_off();
status = gsl_root_fsolver_iterate (s);
r = gsl_root_fsolver_root (s);
x_lo = gsl_root_fsolver_x_lower (s);
x_hi = gsl_root_fsolver_x_upper (s);
status = gsl_root_test_interval (x_lo, x_hi,
0, 0.001);
printf("%f %f\n",x_lo,x_hi);
}
while (status == GSL_CONTINUE && iter < max_iter);
return r;
}
int main(int argc, char const *argv[])
{
struct my_f_params params = {1, 1, -1};
printf("root of x2+x1-1=0 %f\n", root(params,1.25));
return 0;
}
现在,如果起始 x_lo , x_hi
涵盖 2 个解积分,它不会继续寻找 最接近的 一个,给出错误
gsl: falsepos.c:74: ERROR: endpoints do not straddle y=0
Default GSL error handler invoked.
Aborted (core dumped)
在我发帖之前已经尝试了很多 google 的东西。
真的非常感谢您的宝贵时间,任何事情都将不胜感激!
您需要的是研究这个类似的问题,并很好地解释如何让它发挥作用 error in GSL - root finding。
为了提供帮助,您可以使用 https://www.desmos.com/calculator/zuaqvcvpbz 查看函数,您可以像这样设置初始值:
双 x_lo = 0.0, x_hi = 1.0;
在您的实施中使其成为 运行;
添加此代码将有助于找到 x_lo 和 x_hi 的适当值:
gsl_set_error_handler_off(); // this turns off error reporting
int check = gsl_root_fsolver_set(s, &F, x_lo, x_hi);
if (check == GSL_EINVAL) {// this is the error code you got
do {
x_lo += 0.1; // it would be appropriate to check the sign in both
x_hi -= 0.1; // cases, to make sure interval is adjusted properly
check = gsl_root_fsolver_set(s, &F, x_lo, x_hi);
} while (check != 0);
}
首先,我是 C++ 新手。老实说,我发现很难“习惯”,但由于计算时间要求,上周我一直在尝试将脚本从 Python 翻译成 C++。
我遇到的问题之一是简单一维函数的求根:
首先是 Python 中的简单 MWE: 试图解决 ax^2+bx+c = 0 :
def f(x,a,b,c):
return a*x**2+b*x+c
optimize.fsolve(f,-1.0e2,args=(1,1,-1))
这将 return -1.618
或 0.618
取决于开始的猜测符号
好的,我在网上搜索到的 C++ 有点复杂,并使用了 GSL Root finding 库。
对于简单的非多项式函数,它就像一个魅力,但是当二阶进来时, 当您简化搜索“快速”解决方案时,添加端点 似乎是个问题:
#include <stdio.h>
#include <math.h>
#include <functional>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <gsl/gsl_math.h>
#include <gsl/gsl_interp2d.h>
#include <gsl/gsl_spline2d.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_spline.h>
#include <gsl/gsl_integration.h>
#include <gsl/gsl_roots.h>
struct my_f_params { double a; double b; double c; };
double
my_f (double x, void * p)
{
struct my_f_params * params = (struct my_f_params *)p;
double a = (params->a);
double b = (params->b);
double c = (params->c);
return (a * x + b) * x + c;
}
double root (struct my_f_params prms, double r)
{
int status;
int iter = 0, max_iter = 50;
const gsl_root_fsolver_type *T;
gsl_root_fsolver *s;
double x_lo= -5e0, x_hi=11e0;
gsl_function F;
F.function = &my_f;
F.params = &prms;
T = gsl_root_fsolver_falsepos;
s = gsl_root_fsolver_alloc (T);
gsl_root_fsolver_set (s, &F, x_lo, x_hi);
do
{
iter++;
gsl_set_error_handler_off();
status = gsl_root_fsolver_iterate (s);
r = gsl_root_fsolver_root (s);
x_lo = gsl_root_fsolver_x_lower (s);
x_hi = gsl_root_fsolver_x_upper (s);
status = gsl_root_test_interval (x_lo, x_hi,
0, 0.001);
printf("%f %f\n",x_lo,x_hi);
}
while (status == GSL_CONTINUE && iter < max_iter);
return r;
}
int main(int argc, char const *argv[])
{
struct my_f_params params = {1, 1, -1};
printf("root of x2+x1-1=0 %f\n", root(params,1.25));
return 0;
}
现在,如果起始 x_lo , x_hi
涵盖 2 个解积分,它不会继续寻找 最接近的 一个,给出错误
gsl: falsepos.c:74: ERROR: endpoints do not straddle y=0
Default GSL error handler invoked.
Aborted (core dumped)
在我发帖之前已经尝试了很多 google 的东西。
真的非常感谢您的宝贵时间,任何事情都将不胜感激!
您需要的是研究这个类似的问题,并很好地解释如何让它发挥作用 error in GSL - root finding。 为了提供帮助,您可以使用 https://www.desmos.com/calculator/zuaqvcvpbz 查看函数,您可以像这样设置初始值: 双 x_lo = 0.0, x_hi = 1.0; 在您的实施中使其成为 运行; 添加此代码将有助于找到 x_lo 和 x_hi 的适当值:
gsl_set_error_handler_off(); // this turns off error reporting
int check = gsl_root_fsolver_set(s, &F, x_lo, x_hi);
if (check == GSL_EINVAL) {// this is the error code you got
do {
x_lo += 0.1; // it would be appropriate to check the sign in both
x_hi -= 0.1; // cases, to make sure interval is adjusted properly
check = gsl_root_fsolver_set(s, &F, x_lo, x_hi);
} while (check != 0);
}