ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Minimizer1D.cpp
Revision: 1031
Committed: Fri Feb 6 18:58:06 2004 UTC (20 years, 5 months ago) by tim
File size: 8856 byte(s)
Log Message:
Add some lines into global.cpp to make it work with energy minimization

File Contents

# User Rev Content
1 tim 1002 #include "Minimizer1D.hpp"
2 tim 1005 #include "math.h"
3 tim 1023 #include "Utility.hpp"
4 tim 1005 GoldenSectionMinimizer::GoldenSectionMinimizer(NLModel* nlp)
5     :Minimizer1D(nlp){
6     setName("GoldenSection");
7     }
8 tim 1002
9 tim 1005 int GoldenSectionMinimizer::checkConvergence(){
10    
11 tim 1002 if ((rightVar - leftVar) < stepTol)
12 tim 1010 return 1;
13 tim 1002 else
14     return -1;
15     }
16 tim 1031
17 tim 1002 void GoldenSectionMinimizer::minimize(){
18     vector<double> tempX;
19     vector <double> currentX;
20    
21     const double goldenRatio = 0.618034;
22    
23 tim 1015 tempX = currentX = model->getX();
24 tim 1002
25     alpha = leftVar + (1 - goldenRatio) * (rightVar - leftVar);
26     beta = leftVar + goldenRatio * (rightVar - leftVar);
27    
28 tim 1015 for (int i = 0; i < tempX.size(); i ++)
29     tempX[i] = currentX[i] + direction[i] * alpha;
30    
31 tim 1002 fAlpha = model->calcF(tempX);
32    
33 tim 1015 for (int i = 0; i < tempX.size(); i ++)
34     tempX[i] = currentX[i] + direction[i] * beta;
35    
36 tim 1002 fBeta = model->calcF(tempX);
37    
38     for(currentIter = 0; currentIter < maxIteration; currentIter++){
39    
40     if (checkConvergence() > 0){
41     minStatus = MINSTATUS_CONVERGE;
42     return;
43     }
44    
45     if (fAlpha > fBeta){
46     leftVar = alpha;
47     alpha = beta;
48 tim 1023
49 tim 1002 beta = leftVar + goldenRatio * (rightVar - leftVar);
50    
51 tim 1015 for (int i = 0; i < tempX.size(); i ++)
52     tempX[i] = currentX[i] + direction[i] * beta;
53 tim 1023 fAlpha = fBeta;
54     fBeta = model->calcF(tempX);
55 tim 1002
56 tim 1023 prevMinVar = alpha;
57     fPrevMinVar = fAlpha;
58 tim 1002 minVar = beta;
59 tim 1023 fMinVar = fBeta;
60 tim 1002 }
61     else{
62     rightVar = beta;
63     beta = alpha;
64 tim 1023
65 tim 1002 alpha = leftVar + (1 - goldenRatio) * (rightVar - leftVar);
66    
67 tim 1015 for (int i = 0; i < tempX.size(); i ++)
68     tempX[i] = currentX[i] + direction[i] * alpha;
69 tim 1002
70 tim 1023 fBeta = fAlpha;
71     fAlpha = model->calcF(tempX);
72    
73     prevMinVar = beta;
74     fPrevMinVar = fBeta;
75    
76 tim 1002 minVar = alpha;
77 tim 1023 fMinVar = fAlpha;
78 tim 1002 }
79    
80     }
81    
82     minStatus = MINSTATUS_MAXITER;
83    
84     }
85    
86 tim 1005 /**
87     * Brent's method is a root-finding algorithm which combines root bracketing, interval bisection,
88     * and inverse quadratic interpolation.
89 tim 1002 */
90 tim 1005 BrentMinimizer::BrentMinimizer(NLModel* nlp)
91     :Minimizer1D(nlp){
92     setName("Brent");
93     }
94 tim 1002
95 tim 1031 void BrentMinimizer::minimize(vector<double>& direction, double left, double right){
96    
97     //brent algorithm ascending order
98    
99     if (left > right)
100     setRange(right, left);
101     else
102     setRange(left, right);
103    
104     setDirection(direction);
105    
106     minimize();
107     }
108 tim 1002 void BrentMinimizer::minimize(){
109    
110 tim 1005 double fu, fv, fw;
111     double p, q, r;
112     double u, v, w;
113     double d;
114     double e;
115     double etemp;
116     double stepTol2;
117 tim 1010 double fLeftVar, fRightVar;
118 tim 1005 const double goldenRatio = 0.3819660;
119     vector<double> tempX, currentX;
120    
121     stepTol2 = 2 * stepTol;
122 tim 1031
123 tim 1005 e = 0;
124     d = 0;
125    
126 tim 1031 currentX = model->getX();
127     tempX.resize(currentX.size());
128 tim 1005
129 tim 1031
130    
131    
132 tim 1015 for (int i = 0; i < tempX.size(); i ++)
133     tempX[i] = currentX[i] + direction[i] * leftVar;
134    
135 tim 1010 fLeftVar = model->calcF(tempX);
136 tim 1015
137     for (int i = 0; i < tempX.size(); i ++)
138     tempX[i] = currentX[i] + direction[i] * rightVar;
139 tim 1005
140 tim 1010 fRightVar = model->calcF(tempX);
141 tim 1005
142 tim 1031 // find an interior point left < interior < right which satisfy f(left) > f(interior) and f(right) > f(interior)
143    
144     bracket(minVar, fMinVar, leftVar, fLeftVar, rightVar, fRightVar);
145    
146 tim 1010 if(fRightVar < fLeftVar) {
147     prevMinVar = rightVar;
148     fPrevMinVar = fRightVar;
149 tim 1005 v = leftVar;
150     fv = fLeftVar;
151     }
152     else {
153     prevMinVar = leftVar;
154 tim 1010 fPrevMinVar = fLeftVar;
155 tim 1005 v = rightVar;
156 tim 1010 fv = fRightVar;
157 tim 1005 }
158 tim 1031
159     minVar = rightVar+ goldenRatio * (rightVar - leftVar);
160 tim 1010
161 tim 1031 for (int i = 0; i < tempX.size(); i ++)
162     tempX[i] = currentX[i] + direction[i] * minVar;
163    
164     fMinVar = model->calcF(tempX);
165    
166     prevMinVar = v = minVar;
167     fPrevMinVar = fv = fMinVar;
168 tim 1023 midVar = (leftVar + rightVar) / 2;
169 tim 1005
170 tim 1023 for(currentIter = 0; currentIter < maxIteration; currentIter++){
171 tim 1002
172 tim 1031 //construct a trial parabolic fit
173 tim 1005 if (fabs(e) > stepTol){
174 tim 1002
175 tim 1005 r = (minVar - prevMinVar) * (fMinVar - fv);
176     q = (minVar - v) * (fMinVar - fPrevMinVar);
177     p = (minVar - v) *q -(minVar - prevMinVar)*r;
178     q = 2.0 *(q-r);
179 tim 1002
180 tim 1005 if (q > 0.0)
181     p = -p;
182 tim 1002
183 tim 1005 q = fabs(q);
184    
185     etemp = e;
186     e = d;
187    
188 tim 1010 if(fabs(p) >= fabs(0.5*q*etemp) || p <= q*(leftVar - minVar) || p >= q*(rightVar - minVar)){
189 tim 1031 //reject parabolic fit and use golden section step instead
190 tim 1005 e = minVar >= midVar ? leftVar - minVar : rightVar - minVar;
191     d = goldenRatio * e;
192     }
193     else{
194 tim 1031
195     //take the parabolic step
196 tim 1005 d = p/q;
197     u = minVar + d;
198     if ( u - leftVar < stepTol2 || rightVar - u < stepTol2)
199     d = midVar > minVar ? stepTol : - stepTol;
200     }
201 tim 1031
202 tim 1005 }
203     else{
204 tim 1031 e = minVar >= midVar ? leftVar -minVar : rightVar-minVar;
205     d = goldenRatio * e;
206 tim 1005 }
207    
208 tim 1031 u = fabs(d) >= stepTol ? minVar + d : minVar + copysign(stepTol, d);
209 tim 1005
210 tim 1015 for (int i = 0; i < tempX.size(); i ++)
211     tempX[i] = currentX[i] + direction[i] * u;
212    
213 tim 1023 fu = model->calcF(tempX);
214 tim 1005
215     if(fu <= fMinVar){
216    
217     if(u >= minVar)
218     leftVar = minVar;
219     else
220     rightVar = minVar;
221    
222     v = prevMinVar;
223 tim 1031 prevMinVar = minVar;
224     minVar = u;
225    
226 tim 1005 fv = fPrevMinVar;
227     fPrevMinVar = fMinVar;
228     fMinVar = fu;
229    
230     }
231     else{
232     if (u < minVar) leftVar = u;
233 tim 1031 else rightVar= u;
234    
235 tim 1005 if(fu <= fPrevMinVar || prevMinVar == minVar) {
236     v = prevMinVar;
237     fv = fPrevMinVar;
238     prevMinVar = u;
239     fPrevMinVar = fu;
240     }
241     else if ( fu <= fv || v == minVar || v == prevMinVar ) {
242     v = u;
243     fv = fu;
244     }
245     }
246    
247 tim 1023 midVar = (leftVar + rightVar) /2;
248 tim 1005
249     if (checkConvergence() > 0){
250     minStatus = MINSTATUS_CONVERGE;
251     return;
252     }
253    
254 tim 1002 }
255    
256    
257     minStatus = MINSTATUS_MAXITER;
258 tim 1010 return;
259 tim 1002 }
260 tim 1005
261 tim 1010 int BrentMinimizer::checkConvergence(){
262 tim 1005
263     if (fabs(minVar - midVar) < stepTol)
264     return 1;
265     else
266     return -1;
267     }
268 tim 1031
269     /*******************************************************
270     * Bracketing a minimum of a real function Y=F(X) *
271     * using MNBRAK subroutine *
272     * ---------------------------------------------------- *
273     * REFERENCE: "Numerical recipes, The Art of Scientific *
274     * Computing by W.H. Press, B.P. Flannery, *
275     * S.A. Teukolsky and W.T. Vetterling, *
276     * Cambridge university Press, 1986". *
277     * ---------------------------------------------------- *
278     * We have different situation here, we want to limit the
279     ********************************************************/
280     void BrentMinimizer::bracket(double& cx, double& fc, double& ax, double& fa, double& bx, double& fb){
281     vector<double> currentX;
282     vector<double> tempX;
283     double u, r, q;
284     double fu;
285     double ulim;
286     const double TINY = 1.0e-20;
287     const double GLIMIT = 100.0;
288     const double GoldenRatio = 0.618034;
289     const int MAXBRACKETITER = 100;
290     currentX = model->getX();
291     tempX.resize(currentX.size());
292    
293     if (fb > fa){
294     swap(fa, fb);
295     swap(ax, bx);
296     }
297    
298     cx = bx + GoldenRatio * (bx - ax);
299    
300     fc = model->calcF(tempX);
301    
302     for(int k = 0; k < MAXBRACKETITER && (fb < fc); k++){
303    
304     r = (bx - ax) * (fb -fc);
305     q = (bx - cx) * (fb - fa);
306     u = bx -((bx - cx)*q - (bx-ax)*r)/(2.0 * copysign(max(fabs(q-r), TINY) ,q-r));
307     ulim = bx + GLIMIT *(cx - bx);
308    
309     for (int i = 0; i < tempX.size(); i ++)
310     tempX[i] = currentX[i] + direction[i] * u;
311    
312     if ((bx -u) * (u -cx) > 0){
313     fu = model->calcF(tempX);
314    
315     if (fu < fc){
316     ax = bx;
317     bx = u;
318     fa = fb;
319     fb = fu;
320     }
321     else if (fu > fb){
322     cx = u;
323     fc = fu;
324     return;
325     }
326     }
327     else if ((cx - u)* (u - ulim) > 0.0){
328    
329     fu = model->calcF(tempX);
330    
331     if (fu < fc){
332     bx = cx;
333     cx = u;
334     u = cx + GoldenRatio * (cx - bx);
335    
336     fb = fc;
337     fc = fu;
338    
339     for (int i = 0; i < tempX.size(); i ++)
340     tempX[i] = currentX[i] + direction[i] * u;
341    
342     fu = model->calcF(tempX);
343     }
344     }
345     else if ((u-ulim) * (ulim - cx) >= 0.0){
346     u = ulim;
347    
348     fu = model->calcF(tempX);
349    
350     }
351     else {
352     u = cx + GoldenRatio * (cx -bx);
353    
354     fu = model->calcF(tempX);
355     }
356    
357     ax = bx;
358     bx = cx;
359     cx = u;
360    
361     fa = fb;
362     fb = fc;
363     fc = fu;
364    
365     }
366    
367     }
368    

Properties

Name Value
svn:executable *