# include # include /******************************************************************************/ double glomin_nogoto ( double a, double b, double c, double m, double e, double t, double f ( double x ), double *x, int *calls ) /******************************************************************************/ /* Purpose: glomin_nogoto() seeks a global minimum of a function in an interval. Discussion: This function assumes: * F(X) is twice continuously differentiable over [A,B]; * F''(X) <= M for all X in [A,B]; * the user can supply the value of this upper bound M. Thanks to Hans Bieshaar for supplying several corrections to the code, 03 June 2021. Thanks to Hans Bieshaar for rewriting the code so that it has no goto statements, 13 July 2021. Licensing: This code is distributed under the MIT license. Modified: 13 July 2021 Author: Original FORTRAN77 version by Richard Brent. C version by John Burkardt. Reference: Richard Brent, Algorithms for Minimization Without Derivatives, Dover, 2002, ISBN: 0-486-41998-3, LC: QA402.5.B74. Input: double A, B, the endpoints of the interval. It must be the case that A < B. double C, an initial guess for the global minimizer. If no good guess is known, C = A or B is acceptable. double M, the bound on the second derivative. double E, a positive tolerance, a bound for the absolute error in the evaluation of F(X) for any X in [A,B]. double T, a positive error tolerance. double F ( double x ), a user-supplied function whose global minimum is being sought. Output: double *X: the estimated value of the abscissa for which F attains its global minimum value in [A,B]. int *CALLS: the number of function calls. double GLOMIN_NOGOTO: the value F(X). */ { // Initialization *calls = 0; double a0 = b; *x = a0; double a2 = a; double y0 = f ( b ); *calls = *calls + 1; double yb = y0; double y2 = f ( a ); *calls = *calls + 1; double y = y2; if ( y0 < y ) y = y0; else *x = a; if ( m <= 0.0 || b <= a ) return y; // Nontrivial case (m>0, a 0.0 ? a2 + p / q : r ); double y3; for ( ; ; ) { // inner: if ( a3 < r ) a3 = r; if ( b <= a3 ) { a3 = b; y3 = yb; } else { y3 = f ( a3 ); *calls = *calls + 1; } if ( y3 < y ) { *x = a3; y = y3; } d0 = a3 - a2; if ( a3 <= r ) break; // Inspect the parabolic lower bound on f in (a2, a3) p = 2.0 * ( y2 - y3 ) / ( m * d0 ); if ( ( 1.0 + 9.0 * DBL_EPSILON) * d0 <= fabs ( p ) ) break; if ( 0.5 * m2 * ( d0 * d0 + p * p ) <= ( y2 - y ) + ( y3 - y ) + 2.0 * t ) break; // Halve the step and try again a3 = 0.5 * ( a2 + a3 ); h = h * 0.9; } // end inner loop if ( b <= a3 ) return y; // Prepare for the next step a0 = c; c = a2; a2 = a3; y0 = y1; y1 = y2; y2 = y3; } // end main loop }