1 /* multimin/directional_minimize.c
3 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Fabrice Rossi
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 take_step (const gsl_vector * x, const gsl_vector * p,
22 double step, double lambda, gsl_vector * x1, gsl_vector * dx)
24 gsl_vector_set_zero (dx);
25 gsl_blas_daxpy (-step * lambda, p, dx);
27 gsl_vector_memcpy (x1, x);
28 gsl_blas_daxpy (1.0, dx, x1);
32 intermediate_point (gsl_multimin_function_fdf * fdf,
33 const gsl_vector * x, const gsl_vector * p,
36 double stepa, double stepc,
38 gsl_vector * x1, gsl_vector * dx, gsl_vector * gradient,
39 double * step, double * f)
45 double u = fabs (pg * lambda * stepc);
46 stepb = 0.5 * stepc * u / ((fc - fa) + u);
49 take_step (x, p, stepb, lambda, x1, dx);
51 fb = GSL_MULTIMIN_FN_EVAL_F (fdf, x1);
54 printf ("trying stepb = %g fb = %.18e\n", stepb, fb);
57 if (fb >= fa && stepb > 0.0)
59 /* downhill step failed, reduce step-size and try again */
70 GSL_MULTIMIN_FN_EVAL_DF(fdf, x1, gradient);
74 minimize (gsl_multimin_function_fdf * fdf,
75 const gsl_vector * x, const gsl_vector * p,
77 double stepa, double stepb, double stepc,
78 double fa, double fb, double fc, double tol,
79 gsl_vector * x1, gsl_vector * dx1,
80 gsl_vector * x2, gsl_vector * dx2, gsl_vector * gradient,
81 double * step, double * f, double * gnorm)
83 /* Starting at (x0, f0) move along the direction p to find a minimum
84 f(x0 - lambda * p), returning the new point x1 = x0-lambda*p,
85 f1=f(x1) and g1 = grad(f) at x1. */
94 double old2 = fabs(w - v);
95 double old1 = fabs(v - u);
97 double stepm, fm, pg, gnorm1;
101 gsl_vector_memcpy (x2, x1);
102 gsl_vector_memcpy (dx2, dx1);
106 *gnorm = gsl_blas_dnrm2 (gradient);
114 return; /* MAX ITERATIONS */
122 double e1 = ((fv - fu) * dw * dw + (fu - fw) * dv * dv);
123 double e2 = 2.0 * ((fv - fu) * dw + (fu - fw) * dv);
130 if (du > 0.0 && du < (stepc - stepb) && fabs(du) < 0.5 * old2)
134 else if (du < 0.0 && du > (stepa - stepb) && fabs(du) < 0.5 * old2)
138 else if ((stepc - stepb) > (stepb - stepa))
140 stepm = 0.38 * (stepc - stepb) + stepb;
144 stepm = stepb - 0.38 * (stepb - stepa);
148 take_step (x, p, stepm, lambda, x1, dx1);
150 fm = GSL_MULTIMIN_FN_EVAL_F (fdf, x1);
153 printf ("trying stepm = %g fm = %.18e\n", stepm, fm);
186 old1 = fabs(u - stepm);
194 gsl_vector_memcpy (x2, x1);
195 gsl_vector_memcpy (dx2, dx1);
197 GSL_MULTIMIN_FN_EVAL_DF (fdf, x1, gradient);
198 gsl_blas_ddot (p, gradient, &pg);
199 gnorm1 = gsl_blas_dnrm2 (gradient);
202 printf ("p: "); gsl_vector_fprintf(stdout, p, "%g");
203 printf ("g: "); gsl_vector_fprintf(stdout, gradient, "%g");
204 printf ("gnorm: %.18e\n", gnorm1);
205 printf ("pg: %.18e\n", pg);
206 printf ("orth: %g\n", fabs (pg * lambda/ gnorm1));
212 if (fabs (pg * lambda / gnorm1) < tol)
217 return; /* SUCCESS */