我正在尝试找到输入到我的代码的正确参数,以产生所需的结果。而不是猜测和检查我使用根查找找到给出所需结果的参数。有两个变量可以自由变化,但我在运行根查找器时遇到了困难。我更改了代码以单独解决每个变量,并发现我在优化一个变量时遇到了问题。
似乎问题是gsl_multiroot_iterate在第一次迭代后为x1猜测nan。至少这是x1的值在该点之后的function()调用中返回的内容,当我为x1输入printf语句时。
我正在运行的模拟只允许x1的值介于0和1之间。虽然我在模拟中检查以确保x1介于0和1之间,并且从不抛出问题,但这可能导致问题。此外,当x1是nan时。无论如何设置迭代尝试x1的值的范围?并且有人知道迭代尝试使用nan for x1吗?
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_multiroots.h>
struct rparams{
double target1;
};
int function(const gsl_vector * x, void *params, gsl_vector * f);
int main(int argc, char* argv[]) {
double target1;
sscanf(argv[1],"%lf",&target1);
const gsl_multiroot_fsolver_type *T;
gsl_multiroot_fsolver *s;
int status;
unsigned int iter = 0;
const size_t n = 1;
struct rparams p;
p.target1 = target1;
gsl_multiroot_function f = {&function, n, &p};
double x_init[1] = {.1};
gsl_vector * x = gsl_vector_alloc(n);
gsl_vector_set(x, 0, x_init[0]);
T = gsl_multiroot_fsolver_hybrid;
s = gsl_multiroot_fsolver_alloc(T, 1);
gsl_multiroot_fsolver_set(s, &f, x);
print_state(iter, s);
do
{
iter++;
status = gsl_multiroot_fsolver_iterate (s);
print_state(iter, s);
/* check if solver is stuck */
if (status){
break;
}
status = gsl_multiroot_test_residual (s->f, 1e-7);
}
while (status == GSL_CONTINUE && iter < 1000);
printf("status = %s\n", gsl_strerror (status));
gsl_multiroot_fsolver_free (s);
gsl_vector_free (x);
return 0;
}
int function(const gsl_vector * x, void *params, gsl_vector * f){
double target1 = ((struct rparams *) params)->target1;
double x1 = gsl_vector_get(x, 0);
/* Run simulation here using x1 parameter */
/* Assign output to temp1, which I am trying to match to target1 */
const double y1 = temp1 - target1;
gsl_vector_set (f, 0, y1);
return GSL_SUCCESS;
}
答案 0 :(得分:0)
设计要从中获取根的功能时要小心。事实上,对于测试,我尝试了一个具有恒定输出的函数。这导致算法丢弃NaN。
答案 1 :(得分:0)
如果您只需要查找单个等式的根,则可以使用gsl_roots
库而不是gsl_multiroots
。 gsl_roots
库有几个二分算法,您可以为其指定范围而不是初始猜测。如果您知道根位于区间(0,1)内,则将其设置为目标区间,算法将永远不会超出该区间。 C ++中演示二分法的最小完整示例如下。如果你不能使用C ++ 11 lambda函数,那么你必须像在原始问题中那样定义目标函数。
#include <iostream>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_roots.h>
using namespace std;
int
main (void)
{
//Set the solver type (bisection method)
gsl_root_fsolver* s = gsl_root_fsolver_alloc(gsl_root_fsolver_bisection);
//Use a lambda to define the objective function.
//This is a parabola with the equation: y = (x-1)^2 - 1
//It has roots at x = 0 and x = 2.
gsl_function F;
F.function = [](double x, void*){return ((x-1) * (x-1)) - 1;};
//Initialize the solver; make a guess that the root is between x = 0.5 and x = 10
gsl_root_fsolver_set(s, &F, 0.5, 10.0);
//Run the solver until the root is found to within 0.001
int status;
do {
gsl_root_fsolver_iterate(s);
double r = gsl_root_fsolver_root(s);
double x_low = gsl_root_fsolver_x_lower(s);
double x_high = gsl_root_fsolver_x_upper(s);
status = gsl_root_test_interval(x_low, x_high, 0, 0.001);
if (status == GSL_SUCCESS)
cout << "Converged" << endl;
cout << "x_low = " << x_low;
cout << "; x_high = " << x_high;
cout << "; root = " << r << endl;
}
while (status == GSL_CONTINUE);
return status;
}