Using the GSL function minimization routines to minimize the twodimensional function used as an example in the Optimization Methods note using the Steepest Descent Method Define the functions ex4_f, ex4_df, and ex4_fdf 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 ex4_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); } #include<stdio.h> #include<stdlib.h> #include<gsl/gsl_vector.h> void ex4_df (const gsl_vector *v, void *m, gsl_vector *df) { double x,y,g0,g1; x = gsl_vector_get(v, 0); y = gsl_vector_get(v, 1); g0= 200.0 * (x - 15.0) - 40.0* (28.0-x) - 200.0*(y-x) - 40.0*(38.0-x-y); g1= 200.0*(y-x)- 40.0*(38.0-x-y); gsl_vector_set(df, 0, g0); gsl_vector_set(df, 1, g1); } #include<stdio.h> #include<stdlib.h> #include<gsl/gsl_vector.h> double ex4_f (const gsl_vector *, void *); void ex4_df (const gsl_vector *, void *, gsl_vector *); /* Compute both f and df together. */ void ex4_fdf (const gsl_vector *x, void *m, double *f, gsl_vector *df) { *f = ex4_f(x, m); ex4_df(x, m, df); } The staring values are set using the statements: x = gsl_vector_alloc (np); gsl_vector_set (x, 0, 10.0); gsl_vector_set (x, 1, 14.0); Then we use s = gsl_multimin_fdfminimizer_alloc (gsl_multimin_fdfminimizer_steepest_descent, np); and gsl_multimin_fdfminimizer_set (s, &ex4_funs, x, 0.1, 0.01); to initialize the minimizer to minimize the function ex4_funs, starting from the initial point x. The steepest descent algorithm follows the downhill gradient of the function at each step. When a downhill step is successful the step-size (here =0.1) is increased by a factor of two. If the downhill step leads to a higher function value then the algorithm backtracks and the step size is decreased using the parameter tol (here=0.01). The ex4_funs function is of the data type gsl_multimin_function_fdf which is a structure. It is declared in the statement gsl_multimin_function_fdf ex4_funs; We set values to the components of ex4_funs using the statements: ex4_funs.f = &ex4_f; ex4_funs.df = &ex4_df; ex4_funs.fdf = &ex4_fdf; ex4_funs.n = np; ex4_funs.params = (void *)&par; /* Address of the function */ /* Address of the first derivative */ /* Address of the combined function */ /* Dimension of the problem*/ /* Additional parms to define the fn*/ These are followed by the main loop that uses the function gsl_multimin_fdfminimizer_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. The function gsl_multimin_test_gradient is used to test the norm of the gradient against a tolerance. The test returns GSL_SUCCESS if the absolute gradient is below the tolerance. #include<stdio.h> #include<stdlib.h> #include<gsl/gsl_multimin.h> #include<gsl/gsl_vector.h> double ex4_f (const gsl_vector *, void *); void ex4_df (const gsl_vector *, void *, gsl_vector *); void ex4_fdf (const gsl_vector *, void *, double *,gsl_vector *); int main(void) { size_t iter = 0, np=2; int status; gsl_multimin_fdfminimizer *s; gsl_vector *ss,*x; double par; /* Initial vertex size vector */ ss = gsl_vector_alloc (np); /* Set all step sizes to 1 */ gsl_vector_set_all (ss,2.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 */ gsl_multimin_function_fdf ex4_funs; ex4_funs.f = &ex4_f; ex4_funs.df = &ex4_df; ex4_funs.fdf = &ex4_fdf; ex4_funs.n = np; ex4_funs.params = (void *)&par; s = gsl_multimin_fdfminimizer_alloc (gsl_multimin_fdfminimizer_steepest_descent, np); gsl_multimin_fdfminimizer_set (s, &ex4_funs, x, 0.1, 0.01); do { iter++; status = gsl_multimin_fdfminimizer_iterate (s); if (status) break; status = gsl_multimin_test_gradient (s->gradient, .001); if (status == GSL_SUCCESS) printf ("Minimum found at:\n"); printf ("%5zd %15.10f %15.10f %17.10f\n", iter, gsl_vector_get (s->x, 0), gsl_vector_get (s->x, 1), s->f); } while (status == GSL_CONTINUE && iter < 1000); gsl_multimin_fdfminimizer_free (s); gsl_vector_free (x); return 0; } Compiling and running as usual: $ gcc -Wall -c ex4.c $ gcc -Wall -c ex4_f.c $ gcc -Wall -c ex4_df.c $ gcc -Wall -c ex4_fdf.c $ gcc –Wall -I/usr/local/include -o ex4.exe ex4.o ex4_f.o ex4_df.o ex4_fdf.o -lgsl - lgslcblas –lm $ ./ex4.exe 1 10.0996977831 13.9922313416 14193.5830308027 2 10.2991625595 13.9776093392 13595.8170475800 3 10.6983540041 13.9521890610 12460.2591775553 4 11.4976267683 13.9180855650 10426.3762711687 5 13.0975728343 13.9312227560 7280.4133637707 6 16.2512679276 14.4736315124 4291.7621344991 7 17.7448996335 20.6968994905 3732.1231152058 8 17.8192544344 20.5927104144 3640.3712700156 9 17.8199654974 20.5916460886 3639.4924020177 10 17.8213869401 20.5895169806 3637.7369357875 11 17.8242270856 20.5852569367 3634.2350783967 12 17.8298963631 20.5767295167 3627.2676317901 13 17.8411904332 20.5596451853 3613.4775518256 14 17.8635971063 20.5253572486 3586.4745265093 15 17.9076551137 20.4562936664 3534.7593536356 16 17.9924922445 20.3161287391 3440.3388070236 17 18.1465746387 20.0269353813 3286.0707894928 18 18.3629283970 19.4083177443 3098.7221772648 19 17.9360104226 18.1690728284 2964.9394426503 20 17.9122761637 18.1802029554 2963.3298841092 21 17.9120382813 18.1803130982 2963.3157308607 22 17.9115625036 18.1805333559 2963.2875397378 23 17.9106108964 18.1809737595 2963.2316189865 24 17.9087074717 18.1818541124 2963.1216234446 25 17.9048997566 18.1836129448 2962.9090160580 26 27 28 29 30 17.8972806463 17.8820256765 17.8514255463 17.8508048261 17.8507986158 . . . . . . . 50 17.8241650566 51 17.8235213612 52 17.8223841830 53 17.8215573403 54 17.8215176663 55 17.8215172852 56 17.8215165231 57 17.8215150005 58 17.8215119609 59 17.8215059046 60 17.8214938880 61 17.8214702704 62 17.8214250111 63 17.8213463078 . . . . . . . 70 17.8213434821 71 17.8213451652 72 17.8213485325 73 17.8213552712 74 17.8213687668 75 17.8213958541 76 17.8214508536 77 17.8214498251 78 17.8214498148 79 17.8214497943 80 17.8214497532 81 17.8214496710 82 17.8214495066 83 17.8214491779 84 17.8214485207 85 17.8214472071 86 17.8214445837 87 17.8214393550 88 17.8214290142 89 17.8214288582 90 17.8214288567 91 17.8214288537 92 17.8214288477 93 17.8214288358 94 17.8214288119 95 17.8214287646 Minimum found at: 96 17.8214286714 18.1871226317 18.1941055304 18.2078725901 18.2081276713 18.2081302146 . . . . . . . 18.2175624944 18.2172781842 18.2164490102 18.2137584438 18.2137983825 18.2137987968 18.2137996256 18.2138012846 18.2138046077 18.2138112749 18.2138246958 18.2138519039 18.2139079743 18.2140287012 . . . . . . . 18.2143136645 18.2143129097 18.2143114021 18.2143083961 18.2143024254 18.2142907036 18.2142692665 18.2142698463 18.2142698521 18.2142698637 18.2142698870 18.2142699335 18.2142700266 18.2142702128 18.2142705856 18.2142713326 18.2142728333 18.2142758661 18.2142821286 18.2142823133 18.2142823152 18.2142823190 18.2142823266 18.2142823418 18.2142823723 18.2142824335 2962.5133348117 2961.8400944041 2960.9659574252 2960.9548917724 2960.9547823845 . . . . . . . . 2960.7159366955 2960.7154094264 2960.7147356993 2960.7143339189 2960.7143230655 2960.7143229652 2960.7143227650 2960.7143223667 2960.7143215779 2960.7143200311 2960.7143170607 2960.7143116089 2960.7143026246 2960.7142918823 . . . . . . . . 2960.7142879262 2960.7142878355 2960.7142876599 2960.7142873315 2960.7142867661 2960.7142860003 2960.7142859245 2960.7142859069 2960.7142859067 2960.7142859064 2960.7142859057 2960.7142859043 2960.7142859016 2960.7142858961 2960.7142858856 2960.7142858653 2960.7142858287 2960.7142857708 2960.7142857161 2960.7142857158 2960.7142857158 2960.7142857158 2960.7142857158 2960.7142857158 2960.7142857158 2960.7142857157 18.2142825570 2960.7142857155