GteMinimizeN.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/GteWrapper.h>
11 #include <Mathematics/GteGVector.h>
13 #include <cstring>
14 
15 // The Cartesian-product domain provided to GetMinimum(*) has minimum values
16 // stored in t0[0..d-1] and maximum values stored in t1[0..d-1], where d is
17 // 'dimensions'. The domain is searched along lines through the current
18 // estimate of the minimum location. Each such line is searched for a minimum
19 // using a Minimize1<Real> object. This is called "Powell's Direction Set
20 // Method". The parameters 'maxLevel' and 'maxBracket' are used by
21 // Minimize1<Real>, so read the documentation for that class (in its header
22 // file) to understand what these mean. The input 'maxIterations' is the
23 // number of iterations for the direction-set method.
24 
25 namespace gte
26 {
27 
28 template <typename Real>
29 class MinimizeN
30 {
31 public:
32  // Construction.
33  MinimizeN(int dimensions, std::function<Real(Real const*)> const& F,
34  int maxLevel, int maxBracket, int maxIterations);
35 
36  // Find the minimum on the Cartesian-product domain whose minimum values
37  // are stored in t0[0..d-1] and whose maximum values are stored in
38  // t1[0..d-1], where d is 'dimensions'. An initial guess is specified in
39  // tInitial[0..d-1]. The location of the minimum is tMin[0..d-1] and
40  // the value of the minimum is 'fMin'.
41  void GetMinimum(Real const* t0, Real const* t1, Real const* tInitial,
42  Real* tMin, Real& fMin);
43 
44 private:
45  // The current estimate of the minimum location is mTCurr[0..d-1]. The
46  // direction of the current line to search is mDCurr[0..d-1]. This line
47  // must be clipped against the Cartesian-product domain, a process
48  // implemented in this function. If the line is mTCurr+s*mDCurr, the
49  // clip result is the s-interval [ell0,ell1].
50  void ComputeDomain(Real const* t0, Real const* t1, Real& ell0,
51  Real& ell1);
52 
54  std::function<Real(Real const*)> mFunction;
56  std::vector<GVector<Real>> mDirections;
61  Real mFCurr;
63 };
64 
65 
66 template <typename Real>
68  std::function<Real(Real const*)> const& F, int maxLevel, int maxBracket,
69  int maxIterations)
70  :
71  mDimensions(dimensions),
72  mFunction(F),
73  mMaxIterations(maxIterations),
74  mDirections(dimensions + 1),
75  mDConjIndex(dimensions),
76  mDCurrIndex(0),
77  mTCurr(dimensions),
78  mTSave(dimensions),
79  mMinimizer(
80  [this](Real t)
81 {
82  return mFunction(&(mTCurr + t*mDirections[mDCurrIndex])[0]);
83 },
84 maxLevel, maxBracket)
85 {
86  for (auto& direction : mDirections)
87  {
88  direction.SetSize(dimensions);
89  }
90 }
91 
92 template <typename Real>
93 void MinimizeN<Real>::GetMinimum(Real const* t0, Real const* t1,
94  Real const* tInitial, Real* tMin, Real& fMin)
95 {
96  // The initial guess.
97  size_t numBytes = mDimensions*sizeof(Real);
98  mFCurr = mFunction(tInitial);
99  Memcpy(&mTSave[0], tInitial, numBytes);
100  Memcpy(&mTCurr[0], tInitial, numBytes);
101 
102  // Initialize the direction set to the standard Euclidean basis.
103  for (int i = 0; i < mDimensions; ++i)
104  {
105  mDirections[i].MakeUnit(i);
106  }
107 
108  Real ell0, ell1, ellMin;
109  for (int iter = 0; iter < mMaxIterations; ++iter)
110  {
111  // Find minimum in each direction and update current location.
112  for (int i = 0; i < mDimensions; ++i)
113  {
114  mDCurrIndex = i;
115  ComputeDomain(t0, t1, ell0, ell1);
116  mMinimizer.GetMinimum(ell0, ell1, (Real)0, ellMin, mFCurr);
117  mTCurr += ellMin*mDirections[i];
118  }
119 
120  // Estimate a unit-length conjugate direction. TODO: Expose
121  // epsilon to the caller.
124  Real const epsilon = (Real)1e-06;
125  if (length < epsilon)
126  {
127  // New position did not change significantly from old one.
128  // Should there be a better convergence criterion here?
129  break;
130  }
131 
133 
134  // Minimize in conjugate direction.
136  ComputeDomain(t0, t1, ell0, ell1);
137  mMinimizer.GetMinimum(ell0, ell1, (Real)0, ellMin, mFCurr);
138  mTCurr += ellMin*mDirections[mDCurrIndex];
139 
140  // Cycle the directions and add conjugate direction to set.
141  mDConjIndex = 0;
142  for (int i = 0; i < mDimensions; ++i)
143  {
144  mDirections[i] = mDirections[i + 1];
145  }
146 
147  // Set parameters for next pass.
148  mTSave = mTCurr;
149  }
150 
151  Memcpy(tMin, &mTCurr[0], numBytes);
152  fMin = mFCurr;
153 }
154 
155 template <typename Real>
156 void MinimizeN<Real>::ComputeDomain(Real const* t0, Real const* t1,
157  Real& ell0, Real& ell1)
158 {
159  ell0 = -std::numeric_limits<Real>::max();
160  ell1 = +std::numeric_limits<Real>::max();
161 
162  for (int i = 0; i < mDimensions; ++i)
163  {
164  Real value = mDirections[mDCurrIndex][i];
165  if (value != (Real)0)
166  {
167  Real b0 = t0[i] - mTCurr[i];
168  Real b1 = t1[i] - mTCurr[i];
169  Real inv = ((Real)1) / value;
170  if (value >(Real)0)
171  {
172  // The valid t-interval is [b0,b1].
173  b0 *= inv;
174  if (b0 > ell0)
175  {
176  ell0 = b0;
177  }
178  b1 *= inv;
179  if (b1 < ell1)
180  {
181  ell1 = b1;
182  }
183  }
184  else
185  {
186  // The valid t-interval is [b1,b0].
187  b0 *= inv;
188  if (b0 < ell1)
189  {
190  ell1 = b0;
191  }
192  b1 *= inv;
193  if (b1 > ell0)
194  {
195  ell0 = b1;
196  }
197  }
198  }
199  }
200 
201  // Correction if numerical errors lead to values nearly zero.
202  if (ell0 > (Real)0)
203  {
204  ell0 = (Real)0;
205  }
206  if (ell1 < (Real)0)
207  {
208  ell1 = (Real)0;
209  }
210 }
211 
212 
213 }
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
Definition: glext.h:9013
void ComputeDomain(Real const *t0, Real const *t1, Real &ell0, Real &ell1)
Definition: GteMinimizeN.h:156
GVector< Real > mTCurr
Definition: GteMinimizeN.h:59
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition: glext.h:9013
GLsizei const GLfloat * value
Definition: glcorearb.h:819
Minimize1< Real > mMinimizer
Definition: GteMinimizeN.h:62
void GetMinimum(Real const *t0, Real const *t1, Real const *tInitial, Real *tMin, Real &fMin)
Definition: GteMinimizeN.h:93
std::vector< GVector< Real > > mDirections
Definition: GteMinimizeN.h:56
GLdouble GLdouble t
Definition: glext.h:239
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:790
DualQuaternion< Real > Length(DualQuaternion< Real > const &d, bool robust=false)
GVector< Real > mTSave
Definition: GteMinimizeN.h:60
std::function< Real(Real const *)> mFunction
Definition: GteMinimizeN.h:54
void Memcpy(void *target, void const *source, size_t count)
Definition: GteWrapper.cpp:16
MinimizeN(int dimensions, std::function< Real(Real const *)> const &F, int maxLevel, int maxBracket, int maxIterations)
Definition: GteMinimizeN.h:67


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