gsl_multimin__directional_minimize.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /* multimin/directional_minimize.c
  2. *
  3. * Copyright (C) 1996, 1997, 1998, 1999, 2000 Fabrice Rossi
  4. *
  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.
  9. *
  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.
  14. *
  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.
  18. */
  19. static void
  20. take_step (const gsl_vector * x, const gsl_vector * p,
  21. double step, double lambda, gsl_vector * x1, gsl_vector * dx)
  22. {
  23. gsl_vector_set_zero (dx);
  24. gsl_blas_daxpy (-step * lambda, p, dx);
  25. gsl_vector_memcpy (x1, x);
  26. gsl_blas_daxpy (1.0, dx, x1);
  27. }
  28. static void
  29. intermediate_point (gsl_multimin_function_fdf * fdf,
  30. const gsl_vector * x, const gsl_vector * p,
  31. double lambda,
  32. double pg,
  33. double stepa, double stepc,
  34. double fa, double fc,
  35. gsl_vector * x1, gsl_vector * dx, gsl_vector * gradient,
  36. double * step, double * f)
  37. {
  38. double stepb, fb;
  39. trial:
  40. {
  41. double u = fabs (pg * lambda * stepc);
  42. stepb = 0.5 * stepc * u / ((fc - fa) + u);
  43. }
  44. take_step (x, p, stepb, lambda, x1, dx);
  45. fb = GSL_MULTIMIN_FN_EVAL_F (fdf, x1);
  46. #ifdef DEBUG
  47. printf ("trying stepb = %g fb = %.18e\n", stepb, fb);
  48. #endif
  49. if (fb >= fa && stepb > 0.0)
  50. {
  51. /* downhill step failed, reduce step-size and try again */
  52. fc = fb;
  53. stepc = stepb;
  54. goto trial;
  55. }
  56. #ifdef DEBUG
  57. printf ("ok!\n");
  58. #endif
  59. *step = stepb;
  60. *f = fb;
  61. GSL_MULTIMIN_FN_EVAL_DF(fdf, x1, gradient);
  62. }
  63. static void
  64. minimize (gsl_multimin_function_fdf * fdf,
  65. const gsl_vector * x, const gsl_vector * p,
  66. double lambda,
  67. double stepa, double stepb, double stepc,
  68. double fa, double fb, double fc, double tol,
  69. gsl_vector * x1, gsl_vector * dx1,
  70. gsl_vector * x2, gsl_vector * dx2, gsl_vector * gradient,
  71. double * step, double * f, double * gnorm)
  72. {
  73. /* Starting at (x0, f0) move along the direction p to find a minimum
  74. f(x0 - lambda * p), returning the new point x1 = x0-lambda*p,
  75. f1=f(x1) and g1 = grad(f) at x1. */
  76. double u = stepb;
  77. double v = stepa;
  78. double w = stepc;
  79. double fu = fb;
  80. double fv = fa;
  81. double fw = fc;
  82. double old2 = fabs(w - v);
  83. double old1 = fabs(v - u);
  84. double stepm, fm, pg, gnorm1;
  85. int iter = 0;
  86. gsl_vector_memcpy (x2, x1);
  87. gsl_vector_memcpy (dx2, dx1);
  88. *f = fb;
  89. *step = stepb;
  90. *gnorm = gsl_blas_dnrm2 (gradient);
  91. mid_trial:
  92. iter++;
  93. if (iter > 10)
  94. {
  95. return; /* MAX ITERATIONS */
  96. }
  97. {
  98. double dw = w - u;
  99. double dv = v - u;
  100. double du = 0.0;
  101. double e1 = ((fv - fu) * dw * dw + (fu - fw) * dv * dv);
  102. double e2 = 2.0 * ((fv - fu) * dw + (fu - fw) * dv);
  103. if (e2 != 0.0)
  104. {
  105. du = e1 / e2;
  106. }
  107. if (du > 0.0 && du < (stepc - stepb) && fabs(du) < 0.5 * old2)
  108. {
  109. stepm = u + du;
  110. }
  111. else if (du < 0.0 && du > (stepa - stepb) && fabs(du) < 0.5 * old2)
  112. {
  113. stepm = u + du;
  114. }
  115. else if ((stepc - stepb) > (stepb - stepa))
  116. {
  117. stepm = 0.38 * (stepc - stepb) + stepb;
  118. }
  119. else
  120. {
  121. stepm = stepb - 0.38 * (stepb - stepa);
  122. }
  123. }
  124. take_step (x, p, stepm, lambda, x1, dx1);
  125. fm = GSL_MULTIMIN_FN_EVAL_F (fdf, x1);
  126. #ifdef DEBUG
  127. printf ("trying stepm = %g fm = %.18e\n", stepm, fm);
  128. #endif
  129. if (fm > fb)
  130. {
  131. if (fm < fv)
  132. {
  133. w = v;
  134. v = stepm;
  135. fw = fv;
  136. fv = fm;
  137. }
  138. else if (fm < fw)
  139. {
  140. w = stepm;
  141. fw = fm;
  142. }
  143. if (stepm < stepb)
  144. {
  145. stepa = stepm;
  146. fa = fm;
  147. }
  148. else
  149. {
  150. stepc = stepm;
  151. fc = fm;
  152. }
  153. goto mid_trial;
  154. }
  155. else if (fm <= fb)
  156. {
  157. old2 = old1;
  158. old1 = fabs(u - stepm);
  159. w = v;
  160. v = u;
  161. u = stepm;
  162. fw = fv;
  163. fv = fu;
  164. fu = fm;
  165. gsl_vector_memcpy (x2, x1);
  166. gsl_vector_memcpy (dx2, dx1);
  167. GSL_MULTIMIN_FN_EVAL_DF (fdf, x1, gradient);
  168. gsl_blas_ddot (p, gradient, &pg);
  169. gnorm1 = gsl_blas_dnrm2 (gradient);
  170. #ifdef DEBUG
  171. printf ("p: "); gsl_vector_fprintf(stdout, p, "%g");
  172. printf ("g: "); gsl_vector_fprintf(stdout, gradient, "%g");
  173. printf ("gnorm: %.18e\n", gnorm1);
  174. printf ("pg: %.18e\n", pg);
  175. printf ("orth: %g\n", fabs (pg * lambda/ gnorm1));
  176. #endif
  177. *f = fm;
  178. *step = stepm;
  179. *gnorm = gnorm1;
  180. if (fabs (pg * lambda / gnorm1) < tol)
  181. {
  182. #ifdef DEBUG
  183. printf("ok!\n");
  184. #endif
  185. return; /* SUCCESS */
  186. }
  187. if (stepm < stepb)
  188. {
  189. stepc = stepb;
  190. fc = fb;
  191. stepb = stepm;
  192. fb = fm;
  193. }
  194. else
  195. {
  196. stepa = stepb;
  197. fa = fb;
  198. stepb = stepm;
  199. fb = fm;
  200. }
  201. goto mid_trial;
  202. }
  203. }