ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/Minimizer1D.cpp
Revision: 1057
Committed: Tue Feb 17 19:23:44 2004 UTC (21 years, 2 months ago) by tim
File size: 8935 byte(s)
Log Message:
adding function shakeF in order to remove the constraint force along bond direction

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

Properties

Name Value
svn:executable *