fastglmm
Massively scalable generalized linear mixed models
Loading...
Searching...
No Matches
local_min.h
Go to the documentation of this file.
1#ifndef LOCAL_MIN_H
2#define LOCAL_MIN_H
3
4
5# include <cfloat>
6# include <cmath>
7# include <cstdlib>
8# include <iostream>
9
10using namespace std;
11
12// Adapted from
13// https://people.sc.fsu.edu/~jburkardt/cpp_src/local_min/local_min.cpp
14
15// pass this object to local_min,
16// so pass void * arguments too
18{
19 double (* function) (double x, void * params);
20 void * params;
21};
22
23//****************************************************************************80
24
25inline double local_min ( double a, double b, double t, funcStruct *f, double &x, int &calls )
26
27//****************************************************************************80
28//
29// Purpose:
30//
31// local_min() seeks a local minimum of a function F(X) in an interval [A,B].
32//
33// Discussion:
34//
35// If the function F is defined on the interval (A,B), then local_min
36// finds an approximation X to the point at which F attatains its minimum
37// (or the appropriate limit point), and returns the value of F at X.
38//
39// T and EPS define a tolerance TOL = EPS * abs ( X ) + T.
40// F is never evaluated at two points closer than TOL.
41//
42// If F is delta-unimodal for some delta less than TOL, the X approximates
43// the global minimum of F with an error less than 3*TOL.
44//
45// If F is not delta-unimodal, then X may approximate a local, but
46// perhaps non-global, minimum.
47//
48// The method used is a combination of golden section search and
49// successive parabolic interpolation. Convergence is never much slower
50// than that for a Fibonacci search. If F has a continuous second
51// derivative which is positive at the minimum (which is not at A or
52// B), then, ignoring rounding errors, convergence is superlinear, and
53// usually of the order of about 1.3247.
54//
55// Licensing:
56//
57// This code is distributed under the MIT license.
58//
59// Modified:
60//
61// 30 May 2021
62//
63// Author:
64//
65// Original FORTRAN77 version by Richard Brent.
66// C++ version by John Burkardt.
67//
68// Reference:
69//
70// Richard Brent,
71// Algorithms for Minimization Without Derivatives,
72// Dover, 2002,
73// ISBN: 0-486-41998-3,
74// LC: QA402.5.B74.
75//
76// Input:
77//
78// double A, B, the endpoints of the interval.
79//
80// double T, a positive absolute error tolerance.
81//
82// double F(double x), the name of a user-supplied function.
83//
84// Output:
85//
86// double &X, the estimated value of an abscissa
87// for which F attains a local minimum value in [A,B].
88//
89// int &CALLS: the number of calls to F.
90//
91// double LOCAL_MIN, the value F(X).
92//
93{
94 double c;
95 double d;
96 double e;
97 double eps;
98 double fu;
99 double fv;
100 double fw;
101 double fx;
102 double m;
103 double p;
104 double q;
105 double r;
106 double sa;
107 double sb;
108 double t2;
109 double tol;
110 double u;
111 double v;
112 double w;
113
114 calls = 0;
115//
116// C is the square of the inverse of the golden ratio.
117//
118 c = 0.5 * ( 3.0 - sqrt ( 5.0 ) );
119
120 eps = sqrt ( DBL_EPSILON );
121
122 sa = a;
123 sb = b;
124 x = sa + c * ( b - a );
125 w = x;
126 v = w;
127 e = 0.0;
128 // fx = f ( x );
129 fx = f->function(x, f->params);
130 calls = calls + 1;
131 fw = fx;
132 fv = fw;
133
134 for ( ; ; )
135 {
136 m = 0.5 * ( sa + sb ) ;
137 tol = eps * fabs ( x ) + t;
138 t2 = 2.0 * tol;
139//
140// Check the stopping criterion.
141//
142 if ( fabs ( x - m ) <= t2 - 0.5 * ( sb - sa ) )
143 {
144 break;
145 }
146//
147// Fit a parabola.
148//
149 r = 0.0;
150 q = r;
151 p = q;
152
153 if ( tol < fabs ( e ) )
154 {
155 r = ( x - w ) * ( fx - fv );
156 q = ( x - v ) * ( fx - fw );
157 p = ( x - v ) * q - ( x - w ) * r;
158 q = 2.0 * ( q - r );
159 if ( 0.0 < q )
160 {
161 p = - p;
162 }
163 q = fabs ( q );
164 r = e;
165 e = d;
166 }
167
168 if ( fabs ( p ) < fabs ( 0.5 * q * r ) &&
169 q * ( sa - x ) < p &&
170 p < q * ( sb - x ) )
171 {
172//
173// Take the parabolic interpolation step.
174//
175 d = p / q;
176 u = x + d;
177//
178// F must not be evaluated too close to A or B.
179//
180 if ( ( u - sa ) < t2 || ( sb - u ) < t2 )
181 {
182 if ( x < m )
183 {
184 d = tol;
185 }
186 else
187 {
188 d = - tol;
189 }
190 }
191 }
192//
193// A golden-section step.
194//
195 else
196 {
197 if ( x < m )
198 {
199 e = sb - x;
200 }
201 else
202 {
203 e = sa - x;
204 }
205 d = c * e;
206 }
207//
208// F must not be evaluated too close to X.
209//
210 if ( tol <= fabs ( d ) )
211 {
212 u = x + d;
213 }
214 else if ( 0.0 < d )
215 {
216 u = x + tol;
217 }
218 else
219 {
220 u = x - tol;
221 }
222
223 // fu = f ( u );
224 fu = f->function(u, f->params);
225 calls = calls + 1;
226//
227// Update A, B, V, W, and X.
228//
229 if ( fu <= fx )
230 {
231 if ( u < x )
232 {
233 sb = x;
234 }
235 else
236 {
237 sa = x;
238 }
239 v = w;
240 fv = fw;
241 w = x;
242 fw = fx;
243 x = u;
244 fx = fu;
245 }
246 else
247 {
248 if ( u < x )
249 {
250 sa = u;
251 }
252 else
253 {
254 sb = u;
255 }
256
257 if ( fu <= fw || w == x )
258 {
259 v = w;
260 fv = fw;
261 w = u;
262 fw = fu;
263 }
264 else if ( fu <= fv || v == x || v == w )
265 {
266 v = u;
267 fv = fu;
268 }
269 }
270 }
271 return fx;
272}
273#endif
274
double local_min(double a, double b, double t, funcStruct *f, double &x, int &calls)
Definition local_min.h:25
Definition local_min.h:18
double(* function)(double x, void *params)
Definition local_min.h:19
void * params
Definition local_min.h:20