一维求根
本章描述了寻找任意一维函数根的程序。本库提供了用于各种迭代求解器和收敛测试的低级组件。用户可以将这些组合起来以实现所需的解决方案,并完全访问迭代的中间步骤。每一类方法都使用相同的框架,因此您可以在运行时在求解器之间切换,而不需要重新编译程序。求解器的每个实例都跟踪自己的状态,允许在多线程程序中使用求解器。
头文件gsl_root .h包含根查找函数和相关声明的原型。
36.1 概述
一维寻根算法可分为两类:根交叉法和根修正法。通过交叉求根的算法保证收敛。根交叉法从已知包含一个根的有界区域开始,不断地缩小这个有界区域的大小,直到它将根封闭到所需的误差精度。这为根的位置提供了一个严格的错误估计。
根修正法技术试图提高对根的初步猜测。这个算法只有在开始时“足够接近”一个根,并且为了速度牺牲了严格的误差范围时才收敛。通过近似一个函数在根附近的行为,他们试图找到一个初始猜想的高阶改进。当函数的行为与算法相匹配且初始猜测良好时,根修正法可以确保快速收敛。
在GSL中,这两种算法都在类似的框架中使用。用户为算法提供高级驱动程序,本库提供每个步骤所需的单独函数。迭代有三个主要阶段,步骤是,
• 为算法T初始化解决器状态s
• 使用迭代T更新s
• 测试收敛性,必要时重复迭代。
根交叉法求解器的状态保存在gsl_root_fsolver结构体中。更新过程只使用函数求值(而不是导数)。根修正法求解器的状态保存在gsl_root_fdfsolver结构体中。更新要求用户同时提供函数及其导数(因此命名为fdf)。
36.2 警告说明
注意,根查找函数一次只能搜索一个根。当搜索区域中有多个根时,将返回找到的第一个根;然而,很难预测这将是哪一个根。在大多数情况下,如果您试图在一个有多个根的区域中找到一个根,不会报告错误。
必须注意,当一个函数可能有多个根时(如f(x) = (x−x0)2或f(x) = (x−x0)3。不可能在偶数多重根上使用根交叉法。对于这些算法,初始区间必须包含过零点,其中函数在区间的一端为负,在另一端为正。偶数重的根不与零相交,而只是瞬间接触它。基于根交叉法仍然适用于奇多重根(例如三次根,五次根,…)。根修正法通常适用于更高的根数,但收敛速度较低。在这种情况下,Steffenson算法可以用来加速多重根的收敛。
虽然不是绝对要求f在搜索区域内有一个根,但不应该随意使用数值求根函数来检查根的存在性。有更好的方法来做这个事情,因为很容易出现数值求根查找器失败的情况,所以在您不太了解的函数上采用根查找器不是一个好主意。一般来说,最好是在寻找根之前通过作图直观地检查函数。
36.3 初始化求解器
gsl_root_fsolver
这是一个不需要使用导数的方法来查找根的工作空间。
gsl_root_fdfsolver
这是一个需要使用导数的方法来查找根的工作空间
gsl_root_fsolver * gsl_root_fsolver_alloc(const gsl_root_fsolver_type * T)
本函数返回一个指针,指向新分配的T类型求解器实例。例如,下面的代码创建了一个二分求解器实例:
const gsl_root_fsolver_type * T = gsl_root_fsolver_bisection; gsl_root_fsolver * s = gsl_root_fsolver_alloc (T); |
如果没有足够的内存来创建求解器,则函数返回一个空指针,错误处理程序将使用错误代码GSL_ENOMEM调用。
gsl_root_fdfsolver * gsl_root_fdfsolver_alloc(const gsl_root_fdfsolver_type * T)
本函数返回一个指针,指向新分配的基于派生的T型求解器实例。例如,下面的代码创建了一个Newton-Raphson求解器实例:
const gsl_root_fdfsolver_type * T = gsl_root_fdfsolver_newton; gsl_root_fdfsolver * s = gsl_root_fdfsolver_alloc (T); |
如果没有足够的内存来创建求解器,则函数返回一个空指针,错误处理程序将使用错误代码GSL_ENOMEM调用。
int gsl_root_fsolver_set(gsl_root_fsolver * s, gsl_function * f, double x_lower,
double x_upper)
本函数用函数f和初始搜索区间[x_lower, x_upper]初始化,或重新初始化,一个已经存在的求解器s。
int gsl_root_fdfsolver_set(gsl_root_fdfsolver * s, gsl_function_fdf * fdf, double root)
本函数用函数和导数fdf以及初始的猜想根初始化,或重新初始化,一个已经存在的求解器。
void gsl_root_fsolver_free(gsl_root_fsolver * s)
void gsl_root_fdfsolver_free(gsl_root_fdfsolver * s)
这些函数释放了与求解器s有关的所有内存。
const char * gsl_root_fsolver_name(const gsl_root_fsolver * s)
const char * gsl_root_fdfsolver_name(const gsl_root_fdfsolver * s)
这些函数返回一个指向求解器名称的指针。例如:
printf ("s is a '%s' solver\n", gsl_root_fsolver_name (s)); |
打印出类似如下内容:s is a 'bisection' solver.