Using the GSL function minimization routines to minimize the two-

advertisement
Using the GSL function minimization routines to minimize the twodimensional function used as an example in the Optimization Methods
note using the Nelder-Mead Simplex Method
Define the function using the GSL matrix and vector facility (note that it is possible to
pass a parameter vector to be used in this definition but we do not make use of it here)
#include<stdio.h>
#include<stdlib.h>
#include<gsl/gsl_vector.h>
double my_f (const gsl_vector *v, void *params)
{
double x, y;
double *dp = (double *)params;
x = gsl_vector_get(v, 0);
y = gsl_vector_get(v, 1);
return 100.0 * pow((x - 15.0),2) + 20.0* pow((28.0-x),2) + 100.0*pow((y-x),2) +
20.0*pow((38.0-x-y),2);
}
Below we use
s = gsl_multimin_fminimizer_alloc (gsl_multimin_fminimizer_nmsimplex , np);
and
gsl_multimin_fminimizer_set (s, &ex4_fn, x, ss);
to initialize the minimizer to minimize the function ex4_fn, starting from the initial point
x. The size of the initial trial steps is given in vector ss. The ex4_fn function is of the data
type gsl_multimin_function which is a structure. We set values to the components of
ex4_fn using the statements:
ex4_fn.f = &my_f;
ex4_fn.n = np;
ex4_fn.params = (void *)∥
/* Address of the function */
/* Dimension of the problem*/
/* Additional parms to define the fn*/
and the step size vector ss using the statements:
ss = gsl_vector_alloc (np);
gsl_vector_set_all (ss, 1.0);
These are followed by the main loop that uses the function
gsl_multimin_fminimizer_iterate to drive the iteration. This function performs one
iteration to update the state of the minimizer. If the iteration encounters an unexpected
problem then an error code will be returned. It also calculates the minimizer specific
characteristic size as the average distance from the geometrical center of the simplex to
all its vertices. This size can be used as a stopping criteria, as the simplex contracts itself
near the minimum. The size is returned by the function gsl_multimin_fminimizer_size.
#include<stdio.h>
#include<stdlib.h>
#include<gsl/gsl_multimin.h>
double my_f (const gsl_vector *, void *);
int main(void)
{
size_t np = 2;
/* The parameter vector for the function defn: UNUSED */
double par[2] = {1.0, 2.0};
gsl_multimin_fminimizer *s ;
gsl_vector *ss, *x;
gsl_multimin_function ex4_fn;
size_t iter = 0, i;
int status;
double size;
/* Initial vertex size vector */
ss = gsl_vector_alloc (np);
/* Set all step sizes to 1 */
gsl_vector_set_all (ss, 1.0);
/* Starting point */
x = gsl_vector_alloc (np);
gsl_vector_set (x, 0, 10.0);
gsl_vector_set (x, 1, 14.0);
/* Initialize method and iterate */
ex4_fn.f = &my_f;
ex4_fn.n = np;
ex4_fn.params = (void *)&par
s = gsl_multimin_fminimizer_alloc (gsl_multimin_fminimizer_nmsimplex , np);
gsl_multimin_fminimizer_set (s, &ex4_fn, x, ss);
do
{
iter++;
status = gsl_multimin_fminimizer_iterate(s);
if (status)
break;
size = gsl_multimin_fminimizer_size (s);
status = gsl_multimin_test_size (size, 1e-3);
if (status == GSL_SUCCESS)
{
printf ("converged to minimum at\n");
}
printf ("%5d ", iter);
for (i = 0; i < np; i++)
{
printf ("%10.3e ", gsl_vector_get (s->x, i));
}
printf ("f() = %7.3f size = %.3f\n", s->fval, size);
}
while (status == GSL_CONTINUE && iter < 100);
gsl_vector_free(x);
gsl_vector_free(ss);
gsl_multimin_fminimizer_free (s);
return status;
}
Compiling and running as usual:
gcc -c nmfunc.c
gcc -o nmsimplex.exe nmsimplex.c nmfunc.o -lgsl -lgslcblas –lm
./nmsimplex.exe > nmsimplex.output
Results:
1 1.100e+01 1.400e+01 f() = 11660.000 size = 0.654
2 1.300e+01 1.250e+01 f() = 8050.000 size = 1.082
3 1.400e+01 1.375e+01 f() = 6127.500 size = 1.372
4 1.400e+01 1.375e+01 f() = 6127.500 size = 1.372
5 1.700e+01 1.350e+01 f() = 5170.000 size = 1.372
6 1.450e+01 1.638e+01 f() = 5036.875 size = 1.823
7 1.925e+01 1.731e+01 f() = 3754.219 size = 2.517
8 1.925e+01 1.731e+01 f() = 3754.219 size = 2.517
9 1.625e+01 1.756e+01 f() = 3440.469 size = 1.823
10 1.725e+01 1.881e+01 f() = 3136.719 size = 1.372
11 1.800e+01 1.775e+01 f() = 3007.500 size = 0.898
12 1.831e+01 1.864e+01 f() = 3006.904 size = 0.638
13 1.770e+01 1.850e+01 f() = 2979.621 size = 0.458
14 1.800e+01 1.816e+01 f() = 2970.597 size = 0.318
15 1.762e+01 1.818e+01 f() = 2969.089 size = 0.225
16 1.776e+01 1.834e+01 f() = 2964.699 size = 0.171
17 1.785e+01 1.821e+01 f() = 2960.902 size = 0.114
18 1.785e+01 1.821e+01 f() = 2960.902 size = 0.079
19 1.785e+01 1.821e+01 f() = 2960.902 size = 0.057
20 1.785e+01 1.821e+01 f() = 2960.902 size = 0.057
21 1.785e+01 1.821e+01 f() = 2960.902 size = 0.040
22 1.780e+01 1.821e+01 f() = 2960.817 size = 0.028
23 1.782e+01 1.823e+01 f() = 2960.757 size = 0.021
24 1.783e+01 1.821e+01 f() = 2960.724 size = 0.014
25 1.783e+01 1.821e+01 f() = 2960.724 size = 0.010
26 1.783e+01 1.821e+01 f() = 2960.724 size = 0.010
27 1.782e+01 1.821e+01 f() = 2960.717 size = 0.007
28 1.782e+01 1.821e+01 f() = 2960.717 size = 0.007
29 1.782e+01 1.821e+01 f() = 2960.717 size = 0.005
30 1.782e+01 1.822e+01 f() = 2960.716 size = 0.004
31 1.782e+01 1.822e+01 f() = 2960.715 size = 0.003
32 1.782e+01 1.821e+01 f() = 2960.714 size = 0.002
33 1.782e+01 1.821e+01 f() = 2960.714 size = 0.001
34 1.782e+01 1.821e+01 f() = 2960.714 size = 0.001
converged to minimum at
35 1.782e+01 1.821e+01 f() = 2960.714 size = 0.001
Download