GteMinimize1.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <LowLevel/GteLogger.h>
11 #include <cmath>
12 #include <functional>
13 
14 // The interval [t0,t1] provided to GetMinimum(Real,Real,Real,Real&,Real&)
15 // is processed by examining subintervals. On each subinteral [a,b], the
16 // values f0 = F(a), f1 = F((a+b)/2), and f2 = F(b) are examined. If
17 // {f0,f1,f2} is monotonic, then [a,b] is subdivided and processed. The
18 // maximum depth of the recursion is limited by 'maxLevel'. If {f0,f1,f2}
19 // is not monotonic, then two cases arise. First, if f1 = min{f0,f1,f2},
20 // then {f0,f1,f2} is said to "bracket a minimum" and GetBracketedMinimum(*)
21 // is called to locate the function minimum. The process uses a form of
22 // bisection called "parabolic interpolation" and the maximum number of
23 // bisection steps is 'maxBracket'. Second, if f1 = max{f0,f1,f2}, then
24 // {f0,f1,f2} brackets a maximum. The minimum search continues recursively
25 // as before on [a,(a+b)/2] and [(a+b)/2,b].
26 
27 namespace gte
28 {
29 
30 template <typename Real>
31 class Minimize1
32 {
33 public:
34  // Construction.
35  Minimize1(std::function<Real(Real)> const& F, int maxLevel,
36  int maxBracket);
37 
38  // Search for a minimum of 'function' on the interval [t0,t1] using an
39  // initial guess of 'tInitial'. The location of the minimum is 'tMin' and
40  // the value of the minimum is 'fMin'.
41  void GetMinimum(Real t0, Real t1, Real tInitial, Real& tMin, Real& fMin);
42 
43 private:
44  // This is called to start the search on [t0,tInitial] and [tInitial,t1].
45  void GetMinimum(Real t0, Real f0, Real t1, Real f1, int level);
46 
47  // This is called recursively to search [a,(a+b)/2] and [(a+b)/2,b].
48  void GetMinimum(Real t0, Real f0, Real tm, Real fm, Real t1, Real f1,
49  int level);
50 
51  // This is called when {f0,f1,f2} brackets a minimum.
52  void GetBracketedMinimum(Real t0, Real f0, Real tm, Real fm, Real t1,
53  Real f1, int level);
54 
55  std::function<Real(Real)> mFunction;
56  int mMaxLevel;
58  Real mTMin, mFMin;
59 };
60 
61 
62 template <typename Real>
63 Minimize1<Real>::Minimize1(std::function<Real(Real)> const& F, int maxLevel,
64  int maxBracket)
65  :
66  mFunction(F),
67  mMaxLevel(maxLevel),
68  mMaxBracket(maxBracket)
69 {
70 }
71 
72 template <typename Real>
73 void Minimize1<Real>::GetMinimum(Real t0, Real t1, Real tInitial,
74  Real& tMin, Real& fMin)
75 {
76  LogAssert(t0 <= tInitial && tInitial <= t1, "Invalid initial t value.");
77 
78  mTMin = std::numeric_limits<Real>::max();
79  mFMin = std::numeric_limits<Real>::max();
80 
81  Real f0 = mFunction(t0);
82  if (f0 < mFMin)
83  {
84  mTMin = t0;
85  mFMin = f0;
86  }
87 
88  Real fInitial = mFunction(tInitial);
89  if (fInitial < mFMin)
90  {
91  mTMin = tInitial;
92  mFMin = fInitial;
93  }
94 
95  Real f1 = mFunction(t1);
96  if (f1 < mFMin)
97  {
98  mTMin = t1;
99  mFMin = f1;
100  }
101 
102  GetMinimum(t0, f0, tInitial, fInitial, t1, f1, mMaxLevel);
103 
104  tMin = mTMin;
105  fMin = mFMin;
106 }
107 
108 template <typename Real>
109 void Minimize1<Real>::GetMinimum(Real t0, Real f0, Real tm, Real fm, Real t1,
110  Real f1, int level)
111 {
112  if (level-- == 0)
113  {
114  return;
115  }
116 
117  if ((t1 - tm)*(f0 - fm) > (tm - t0)*(fm - f1))
118  {
119  // The quadratic fit has positive second derivative at the midpoint.
120  if (f1 > f0)
121  {
122  if (fm >= f0)
123  {
124  // Increasing, repeat on [t0,tm].
125  GetMinimum(t0, f0, tm, fm, level);
126  }
127  else
128  {
129  // Not monotonic, have a bracket.
130  GetBracketedMinimum(t0, f0, tm, fm, t1, f1, level);
131  }
132  }
133  else if (f1 < f0)
134  {
135  if (fm >= f1)
136  {
137  // Decreasing, repeat on [tm,t1].
138  GetMinimum(tm, fm, t1, f1, level);
139  }
140  else
141  {
142  // Not monotonic, have a bracket.
143  GetBracketedMinimum(t0, f0, tm, fm, t1, f1, level);
144  }
145  }
146  else
147  {
148  // Constant, repeat on [t0,tm] and [tm,t1].
149  GetMinimum(t0, f0, tm, fm, level);
150  GetMinimum(tm, fm, t1, f1, level);
151  }
152  }
153  else
154  {
155  // The quadratic fit has a nonpositive second derivative at the
156  // midpoint.
157  if (f1 > f0)
158  {
159  // Repeat on [t0,tm].
160  GetMinimum(t0, f0, tm, fm, level);
161  }
162  else if (f1 < f0)
163  {
164  // Repeat on [tm,t1].
165  GetMinimum(tm, fm, t1, f1, level);
166  }
167  else
168  {
169  // Repeat on [t0,tm] and [tm,t1].
170  GetMinimum(t0, f0, tm, fm, level);
171  GetMinimum(tm, fm, t1, f1, level);
172  }
173  }
174 }
175 
176 template <typename Real>
177 void Minimize1<Real>::GetMinimum(Real t0, Real f0, Real t1, Real f1,
178  int level)
179 {
180  if (level-- == 0)
181  {
182  return;
183  }
184 
185  Real tm = ((Real)0.5)*(t0 + t1);
186  Real fm = mFunction(tm);
187  if (fm < mFMin)
188  {
189  mTMin = tm;
190  mFMin = fm;
191  }
192 
193  if (f0 - ((Real)2)*fm + f1 >(Real)0)
194  {
195  // The quadratic fit has positive second derivative at the midpoint.
196  if (f1 > f0)
197  {
198  if (fm >= f0)
199  {
200  // Increasing, repeat on [t0,tm].
201  GetMinimum(t0, f0, tm, fm, level);
202  }
203  else
204  {
205  // Not monotonic, have a bracket.
206  GetBracketedMinimum(t0, f0, tm, fm, t1, f1, level);
207  }
208  }
209  else if (f1 < f0)
210  {
211  if (fm >= f1)
212  {
213  // Decreasing, repeat on [tm,t1].
214  GetMinimum(tm, fm, t1, f1, level);
215  }
216  else
217  {
218  // Not monotonic, have a bracket.
219  GetBracketedMinimum(t0, f0, tm, fm, t1, f1, level);
220  }
221  }
222  else
223  {
224  // Constant, repeat on [t0,tm] and [tm,t1].
225  GetMinimum(t0, f0, tm, fm, level);
226  GetMinimum(tm, fm, t1, f1, level);
227  }
228  }
229  else
230  {
231  // The quadratic fit has nonpositive second derivative at the
232  // midpoint.
233  if (f1 > f0)
234  {
235  // Repeat on [t0,tm].
236  GetMinimum(t0, f0, tm, fm, level);
237  }
238  else if (f1 < f0)
239  {
240  // Repeat on [tm,t1].
241  GetMinimum(tm, fm, t1, f1, level);
242  }
243  else
244  {
245  // Repeat on [t0,tm] and [tm,t1].
246  GetMinimum(t0, f0, tm, fm, level);
247  GetMinimum(tm, fm, t1, f1, level);
248  }
249  }
250 }
251 
252 template <typename Real>
253 void Minimize1<Real>::GetBracketedMinimum(Real t0, Real f0, Real tm,
254  Real fm, Real t1, Real f1, int level)
255 {
256  for (int i = 0; i < mMaxBracket; ++i)
257  {
258  // Update minimum value.
259  if (fm < mFMin)
260  {
261  mTMin = tm;
262  mFMin = fm;
263  }
264 
265  // Test for convergence. TODO: Expose the epsilon and tolerance
266  // parameters to the caller.
267  Real const epsilon = (Real)1e-08;
268  Real const tolerance = (Real)1e-04;
269  if (std::abs(t1 - t0) <= ((Real)2)*tolerance*std::abs(tm) + epsilon)
270  {
271  break;
272  }
273 
274  // Compute vertex of interpolating parabola.
275  Real dt0 = t0 - tm;
276  Real dt1 = t1 - tm;
277  Real df0 = f0 - fm;
278  Real df1 = f1 - fm;
279  Real tmp0 = dt0*df1;
280  Real tmp1 = dt1*df0;
281  Real denom = tmp1 - tmp0;
282  if (std::abs(denom) < epsilon)
283  {
284  return;
285  }
286 
287  Real tv = tm + ((Real)0.5)*(dt1*tmp1 - dt0*tmp0) / denom;
288  LogAssert(t0 <= tv && tv <= t1, "Vertex not in interval.");
289  Real fv = mFunction(tv);
290  if (fv < mFMin)
291  {
292  mTMin = tv;
293  mFMin = fv;
294  }
295 
296  if (tv < tm)
297  {
298  if (fv < fm)
299  {
300  t1 = tm;
301  f1 = fm;
302  tm = tv;
303  fm = fv;
304  }
305  else
306  {
307  t0 = tv;
308  f0 = fv;
309  }
310  }
311  else if (tv > tm)
312  {
313  if (fv < fm)
314  {
315  t0 = tm;
316  f0 = fm;
317  tm = tv;
318  fm = fv;
319  }
320  else
321  {
322  t1 = tv;
323  f1 = fv;
324  }
325  }
326  else
327  {
328  // The vertex of parabola is already at middle sample point.
329  GetMinimum(t0, f0, tm, fm, level);
330  GetMinimum(tm, fm, t1, f1, level);
331  }
332  }
333 }
334 
335 
336 }
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
Definition: glext.h:9013
#define LogAssert(condition, message)
Definition: GteLogger.h:86
GLint level
Definition: glcorearb.h:103
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition: glext.h:9013
void GetBracketedMinimum(Real t0, Real f0, Real tm, Real fm, Real t1, Real f1, int level)
Definition: GteMinimize1.h:253
std::function< Real(Real)> mFunction
Definition: GteMinimize1.h:55
Minimize1(std::function< Real(Real)> const &F, int maxLevel, int maxBracket)
Definition: GteMinimize1.h:63
void GetMinimum(Real t0, Real t1, Real tInitial, Real &tMin, Real &fMin)
Definition: GteMinimize1.h:73


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:01