Log In | Get Help   
Home My Page Projects Code Snippets Project Openings Mareframe
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files
[mareframe] Diff of /trunk/gadget/hooke.cc
[mareframe] / trunk / gadget / hooke.cc Repository:
ViewVC logotype

Diff of /trunk/gadget/hooke.cc

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1, Mon Feb 10 17:09:07 2014 UTC revision 26, Mon May 8 07:59:53 2017 UTC
# Line 1  Line 1 
1  /* Nonlinear Optimization using the algorithm of Hooke and Jeeves  */  /* Nonlinear Optimization using the algorithm of Hooke and Jeeves  */
2  /*  12 February 1994    author: Mark G. Johnson                    */  /*  12 February 1994    author: Mark G. Johnson                    */
3    //
4  /* Find a point X where the nonlinear function f(X) has a local    */  /* Find a point X where the nonlinear function f(X) has a local    */
5  /* minimum.  X is an n-vector and f(X) is a scalar.  In mathe-     */  /* minimum.  X is an n-vector and f(X) is a scalar.  In mathe-     */
6  /* matical notation  f: R^n -> R^1.  The objective function f()    */  /* matical notation  f: R^n -> R^1.  The objective function f()    */
7  /* is not required to be continuous.  Nor does f() need to be      */  /* is not required to be continuous.  Nor does f() need to be      */
8  /* differentiable.  The program does not use or require            */  /* differentiable.  The program does not use or require            */
9  /* derivatives of f().                                             */  /* derivatives of f().                                             */
10    //
11  /* The software user supplies three things: a subroutine that      */  /* The software user supplies three things: a subroutine that      */
12  /* computes f(X), an initial "starting guess" of the minimum point */  /* computes f(X), an initial "starting guess" of the minimum point */
13  /* X, and values for the algorithm convergence parameters.  Then   */  /* X, and values for the algorithm convergence parameters.  Then   */
14  /* the program searches for a local minimum, beginning from the    */  /* the program searches for a local minimum, beginning from the    */
15  /* starting guess, using the Direct Search algorithm of Hooke and  */  /* starting guess, using the Direct Search algorithm of Hooke and  */
16  /* Jeeves.                                                         */  /* Jeeves.                                                         */
17    //
18  /* This C program is adapted from the Algol pseudocode found in    */  /* This C program is adapted from the Algol pseudocode found in    */
19  /* "Algorithm 178: Direct Search" by Arthur F. Kaupe Jr., Commun-  */  /* "Algorithm 178: Direct Search" by Arthur F. Kaupe Jr., Commun-  */
20  /* ications of the ACM, Vol 6. p.313 (June 1963).  It includes the */  /* ications of the ACM, Vol 6. p.313 (June 1963).  It includes the */
# Line 24  Line 24 
24  /* highly as the one by A. Kaupe, is:  R. Hooke and T. A. Jeeves,  */  /* highly as the one by A. Kaupe, is:  R. Hooke and T. A. Jeeves,  */
25  /* "Direct Search Solution of Numerical and Statistical Problems", */  /* "Direct Search Solution of Numerical and Statistical Problems", */
26  /* Journal of the ACM, Vol. 8, April 1961, pp. 212-229.            */  /* Journal of the ACM, Vol. 8, April 1961, pp. 212-229.            */
27    //
28  /* Calling sequence:                                               */  /* Calling sequence:                                               */
29  /*  int hooke(nvars, startpt, endpt, rho, epsilon, itermax)        */  /*  int hooke(nvars, startpt, endpt, rho, epsilon, itermax)        */
30  /*                                                                 */  /*                                                                 */
# Line 59  Line 59 
59  /*     itermax     {an integer}  A second, rarely used, halting    */  /*     itermax     {an integer}  A second, rarely used, halting    */
60  /*         criterion.  If the algorithm uses >= itermax            */  /*         criterion.  If the algorithm uses >= itermax            */
61  /*         iterations, halt.                                       */  /*         iterations, halt.                                       */
62    //
63  /* The user-supplied objective function f(x,n) should return a C   */  /* The user-supplied objective function f(x,n) should return a C   */
64  /* "double".  Its  arguments are  x -- an array of doubles, and    */  /* "double".  Its  arguments are  x -- an array of doubles, and    */
65  /* n -- an integer.  x is the point at which f(x) should be        */  /* n -- an integer.  x is the point at which f(x) should be        */
66  /* evaluated, and n is the number of coordinates of x.  That is,   */  /* evaluated, and n is the number of coordinates of x.  That is,   */
67  /* n is the number of coefficients being fitted.                   */  /* n is the number of coefficients being fitted.                   */
68    //
69  /*             rho, the algorithm convergence control              */  /*             rho, the algorithm convergence control              */
70    //
71  /*  The algorithm works by taking "steps" from one estimate of     */  /*  The algorithm works by taking "steps" from one estimate of     */
72  /*    a minimum, to another (hopefully better) estimate.  Taking   */  /*    a minimum, to another (hopefully better) estimate.  Taking   */
73  /*    big steps gets to the minimum more quickly, at the risk of   */  /*    big steps gets to the minimum more quickly, at the risk of   */
# Line 95  Line 95 
95  /*    again with a larger value of rho such as 0.85, using the     */  /*    again with a larger value of rho such as 0.85, using the     */
96  /*    result of the first minimization as the starting guess to    */  /*    result of the first minimization as the starting guess to    */
97  /*    begin the second minimization.                               */  /*    begin the second minimization.                               */
98    //
99  /*                        Normal use:                              */  /*                        Normal use:                              */
100  /*    (1) Code your function f() in the C language                 */  /*    (1) Code your function f() in the C language                 */
101  /*    (2) Install your starting guess {or read it in}              */  /*    (2) Install your starting guess {or read it in}              */
102  /*    (3) Run the program                                          */  /*    (3) Run the program                                          */
103  /*    (4) {for the skeptical}: Use the computed minimum            */  /*    (4) {for the skeptical}: Use the computed minimum            */
104  /*        as the starting point for another run                    */  /*        as the starting point for another run                    */
105    //
106  /* Data Fitting:                                                   */  /* Data Fitting:                                                   */
107  /*  Code your function f() to be the sum of the squares of the     */  /*  Code your function f() to be the sum of the squares of the     */
108  /*  errors (differences) between the computed values and the       */  /*  errors (differences) between the computed values and the       */
# Line 113  Line 113 
113  /*  f(x) = SUM (measured_y[i] - ((A*t[i]*t[i]) + (B*exp(t[i]))     */  /*  f(x) = SUM (measured_y[i] - ((A*t[i]*t[i]) + (B*exp(t[i]))     */
114  /*                + (C*tan(t[i]))))^2                              */  /*                + (C*tan(t[i]))))^2                              */
115  /*  where x[] is a 3-vector consisting of {A, B, C}.               */  /*  where x[] is a 3-vector consisting of {A, B, C}.               */
116    //
117  /*  The author of this software is M.G. Johnson.                   */  /*  The author of this software is M.G. Johnson.                   */
118  /*  Permission to use, copy, modify, and distribute this software  */  /*  Permission to use, copy, modify, and distribute this software  */
119  /*  for any purpose without fee is hereby granted, provided that   */  /*  for any purpose without fee is hereby granted, provided that   */
# Line 125  Line 125 
125  /*  AUTHOR NOR AT&T MAKE ANY REPRESENTATION OR WARRANTY OF ANY     */  /*  AUTHOR NOR AT&T MAKE ANY REPRESENTATION OR WARRANTY OF ANY     */
126  /*  KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS    */  /*  KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS    */
127  /*  FITNESS FOR ANY PARTICULAR PURPOSE.                            */  /*  FITNESS FOR ANY PARTICULAR PURPOSE.                            */
128    //
129  /* JMB this has been modified to work with the gadget object structure   */  /* JMB this has been modified to work with the gadget object structure   */
130  /* This means that the function has been replaced by a call to ecosystem */  /* This means that the function has been replaced by a call to ecosystem */
131  /* object, and we can use the vector objects that have been defined      */  /* object, and we can use the vector objects that have been defined      */
# Line 139  Line 139 
139  #include "ecosystem.h"  #include "ecosystem.h"
140  #include "global.h"  #include "global.h"
141    
142  extern Ecosystem* EcoSystem;  #ifdef _OPENMP
143    #include "omp.h"
144    #endif
145    
146    extern Ecosystem* EcoSystem;
147    #ifdef _OPENMP
148    extern Ecosystem** EcoSystems;
149    #endif
150    
151  /* given a point, look for a better one nearby, one coord at a time */  /* given a point, look for a better one nearby, one coord at a time */
152  double OptInfoHooke::bestNearby(DoubleVector& delta, DoubleVector& point, double prevbest, IntVector& param) {  double OptInfoHooke::bestNearby(DoubleVector& delta, DoubleVector& point, double prevbest, IntVector& param) {
# Line 171  Line 177 
177    return minf;    return minf;
178  }  }
179    
180    /* given a point, look for a better one nearby, one coord at a time */
181    #ifdef _OPENMP
182    /*
183     * function bestBeraby parallelized with OpenMP
184     * · 2 threads per coord to parallelize the calculation of +delta/-delta
185     * · parallelize the calculation of the best nearby of the coord
186     */
187    double OptInfoHooke::bestNearbyRepro(DoubleVector& delta, DoubleVector& point, double prevbest, IntVector& param) {
188      double minf;//, ftmp;
189      int i, j, k;
190      DoubleVector z(point);
191    
192      struct Storage {
193              DoubleVector z;
194              DoubleVector delta;
195              double ftmp;
196              int iters;
197      };
198    
199      minf = prevbest;
200      i = 0;
201    
202      int paral_tokens, numThr, nvars = point.Size();
203      numThr = omp_get_max_threads ( );
204    
205      Storage* storage = new Storage[numThr];
206      if ((numThr % 2) == 0)
207              paral_tokens = numThr / 2;
208      else {
209              return -1;
210      }
211    
212    //  omp_set_dynamic(0);
213    //  omp_set_nested(1); //permit the nested parallelization
214      while ( i < nvars) {
215              if ((i + paral_tokens -1) >= nvars)
216                      paral_tokens = nvars - i;
217    #pragma omp parallel for num_threads(paral_tokens*2) private(k) //parallelize the parameters (numThr)
218              for (j = 0; j < (paral_tokens*2); ++j) {
219                      storage[j].z = z;
220                      storage[j].delta = delta;
221                      DoubleVector v(z);
222    
223                      if (j<paral_tokens) {
224                              k = param[i+j];
225                              v[k] +=  delta[k];
226                      }
227                      else {
228                              k = param[i+j-paral_tokens];
229                              v[k] -=  delta[k];
230                      }
231    
232                      storage[j].ftmp = EcoSystems[j]->SimulateAndUpdate(v);
233                      storage[j].z[k] = v[k];
234              }
235              for (j = 0; j < paral_tokens; ++j) {
236                      k = param[i+j];
237                      if (storage[j].ftmp < minf) {
238                              storage[j].iters = 1;
239    //                        storage[j].z[k] = v1[k];
240                      } else {
241                              storage[j].iters = 2;
242                              storage[j].delta[k] = 0.0 - delta[k];
243                              if (storage[j+paral_tokens].ftmp < minf) {
244                                      storage[j].ftmp = storage[j+paral_tokens].ftmp;
245                                      storage[j].z[k] = storage[j+paral_tokens].z[k];;
246                              }
247                      }
248              }
249    
250              for (j = 0; j < paral_tokens; ++j) {
251                      i++;
252                      iters += storage[j].iters;
253                      if (storage[j].ftmp < minf) {
254                              minf = storage[j].ftmp;
255                              z = storage[j].z;
256                              delta = storage[j].delta;
257                              break;
258                      }
259              }
260      }
261      delete[] storage;
262      for (i = 0; i < nvars; ++i)
263        point[i] = z[i];
264      return minf;
265    }
266    void OptInfoHooke::OptimiseLikelihoodREP() {
267    
268      double oldf, newf, bestf, steplength, tmp;
269      int    i, offset;
270      int    rchange, rcheck, rnumber;  //Used to randomise the order of the parameters
271    
272      handle.logMessage(LOGINFO, "\nStarting Hooke & Jeeves optimisation algorithm\n");
273      int nvars = EcoSystem->numOptVariables();
274      DoubleVector x(nvars);
275      DoubleVector trialx(nvars);
276      DoubleVector bestx(nvars);
277      DoubleVector lowerb(nvars);
278      DoubleVector upperb(nvars);
279      DoubleVector init(nvars);
280      DoubleVector initialstep(nvars, rho);
281      DoubleVector delta(nvars);
282      IntVector param(nvars, 0);
283      IntVector lbound(nvars, 0);
284      IntVector rbounds(nvars, 0);
285      IntVector trapped(nvars, 0);
286    
287      EcoSystem->scaleVariables();
288      int numThr = omp_get_max_threads ( );
289      for (i = 0; i < numThr; i++) // scale the variables for the ecosystem of every thread
290              EcoSystems[i]->scaleVariables();
291      EcoSystem->getOptScaledValues(x);
292      EcoSystem->getOptLowerBounds(lowerb);
293      EcoSystem->getOptUpperBounds(upperb);
294      EcoSystem->getOptInitialValues(init);
295    
296      for (i = 0; i < nvars; i++) {
297        // Scaling the bounds, because the parameters are scaled
298        lowerb[i] = lowerb[i] / init[i];
299        upperb[i] = upperb[i] / init[i];
300        if (lowerb[i] > upperb[i]) {
301          tmp = lowerb[i];
302          lowerb[i] = upperb[i];
303          upperb[i] = tmp;
304        }
305    
306        bestx[i] = x[i];
307        trialx[i] = x[i];
308        param[i] = i;
309        delta[i] = ((2 * (rand() % 2)) - 1) * rho;  //JMB - randomise the sign
310      }
311    
312      bestf = EcoSystem->SimulateAndUpdate(trialx);
313      if (bestf != bestf) { //check for NaN
314        handle.logMessage(LOGINFO, "Error starting Hooke & Jeeves optimisation with f(x) = infinity");
315        converge = -1;
316        iters = 1;
317        return;
318      }
319    
320      offset = EcoSystem->getFuncEval();  //number of function evaluations done before loop
321      newf = bestf;
322      oldf = bestf;
323      steplength = lambda;
324      if (isZero(steplength))
325        steplength = rho;
326    
327      iters = 0;
328    
329      while (1) {
330        if (isZero(bestf)) {
331    //      iters = EcoSystem->getFuncEval() - offset;
332          handle.logMessage(LOGINFO, "Error in Hooke & Jeeves optimisation after", iters, "function evaluations, f(x) = 0");
333          converge = -1;
334          return;
335        }
336    
337        /* randomize the order of the parameters once in a while */
338        rchange = 0;
339        while (rchange < nvars) {
340          rnumber = rand() % nvars;
341          rcheck = 1;
342          for (i = 0; i < rchange; i++)
343            if (param[i] == rnumber)
344              rcheck = 0;
345          if (rcheck) {
346            param[rchange] = rnumber;
347            rchange++;
348          }
349        }
350    
351        /* find best new point, one coord at a time */
352        for (i = 0; i < nvars; i++)
353          trialx[i] = x[i];
354        newf = this->bestNearbyRepro(delta, trialx, bestf, param);
355        if (newf == -1) {
356            handle.logMessage(LOGINFO, "\nStopping Hooke & Jeeves optimisation algorithm\n");
357            handle.logMessage(LOGINFO, "\nThe number of threads must be a multiple of 2\n");
358            return;
359        }
360        /* if too many function evaluations occur, terminate the algorithm */
361    
362    //    iters = EcoSystem->getFuncEval() - offset;
363        if (iters > hookeiter) {
364          handle.logMessage(LOGINFO, "\nStopping Hooke & Jeeves optimisation algorithm\n");
365          handle.logMessage(LOGINFO, "The optimisation stopped after", iters, "function evaluations");
366          handle.logMessage(LOGINFO, "The steplength was reduced to", steplength);
367          handle.logMessage(LOGINFO, "The optimisation stopped because the maximum number of function evaluations");
368          handle.logMessage(LOGINFO, "was reached and NOT because an optimum was found for this run");
369    
370          score = EcoSystem->SimulateAndUpdate(trialx);
371          handle.logMessage(LOGINFO, "\nHooke & Jeeves finished with a likelihood score of", score);
372          for (i = 0; i < nvars; i++)
373            bestx[i] = trialx[i] * init[i];
374          EcoSystem->storeVariables(score, bestx);
375          return;
376        }
377    
378        /* if we made some improvements, pursue that direction */
379        while (newf < bestf) {
380          for (i = 0; i < nvars; i++) {
381            /* if it has been trapped but f has now gotten better (bndcheck) */
382            /* we assume that we are out of the trap, reset the counters     */
383            /* and go back to the stepsize we had when we got trapped        */
384            if ((trapped[i]) && (newf < oldf * bndcheck)) {
385              trapped[i] = 0;
386              lbound[i] = 0;
387              rbounds[i] = 0;
388              delta[i] = initialstep[i];
389    
390            } else if (trialx[i] < (lowerb[i] + verysmall)) {
391              lbound[i]++;
392              trialx[i] = lowerb[i];
393              if (!trapped[i]) {
394                initialstep[i] = delta[i];
395                trapped[i] = 1;
396              }
397              /* if it has hit the bounds 2 times then increase the stepsize */
398              if (lbound[i] >= 2)
399                delta[i] /= rho;
400    
401            } else if (trialx[i] > (upperb[i] - verysmall)) {
402              rbounds[i]++;
403              trialx[i] = upperb[i];
404              if (!trapped[i]) {
405                initialstep[i] = delta[i];
406                trapped[i] = 1;
407              }
408              /* if it has hit the bounds 2 times then increase the stepsize */
409              if (rbounds[i] >= 2)
410                delta[i] /= rho;
411            }
412          }
413    
414          for (i = 0; i < nvars; i++) {
415            /* firstly, arrange the sign of delta[] */
416            if (trialx[i] < x[i])
417              delta[i] = 0.0 - fabs(delta[i]);
418            else
419              delta[i] = fabs(delta[i]);
420    
421            /* now, move further in this direction  */
422            tmp = x[i];
423            x[i] = trialx[i];
424            trialx[i] = trialx[i] + trialx[i] - tmp;
425          }
426    
427          /* only move forward if this is really an improvement    */
428          oldf = newf;
429          newf = EcoSystem->SimulateAndUpdate(trialx);
430          iters++;
431          if ((isEqual(newf, oldf)) || (newf > oldf)) {
432            newf = oldf;  //JMB no improvement, so reset the value of newf
433            break;
434          }
435    
436          /* OK, it's better, so update variables and look around  */
437          bestf = newf;
438          for (i = 0; i < nvars; i++)
439            x[i] = trialx[i];
440    
441          newf = this->bestNearbyRepro(delta, trialx, bestf, param);
442          if (newf == -1) {
443                    handle.logMessage(LOGINFO, "\nStopping Hooke & Jeeves optimisation algorithm\n");
444                    handle.logMessage(LOGINFO, "\nThe number of threads must be a multiple of 2\n");
445                    return;
446              }
447          if (isEqual(newf, bestf))
448            break;
449    
450          /* if too many function evaluations occur, terminate the algorithm */
451    //      iters = EcoSystem->getFuncEval() - offset;
452          if (iters > hookeiter) {
453            handle.logMessage(LOGINFO, "\nStopping Hooke & Jeeves optimisation algorithm\n");
454            handle.logMessage(LOGINFO, "The optimisation stopped after", iters, "function evaluations");
455            handle.logMessage(LOGINFO, "The steplength was reduced to", steplength);
456            handle.logMessage(LOGINFO, "The optimisation stopped because the maximum number of function evaluations");
457            handle.logMessage(LOGINFO, "was reached and NOT because an optimum was found for this run");
458    
459            score = EcoSystem->SimulateAndUpdate(trialx);
460            handle.logMessage(LOGINFO, "\nHooke & Jeeves finished with a likelihood score of", score);
461            for (i = 0; i < nvars; i++)
462              bestx[i] = trialx[i] * init[i];
463            EcoSystem->storeVariables(score, bestx);
464            return;
465          }
466        } // while (newf < bestf)
467    
468    //    iters = EcoSystem->getFuncEval() - offset;
469        if (newf < bestf) {
470          for (i = 0; i < nvars; i++)
471            bestx[i] = x[i] * init[i];
472          bestf = newf;
473          handle.logMessage(LOGINFO, "\nNew optimum found after", iters, "function evaluations");
474          handle.logMessage(LOGINFO, "The likelihood score is", bestf, "at the point");
475          EcoSystem->storeVariables(bestf, bestx);
476          EcoSystem->writeBestValues();
477    
478        } else
479          handle.logMessage(LOGINFO, "Checking convergence criteria after", iters, "function evaluations ...");
480    
481        /* if the step length is less than hookeeps, terminate the algorithm */
482        if (steplength < hookeeps) {
483          handle.logMessage(LOGINFO, "\nStopping Hooke & Jeeves optimisation algorithm\n");
484          handle.logMessage(LOGINFO, "The optimisation stopped after", iters, "function evaluations");
485          handle.logMessage(LOGINFO, "The steplength was reduced to", steplength);
486          handle.logMessage(LOGINFO, "The optimisation stopped because an optimum was found for this run");
487    
488          converge = 1;
489          score = bestf;
490          handle.logMessage(LOGINFO, "\nHooke & Jeeves finished with a likelihood score of", score);
491          EcoSystem->storeVariables(bestf, bestx);
492          return;
493        }
494    
495        steplength *= rho;
496        handle.logMessage(LOGINFO, "Reducing the steplength to", steplength);
497        for (i = 0; i < nvars; i++)
498          delta[i] *= rho;
499      }
500    }
501    #endif
502    
503  void OptInfoHooke::OptimiseLikelihood() {  void OptInfoHooke::OptimiseLikelihood() {
504    
505    double oldf, newf, bestf, steplength, tmp;    double oldf, newf, bestf, steplength, tmp;
# Line 229  Line 558 
558    if (isZero(steplength))    if (isZero(steplength))
559      steplength = rho;      steplength = rho;
560    
561      iters = 0;
562    
563    while (1) {    while (1) {
564      if (isZero(bestf)) {      if (isZero(bestf)) {
565        iters = EcoSystem->getFuncEval() - offset;        iters = EcoSystem->getFuncEval() - offset;
# Line 255  Line 586 
586      for (i = 0; i < nvars; i++)      for (i = 0; i < nvars; i++)
587        trialx[i] = x[i];        trialx[i] = x[i];
588      newf = this->bestNearby(delta, trialx, bestf, param);      newf = this->bestNearby(delta, trialx, bestf, param);
   
589      /* if too many function evaluations occur, terminate the algorithm */      /* if too many function evaluations occur, terminate the algorithm */
590    
591      iters = EcoSystem->getFuncEval() - offset;      iters = EcoSystem->getFuncEval() - offset;
592      if (iters > hookeiter) {      if (iters > hookeiter) {
593        handle.logMessage(LOGINFO, "\nStopping Hooke & Jeeves optimisation algorithm\n");        handle.logMessage(LOGINFO, "\nStopping Hooke & Jeeves optimisation algorithm\n");
# Line 354  Line 685 
685          EcoSystem->storeVariables(score, bestx);          EcoSystem->storeVariables(score, bestx);
686          return;          return;
687        }        }
688      }      } // while (newf < bestf)
689    
690      iters = EcoSystem->getFuncEval() - offset;      iters = EcoSystem->getFuncEval() - offset;
691      if (newf < bestf) {      if (newf < bestf) {
# Line 389  Line 720 
720        delta[i] *= rho;        delta[i] *= rho;
721    }    }
722  }  }
723    
724    /* Functions to perform the parallelization of the algorithm of HJ with OpenMP*/
725    #ifdef _OPENMP
726    //#ifdef SPECULATIVE
727    double OptInfoHooke::bestNearbySpec(DoubleVector& delta, DoubleVector& point, double prevbest, IntVector& param) {
728      double minf;
729      int i, j, k, ii;
730      DoubleVector z(point);
731      int bestId = 0;
732      struct Storage {
733              DoubleVector z;
734              DoubleVector delta;
735              double ftmp;
736              int iters;
737      };
738    
739      minf = prevbest;
740    
741      int paral_tokens, numThr, nvars = point.Size();
742      numThr = omp_get_max_threads ( );
743    
744      Storage* storage = new Storage[numThr];
745      if ((numThr % 2) == 0)
746              paral_tokens = numThr / 2;
747      else {
748              return -1;
749      }
750    
751    //  omp_set_dynamic(0);
752    //  omp_set_nested(1); //permit the nested parallelization
753      for (ii=0; ii< paral_tokens; ii++) {
754              i = 0;
755              while ( i < nvars) {
756                      if ((i + paral_tokens -1) >= nvars)
757                              paral_tokens = nvars - i;
758            #pragma omp parallel for num_threads(paral_tokens*2) private(k)
759                      for (j = 0; j < (paral_tokens*2); ++j) {
760                              storage[j].z = z;
761                              storage[j].delta = delta;
762                              DoubleVector v(z);
763    
764                              if (j<paral_tokens) {
765                                      k = param[i+j];
766                                      v[k] +=  delta[k];
767                              }
768                              else {
769                                      k = param[i+j-paral_tokens];
770                                      v[k] -=  delta[k];
771                              }
772    
773                              storage[j].ftmp = EcoSystems[j]->SimulateAndUpdate(v);
774                              storage[j].z[k] = v[k];
775                      }
776    
777                      for (j = 0; j < paral_tokens; ++j) {
778                              k = param[i+j];
779                              if (storage[j].ftmp < minf) {
780                                      storage[j].iters = 1;
781    //                                storage[j].z[k] = v1[k];
782                              } else {
783                                      storage[j].iters = 2;
784                                      storage[j].delta[k] = 0.0 - delta[k];
785                                      if (storage[j+paral_tokens].ftmp < minf) {
786                                              storage[j].ftmp = storage[j+paral_tokens].ftmp;
787                                              storage[j].z[k] = storage[j+paral_tokens].z[k];
788                                      }
789                                      else iters += 2;
790                              }
791                      }
792    
793                      bestId = 0;
794                      for (j = 1; j < paral_tokens; ++j) {
795                              if (storage[j].ftmp < storage[bestId].ftmp)
796                                      bestId = j;
797                      }
798                      if (storage[bestId].ftmp < minf) {
799                              iters += storage[bestId].iters;
800                              minf = storage[bestId].ftmp;
801                              z = storage[bestId].z;
802                              delta = storage[bestId].delta;
803                      }
804    
805                      i += paral_tokens;
806              }
807              paral_tokens = numThr / 2;
808            }
809    
810      delete[] storage;
811      for (i = 0; i < nvars; ++i)
812        point[i] = z[i];
813    
814      return minf;
815    }
816    
817      void OptInfoHooke::OptimiseLikelihoodOMP() {
818              double oldf, newf, bestf, steplength, tmp;
819               int    i, offset;
820               int    rchange, rcheck, rnumber;  //Used to randomise the order of the parameters
821    
822               handle.logMessage(LOGINFO, "\nStarting Hooke & Jeeves optimisation algorithm\n");
823               int nvars = EcoSystem->numOptVariables();
824               DoubleVector x(nvars);
825               DoubleVector trialx(nvars);
826               DoubleVector bestx(nvars);
827               DoubleVector lowerb(nvars);
828               DoubleVector upperb(nvars);
829               DoubleVector init(nvars);
830               DoubleVector initialstep(nvars, rho);
831               DoubleVector delta(nvars);
832               IntVector param(nvars, 0);
833               IntVector lbound(nvars, 0);
834               IntVector rbounds(nvars, 0);
835               IntVector trapped(nvars, 0);
836    
837               EcoSystem->scaleVariables();
838               int numThr = omp_get_max_threads ( );
839               for (i = 0; i < numThr; i++) // scale the variables for the ecosystem of every thread
840                      EcoSystems[i]->scaleVariables();
841               EcoSystem->getOptScaledValues(x);
842               EcoSystem->getOptLowerBounds(lowerb);
843               EcoSystem->getOptUpperBounds(upperb);
844               EcoSystem->getOptInitialValues(init);
845    
846               for (i = 0; i < nvars; i++) {
847                 // Scaling the bounds, because the parameters are scaled
848                 lowerb[i] = lowerb[i] / init[i];
849                 upperb[i] = upperb[i] / init[i];
850                 if (lowerb[i] > upperb[i]) {
851                   tmp = lowerb[i];
852                   lowerb[i] = upperb[i];
853                   upperb[i] = tmp;
854                 }
855    
856                 bestx[i] = x[i];
857                 trialx[i] = x[i];
858                 param[i] = i;
859                 delta[i] = ((2 * (rand() % 2)) - 1) * rho;  //JMB - randomise the sign
860               }
861    
862               bestf = EcoSystem->SimulateAndUpdate(trialx);
863               if (bestf != bestf) { //check for NaN
864                 handle.logMessage(LOGINFO, "Error starting Hooke & Jeeves optimisation with f(x) = infinity");
865                 converge = -1;
866                 iters = 1;
867                 return;
868               }
869    
870               offset = EcoSystem->getFuncEval();  //number of function evaluations done before loop
871               newf = bestf;
872               oldf = bestf;
873               steplength = lambda;
874               if (isZero(steplength))
875                 steplength = rho;
876    
877               iters = 0;
878    
879               while (1) {
880                 if (isZero(bestf)) {
881    //       #ifndef _OPENMP
882    //             iters = EcoSystem->getFuncEval() - offset;
883    //       #endif
884                   handle.logMessage(LOGINFO, "Error in Hooke & Jeeves optimisation after", iters, "function evaluations, f(x) = 0");
885                   converge = -1;
886                   return;
887                 }
888    
889                 /* randomize the order of the parameters once in a while */
890                 rchange = 0;
891                 while (rchange < nvars) {
892                   rnumber = rand() % nvars;
893                   rcheck = 1;
894                   for (i = 0; i < rchange; i++)
895                     if (param[i] == rnumber)
896                       rcheck = 0;
897                   if (rcheck) {
898                     param[rchange] = rnumber;
899                     rchange++;
900                   }
901                 }
902    
903                 /* find best new point, one coord at a time */
904                 for (i = 0; i < nvars; i++)
905                   trialx[i] = x[i];
906    //       #ifdef _OPENMP
907                 newf = this->bestNearbySpec(delta, trialx, bestf, param);
908                 if (newf == -1) {
909                    handle.logMessage(LOGINFO, "\nStopping Hooke & Jeeves optimisation algorithm\n");
910                    handle.logMessage(LOGINFO, "\nThe number of threads must be a multiple of 2\n");
911                    return;
912                 }
913    //       #else
914    //           newf = this->bestNearby(delta, trialx, bestf, param);
915    //       #endif
916                 /* if too many function evaluations occur, terminate the algorithm */
917    
918    //       #ifndef _OPENMP
919    //           iters = EcoSystem->getFuncEval() - offset;
920    //       #endif
921                 if (iters > hookeiter) {
922                   handle.logMessage(LOGINFO, "\nStopping Hooke & Jeeves optimisation algorithm\n");
923                   handle.logMessage(LOGINFO, "The optimisation stopped after", iters, "function evaluations");
924                   handle.logMessage(LOGINFO, "The steplength was reduced to", steplength);
925                   handle.logMessage(LOGINFO, "The optimisation stopped because the maximum number of function evaluations");
926                   handle.logMessage(LOGINFO, "was reached and NOT because an optimum was found for this run");
927    
928                   score = EcoSystem->SimulateAndUpdate(trialx);
929                   handle.logMessage(LOGINFO, "\nHooke & Jeeves finished with a likelihood score of", score);
930                   for (i = 0; i < nvars; i++)
931                     bestx[i] = trialx[i] * init[i];
932                   EcoSystem->storeVariables(score, bestx);
933                   return;
934                 }
935    
936                 /* if we made some improvements, pursue that direction */
937                 while (newf < bestf) {
938                   for (i = 0; i < nvars; i++) {
939                     /* if it has been trapped but f has now gotten better (bndcheck) */
940                     /* we assume that we are out of the trap, reset the counters     */
941                     /* and go back to the stepsize we had when we got trapped        */
942                     if ((trapped[i]) && (newf < oldf * bndcheck)) {
943                       trapped[i] = 0;
944                       lbound[i] = 0;
945                       rbounds[i] = 0;
946                       delta[i] = initialstep[i];
947    
948                     } else if (trialx[i] < (lowerb[i] + verysmall)) {
949                       lbound[i]++;
950                       trialx[i] = lowerb[i];
951                       if (!trapped[i]) {
952                         initialstep[i] = delta[i];
953                         trapped[i] = 1;
954                       }
955                       /* if it has hit the bounds 2 times then increase the stepsize */
956                       if (lbound[i] >= 2)
957                         delta[i] /= rho;
958    
959                     } else if (trialx[i] > (upperb[i] - verysmall)) {
960                       rbounds[i]++;
961                       trialx[i] = upperb[i];
962                       if (!trapped[i]) {
963                         initialstep[i] = delta[i];
964                         trapped[i] = 1;
965                       }
966                       /* if it has hit the bounds 2 times then increase the stepsize */
967                       if (rbounds[i] >= 2)
968                         delta[i] /= rho;
969                     }
970                   }
971    
972                   for (i = 0; i < nvars; i++) {
973                     /* firstly, arrange the sign of delta[] */
974                     if (trialx[i] < x[i])
975                       delta[i] = 0.0 - fabs(delta[i]);
976                     else
977                       delta[i] = fabs(delta[i]);
978    
979                     /* now, move further in this direction  */
980                     tmp = x[i];
981                     x[i] = trialx[i];
982                     trialx[i] = trialx[i] + trialx[i] - tmp;
983                   }
984    
985                   /* only move forward if this is really an improvement    */
986                   oldf = newf;
987                   newf = EcoSystem->SimulateAndUpdate(trialx);
988    //       #ifdef _OPENMP
989                   iters++;
990    //       #endif
991                   if ((isEqual(newf, oldf)) || (newf > oldf)) {
992                     newf = oldf;  //JMB no improvement, so reset the value of newf
993                     break;
994                   }
995    
996                   /* OK, it's better, so update variables and look around  */
997                   bestf = newf;
998                   for (i = 0; i < nvars; i++)
999                     x[i] = trialx[i];
1000    
1001    //       #ifdef _OPENMP
1002                   newf = this->bestNearbySpec(delta, trialx, bestf, param);
1003                   if (newf == -1) {
1004                            handle.logMessage(LOGINFO, "\nStopping Hooke & Jeeves optimisation algorithm\n");
1005                            handle.logMessage(LOGINFO, "\nThe number of threads must be a multiple of 2\n");
1006                            return;
1007                       }
1008    //       #else
1009    //             newf = this->bestNearby(delta, trialx, bestf, param);
1010    //       #endif
1011                   if (isEqual(newf, bestf))
1012                     break;
1013    
1014                   /* if too many function evaluations occur, terminate the algorithm */
1015    //       #ifndef _OPENMP
1016    //             iters = EcoSystem->getFuncEval() - offset;
1017    //       #endif
1018                   if (iters > hookeiter) {
1019                     handle.logMessage(LOGINFO, "\nStopping Hooke & Jeeves optimisation algorithm\n");
1020                     handle.logMessage(LOGINFO, "The optimisation stopped after", iters, "function evaluations");
1021                     handle.logMessage(LOGINFO, "The steplength was reduced to", steplength);
1022                     handle.logMessage(LOGINFO, "The optimisation stopped because the maximum number of function evaluations");
1023                     handle.logMessage(LOGINFO, "was reached and NOT because an optimum was found for this run");
1024    
1025                     score = EcoSystem->SimulateAndUpdate(trialx);
1026                     handle.logMessage(LOGINFO, "\nHooke & Jeeves finished with a likelihood score of", score);
1027                     for (i = 0; i < nvars; i++)
1028                       bestx[i] = trialx[i] * init[i];
1029                     EcoSystem->storeVariables(score, bestx);
1030                     return;
1031                   }
1032                 }
1033    
1034    //       #ifndef _OPENMP
1035    //           iters = EcoSystem->getFuncEval() - offset;
1036    //       #endif
1037                 if (newf < bestf) {
1038                   for (i = 0; i < nvars; i++)
1039                     bestx[i] = x[i] * init[i];
1040                   bestf = newf;
1041                   handle.logMessage(LOGINFO, "\nNew optimum found after", iters, "function evaluations");
1042                   handle.logMessage(LOGINFO, "The likelihood score is", bestf, "at the point");
1043                   EcoSystem->storeVariables(bestf, bestx);
1044                   EcoSystem->writeBestValues();
1045    
1046                 } else
1047                   handle.logMessage(LOGINFO, "Checking convergence criteria after", iters, "function evaluations ...");
1048    
1049                 /* if the step length is less than hookeeps, terminate the algorithm */
1050                 if (steplength < hookeeps) {
1051                   handle.logMessage(LOGINFO, "\nStopping Hooke & Jeeves optimisation algorithm\n");
1052                   handle.logMessage(LOGINFO, "The optimisation stopped after", iters, "function evaluations");
1053                   handle.logMessage(LOGINFO, "The steplength was reduced to", steplength);
1054                   handle.logMessage(LOGINFO, "The optimisation stopped because an optimum was found for this run");
1055    
1056                   converge = 1;
1057                   score = bestf;
1058                   handle.logMessage(LOGINFO, "\nHooke & Jeeves finished with a likelihood score of", score);
1059                   EcoSystem->storeVariables(bestf, bestx);
1060                   return;
1061                 }
1062    
1063                 steplength *= rho;
1064                 handle.logMessage(LOGINFO, "Reducing the steplength to", steplength);
1065                 for (i = 0; i < nvars; i++)
1066                   delta[i] *= rho;
1067               }
1068      }
1069    //#endif
1070    #endif

Legend:
Removed from v.1  
changed lines
  Added in v.26

root@forge.cesga.es
ViewVC Help
Powered by ViewVC 1.0.0  

Powered By FusionForge