尝试nan的gsl multiroot迭代?

时间:2014-06-04 03:59:14

标签: c gsl

我正在尝试找到输入到我的代码的正确参数,以产生所需的结果。而不是猜测和检查我使用根查找找到给出所需结果的参数。有两个变量可以自由变化,但我在运行根查找器时遇到了困难。我更改了代码以单独解决每个变量,并发现我在优化一个变量时遇到了问题。

似乎问题是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;
}

2 个答案:

答案 0 :(得分:0)

设计要从中获取根的功能时要小心。事实上,对于测试,我尝试了一个具有恒定输出的函数。这导致算法丢弃NaN。

答案 1 :(得分:0)

如果您只需要查找单个等式的根,则可以使用gsl_roots库而不是gsl_multirootsgsl_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;
}