You must provide @math{n} functions of @math{n} variables for the root finders to operate on. In order to allow for general parameters the functions are defined by the following data types:
int (* f) (const gsl_vector * x, void * params, gsl_vector * f)
size_t n
void * params
Here is an example using Powell's test function,
with @math{A = 10^4}. The following code defines a
gsl_multiroot_function
system F
which you could pass to a
solver:
struct powell_params { double A; }; int powell (gsl_vector * x, void * p, gsl_vector * f) { struct powell_params * params = *(struct powell_params *)p; double A = (params->A); double x0 = gsl_vector_get(x,0); double x1 = gsl_vector_get(x,1); gsl_vector_set (f, 0, A * x0 * x1 - 1) gsl_vector_set (f, 1, (exp(-x0) + exp(-x1) - (1.0 + 1.0/A))) return GSL_SUCCESS } gsl_multiroot_function F; struct powell_params params = { 10000.0 }; F.function = &powell; F.n = 2; F.params = ¶ms;
int (* f) (const gsl_vector * x, void * params, gsl_vector * f)
int (* df) (const gsl_vector * x, void * params, gsl_matrix * J)
int (* fdf) (const gsl_vector * x, void * params, gsl_vector * f, gsl_matrix * J)
size_t n
void * params
The example of Powell's test function defined above can be extended to include analytic derivatives using the following code,
int powell_df (gsl_vector * x, void * p, gsl_matrix * J) { struct powell_params * params = *(struct powell_params *)p; double A = (params->A); double x0 = gsl_vector_get(x,0); double x1 = gsl_vector_get(x,1); gsl_vector_set (J, 0, 0, A * x1) gsl_vector_set (J, 0, 1, A * x0) gsl_vector_set (J, 1, 0, -exp(-x0)) gsl_vector_set (J, 1, 1, -exp(-x1)) return GSL_SUCCESS } int powell_fdf (gsl_vector * x, void * p, gsl_matrix * f, gsl_matrix * J) { struct powell_params * params = *(struct powell_params *)p; double A = (params->A); double x0 = gsl_vector_get(x,0); double x1 = gsl_vector_get(x,1); double u0 = exp(-x0); double u1 = exp(-x1); gsl_vector_set (f, 0, A * x0 * x1 - 1) gsl_vector_set (f, 1, u0 + u1 - (1 + 1/A)) gsl_vector_set (J, 0, 0, A * x1) gsl_vector_set (J, 0, 1, A * x0) gsl_vector_set (J, 1, 0, -u0) gsl_vector_set (J, 1, 1, -u1) return GSL_SUCCESS } gsl_multiroot_function_fdf FDF; FDF.f = &powell_f; FDF.df = &powell_df; FDF.fdf = &powell_fdf; FDF.n = 2; FDF.params = 0;
Note that the function powell_fdf
is able to reuse existing terms
from the function when calculating the Jacobian, thus saving time.