~ubuntu-branches/ubuntu/maverick/cdk/maverick

« back to all changes in this revision

Viewing changes to src/org/openscience/cdk/modeling/forcefield/LineSearchForTheWolfeConditions.java

  • Committer: Bazaar Package Importer
  • Author(s): Paul Cager
  • Date: 2008-04-09 21:17:53 UTC
  • Revision ID: james.westby@ubuntu.com-20080409211753-46lmjw5z8mx5pd8d
Tags: upstream-1.0.2
ImportĀ upstreamĀ versionĀ 1.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.openscience.cdk.modeling.forcefield;
 
2
 
 
3
import javax.vecmath.GVector;
 
4
 
 
5
//import org.openscience.cdk.tools.LoggingTool;
 
6
/**
 
7
 * 
 
8
 *
 
9
 * @author     vlabarta
 
10
 *@cdk.module     forcefield
 
11
 * 
 
12
 */
 
13
public class LineSearchForTheWolfeConditions {
 
14
        
 
15
        //initial values
 
16
        private GVector x = null;
 
17
        private double linearFunctionInAlpha0;
 
18
        private GVector dfx = null;
 
19
        private GVector direction = null;
 
20
        private double linearFunctionDerivativeInAlpha0;
 
21
        private IPotentialFunction pf = null;
 
22
        private double alphaInitialStep;
 
23
 
 
24
        
 
25
        //line search algorithm
 
26
        private double[] alpha = new double[3];
 
27
        private double[] linearFunctionInAlpha = new double[3];
 
28
        private double[] linearFunctionDerivativeInAlpha = new double[3];
 
29
 
 
30
        private GVector[] dfInAlpha = new GVector[3];
 
31
        private double[] brentStep = new double[3];
 
32
 
 
33
        private final double c1 = 0.0001;
 
34
        private double c2;
 
35
        
 
36
        //private double linearFunctionGoldenAlpha;
 
37
        private double linearFunctionAlphaInterpolation;
 
38
        
 
39
        public boolean derivativeSmallEnough = true;
 
40
 
 
41
        public double alphaOptimum;
 
42
        public double linearFunctionInAlphaOptimum;
 
43
        public GVector dfOptimum = null;
 
44
        
 
45
        //zoom
 
46
        private double alphaj;
 
47
        private double linearFunctionInAlphaj;
 
48
        private double linearFunctionDerivativeInAlphaj;
 
49
        private GVector dfInAlphaj;
 
50
        private int functionEvaluationNumber;
 
51
        
 
52
        //energy function evaluation
 
53
        private GVector xAlpha = null;
 
54
 
 
55
        //interpolation
 
56
        private double a;
 
57
        private double b;
 
58
        
 
59
        //cubic interpolation
 
60
        private double alphaTemporal;
 
61
        private double linearFunctionInAlphaTemporal;
 
62
        private double linearFunctionDerivativeInAlphaTemporal;
 
63
        private double d1;
 
64
        private double d2;
 
65
        private double alphaiplus1;
 
66
        
 
67
        //private LoggingTool logger;
 
68
 
 
69
        
 
70
        public LineSearchForTheWolfeConditions(IPotentialFunction pfUser, String method) {
 
71
                this.pf = pfUser;
 
72
                if ((method == "sdm") | (method == "cgm")) {c2 = 0.07;}
 
73
                else {c2 = 0.9;} 
 
74
        }
 
75
        
 
76
        public void initialize(GVector xUser, double fxUser, GVector dfxUser, GVector directionUser, double linearFunctionDerivativeUser, double alphaInitialStepUser) {
 
77
                this.x = xUser;
 
78
                this.linearFunctionInAlpha0 = fxUser;
 
79
                this.dfx = dfxUser;
 
80
                //logger.debug("derivativeSmallEnough = " + this.derivativeSmallEnough);
 
81
                this.direction = directionUser;
 
82
                this.linearFunctionDerivativeInAlpha0 = linearFunctionDerivativeUser;
 
83
                //logger.debug("linearFunctionDerivativeInAlpha0 = " + linearFunctionDerivativeInAlpha0);
 
84
                this.alphaOptimum = 0;
 
85
                this.linearFunctionInAlphaOptimum = linearFunctionInAlpha0;
 
86
                dfOptimum = this.dfx;
 
87
                this.alphaInitialStep = alphaInitialStepUser;
 
88
                this.derivativeSmallEnough = false;
 
89
                this.xAlpha = new GVector(x.getSize());
 
90
        }
 
91
        
 
92
         /*     Line Search Algorithm for the Wolfe conditions. Jorge Nocedal and Stephen J.Wright. Numerical Optimization. 1999.
 
93
         * The algorithm has two stages. This first stage begins with a trial estimate alpha1, 
 
94
         * and keeps increasing it until it finds either an acceptable step length or an interval 
 
95
         * that brackets the desired step lengths. In the later case, the second stage is invoked 
 
96
         * by calling a function called zoom, which successively decreases the size of the interval 
 
97
         * until an acceptable step length is identified. 
 
98
         *
 
99
         * @param alphaMax                              Maximum step length
 
100
         */
 
101
        public void lineSearchAlgorithm (double alphaMax) {
 
102
                
 
103
                //logger.debug("Line search for the strong wolfe conditions");
 
104
 
 
105
                alpha[0] = 0.0;
 
106
                linearFunctionInAlpha[0] = linearFunctionInAlpha0; 
 
107
                linearFunctionDerivativeInAlpha[0] = linearFunctionDerivativeInAlpha0;  //To Analyse the possibility of eliminate linearFunctionDerivativeInAlpha[0]
 
108
                dfInAlpha[0] = this.dfx;
 
109
                
 
110
                alpha[1] = this.alphaInitialStep;
 
111
                
 
112
                //logger.debug("alpha[1] = this.alphaInitialStep = " + alpha[1]);
 
113
                
 
114
                brentStep[0] = alpha[0];
 
115
                brentStep[1] = alpha[1];
 
116
                
 
117
                int i=1;
 
118
                
 
119
                this.functionEvaluationNumber = 0;
 
120
 
 
121
                if (alpha[1] > alphaMax) {
 
122
                        alpha[1] = alphaMax;
 
123
                        //logger.debug("line search algorithm error: alphaInitialStep > alphaMax");
 
124
                }
 
125
                //      alpha[1] = alphaMax/2;
 
126
                //}
 
127
 
 
128
                try {
 
129
                do {
 
130
 
 
131
                        if (alpha[1] == 0) {
 
132
                                System.out.println("alpha[1] == 0");
 
133
                                break;
 
134
                        }
 
135
                        
 
136
                        //logger.debug("alpha[" + i + "] = " + alpha[i]);
 
137
                        linearFunctionInAlpha[i] = evaluateEnergyFunction(alpha[i]);
 
138
                        //logger.debug("linearFunctionInAlpha[" + i + "] = " + linearFunctionInAlpha[i]);
 
139
                        
 
140
                        if ((linearFunctionInAlpha[i] > linearFunctionInAlpha[0] + c1 * alpha[i] * linearFunctionDerivativeInAlpha[0]) | 
 
141
                                        ((linearFunctionInAlpha[i] >= linearFunctionInAlpha[i-1]) & (i>1))) {                   //The interval alpha[i-1] and alpha[i] brackets the desired step lengths.
 
142
                                //logger.debug("zoom(" + alpha[i-1] + ", " + linearFunctionInAlpha[i-1] + ", " + linearFunctionDerivativeInAlpha[i-1] + ", " + dfInAlpha[i-1] + ", " + alpha[i] + ", " + linearFunctionInAlpha[i] + ")");
 
143
                                //dfInAlpha[i] = evaluateEnergyFunctionDerivative(alpha[i]);
 
144
                                //linearFunctionDerivativeInAlpha[i] = dfInAlpha[i].dot(direction);
 
145
                                //zoom(alpha[i-1], linearFunctionInAlpha[i-1], linearFunctionDerivativeInAlpha[i-1], dfInAlpha[i-1], alpha[i], linearFunctionInAlpha[i], linearFunctionDerivativeInAlpha[i], dfInAlpha[i]);
 
146
                                zoom(alpha[i-1], linearFunctionInAlpha[i-1], linearFunctionDerivativeInAlpha[i-1], dfInAlpha[i-1], alpha[i], linearFunctionInAlpha[i]);
 
147
                                break;
 
148
                        } 
 
149
 
 
150
                        //The first strong Wolfe condition is satisfied for alpha[i].
 
151
                        dfInAlpha[i] = evaluateEnergyFunctionDerivative(alpha[i]);
 
152
                        //logger.debug("dfOptimum = " + dfOptimum);
 
153
                        linearFunctionDerivativeInAlpha[i] = dfInAlpha[i].dot(direction);
 
154
                        //logger.debug("linearFunctionDerivativeInAlpha[" + i + "] = " + linearFunctionDerivativeInAlpha[i]);
 
155
                        
 
156
                        if (Math.abs(linearFunctionDerivativeInAlpha[i]) <= -c2 * linearFunctionDerivativeInAlpha[0]) { //The second strong Wolfe condition is also satisfied for alpha[i]
 
157
                                //logger.debug("The second strong Wolfe condition is also satisfied for " + alpha[i]);
 
158
                                alphaOptimum = alpha[i];
 
159
                                linearFunctionInAlphaOptimum = linearFunctionInAlpha[i];
 
160
                                dfOptimum = dfInAlpha[i];
 
161
                                //logger.debug("alphaOptimun = " + alphaOptimum);
 
162
                                //logger.debug("linearFunctionInAlphaOptimun = " + linearFunctionInAlphaOptimum);
 
163
                                //logger.debug("dfOptimum = " + dfOptimum);
 
164
                                this.derivativeSmallEnough = true;
 
165
                                break;
 
166
                        }
 
167
                        
 
168
                        if (linearFunctionDerivativeInAlpha[i] >= 0) {          //The interval alpha[i-1] and alpha[i] brackets the desired step lengths.
 
169
                                /*System.out.println("zoom(" + alpha[i-1] + ", " + linearFunctionInAlpha[i-1] + ", " + linearFunctionDerivativeInAlpha[i-1] + ", " + dfInAlpha[i-1] + ", " + 
 
170
                                                alpha[i] + ", " + linearFunctionInAlpha[i] + ")");*/
 
171
                                
 
172
                                /*zoom(alpha[i], linearFunctionInAlpha[i], linearFunctionDerivativeInAlpha[i], dfInAlpha[i], 
 
173
                                                alpha[i-1], linearFunctionInAlpha[i-1], linearFunctionDerivativeInAlpha[i], dfInAlpha[i]);*/
 
174
                                zoom(alpha[i-1], linearFunctionInAlpha[i-1], linearFunctionDerivativeInAlpha[i-1], dfInAlpha[i-1], 
 
175
                                                alpha[i], linearFunctionInAlpha[i]);
 
176
                                break;
 
177
                        }
 
178
                
 
179
                        if (alpha[i] == alphaMax) {     
 
180
                                //logger.debug("LINE SEARCH ALGORITHM WAS TERMINATE EARLIER BECAUSE alpha[i] == alphaMax");
 
181
                                alphaOptimum = alpha[i];
 
182
                                linearFunctionInAlphaOptimum = linearFunctionInAlpha[i];
 
183
                                dfOptimum = dfInAlpha[i];
 
184
                                //logger.debug("alphaOptimun = " + alphaOptimum);
 
185
                                //logger.debug("linearFunctionInAlphaOptimun = " + linearFunctionInAlphaOptimum);
 
186
                                //logger.debug("dfOptimum = " + dfOptimum);
 
187
                                break;
 
188
                        }
 
189
                        
 
190
                        functionEvaluationNumber = functionEvaluationNumber + 1;
 
191
                        if (functionEvaluationNumber == 10) {
 
192
                                //logger.debug("LINE SEARCH ALGORITHM WAS TERMINATE EARLIER BECAUSE functionEvaluationNumber == 10");
 
193
                                alphaOptimum = alpha[i];
 
194
                                linearFunctionInAlphaOptimum = linearFunctionInAlpha[i];
 
195
                                dfOptimum = dfInAlpha[i];
 
196
                                //logger.debug("alphaOptimun = " + alphaOptimum);
 
197
                                //logger.debug("linearFunctionInAlphaOptimun = " + linearFunctionInAlphaOptimum);
 
198
                                //logger.debug("dfOptimum = " + dfOptimum);
 
199
                                break;
 
200
                        }
 
201
                        
 
202
                        if (i>1) {
 
203
                                brentStep[0] = brentStep[1];
 
204
                                brentStep[1] = brentStep[2];
 
205
 
 
206
                                alpha[1] = alpha[2];
 
207
                                linearFunctionInAlpha[1] = linearFunctionInAlpha[2];
 
208
                                linearFunctionDerivativeInAlpha[1] = linearFunctionDerivativeInAlpha[2];
 
209
                                dfInAlpha[1] = dfInAlpha[2];
 
210
                        } 
 
211
                        
 
212
                        brentStep[2] = brentStep[1] + 1.618 * (brentStep[1]-brentStep[0]);
 
213
                        //logger.debug("brentStep[2] = " + brentStep[2]);
 
214
 
 
215
                        if (brentStep[2] > alphaMax) {brentStep[2] = alphaMax;}
 
216
                        /*linearFunctionInBrentStep = this.evaluateEnergyFunction(brentStep[2]);
 
217
                        linearFunctionDerivativeInBrentStep = this.evaluateEnergyFunctionDerivative(brentStep[2]).dot(direction);
 
218
                        */
 
219
                        alpha[2] = brentStep[2];
 
220
                        /*alpha[2] = this.cubicInterpolation(alpha[1], linearFunctionInAlpha[1], linearFunctionDerivativeInAlpha[1], 
 
221
                                        brentStep[2], linearFunctionInBrentStep, linearFunctionDerivativeInBrentStep, alpha[1], brentStep[2]);
 
222
                                        */
 
223
 
 
224
                        i=2;
 
225
                        
 
226
                } while ((alpha[2] <= alphaMax) & (alpha[1] < alpha[2]) & (functionEvaluationNumber < 10));
 
227
                
 
228
                } catch (Exception exception) {
 
229
                System.out.println("Line search for the strong wolfe conditions: " + exception.getMessage());
 
230
                System.out.println(exception);
 
231
        }
 
232
                
 
233
 
 
234
        }
 
235
        
 
236
 
 
237
         /*     Each iteration of zoom generates an iterate alphaj between alphaLow and alphaHigh, 
 
238
         * and then replaces one of these endpoints by alphaj in such a way that the properties 
 
239
         * (a), (b) and (c) continue to hold.
 
240
         * (a)The interval bounded by alphaLow and alphaHigh contains step lengths that satisfy the strong Wolfe conditions.  
 
241
     * (b)alphaLow is, among all step lengths generated so far and satisfying the sufficient decrease condition, 
 
242
     * the one giving the smallest function value.
 
243
     * (c)alphaHigh is chosen so that linearFunctionDerivativeInAlphaj * (alphaHigh-alphaLow) < 0
 
244
     *   
 
245
         *@param  alphaLow                                              Among all step lengths generated so far and satisfying the sufficient decrease condition, the one giving the smallest function value.
 
246
         *@param  linearFunctionInAlphaLow                      Function value at alphaLow.
 
247
         *@param  linearFunctionDerivativeInAlphaLow    Derivative value at alphaLow.
 
248
         *@param  dfInAlphaLow                                  Gradient at alphaLow.
 
249
         *@param  alphaHigh                                             AlphaHigh is chosen so that linearFunctionDerivativeInAlphaj * (alphaHigh-alphaLow) < 0
 
250
         *@param  linearFunctionInAlphaHigh             Function value at alphaHigh.
 
251
         */
 
252
        private void zoom (double alphaLow, double linearFunctionInAlphaLow, double linearFunctionDerivativeInAlphaLow, GVector dfInAlphaLow, 
 
253
                        double alphaHigh, double linearFunctionInAlphaHigh) {
 
254
                
 
255
                //logger.debug("zoom");
 
256
                
 
257
                functionEvaluationNumber = 0;
 
258
                
 
259
                /*double a;
 
260
                double b;
 
261
                if (alphaLow < alphaHigh) {a = alphaLow; b = alphaHigh;}
 
262
                else {a = alphaHigh; b = alphaLow;}
 
263
                */
 
264
                
 
265
                do {
 
266
                        //Interpolation 
 
267
                        
 
268
                        //alphaj = this.cubicInterpolation(alphaLow, linearFunctionInAlphaLow, linearFunctionDerivativeInAlphaLow, alphaHigh, linearFunctionInAlphaHigh, linearFunctionDerivativeInAlphaHigh, a, b);
 
269
                        /*System.out.println("interpolation(" + alphaLow + ", " + linearFunctionInAlphaLow + ", " + linearFunctionDerivativeInAlphaLow + ", "
 
270
                                        + alphaHigh + ", " + linearFunctionInAlphaHigh + ");");*/
 
271
 
 
272
                        alphaj = this.interpolation(alphaLow, linearFunctionInAlphaLow, linearFunctionDerivativeInAlphaLow, alphaHigh, linearFunctionInAlphaHigh);
 
273
                        //logger.debug("alphaj = " + alphaj);
 
274
                        linearFunctionInAlphaj = this.linearFunctionAlphaInterpolation;
 
275
                        //logger.debug("linearFunctionInAlphaj = " + linearFunctionInAlphaj);
 
276
                        
 
277
                        if ((linearFunctionInAlphaj > linearFunctionInAlpha0 + c1 * alphaj * linearFunctionDerivativeInAlpha0) | //The interval 0 and alphaj brackets the desired step lengths.
 
278
                                        (linearFunctionInAlphaj >= linearFunctionInAlphaLow)) {                 
 
279
 
 
280
                                //logger.debug("The minimum is between alpha1 and alphaj");
 
281
                                alphaHigh = alphaj;
 
282
                                linearFunctionInAlphaHigh = linearFunctionInAlphaj;
 
283
                                //dfInAlphaHigh = this.evaluateEnergyFunctionDerivative(alphaHigh); 
 
284
                                //linearFunctionDerivativeInAlphaHigh = dfInAlphaHigh.dot(direction);
 
285
                        } 
 
286
                        else {
 
287
                                dfInAlphaj = evaluateEnergyFunctionDerivative(alphaj);
 
288
                                linearFunctionDerivativeInAlphaj = dfInAlphaj.dot(direction);
 
289
                                //logger.debug("linearFunctionDerivativeInAlphaj = " + linearFunctionDerivativeInAlphaj);
 
290
                                if (Math.abs(linearFunctionDerivativeInAlphaj) <= -c2 * linearFunctionDerivativeInAlpha0) { //alphaj satisfied the second strong Wolfe condition.
 
291
                                        //logger.debug("Derivative small enough : " + Math.abs(linearFunctionDerivativeInAlphaj) + " <= " + (-c2 * linearFunctionDerivativeInAlpha0));
 
292
                                        this.derivativeSmallEnough = true;
 
293
                                        alphaOptimum = alphaj;
 
294
                                        linearFunctionInAlphaOptimum = linearFunctionInAlphaj;
 
295
                                        dfOptimum = dfInAlphaj;
 
296
                                        //logger.debug("alphaOptimun = " + alphaOptimum);
 
297
                                        //logger.debug("linearFunctionInAlphaOptimun = " + linearFunctionInAlphaOptimum);
 
298
                                        break;
 
299
                                }
 
300
                                if (linearFunctionDerivativeInAlphaj * (alphaHigh-alphaLow) >= 0) {             
 
301
                                        alphaHigh = alphaLow;
 
302
                                        linearFunctionInAlphaHigh = linearFunctionInAlphaLow;
 
303
                                        //linearFunctionDerivativeInAlphaHigh = linearFunctionDerivativeInAlphaLow;
 
304
                                }
 
305
                                alphaLow = alphaj;
 
306
                                linearFunctionInAlphaLow = linearFunctionInAlphaj;
 
307
                                linearFunctionDerivativeInAlphaLow = linearFunctionDerivativeInAlphaj;
 
308
                                dfInAlphaLow = dfInAlphaj;
 
309
                        }
 
310
                        
 
311
                        //logger.debug("AlphaLow = " + alphaLow + ", AlphaHigh = " + alphaHigh);
 
312
                        //logger.debug("linearFunctionInAlphaLow = " + linearFunctionInAlphaLow + ", linearFunctionInAlphaHigh = " + linearFunctionInAlphaHigh);
 
313
                        functionEvaluationNumber = functionEvaluationNumber + 1;
 
314
                        //logger.debug("functionEvaluationNumber = " + functionEvaluationNumber);
 
315
 
 
316
                        if ((functionEvaluationNumber == 10) | (Math.abs(linearFunctionInAlphaHigh - linearFunctionInAlphaLow) <= 0.000001) | (Math.abs(alphaLow - alphaHigh) <= 0.000000000001)) {
 
317
                                //logger.debug("ZOOM WAS TERMINATE EARLIER");
 
318
                                /*System.out.println("functionEvaluationNumber = " + functionEvaluationNumber + 
 
319
                                                ", Math.abs(linearFunctionInAlphaHigh - linearFunctionInAlphaLow) = " + Math.abs(linearFunctionInAlphaHigh - linearFunctionInAlphaLow) + 
 
320
                                                ", Math.abs(alphaLow - alphaHigh) = " + Math.abs(alphaLow - alphaHigh));*/
 
321
                                this.alphaOptimum = alphaLow;
 
322
                                this.linearFunctionInAlphaOptimum = linearFunctionInAlphaLow;
 
323
                                this.dfOptimum = dfInAlphaLow;
 
324
                                
 
325
                                //logger.debug("(functionEvaluationNumber == 10) | (Math.abs(linearFunctionInAlphaHigh - linearFunctionInAlphaLow) <= 0.000001) | (Math.abs(alphaLow - alphaHigh) <= 0.0000001)");
 
326
                                //logger.debug("zoom end -> this.alphaOptimum = " + this.alphaOptimum); 
 
327
                                //logger.debug("zoom end -> this.linearFunctionInAlphaOptimum = " + this.linearFunctionInAlphaOptimum); 
 
328
                                break;
 
329
                        }
 
330
 
 
331
                
 
332
                } while ((Math.abs(linearFunctionInAlphaHigh - linearFunctionInAlphaLow) > 0.000001) 
 
333
                                        & (functionEvaluationNumber < 10) 
 
334
                                        & (Math.abs(alphaLow - alphaHigh) > 0.000000000001));
 
335
                
 
336
                //logger.debug("zoom end");
 
337
                return;
 
338
        }
 
339
 
 
340
        
 
341
         /*
 
342
         * Cubic interpolation in the interval [a,b] known to contain desirable step length 
 
343
         * and given two previous step length estimates in this interval.
 
344
         *
 
345
         *@param        alphai                                                                          Previous step length.                                                                   
 
346
         *@param        linearFunctionInAlphai                                          Function value at the previous step length alphai.
 
347
         *@param        linearFunctionDerivativeInAlphai                        Derivative at the previous step length alphai.
 
348
         *@param        alphaiMinus1                                                            Previous step length.
 
349
         *@param        linearFunctionInAlphaiMinus1                            Function value at the previous step length alphaiMinus1.
 
350
         *@param        linearFunctionDerivativeInAlphaiMinus1          Derivative value at the previous step length alphaiMinus1.
 
351
         *@param        a                                                                                       Inferior value of the interval [a,b].
 
352
         *@param        b                                                                                       Superior value of the interval [a,b].   
 
353
         *        
 
354
         * @return                                                                                              Cubic interpolation in the interval [a,b]
 
355
         */
 
356
        public double cubicInterpolation(double alphai, double linearFunctionInAlphai, double linearFunctionDerivativeInAlphai, 
 
357
                                                                        double alphaiMinus1, double linearFunctionInAlphaiMinus1, double linearFunctionDerivativeInAlphaiMinus1, 
 
358
                                                                        double a, double b) {
 
359
                
 
360
                //logger.debug("The interval [" + a + ", " + b + "] contains acceptable step lengths.");
 
361
                
 
362
                if (alphai < alphaiMinus1) {
 
363
                        this.alphaTemporal = alphai;
 
364
                        this.linearFunctionInAlphaTemporal = linearFunctionInAlphai;
 
365
                        this.linearFunctionDerivativeInAlphaTemporal = linearFunctionDerivativeInAlphai;
 
366
                        alphai = alphaiMinus1;
 
367
                        linearFunctionInAlphai = linearFunctionInAlphaiMinus1;
 
368
                        linearFunctionDerivativeInAlphai = linearFunctionDerivativeInAlphaiMinus1;
 
369
                        alphaiMinus1 = this.alphaTemporal;
 
370
                        linearFunctionInAlphaiMinus1 = this.linearFunctionInAlphaTemporal;
 
371
                        linearFunctionDerivativeInAlphaiMinus1 = this.linearFunctionDerivativeInAlphaTemporal;
 
372
                }
 
373
                
 
374
                this.d1 = linearFunctionDerivativeInAlphaiMinus1 + linearFunctionDerivativeInAlphai - 3 * ((linearFunctionInAlphaiMinus1 - linearFunctionInAlphai)/(alphaiMinus1 - alphai));
 
375
                //logger.debug("d1 = " + d1);
 
376
                
 
377
                //logger.debug("linearFunctionDerivativeInAlphaiMinus1 = " + linearFunctionDerivativeInAlphaiMinus1);
 
378
                //logger.debug("linearFunctionDerivativeInAlphai = " + linearFunctionDerivativeInAlphai);
 
379
                
 
380
                this.d2 = Math.sqrt(Math.abs(Math.pow(d1,2) - linearFunctionDerivativeInAlphaiMinus1 * linearFunctionDerivativeInAlphai));
 
381
                //logger.debug("d2 = " + d2);
 
382
                
 
383
                this.alphaiplus1 = alphai-(alphai-alphaiMinus1) * ((linearFunctionDerivativeInAlphai + d2 - d1) / (linearFunctionDerivativeInAlphai - linearFunctionDerivativeInAlphaiMinus1 + 2 * d2));
 
384
                
 
385
                //logger.debug("alphaiplus1 = " + alphaiplus1);
 
386
                
 
387
                if (alphaiplus1 < a) {alphaiplus1 = a;}
 
388
                if (alphaiplus1 > b) {alphaiplus1 = b;}
 
389
                
 
390
                //logger.debug("alphaiplus1 = " + alphaiplus1);
 
391
                
 
392
                if (Math.abs(alphaiplus1 - alphai) < 0.000000001) {
 
393
                        /*System.out.println("We reset alphaiplus1 = (alphaiMinus1 + alphai) / 2, because alphaiplus1 = " + alphaiplus1 + " is too close to its predecessor " +
 
394
                                        "alphaiMinus1 = " + alphaiMinus1); */
 
395
                        alphaiplus1 = (alphaiMinus1 + alphai) / 2;
 
396
                } else {if (alphaiplus1 < (alphai - 9 * (alphai-alphaiMinus1) / 10)) {
 
397
                        //logger.debug("We reset alphaiplus1 = (alphaiMinus1 + alphai) / 2, because alphaiplus1 = " + alphaiplus1 + " is        too much smaller than alphai = " + alphai); 
 
398
                        alphaiplus1 = (alphaiMinus1 + alphai) / 2;;
 
399
                        }
 
400
                }
 
401
        
 
402
                return alphaiplus1;
 
403
        }
 
404
        
 
405
 
 
406
         /*
 
407
         *      The aim is to find a value of alpha that satisfies the sufficient decrease condition, without being too small.
 
408
         *      The procedures generate a value alphai such that is not too much smaller than its predecesor alphai-1. 
 
409
         *  The interpolation in the first is quadratic but if the sufficient decrease condition is not satisfied 
 
410
         *  then the interpolation is cubic.
 
411
         *
 
412
         * @param alphaLow                                                              Among all step lengths generated so far and satisfying the sufficient decrease condition, the one giving the smallest function value.
 
413
         * @param linearFunctionInAlphaLow                              Energy function value at alphaLow.
 
414
         * @param linearFunctionDerivativeInAlphaLow    Derivative value at alphaLow.
 
415
         * @param alphaHigh                                                             AlphaHigh is chosen so that linearFunctionDerivativeInAlphaj * (alphaHigh-alphaLow) < 0
 
416
         * @param linearFunctionInAlphaHigh                             Energy function value at alphaHigh.
 
417
         * @return                                                                              Value of alpha that satisfies the sufficient decrease condition, without being too small.
 
418
         */
 
419
        private double interpolation(double alphaLow, double linearFunctionInAlphaLow, double linearFunctionDerivativeInAlphaLow, 
 
420
                                                                double alphaHigh, double linearFunctionInAlphaHigh) {
 
421
                
 
422
                double minAlpha = Math.min(alphaLow, alphaHigh);
 
423
                double alphaDiff = Math.abs(alphaHigh - alphaLow);
 
424
                double alphaInterpolation;
 
425
 
 
426
                //logger.debug("We form a quadratic approximation to the linear function");
 
427
                double alpha1 = -1 * ((linearFunctionDerivativeInAlphaLow * Math.pow(alphaDiff,2)) / (2 * (linearFunctionInAlphaHigh - linearFunctionInAlphaLow - linearFunctionDerivativeInAlphaLow * alphaDiff)));
 
428
                
 
429
                //logger.debug("The value alpha1 = " + alpha1 + ", is the minimizer of this quadratic function");
 
430
                
 
431
                if ((alpha1 > alphaDiff) | (Math.abs(alpha1 - alphaDiff) < 0.000000001)) {
 
432
                        if (alpha1 < 1E-7) {}
 
433
                        else {
 
434
                                /*System.out.println("We reset alpha1 = alphaDiff / 2, because alphaInterpolation = " + alpha1 + " is too close to its predecessor " +
 
435
                                                "alphaiMinus1 = " + alphaDiff); */
 
436
                                alpha1 = alphaDiff / 2;
 
437
                        }
 
438
                } else {
 
439
                        if ((alpha1 < 0) & (alpha1 < (alphaDiff - 9 * alphaDiff / 10))) {
 
440
                                if (alpha1 < 1E-7) {}
 
441
                                else {
 
442
                                        //logger.debug("We reset alphai = alphaiMinus1 / 2, because alphaInterpolation = " + alpha1 + " is      too much smaller than alphaiMinus1 = " + alphaDiff); 
 
443
                                        alpha1 = alphaDiff / 2;
 
444
                                }
 
445
                        }
 
446
                }
 
447
 
 
448
                //logger.debug("alpha1 = " + alpha1);
 
449
 
 
450
                alphaInterpolation = minAlpha + alpha1;
 
451
                this.linearFunctionAlphaInterpolation = this.evaluateEnergyFunction(alphaInterpolation);
 
452
                //logger.debug("alphaInterpolation = " + alphaInterpolation);
 
453
                //logger.debug("linearFunctionAlphaInterpolation = " + this.linearFunctionAlphaInterpolation);
 
454
                if (this.linearFunctionAlphaInterpolation <= this.linearFunctionInAlpha0 + this.c1 * (alphaInterpolation) * this.linearFunctionDerivativeInAlpha0) {
 
455
                        //logger.debug("The sufficient decrease condition is satisfied at alpha1 and we termine the interpolation");
 
456
                }
 
457
                else {
 
458
                        //double alphaiMinus2;
 
459
                        //double alphaiMinus1 = alphaDiff;
 
460
                        //double linearFunctionInAlphaiMinus2;
 
461
                        //double linearFunctionInAlphaiMinus1 = linearFunctionInAlphaHigh;
 
462
                        double alphai; // = alpha1;
 
463
                        //double linearFunctionInAlphai = this.linearFunctionAlphaInterpolation;
 
464
                                
 
465
                        //do {
 
466
                                //alphaiMinus2 = alphaiMinus1;
 
467
                                //alphaiMinus1 = alphai;
 
468
                                //linearFunctionInAlphaiMinus2 = linearFunctionInAlphaiMinus1;
 
469
                                //linearFunctionInAlphaiMinus1 = linearFunctionInAlphai;
 
470
                                        
 
471
                                //logger.debug("We construct a cubic function that interpolates the fours pieces of information");      
 
472
                                a = 1/(Math.pow(alphaDiff,2) * Math.pow(alpha1, 2) * (alpha1-alphaDiff));
 
473
                                b = a;
 
474
                                a = a * (Math.pow(alphaDiff,2) * (this.linearFunctionAlphaInterpolation - linearFunctionInAlphaLow - linearFunctionDerivativeInAlphaLow * alpha1) 
 
475
                                                + (-Math.pow(alpha1,2)) * (linearFunctionInAlphaHigh - linearFunctionInAlphaLow - linearFunctionDerivativeInAlphaLow * alphaDiff));
 
476
                                b = b * (- Math.pow(alphaDiff,3) * (this.linearFunctionAlphaInterpolation - linearFunctionInAlphaLow - linearFunctionDerivativeInAlphaLow * alpha1) 
 
477
                                                + Math.pow(alpha1,3) * (linearFunctionInAlphaHigh - linearFunctionInAlphaLow - linearFunctionDerivativeInAlphaLow * alphaDiff));
 
478
                                
 
479
                                //logger.debug("a = " + a);
 
480
                                //logger.debug("b = " + b);
 
481
                                
 
482
                                alphai = (-b + Math.sqrt(Math.pow(b,2) - 3 * a * linearFunctionDerivativeInAlphaLow)) / (3 * a);
 
483
                                //logger.debug("alphai = " + alphai);
 
484
                                
 
485
                                if (Math.abs(alphai - alpha1) < 0.000000001) {
 
486
                                        /*System.out.println("We reset alphai = alpha1 / 2, because alphaInterpolation = " + alphai + " is too close to its predecessor " +
 
487
                                                        "alpha1 = " + alpha1); */
 
488
                                        alphai = alpha1 / 2;
 
489
                                } else {if (alphai < (alpha1 - 9 * alpha1 / 10)) {
 
490
                                        //logger.debug("We reset alphai = alpha1 / 2, because alphaInterpolation = " + alphai + " is    too much smaller than alpha1 = " + alpha1); 
 
491
                                        alphai = alpha1 / 2;
 
492
                                        }
 
493
                                }
 
494
                        
 
495
                                alphaInterpolation = minAlpha + alphai;
 
496
                                this.linearFunctionAlphaInterpolation = this.evaluateEnergyFunction(alphaInterpolation);
 
497
                                //logger.debug("alphaInterpolation = " + alphaInterpolation);
 
498
                                //logger.debug("linearFunctionAlphaInterpolation = " + this.linearFunctionAlphaInterpolation);
 
499
                                //functionEvaluationNumber = functionEvaluationNumber + 1;
 
500
                                
 
501
                        /*} while (((linearFunctionInAlphai > linearFunctionInAlphaLow + this.c1 * (alphaLow + alphai) * linearFunctionDerivativeInAlphaLow) & (functionEvaluationNumber < 5)) 
 
502
                                        | ((linearFunctionInAlphai - this.linearFunctionAlphaInterpolation) < 0.00000001) | ((alphai - alpha1) < 0.00000001));*/
 
503
                                
 
504
                                
 
505
                }
 
506
                        
 
507
                return alphaInterpolation;
 
508
        }
 
509
        
 
510
 
 
511
        /**Evaluate the energy function from an alpha value, using the current coordinates and the current direction.
 
512
         * 
 
513
         * @param alpha 
 
514
         * @return                      Energy function value.
 
515
         */
 
516
        private double evaluateEnergyFunction(double alpha) {
 
517
                //logger.debug("alpha= " + alpha);
 
518
                this.xAlpha.set(this.x);
 
519
                //logger.debug("xAlpha = " + xAlpha);
 
520
                GVector directionStep = direction;
 
521
                //logger.debug("directionStep = " + directionStep);
 
522
                xAlpha.scaleAdd(alpha, directionStep, xAlpha);
 
523
                //logger.debug("xAlpha = " + xAlpha);
 
524
                double fxAlpha = pf.energyFunction(xAlpha);
 
525
                //logger.debug("fxAlpha = " + fxAlpha);
 
526
                return fxAlpha;
 
527
        }
 
528
        
 
529
        
 
530
        /**Evaluate the gradient of the energy function from an alpha value, 
 
531
         * using the current coordinates and the current direction.
 
532
         * 
 
533
         * @param alpha         Alpha value for the one-dimensional problem generate from the current coordinates and the current direction.
 
534
         * @return                              Gradient of the energy function at alpha. 
 
535
         */
 
536
        private GVector evaluateEnergyFunctionDerivative(double alpha) {
 
537
                //logger.debug("alpha= " + alpha);
 
538
                this.xAlpha.set(this.x);
 
539
                //logger.debug("xAlpha = " + xAlpha);
 
540
                GVector directionStep = direction;
 
541
                //logger.debug("directionStep = " + directionStep);
 
542
                xAlpha.scaleAdd(alpha, directionStep, xAlpha);
 
543
                //logger.debug("xAlpha = " + xAlpha);
 
544
                pf.setEnergyGradient(xAlpha);
 
545
                GVector dfxAlpha = pf.getEnergyGradient();
 
546
                //logger.debug("dfxAlpha = " + dfxAlpha);
 
547
                return dfxAlpha;
 
548
        }
 
549
 
 
550
        
 
551
        /**
 
552
         *      From the interval [a, b] that bracket the minimum, evaluates the energy function at an intermediate point x 
 
553
         *  and obtain a new, smaller bracketing interval, either (a,x) or (x,b).        
 
554
         *
 
555
         * @param lambdaMin             a
 
556
         * @param flambdaMin            Energy function at a.
 
557
         * @param lambdaMax             b
 
558
         * @param flambdaMax            Energy function at b.
 
559
         * @return                                      An intermediate point x
 
560
         */
 
561
        /*private double goldenSectionMethod(double lambdaMin, double flambdaMin, double lambdaMax, double flambdaMax) {
 
562
 
 
563
                //logger.debug("Golden Section Search");
 
564
                double goldenLambda;
 
565
                
 
566
                double lambda1 = lambdaMin;
 
567
                double lambda4 = lambdaMax;
 
568
                double lambda2 = lambda1 + 0.3819660112 * (lambda4 - lambda1);
 
569
                double lambda3 = lambda1 + 0.6180339887498948482 * (lambda4 - lambda1);
 
570
                
 
571
                //double flambda1 = flambdaMin;
 
572
                double flambda2 = evaluateEnergyFunction(lambda2);
 
573
                double flambda3 = evaluateEnergyFunction(lambda3);
 
574
                //double flambda4 = flambdaMax;
 
575
                
 
576
                //logger.debug("lambda1 = " + lambda1 + ", flambda1 = " + flambda1);
 
577
                //logger.debug("lambda2 = " + lambda2 + ", flambda2 = " + flambda2);
 
578
                //logger.debug("lambda3 = " + lambda3 + ", flambda3 = " + flambda3);
 
579
                //logger.debug("lambda4 = " + lambda4 + ", flambda4 = " + flambda4);
 
580
 
 
581
                if (flambda2 < flambda3) {              //we can bracket the minimum by the interval [lambda1, lambda3]
 
582
                        goldenLambda = lambda2;
 
583
                        linearFunctionGoldenAlpha = flambda2;
 
584
                }       
 
585
                else {                  //we can bracket the minimum by the interval [lambda2, lambda4]
 
586
                        goldenLambda = lambda3;
 
587
                        linearFunctionGoldenAlpha = flambda3;
 
588
                }
 
589
 
 
590
                return goldenLambda;
 
591
        }*/
 
592
 
 
593
 
 
594
}