lbfgsb.h

00001 /*
00002  * All of the documentation and software included in the
00003  * Alchemy Software is copyrighted by Stanley Kok, Parag
00004  * Singla, Matthew Richardson, Pedro Domingos, Marc
00005  * Sumner and Hoifung Poon.
00006  * 
00007  * Copyright [2004-06] Stanley Kok, Parag Singla, Matthew
00008  * Richardson, Pedro Domingos, Marc Sumner and Hoifung
00009  * Poon. All rights reserved.
00010  * 
00011  * Contact: Pedro Domingos, University of Washington
00012  * (pedrod@cs.washington.edu).
00013  * 
00014  * Redistribution and use in source and binary forms, with
00015  * or without modification, are permitted provided that
00016  * the following conditions are met:
00017  * 
00018  * 1. Redistributions of source code must retain the above
00019  * copyright notice, this list of conditions and the
00020  * following disclaimer.
00021  * 
00022  * 2. Redistributions in binary form must reproduce the
00023  * above copyright notice, this list of conditions and the
00024  * following disclaimer in the documentation and/or other
00025  * materials provided with the distribution.
00026  * 
00027  * 3. All advertising materials mentioning features or use
00028  * of this software must display the following
00029  * acknowledgment: "This product includes software
00030  * developed by Stanley Kok, Parag Singla, Matthew
00031  * Richardson, Pedro Domingos, Marc Sumner and Hoifung
00032  * Poon in the Department of Computer Science and
00033  * Engineering at the University of Washington".
00034  * 
00035  * 4. Your publications acknowledge the use or
00036  * contribution made by the Software to your research
00037  * using the following citation(s): 
00038  * Stanley Kok, Parag Singla, Matthew Richardson and
00039  * Pedro Domingos (2005). "The Alchemy System for
00040  * Statistical Relational AI", Technical Report,
00041  * Department of Computer Science and Engineering,
00042  * University of Washington, Seattle, WA.
00043  * http://www.cs.washington.edu/ai/alchemy.
00044  * 
00045  * 5. Neither the name of the University of Washington nor
00046  * the names of its contributors may be used to endorse or
00047  * promote products derived from this software without
00048  * specific prior written permission.
00049  * 
00050  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF WASHINGTON
00051  * AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00052  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00053  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00054  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY
00055  * OF WASHINGTON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00056  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00057  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00058  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00059  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00060  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00061  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00062  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00063  * IF ADVISED OF THE POSS IBILITY OF SUCH DAMAGE.
00064  * 
00065  */
00066 #ifndef LBFGSB_H_SEP_17_2005
00067 #define LBFGSB_H_SEP_17_2005
00068 
00069 #include <cmath>
00070 #include <cstdlib>
00071 #include <fstream>
00072 #include "timer.h"
00073 #include "pseudologlikelihood.h"
00074 #include "Polynomial.h"
00075 
00076 const int LBFGSB_PRINT = -1; //-1: no output; 1: output for every iteration
00077 
00078 // The code below from setulb() onwards is ported from: 
00079 // C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: a
00080 // limited memory FORTRAN code for solving bound constrained
00081 // optimization problems'', Tech. Report, NAM-11, EECS Department,
00082 // Northwestern University.
00083 
00084 class LBFGSB
00085 {
00086  public:
00087   LBFGSB(const int& maxIter, const double& ftol, 
00088          PseudoLogLikelihood* const& pll, const int& numWts) 
00089     : maxIter_(maxIter), ftol_(ftol), pll_(pll),
00090       nbd_(NULL), iwa_(NULL), l_(NULL), u_(NULL), g_(NULL), wa_(NULL)
00091   { init(numWts); }
00092 
00093 
00094   ~LBFGSB() { destroy(); }
00095 
00096   
00097   void setMaxIter(const int& iter) { maxIter_ = iter; }
00098 
00099   void setFtol(const double& tol)  { ftol_ = tol; }
00100 
00101 
00102   void init(const int& numWts)
00103   {
00104     destroy();
00105     numWts_ = numWts;
00106     int mmax = 17;
00107     nbd_ = new int[numWts_+1];
00108     iwa_ = new int[3*numWts_+1];
00109     l_   = new double[numWts_+1];
00110     u_   = new double[numWts_+1];
00111     g_   = new double[numWts_+1];
00112     wa_  = new double[2*mmax*numWts_+4*numWts_+12*mmax*mmax+12*mmax+1];    
00113   }
00114 
00115 
00116   void reInit(const int& numWts)
00117   {
00118           if (numWts_ == numWts) return;
00119           init(numWts);
00120   }
00121 
00122   void destroy() 
00123   {
00124     if (nbd_ != NULL) delete [] nbd_;
00125     if (iwa_ != NULL) delete [] iwa_;
00126     if (l_   != NULL) delete [] l_;
00127     if (u_   != NULL) delete [] u_;
00128     if (g_   != NULL) delete [] g_;
00129     if (wa_  != NULL) delete [] wa_;
00130   }
00131 
00132   double minimize(double* const & wts, int& iter, bool& error)
00133   {
00134           error = false;
00135           int m = 5; //max number of limited memory corrections
00136           double f; // value of function to be optimized
00137           double factr = 0;
00138           double pgtol = 0;
00139           // -1: silent (-1); 1: out at every iteration
00140           ofstream* itfile = NULL;
00141           int iprint = LBFGSB_PRINT; 
00142           if (iprint >= 1) itfile = new ofstream("iterate.dat");
00143           iter = 0;
00144 
00145           //indicate that the elements of x[] are unbounded
00146           for (int i = 0; i <= numWts_; i++) nbd_[i] = 0;
00147 
00148           strcpy(task_,"START");
00149           for (int i = 5; i <= 60; i++) task_[i]=' ';
00150 
00151           setulb(numWts_,m,wts,l_,u_,nbd_,f,g_,factr,pgtol,wa_,iwa_,task_,
00152                   iprint,csave_,lsave_,isave_,dsave_,itfile);
00153 
00154           double initialValue = 0, prevValue = 0, newValue;
00155           bool firstIter = true;
00156 
00157           //while routine returns "FG" or "NEW_X" in task, keep calling it
00158           while (strncmp(task_,"FG",2)==0 || strncmp(task_,"NEW_X",5)==0)
00159           {
00160                   if (strncmp(task_,"FG",2)==0)
00161                   {
00162                           f = getValueAndGradient(g_, wts);
00163 
00164                           setulb(numWts_,m,wts,l_,u_,nbd_,f,g_,factr,pgtol,wa_,iwa_,task_,
00165                                   iprint,csave_,lsave_,isave_,dsave_,itfile);
00166 
00167                           if (firstIter) { firstIter = false; prevValue = f; initialValue = f; }
00168                   }
00169                   else
00170                   {
00171                           //the minimization routine has returned with a new iterate,
00172                           //and we have opted to continue the iteration
00173                           if (iter+1 > maxIter_) break;
00174                           ++iter;
00175                           newValue = f;
00176 
00177                           if (fabs(newValue-prevValue) < ftol_*fabs(prevValue)) break;
00178                           prevValue = newValue;
00179 
00180                           setulb(numWts_,m,wts,l_,u_,nbd_,f,g_,factr,pgtol,wa_,iwa_,task_,
00181                                   iprint,csave_,lsave_,isave_,dsave_,itfile);
00182                   }
00183           }
00184 
00185 
00186           //If task is neither FG nor NEW_X we terminate execution.
00187           //the minimization routine has returned with one of
00188           //{CONV, ABNO, ERROR}
00189 
00190           if (strncmp(task_,"ABNO",4) == 0)
00191           {
00192                   cout << "ERROR: LBFGSB failed. Returned ABNO" << endl;
00193                   error = true;
00194                   return initialValue;
00195           }
00196 
00197           if (strncmp(task_,"ERROR",5)==0)
00198           {
00199                   cout << "ERROR: LBFGSB failed. Returned ERROR" << endl;
00200                   error = true;
00201                   return initialValue;
00202           }
00203 
00204           if (strncmp(task_,"CONV",4)==0)
00205           {
00206                   //cout << "LBFGSB converged!" << endl;
00207           }
00208 
00209           return f;    
00210   }
00211 
00212   double minimize(const int& numWts, double* const & wts, int& iter,bool& error)
00213   {
00214     reInit(numWts);
00215     return minimize(wts, iter, error);
00216   }
00217 
00218   double startPl(double* const & wts, int& iter, bool& error, PolyNomial& pl)
00219   {
00220           error = false;
00221           int m = 5; //max number of limited memory corrections
00222           double f; // value of function to be optimized
00223           double factr = 0;
00224           double pgtol = 0;
00225           // -1: silent (-1); 1: out at every iteration
00226           ofstream* itfile = NULL;
00227           int iprint = LBFGSB_PRINT; 
00228           if (iprint >= 1) itfile = new ofstream("iterate.dat");
00229           iter = 0;
00230           //indicate that the elements of x[] are unbounded
00231           //for (int i = 0; i <= numWts_; i++) nbd_[i] = 0;
00232 
00233           //indicate that the elements of x[] have both upper bounds and lower bounds
00234           for (int i = 0; i <= numWts_; i++) nbd_[i] = 2;
00235 
00236           strcpy(task_,"START");
00237           for (int i = 5; i <= 60; i++) task_[i]=' ';
00238 
00239           // set the initial value of pl here
00240           pl.varValue_.clear();
00241           for(int i = 0; i < numWts_; i++) pl.varValue_.append(wts[i+1]);       
00242 
00243           setulb(numWts_,m,wts,l_,u_,nbd_,f,g_,factr,pgtol,wa_,iwa_,task_,
00244                   iprint,csave_,lsave_,isave_,dsave_,itfile);
00245 
00246           iter++;
00247           pl.varValue_.clear();
00248           for(int i = 0; i < numWts_; i++) pl.varValue_.append(wts[i+1]);       
00249           return f;
00250   }
00251   // assume the lower boudn and upper bound are set
00252   double proceedOneStepPl(double* const & wts, double& initialValue, int& iter, bool& error, PolyNomial& pl)
00253   {
00254           error = false;
00255           int m = 5; //max number of limited memory corrections
00256           double f = initialValue; // value of function to be optimized
00257           double factr = 0;
00258           double pgtol = 0;
00259           // -1: silent (-1); 1: out at every iteration
00260           ofstream* itfile = NULL;
00261           int iprint = LBFGSB_PRINT; 
00262           if (iprint >= 1) itfile = new ofstream("iterate.dat");
00263           //iter = 0;
00264           //while routine returns "FG" or "NEW_X" in task, keep calling it
00265           if (strncmp(task_,"FG",2)==0)
00266           {
00267                   f = getValueAndGradientPl(g_, wts, pl);
00268                   setulb(numWts_,m,wts,l_,u_,nbd_,f,g_,factr,pgtol,wa_,iwa_,task_,
00269                           iprint,csave_,lsave_,isave_,dsave_,itfile);
00270                   pl.varValue_.clear();
00271                   for(int i = 0; i < numWts_; i++) pl.varValue_.append(wts[i+1]);       
00272                   //pl.printVars(cout);
00273           }
00274           else
00275           {
00276                   //the minimization routine has returned with a new iterate,
00277                   //and we have opted to continue the iteration
00278                   if (iter + 1 > maxIter_) return -BigValue;
00279                   ++iter;                 
00280 
00281                   setulb(numWts_,m,wts,l_,u_,nbd_,f,g_,factr,pgtol,wa_,iwa_,task_,
00282                           iprint,csave_,lsave_,isave_,dsave_,itfile);
00283 
00284                   pl.varValue_.clear();
00285                   for(int i = 0; i < numWts_; i++) pl.varValue_.append(wts[i+1]);       
00286                   //pl.printVars(cout);
00287           }
00288 
00289 
00290           //If task is neither FG nor NEW_X we terminate execution.
00291           //the minimization routine has returned with one of
00292           //{CONV, ABNO, ERROR}
00293           return f;  
00294 
00295   }
00296 
00297 
00298   double minimizePl(double* const & wts, int& iter, bool& error, PolyNomial& pl)
00299   {
00300         error = false;
00301         int m = 5; //max number of limited memory corrections
00302         double f; // value of function to be optimized
00303         double factr = 0;
00304         double pgtol = 0;
00305         // -1: silent (-1); 1: out at every iteration
00306         ofstream* itfile = NULL;
00307         int iprint = LBFGSB_PRINT; 
00308         if (iprint >= 1) itfile = new ofstream("iterate.dat");
00309         iter = 0;
00310         //indicate that the elements of x[] are unbounded
00311         //for (int i = 0; i <= numWts_; i++) nbd_[i] = 0;
00312 
00313         //indicate that the elements of x[] have both upper bounds and lower bounds
00314         for (int i = 0; i <= numWts_; i++) nbd_[i] = 2;
00315 
00316         strcpy(task_,"START");
00317         for (int i = 5; i <= 60; i++) task_[i]=' ';
00318 
00319         // set the initial value of pl here
00320         pl.varValue_.clear();
00321         for(int i = 0; i < numWts_; i++) pl.varValue_.append(wts[i+1]); 
00322 
00323         setulb(numWts_,m,wts,l_,u_,nbd_,f,g_,factr,pgtol,wa_,iwa_,task_,
00324                 iprint,csave_,lsave_,isave_,dsave_,itfile);
00325 
00326         pl.varValue_.clear();
00327         for(int i = 0; i < numWts_; i++) pl.varValue_.append(wts[i+1]); 
00328         //pl.printVars(cout);
00329 
00330         double initialValue = 0, prevValue = 0, newValue;
00331         bool firstIter = true;
00332 
00333         //while routine returns "FG" or "NEW_X" in task, keep calling it
00334         while (strncmp(task_,"FG",2)==0 || strncmp(task_,"NEW_X",5)==0)
00335         {
00336                 if (strncmp(task_,"FG",2)==0)
00337                 {
00338                         f = getValueAndGradientPl(g_, wts, pl);
00339 
00340                         setulb(numWts_,m,wts,l_,u_,nbd_,f,g_,factr,pgtol,wa_,iwa_,task_,
00341                                 iprint,csave_,lsave_,isave_,dsave_,itfile);
00342 
00343                         pl.varValue_.clear();
00344                         for(int i = 0; i < numWts_; i++) pl.varValue_.append(wts[i+1]); 
00345                         //pl.printVars(cout);
00346 
00347                         if (firstIter) { firstIter = false; prevValue = f; initialValue = f; }
00348                 }
00349                 else
00350                 {
00351                         //the minimization routine has returned with a new iterate,
00352                         //and we have opted to continue the iteration
00353                         if (iter+1 > maxIter_) break;
00354                         ++iter;
00355                         newValue = f;
00356 
00357                         if (fabs(newValue-prevValue) < ftol_*fabs(prevValue)) break;
00358                         prevValue = newValue;
00359 
00360                         setulb(numWts_,m,wts,l_,u_,nbd_,f,g_,factr,pgtol,wa_,iwa_,task_,
00361                                 iprint,csave_,lsave_,isave_,dsave_,itfile);
00362 
00363                         pl.varValue_.clear();
00364                         for(int i = 0; i < numWts_; i++) pl.varValue_.append(wts[i+1]); 
00365                         //pl.printVars(cout);
00366                 }
00367         }
00368 
00369 
00370         //If task is neither FG nor NEW_X we terminate execution.
00371         //the minimization routine has returned with one of
00372         //{CONV, ABNO, ERROR}
00373 
00374         if (strncmp(task_,"ABNO",4) == 0)
00375         {
00376                 cout << "ERROR: LBFGSB failed. Returned ABNO" << endl;
00377                 error = true;
00378                 return initialValue;
00379         }
00380 
00381         if (strncmp(task_,"ERROR",5)==0)
00382         {
00383                 cout << "ERROR: LBFGSB failed. Returned ERROR" << endl;
00384                 error = true;
00385                 return initialValue;
00386         }
00387 
00388         if (strncmp(task_,"CONV",4)==0)
00389         {
00390                 //cout << "LBFGSB converged!" << endl;
00391         }
00392 
00393         return f;   
00394 
00395   }
00396   
00397  
00398   void setUpperBounds(const double* u)
00399   {
00400         if (numWts_ > 0)
00401         {
00402                 memcpy(u_+1, u, numWts_*sizeof(double));
00403         }       
00404   }
00405 
00406   void setLowerBounds(const double* l)
00407   {
00408           if(numWts_ > 0)
00409           {
00410                   memcpy(l_+1, l, numWts_*sizeof(double));
00411           }
00412   }
00413 
00414  private:
00415   int maxIter_;
00416   double ftol_;
00417   PseudoLogLikelihood* pll_; //not owned by LBFGSB; do not delete
00418   int numWts_;
00419   
00420     // params of lbfgsb algorithm
00421   int*    nbd_;
00422   int*    iwa_;
00423   double* l_;
00424   double* u_;
00425   double* g_;
00426   double* wa_;
00427 
00428   char task_[61];
00429   char csave_[61];
00430   bool lsave_[5];
00431   int  isave_[45];
00432   double dsave_[30];
00433 
00434 
00435  private :
00436 // g for storing gradient, wts for storing current assignment to variables
00437   double getValueAndGradientPl(double* const & g, const double* const & wts, PolyNomial& pl)
00438   {
00439          g[0] = 0;
00440          //set pl var values
00441          //get Pl gradient 
00442          Array<double> gr = pl.GetGradient();
00443         
00444          for(int i = 0; i < gr.size(); i++)
00445          {
00446                 g[i+1] = gr[i];
00447          }
00448 
00449          return pl.ComputePlValue();
00450   }
00451   double getValueAndGradient(double* const & g, const double* const & wts)
00452   {
00453     return (pll_->getValueAndGradient(g+1, wts+1, numWts_));
00454   }
00455 
00456     //function
00457   int getIdx(const int& i, const int& j, const int& idim)
00458   {
00459     return (j-1)*idim + i;
00460   }
00461 
00462 
00463   double max(const double& a, const double& b) { if (a>=b) return a; return b; }
00464 
00465   double min(const double& a, const double& b) { if (a<=b) return a; return b; }
00466 
00467   int min(const int& a, const int& b) { if (a<=b) return a; return b; }
00468 
00469   double max(const double& a, const double& b, const double& c)
00470   {
00471     if (a >= b && a >= c) return a;
00472     if (b >= a && b >= c) return b;
00473     assert(c >= a && c >= b);
00474     return c;
00475   }
00476 
00477 
00478   // The code below is ported from: 
00479   // C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: a
00480   // limited memory FORTRAN code for solving bound constrained
00481   // optimization problems'', Tech. Report, NAM-11, EECS Department,
00482   // Northwestern University.
00483 
00484   // The comments before each function are from the original fortran code.
00485 
00486   //   ************
00487   //
00488   //   Subroutine setulb
00489   //
00490   //   This subroutine partitions the working arrays wa and iwa, and 
00491   //     then uses the limited memory BFGS method to solve the bound
00492   //     constrained optimization problem by calling mainlb.
00493   //     (The direct method will be used in the subspace minimization.)
00494   //
00495   //   n is an integer variable.
00496   //     On entry n is the dimension of the problem.
00497   //     On exit n is unchanged.
00498   //
00499   //   m is an integer variable.
00500   //     On entry m is the maximum number of variable metric corrections
00501   //       used to define the limited memory matrix.
00502   //     On exit m is unchanged.
00503   //
00504   //   x is a double precision array of dimension n.
00505   //     On entry x is an approximation to the solution.
00506   //     On exit x is the current approximation.
00507   //
00508   //   l is a double precision array of dimension n.
00509   //     On entry l is the lower bound on x.
00510   //     On exit l is unchanged.
00511   //
00512   //   u is a double precision array of dimension n.
00513   //     On entry u is the upper bound on x.
00514   //     On exit u is unchanged.
00515   //
00516   //   nbd is an integer array of dimension n.
00517   //     On entry nbd represents the type of bounds imposed on the
00518   //       variables, and must be specified as follows:
00519   //       nbd(i)=0 if x(i) is unbounded,
00520   //              1 if x(i) has only a lower bound,
00521   //              2 if x(i) has both lower and upper bounds, and
00522   //              3 if x(i) has only an upper bound.
00523   //     On exit nbd is unchanged.
00524   //
00525   //   f is a double precision variable.
00526   //     On first entry f is unspecified.
00527   //     On final exit f is the value of the function at x.
00528   //
00529   //   g is a double precision array of dimension n.
00530   //     On first entry g is unspecified.
00531   //     On final exit g is the value of the gradient at x.
00532   //
00533   //   factr is a double precision variable.
00534   //     On entry factr >= 0 is specified by the user.  The iteration
00535   //       will stop when
00536   //
00537   //       (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} <= factr*epsmch
00538   //
00539   //       where epsmch is the machine precision, which is automatically
00540   //       generated by the code. Typical values for factr: 1.d+12 for
00541   //       low accuracy; 1.d+7 for moderate accuracy; 1.d+1 for extremely
00542   //       high accuracy.
00543   //     On exit factr is unchanged.
00544   //
00545   //   pgtol is a double precision variable.
00546   //     On entry pgtol >= 0 is specified by the user.  The iteration
00547   //       will stop when
00548   //
00549   //               max{|proj g_i | i = 1, ..., n} <= pgtol
00550   //
00551   //       where pg_i is the ith component of the projected gradient.   
00552   //     On exit pgtol is unchanged.
00553   //
00554   //   wa is a double precision working array of length 
00555   //     (2mmax + 4)nmax + 12mmax^2 + 12mmax.
00556   //
00557   //   iwa is an integer working array of length 3nmax.
00558   //
00559   //   task is a working string of characters of length 60 indicating
00560   //     the current job when entering and quitting this subroutine.
00561   //
00562   //   iprint is an integer variable that must be set by the user.
00563   //     It controls the frequency and type of output generated:
00564   //      iprint<0    no output is generated;
00565   //      iprint=0    print only one line at the last iteration;
00566   //      0<iprint<99 print also f and |proj g| every iprint iterations;
00567   //      iprint=99   print details of every iteration except n-vectors;
00568   //      iprint=100  print also the changes of active set and final x;
00569   //      iprint>100  print details of every iteration including x and g;
00570   //     When iprint > 0, the file iterate.dat will be created to
00571   //                      summarize the iteration.
00572   //
00573   //   csave is a working string of characters of length 60.
00574   //
00575   //   lsave is a logical working array of dimension 4.
00576   //     On exit with 'task' = NEW_X, the following information is 
00577   //                                                           available:
00578   //       If lsave(1) = true  then  the initial X has been replaced by
00579   //                                   its projection in the feasible set;
00580   //       If lsave(2) = true  then  the problem is constrained;
00581   //       If lsave(3) = true  then  each variable has upper and lower
00582   //                                   bounds;
00583   //
00584   //   isave is an integer working array of dimension 44.
00585   //     On exit with 'task' = NEW_X, the following information is 
00586   //                                                           available:
00587   //       isave(22) = the total number of intervals explored in the 
00588   //                       search of Cauchy points;
00589   //       isave(26) = the total number of skipped BFGS updates before 
00590   //                       the current iteration;
00591   //       isave(30) = the number of current iteration;
00592   //       isave(31) = the total number of BFGS updates prior the current
00593   //                       iteration;
00594   //       isave(33) = the number of intervals explored in the search of
00595   //                       Cauchy point in the current iteration;
00596   //       isave(34) = the total number of function and gradient 
00597   //                       evaluations;
00598   //       isave(36) = the number of function value or gradient
00599   //                                evaluations in the current iteration;
00600   //       if isave(37) = 0  then the subspace argmin is within the box;
00601   //       if isave(37) = 1  then the subspace argmin is beyond the box;
00602   //       isave(38) = the number of free variables in the current
00603   //                       iteration;
00604   //       isave(39) = the number of active constraints in the current
00605   //                       iteration;
00606   //       n + 1 - isave(40) = the number of variables leaving the set of
00607   //                         active constraints in the current iteration;
00608   //       isave(41) = the number of variables entering the set of active
00609   //                       constraints in the current iteration.
00610   //
00611   //   dsave is a double precision working array of dimension 29.
00612   //     On exit with 'task' = NEW_X, the following information is
00613   //                                                           available:
00614   //       dsave(1) = current 'theta' in the BFGS matrix;
00615   //       dsave(2) = f(x) in the previous iteration;
00616   //       dsave(3) = factr*epsmch;
00617   //       dsave(4) = 2-norm of the line search direction vector;
00618   //       dsave(5) = the machine precision epsmch generated by the code;
00619   //       dsave(7) = the accumulated time spent on searching for
00620   //                                                       Cauchy points;
00621   //       dsave(8) = the accumulated time spent on
00622   //                                               subspace minimization;
00623   //       dsave(9) = the accumulated time spent on line search;
00624   //       dsave(11) = the slope of the line search function at
00625   //                                the current point of line search;
00626   //       dsave(12) = the maximum relative step length imposed in
00627   //                                                         line search;
00628   //       dsave(13) = the infinity norm of the projected gradient;
00629   //       dsave(14) = the relative step length in the line search;
00630   //       dsave(15) = the slope of the line search function at
00631   //                               the starting point of the line search;
00632   //       dsave(16) = the square of the 2-norm of the line search
00633   //                                                    direction vector.
00634   //
00635   //   Subprograms called:
00636   //
00637   //     L-BFGS-B Library ... mainlb.    
00638   //
00639   //
00640   //   References:
00641   //
00642   //     [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
00643   //     memory algorithm for bound constrained optimization'',
00644   //     SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
00645   //
00646   //     [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: a
00647   //     limited memory FORTRAN code for solving bound constrained
00648   //     optimization problems'', Tech. Report, NAM-11, EECS Department,
00649   //     Northwestern University, 1994.
00650   //
00651   //     (Postscript files of these papers are available via anonymous
00652   //      ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.)
00653   //
00654   //                         *  *  *
00655   //
00656   //   NEOS, November 1994. (Latest revision June 1996.)
00657   //   Optimization Technology Center.
00658   //   Argonne National Laboratory and Northwestern University.
00659   //   Written by
00660   //                      Ciyou Zhu
00661   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
00662   //
00663   //
00664   // ************
00665   //function
00666   void setulb(const int& n, const int& m, double* const & x, 
00667               const double* const & l, const double* const & u, 
00668               const int* const & nbd, double& f, double* const & g, 
00669               const double& factr, const double& pgtol, 
00670               double* const & wa, int* const & iwa,
00671               char* const & task, const int& iprint,  
00672               char* const & csave, bool* const & lsave, 
00673               int* const & isave, double* const & dsave,
00674               ofstream* itfile)
00675   { 
00676     int l1,l2,l3,lws,lr,lz,lt,ld,lsg,lwa,lyg,
00677         lsgo,lwy,lsy,lss,lyy,lwt,lwn,lsnd,lygo;
00678 
00679     if (strncmp(task,"START",5)==0)
00680     {
00681       isave[1]  = m*n;
00682       isave[2]  = m*m;
00683       isave[3]  = 4*m*m;
00684       isave[4]  = 1;
00685       isave[5]  = isave[4]  + isave[1];
00686       isave[6]  = isave[5]  + isave[1];
00687       isave[7]  = isave[6]  + isave[2];
00688       isave[8]  = isave[7]  + isave[2];
00689       isave[9]  = isave[8]  + isave[2];
00690       isave[10] = isave[9]  + isave[2];
00691       isave[11] = isave[10] + isave[3];
00692       isave[12] = isave[11] + isave[3];
00693       isave[13] = isave[12] + n;
00694       isave[14] = isave[13] + n;
00695       isave[15] = isave[14] + n;
00696       isave[16] = isave[15] + n;
00697       isave[17] = isave[16] + 8*m;
00698       isave[18] = isave[17] + m;
00699       isave[19] = isave[18] + m;
00700       isave[20] = isave[19] + m;
00701     }
00702     l1   = isave[1];
00703     l2   = isave[2];
00704     l3   = isave[3];
00705     lws  = isave[4];
00706     lwy  = isave[5];
00707     lsy  = isave[6];
00708     lss  = isave[7];
00709     lyy  = isave[8];
00710     lwt  = isave[9];
00711     lwn  = isave[10];
00712     lsnd = isave[11];
00713     lz   = isave[12];
00714     lr   = isave[13];
00715     ld   = isave[14];
00716     lt   = isave[15];
00717     lwa  = isave[16];
00718     lsg  = isave[17];
00719     lsgo = isave[18];
00720     lyg  = isave[19];
00721     lygo = isave[20];
00722 
00723     timer_.reset();
00724     
00725     mainlb(n,m,x,l,u,nbd,f,g,factr,pgtol,
00726            &(wa[lws-1]),&(wa[lwy-1]),&(wa[lsy-1]),&(wa[lss-1]),&(wa[lyy-1]),
00727            &(wa[lwt-1]),&(wa[lwn-1]),&(wa[lsnd-1]),&(wa[lz-1]),&(wa[lr-1]),
00728            &(wa[ld-1]),&(wa[lt-1]),&(wa[lwa-1]),&(wa[lsg-1]),&(wa[lsgo-1]),
00729            &(wa[lyg-1]),&(wa[lygo-1]),&(iwa[1-1]),&(iwa[n+1-1]),&(iwa[2*n+1-1]),
00730            task,iprint,csave,lsave,&(isave[22-1]),dsave, itfile);
00731   } //setulb()
00732 
00733 
00734   //   ************
00735   //
00736   //   Subroutine mainlb
00737   //
00738   //   This subroutine solves bound constrained optimization problems by
00739   //     using the compact formula of the limited memory BFGS updates.
00740   //     
00741   //   n is an integer variable.
00742   //     On entry n is the number of variables.
00743   //     On exit n is unchanged.
00744   //
00745   //   m is an integer variable.
00746   //     On entry m is the maximum number of variable metri//
00747   //     corrections allowed in the limited memory matrix.
00748   //     On exit m is unchanged.
00749   //
00750   //   x is a double precision array of dimension n.
00751   //     On entry x is an approximation to the solution.
00752   //     On exit x is the current approximation.
00753   //
00754   //   l is a double precision array of dimension n.
00755   //     On entry l is the lower bound of x.
00756   //     On exit l is unchanged.
00757   //
00758   //   u is a double precision array of dimension n.
00759   //     On entry u is the upper bound of x.
00760   //     On exit u is unchanged.
00761   //
00762   //   nbd is an integer array of dimension n.
00763   //     On entry nbd represents the type of bounds imposed on the
00764   //       variables, and must be specified as follows:
00765   //       nbd(i)=0 if x(i) is unbounded,
00766   //              1 if x(i) has only a lower bound,
00767   //              2 if x(i) has both lower and upper bounds,
00768   //              3 if x(i) has only an upper bound.
00769   //     On exit nbd is unchanged.
00770   //
00771   //   f is a double precision variable.
00772   //     On first entry f is unspecified.
00773   //     On final exit f is the value of the function at x.
00774   //
00775   //   g is a double precision array of dimension n.
00776   //     On first entry g is unspecified.
00777   //     On final exit g is the value of the gradient at x.
00778   //
00779   //   factr is a double precision variable.
00780   //     On entry factr >= 0 is specified by the user.  The iteration
00781   //       will stop when
00782   //
00783   //       (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} <= factr*epsmch
00784   //
00785   //       where epsmch is the machine precision, which is automatically
00786   //       generated by the code.
00787   //     On exit factr is unchanged.
00788   //
00789   //   pgtol is a double precision variable.
00790   //     On entry pgtol >= 0 is specified by the user.  The iteration
00791   //       will stop when
00792   //
00793   //               max{|proj g_i | i = 1, ..., n} <= pgtol
00794   //
00795   //       where pg_i is the ith component of the projected gradient.
00796   //     On exit pgtol is unchanged.
00797   //
00798   //   ws, wy, sy, and wt are double precision working arrays used to
00799   //     store the following information defining the limited memory
00800   //        BFGS matrix:
00801   //        ws, of dimension n x m, stores S, the matrix of s-vectors;
00802   //        wy, of dimension n x m, stores Y, the matrix of y-vectors;
00803   //        sy, of dimension m x m, stores S'Y;
00804   //        ss, of dimension m x m, stores S'S;
00805   //        yy, of dimension m x m, stores Y'Y;
00806   //        wt, of dimension m x m, stores the Cholesky factorization
00807   //                                of (theta*S'S+LD^(-1)L'); see eq.
00808   //                                (2.26) in [3].
00809   //
00810   //   wn is a double precision working array of dimension 2m x 2m
00811   //     used to store the LEL^T factorization of the indefinite matrix
00812   //               K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
00813   //                   [L_a -R_z           theta*S'AA'S ]
00814   //
00815   //     where     E = [-I  0]
00816   //                   [ 0  I]
00817   //
00818   //   snd is a double precision working array of dimension 2m x 2m
00819   //     used to store the lower triangular part of
00820   //               N = [Y' ZZ'Y   L_a'+R_z']
00821   //                   [L_a +R_z  S'AA'S   ]
00822   //         
00823   //   z(n),r(n),d(n),t(n),wa(8*m) are double precision working arrays.
00824   //     z is used at different times to store the Cauchy point and
00825   //     the Newton point.
00826   //
00827   //   sg(m),sgo(m),yg(m),ygo(m) are double precision working arrays. 
00828   //
00829   //   index is an integer working array of dimension n.
00830   //     In subroutine freev, index is used to store the free and fixed
00831   //        variables at the Generalized Cauchy Point (GCP).
00832   //
00833   //   iwhere is an integer working array of dimension n used to record
00834   //     the status of the vector x for GCP computation.
00835   //     iwhere(i)=0 or -3 if x(i) is free and has bounds,
00836   //               1       if x(i) is fixed at l(i), and l(i) != u(i)
00837   //               2       if x(i) is fixed at u(i), and u(i) != l(i)
00838   //               3       if x(i) is always fixed, i.e.,  u(i)=x(i)=l(i)
00839   //              -1       if x(i) is always free, i.e., no bounds on it.
00840   //
00841   //   indx2 is an integer working array of dimension n.
00842   //     Within subroutine cauchy, indx2 corresponds to the array iorder.
00843   //     In subroutine freev, a list of variables entering and leaving
00844   //     the free set is stored in indx2, and it is passed on to
00845   //     subroutine formk with this information.
00846   //
00847   //   task is a working string of characters of length 60 indicating
00848   //     the current job when entering and leaving this subroutine.
00849   //
00850   //   iprint is an INTEGER variable that must be set by the user.
00851   //     It controls the frequency and type of output generated:
00852   //      iprint<0    no output is generated;
00853   //      iprint=0    print only one line at the last iteration;
00854   //      0<iprint<99 print also f and |proj g| every iprint iterations;
00855   //      iprint=99   print details of every iteration except n-vectors;
00856   //      iprint=100  print also the changes of active set and final x;
00857   //      iprint>100  print details of every iteration including x and g;
00858   //     When iprint > 0, the file iterate.dat will be created to
00859   //                      summarize the iteration.
00860   //
00861   //   csave is a working string of characters of length 60.
00862   //
00863   //   lsave is a logical working array of dimension 4.
00864   //
00865   //   isave is an integer working array of dimension 23.
00866   //
00867   //   dsave is a double precision working array of dimension 29.
00868   //
00869   //
00870   //   Subprograms called
00871   //
00872   //     L-BFGS-B Library ... cauchy, subsm, lnsrlb, formk, 
00873   //
00874   //      errclb, prn1lb, prn2lb, prn3lb, active, projgr,
00875   //
00876   //      freev, cmprlb, matupd, formt.
00877   //
00878   //     Minpack2 Library ... timer, dpmeps.
00879   //
00880   //     Linpack Library ... dcopy, ddot.
00881   //
00882   //
00883   //   References:
00884   //
00885   //     [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
00886   //     memory algorithm for bound constrained optimization'',
00887   //     SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
00888   //
00889   //     [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: FORTRAN
00890   //     Subroutines for Large Scale Bound Constrained Optimization''
00891   //     Tech. Report, NAM-11, EECS Department, Northwestern University,
00892   //     1994.
00893   // 
00894   //     [3] R. Byrd, J. Nocedal and R. Schnabel "Representations of
00895   //     Quasi-Newton Matrices and their use in Limited Memory Methods'',
00896   //     Mathematical Programming 63 (1994), no. 4, pp. 129-156.
00897   //
00898   //     (Postscript files of these papers are available via anonymous
00899   //      ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.)
00900   //
00901   //                         *  *  *
00902   //
00903   //   NEOS, November 1994. (Latest revision June 1996.)
00904   //   Optimization Technology Center.
00905   //   Argonne National Laboratory and Northwestern University.
00906   //   Written by
00907   //                      Ciyou Zhu
00908   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
00909   //
00910   //
00911   //   ************
00912   //function
00913 void mainlb(const int& n, const int& m, double* const & x, 
00914                         const double* const & l, const double* const & u, 
00915                         const int* const & nbd, double& f,  double* const & g, 
00916                         const double& factr, const double& pgtol, 
00917                         double* const & ws, double* const & wy, double* const & sy,
00918                         double* const & ss, double* const & yy, double* const & wt,
00919               double* const & wn, double* const & snd, double* const & z,
00920               double* const & r, double* const & d, double* const & t, 
00921               double* const & wa, double* const & sg, double* const& sgo,
00922               double* const & yg, double* const & ygo, int* const& index,
00923               int* const & iwhere, int* const & indx2, char* const& task,
00924               const int& iprint, char* const& csave, bool * const& lsave,
00925               int* const & isave, double* const & dsave, ofstream* itfile)
00926   {
00927     bool   prjctd,cnstnd,boxed,updatd,wrk;
00928     char   word[4];
00929     int    k,nintol,iback,nskip,
00930            head,col,iter,itail,iupdat,
00931            nint,nfgv,info,ifun=0,
00932            iword,nfree,nact,ileave,nenter;
00933     double theta,fold=0,dr,rr,tol,
00934            xstep,sbgnrm,ddum,dnorm=0,dtd,epsmch,
00935            cpu1=0,cpu2,cachyt,sbtime,lnscht,time1,time2,
00936            gd,gdold=0,stp,stpmx=0,time;
00937     double one=1.0,zero=0.0;
00938 
00939     if (iprint > 1) { assert(itfile); }
00940 
00941     if (strncmp(task,"START",5)==0)
00942     {
00943       time1 = timer_.time();
00944 
00945       //Generate the current machine precision.
00946       epsmch = dpmeps();
00947       //epsmch = 1.08420217E-19;
00948       //cout << "L-BFGS-B computed machine precision = " << epsmch << endl;
00949 
00950       //Initialize counters and scalars when task='START'.
00951 
00952       //for the limited memory BFGS matrices:
00953       col    = 0;
00954       head   = 1;
00955       theta  = one;
00956       iupdat = 0;
00957       updatd = false;
00958  
00959       //for operation counts:
00960       iter   = 0;
00961       nfgv   = 0;
00962       nint   = 0;
00963       nintol = 0;
00964       nskip  = 0;
00965       nfree  = n;
00966 
00967       //for stopping tolerance:
00968       tol = factr*epsmch;
00969 
00970       //for measuring running time:
00971       cachyt = 0;
00972       sbtime = 0;
00973       lnscht = 0;
00974 
00975  
00976       //'word' records the status of subspace solutions.
00977       strcpy(word, "---");
00978 
00979       //'info' records the termination information.
00980       info = 0;
00981 
00982       //commented out: file opened at beginning of function
00983       //if (iprint >= 1)
00984       //{
00985       //  //open a summary file 'iterate.dat'
00986       //  ofstream itfile("lbfgsb-iterate.dat");
00987       //}
00988 
00989       //Check the input arguments for errors.
00990       errclb(n,m,factr,l,u,nbd,task,info,k);
00991       if (strncmp(task,"ERROR",5)==0)
00992       {
00993         prn3lb(n,x,f,task,iprint,info,itfile,
00994                iter,nfgv,nintol,nskip,nact,sbgnrm,
00995                zero,nint,word,iback,stp,xstep,k,
00996                cachyt,sbtime,lnscht);
00997         return;
00998       }
00999 
01000       prn1lb(n,m,l,u,x,iprint,itfile,epsmch);
01001  
01002       //Initialize iwhere & project x onto the feasible set.
01003       active(n,l,u,nbd,x,iwhere,iprint,prjctd,cnstnd,boxed) ;
01004 
01005       //The end of the initialization.
01006     } //if (strncmp(task,"START",5)==0)
01007     else
01008     {
01009       //restore local variables.
01010       prjctd = lsave[1];
01011       cnstnd = lsave[2];
01012       boxed  = lsave[3];
01013       updatd = lsave[4];
01014       
01015       nintol = isave[1];
01016       //itfile = isave[3];
01017       iback  = isave[4];
01018       nskip  = isave[5];
01019       head   = isave[6];
01020       col    = isave[7];
01021       itail  = isave[8];
01022       iter   = isave[9];
01023       iupdat = isave[10];
01024       nint   = isave[12];
01025       nfgv   = isave[13];
01026       info   = isave[14];
01027       ifun   = isave[15];
01028       iword  = isave[16];
01029       nfree  = isave[17];
01030       nact   = isave[18];
01031       ileave = isave[19];
01032       nenter = isave[20];
01033 
01034       theta  = dsave[1];
01035       fold   = dsave[2];
01036       tol    = dsave[3];
01037       dnorm  = dsave[4];
01038       epsmch = dsave[5];
01039       cpu1   = dsave[6];
01040       cachyt = dsave[7];
01041       sbtime = dsave[8];
01042       lnscht = dsave[9];
01043       time1  = dsave[10];
01044       gd     = dsave[11];
01045       stpmx  = dsave[12];
01046       sbgnrm = dsave[13];
01047       stp    = dsave[14];
01048       gdold  = dsave[15];
01049       dtd    = dsave[16];
01050          
01051    
01052       //After returning from the driver go to the point where execution
01053       //is to resume.
01054       if (strncmp(task,"FG_LN",5)==0) goto goto66;
01055       if (strncmp(task,"NEW_X",5)==0) goto goto777;
01056       if (strncmp(task,"FG_ST",5)==0) goto goto111;
01057       if (strncmp(task,"STOP",4)==0)  
01058       {
01059         if (strncmp(&(task[6]),"CPU",3)==0)
01060         {
01061           //restore the previous iterate.
01062           dcopy(n,t,1,x,1);
01063           dcopy(n,r,1,g,1);
01064           f = fold;
01065         }
01066         goto goto999;
01067       }
01068     }
01069 
01070     //Compute f0 and g0.
01071     
01072     strcpy(task, "FG_START");
01073     //return to the driver to calculate f and g; reenter at goto111.
01074     goto goto1000;
01075 
01076   goto111:
01077     
01078     nfgv = 1;
01079  
01080     //Compute the infinity norm of the (-) projected gradient.
01081  
01082     projgr(n,l,u,nbd,x,g,sbgnrm);
01083 
01084     if (iprint >= 1)
01085     {
01086       cout << "At iterate " << iter << ": f=" <<f<<",  |proj g|="<<sbgnrm<<endl;
01087       *itfile << "At iterate " << iter << ": nfgv=" << nfgv 
01088               << ", sbgnrm=" << sbgnrm << ", f=" << f << endl;
01089     }
01090 
01091     if (sbgnrm <= pgtol) 
01092     {
01093       //terminate the algorithm.
01094       strcpy(task,"CONVERGENCE: NORM OF PROJECTED GRADIENT <= PGTOL");
01095       goto goto999;
01096     }
01097  
01098     //----------------- the beginning of the loop ---------------------
01099  
01100   goto222:
01101     if (iprint >= 99) cout << "ITERATION " << (iter + 1) << endl;
01102     iword = -1;
01103 
01104     if (!cnstnd && col > 0) 
01105     {
01106       //skip the search for GCP.
01107       dcopy(n,x,1,z,1);
01108       wrk = updatd;
01109       nint = 0;
01110       goto goto333;
01111     }
01112 
01113     /*********************************************************************
01114      *
01115      *     Compute the Generalized Cauchy Point (GCP).
01116      *
01117      *********************************************************************/
01118 
01119     cpu1 = timer_.time();
01120 
01121     cauchy(n,x,l,u,nbd,g,indx2,iwhere,t,d,z,
01122            m,wy,ws,sy,wt,theta,col,head,
01123            &(wa[1-1]),&(wa[2*m+1-1]),&(wa[4*m+1-1]),&(wa[6*m+1-1]),nint,
01124            sg,yg,iprint,sbgnrm,info,epsmch);
01125 
01126     if (info > 0)
01127     { 
01128       //singular triangular system detected; refresh the lbfgs memory.
01129       if (iprint >= 1) 
01130         cout << "Singular triangular system detected; " 
01131              << "refresh the lbfgs memory and restart the iteration." <<endl;
01132       info   = 0;
01133       col    = 0;
01134       head   = 1;
01135       theta  = one;
01136       iupdat = 0;
01137       updatd = false;
01138       cpu2 = timer_.time();
01139       cachyt = cachyt + cpu2 - cpu1;
01140       goto goto222;
01141     }
01142     cpu2 = timer_.time(); 
01143     cachyt = cachyt + cpu2 - cpu1;
01144     nintol = nintol + nint;
01145 
01146     //Count the entering and leaving variables for iter > 0; 
01147     //find the index set of free and active variables at the GCP.
01148 
01149     freev(n,nfree,index,nenter,ileave,indx2,
01150           iwhere,wrk,updatd,cnstnd,iprint,iter);
01151 
01152     nact = n - nfree;
01153  
01154   goto333:
01155  
01156     //If there are no free variables or B=theta*I, then
01157     //skip the subspace minimization.
01158  
01159     if (nfree == 0 || col == 0) goto goto555;
01160  
01161     /**********************************************************************
01162      *
01163      *     Subspace minimization.
01164      *
01165      **********************************************************************/
01166 
01167     cpu1 = timer_.time();
01168 
01169     //Form  the LEL^T factorization of the indefinite
01170     //matrix    K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
01171     //              [L_a -R_z           theta*S'AA'S ]
01172     //where     E = [-I  0]
01173     //              [ 0  I]
01174 
01175     if (wrk) formk(n,nfree,index,nenter,ileave,indx2,iupdat,
01176                    updatd,wn,snd,m,ws,wy,sy,theta,col,head,info);
01177 
01178     if (info != 0) 
01179     {
01180       //nonpositive definiteness in Cholesky factorization;
01181       //refresh the lbfgs memory and restart the iteration.
01182       if(iprint >= 1) 
01183         cout << "Nonpositive definiteness in Cholesky factorization in formk;"
01184              << "refresh the lbfgs memory and restart the iteration." << endl;
01185       info   = 0;
01186       col    = 0;
01187       head   = 1;
01188       theta  = one;
01189       iupdat = 0;
01190       updatd = false;
01191       cpu2 = timer_.time() ;
01192       sbtime = sbtime + cpu2 - cpu1;
01193       goto goto222;
01194     }
01195 
01196     //compute r=-Z'B(xcp-xk)-Z'g (using wa(2m+1)=W'(xcp-x)
01197     //from 'cauchy').
01198     cmprlb(n,m,x,g,ws,wy,sy,wt,z,r,wa,index,
01199            theta,col,head,nfree,cnstnd,info);
01200     
01201     if (info != 0) goto goto444;
01202     //call the direct method.
01203     subsm(n,m,nfree,index,l,u,nbd,z,r,ws,wy,theta,
01204           col,head,iword,wa,wn,iprint,info);
01205 
01206 
01207   goto444:
01208     if (info != 0) 
01209     {
01210       //singular triangular system detected;
01211       //refresh the lbfgs memory and restart the iteration.
01212       if(iprint >= 1)         
01213         cout << "Singular triangular system detected; " 
01214              << "refresh the lbfgs memory and restart the iteration." <<endl;
01215       info   = 0;
01216       col    = 0;
01217       head   = 1;
01218       theta  = one;
01219       iupdat = 0;
01220       updatd = false;
01221       cpu2   = timer_.time(); 
01222       sbtime = sbtime + cpu2 - cpu1;
01223       goto goto222;
01224     }
01225  
01226     cpu2 = timer_.time(); 
01227     sbtime = sbtime + cpu2 - cpu1 ;
01228   goto555:  
01229 
01230     /*********************************************************************
01231      *
01232      *     Line search and optimality tests.
01233      *
01234      *********************************************************************/
01235  
01236     //Generate the search direction d:=z-x.
01237 
01238     for (int i = 1; i <= n; i++)
01239       d[i] = z[i] - x[i];
01240     
01241     cpu1 = timer_.time();
01242   goto66: 
01243 
01244     lnsrlb(n,l,u,nbd,x,f,fold,gd,gdold,g,d,r,t,z,stp,dnorm,
01245            dtd,xstep,stpmx,iter,ifun,iback,nfgv,info,task,
01246            boxed,cnstnd,csave,&(isave[22-1]),&(dsave[17-1]));
01247 
01248     if (info != 0 || iback >= 20)
01249     {
01250       //restore the previous iterate.
01251       dcopy(n,t,1,x,1);
01252       dcopy(n,r,1,g,1);
01253       f = fold;
01254       if (col == 0) 
01255       {
01256         //abnormal termination.
01257         if (info == 0) 
01258         {
01259           info = -9;
01260           //restore the actual number of f and g evaluations etc.
01261           nfgv  -=  1;
01262           ifun  -=  1;
01263           iback -= 1;
01264         }
01265         strcpy(task, "ABNORMAL_TERMINATION_IN_LNSRCH");
01266         iter += 1;
01267         goto goto999;
01268       }
01269       else
01270       {
01271         //refresh the lbfgs memory and restart the iteration.
01272         if(iprint >= 1)
01273           cout << "Bad direction in the line search; " 
01274                << "the lbfgs memory and restart the iteration" << endl;
01275         if (info == 0) nfgv = nfgv - 1;
01276         info   = 0;
01277         col    = 0;
01278         head   = 1;
01279         theta  = one;
01280         iupdat = 0;
01281         updatd = false;
01282         strcpy(task, "RESTART_FROM_LNSRCH");
01283         cpu2 = timer_.time();
01284         lnscht += cpu2 - cpu1;
01285         goto goto222;
01286       }
01287     }
01288     else 
01289     if (strncmp(task,"FG_LN",5)==0) 
01290     {
01291       //return to the driver for calculating f and g; reenter at goto66.
01292       goto goto1000;
01293     }
01294     else 
01295     {
01296       //calculate and print out the quantities related to the new X.
01297       cpu2 = timer_.time() ;
01298       lnscht += cpu2 - cpu1;
01299       iter += 1;
01300       
01301       //Compute the infinity norm of the projected (-)gradient.
01302       
01303       projgr(n,l,u,nbd,x,g,sbgnrm);
01304       
01305       //Print iteration information.
01306       
01307       prn2lb(n,x,f,g,iprint,itfile,iter,nfgv,nact,
01308              sbgnrm,nint,word,iword,iback,stp,xstep);
01309       goto goto1000;
01310     }
01311   goto777:
01312 
01313     //Test for termination.
01314     
01315     if (sbgnrm <= pgtol) 
01316     {
01317       //terminate the algorithm.
01318       strcpy(task, "CONVERGENCE: NORM OF PROJECTED GRADIENT <= PGTOL");
01319       goto goto999;
01320     } 
01321     
01322     ddum = max(fabs(fold), fabs(f), one);
01323     if ((fold - f) <= tol*ddum) 
01324     {
01325       //terminate the algorithm.
01326       strcpy(task, "CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH");
01327       if (iback >= 10) info = -5;
01328         //i.e., to issue a warning if iback>10 in the line search.
01329       goto goto999;
01330     } 
01331     
01332     //Compute d=newx-oldx, r=newg-oldg, rr=y'y and dr=y's.
01333     
01334     for (int i = 1; i <= n; i++)
01335       r[i] = g[i] - r[i];
01336     rr = ddot(n,r,1,r,1);
01337     if (stp == one) 
01338     {  
01339       dr = gd - gdold;
01340       ddum = -gdold;
01341     }
01342     else
01343     {
01344       dr = (gd - gdold)*stp;
01345       dscal(n,stp,d,1);
01346       ddum = -gdold*stp;
01347     }
01348     
01349     if (dr <= epsmch*ddum) 
01350     {
01351       //skip the L-BFGS update.
01352       nskip = nskip + 1;
01353       updatd = false;
01354       if (iprint >= 1) 
01355         cout << "  ys=" << dr << "   -gs=" <<ddum<<" BFSG update SKIPPED"<<endl;
01356       goto goto888;
01357     } 
01358     
01359   /*********************************************************************
01360    *
01361    *     Update the L-BFGS matrix.
01362    *
01363    *********************************************************************/
01364  
01365     updatd = true;
01366     iupdat += 1;
01367 
01368     //Update matrices WS and WY and form the middle matrix in B.
01369 
01370     matupd(n,m,ws,wy,sy,ss,d,r,itail,
01371            iupdat,col,head,theta,rr,dr,stp,dtd);
01372 
01373     //Form the upper half of the pds T = theta*SS + L*D^(-1)*L';
01374     //Store T in the upper triangular of the array wt;
01375     //Cholesky factorize T to J*J' with
01376     //J' stored in the upper triangular of wt.
01377 
01378     formt(m,wt,sy,ss,col,theta,info);
01379  
01380     if (info != 0) 
01381     {
01382       //nonpositive definiteness in Cholesky factorization;
01383       //refresh the lbfgs memory and restart the iteration.
01384       if(iprint >= 1) 
01385         cout << "Nonpositive definiteness in Cholesky factorization in formt; "
01386              << "refresh the lbfgs memory and restart the iteration." << endl;
01387       info = 0;
01388       col  = 0;
01389       head = 1;
01390       theta = one;
01391       iupdat = 0;
01392       updatd = false;
01393       goto goto222;
01394     }
01395 
01396     //Now the inverse of the middle matrix in B is
01397 
01398     //[  D^(1/2)      O ] [ -D^(1/2)  D^(-1/2)*L' ]
01399     //[ -L*D^(-1/2)   J ] [  0        J'          ]
01400 
01401   goto888:
01402  
01403     //-------------------- the end of the loop -----------------------------
01404  
01405     goto goto222;
01406 
01407   goto999:
01408     time2 = timer_.time();
01409     time = time2 - time1;
01410     prn3lb(n,x,f,task,iprint,info,itfile,
01411            iter,nfgv,nintol,nskip,nact,sbgnrm,
01412            time,nint,word,iback,stp,xstep,k,
01413            cachyt,sbtime,lnscht);
01414   goto1000:
01415 
01416     //Save local variables.
01417     lsave[1]  = prjctd;
01418     lsave[2]  = cnstnd;
01419     lsave[3]  = boxed;
01420     lsave[4]  = updatd;
01421 
01422     isave[1]  = nintol; 
01423     //isave[3]  = itfile;
01424     isave[4]  = iback;
01425     isave[5]  = nskip; 
01426     isave[6]  = head;
01427     isave[7]  = col;
01428     isave[8]  = itail;
01429     isave[9]  = iter; 
01430     isave[10] = iupdat; 
01431     isave[12] = nint; 
01432     isave[13] = nfgv; 
01433     isave[14] = info; 
01434     isave[15] = ifun; 
01435     isave[16] = iword; 
01436     isave[17] = nfree; 
01437     isave[18] = nact; 
01438     isave[19] = ileave; 
01439     isave[20] = nenter; 
01440 
01441     dsave[1]  = theta; 
01442     dsave[2]  = fold; 
01443     dsave[3]  = tol; 
01444     dsave[4]  = dnorm; 
01445     dsave[5]  = epsmch; 
01446     dsave[6]  = cpu1; 
01447     dsave[7]  = cachyt; 
01448     dsave[8]  = sbtime; 
01449     dsave[9]  = lnscht; 
01450     dsave[10] = time1;
01451     dsave[11] = gd;
01452     dsave[12] = stpmx; 
01453     dsave[13] = sbgnrm;
01454     dsave[14] = stp;
01455     dsave[15] = gdold;
01456     dsave[16] = dtd;
01457 
01458   }//mainlb()
01459 
01460 
01461   //   ************
01462   //
01463   //   Subroutine active
01464   //
01465   //   This subroutine initializes iwhere and projects the initial x to
01466   //     the feasible set if necessary.
01467   //
01468   //   iwhere is an integer array of dimension n.
01469   //     On entry iwhere is unspecified.
01470   //     On exit iwhere(i)=-1  if x(i) has no bounds
01471   //                       3   if l(i)=u(i)
01472   //                       0   otherwise.
01473   //     In cauchy, iwhere is given finer gradations.
01474   //
01475   //
01476   //                         *  *  *
01477   //
01478   //   NEOS, November 1994. (Latest revision June 1996.)
01479   //   Optimization Technology Center.
01480   //   Argonne National Laboratory and Northwestern University.
01481   //   Written by
01482   //                      Ciyou Zhu
01483   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
01484   //
01485   //
01486   //   ************
01487     //function
01488   void active(const int& n, const double* const & l, 
01489               const double* const & u, const int* const & nbd, 
01490               double* const & x, int* const & iwhere, const int& iprint,
01491               bool& prjctd, bool& cnstnd, bool& boxed)
01492   {
01493     //int i;
01494     int nbdd;
01495     double zero=0.0;
01496 
01497     //Initialize nbdd, prjctd, cnstnd and boxed.
01498     nbdd   = 0;
01499     prjctd = false;
01500     cnstnd = false;
01501     boxed  = true;
01502 
01503     //Project the initial x to the easible set if necessary.
01504 
01505     for (int i = 1; i <= n; i++)
01506     {
01507       if (nbd[i] > 0)
01508       {
01509         if (nbd[i] <= 2 && x[i] <= l[i])
01510         {
01511                 if (x[i] < l[i])
01512           {
01513             prjctd = true;
01514                   x[i] = l[i];
01515           }
01516           nbdd += 1;
01517         }
01518         else 
01519         if (nbd[i] >= 2 && x[i] >= u[i])
01520         {
01521                 if (x[i] > u[i])
01522           {
01523             prjctd = true;
01524                   x[i] = u[i];
01525           }
01526           nbdd += 1;
01527         }
01528       }
01529     }
01530 
01531     //Initialize iwhere and assign values to cnstnd and boxed.
01532 
01533     for (int i = 1; i <= n; i++)
01534     {
01535       if (nbd[i] != 2) boxed = false;
01536       if (nbd[i] == 0)
01537       {
01538         //this variable is always free
01539         iwhere[i] = -1;
01540         //otherwise set x(i)=mid(x(i), u(i), l(i)).
01541       }
01542       else
01543       {
01544         cnstnd = true;
01545         if (nbd[i] == 2 && (u[i]-l[i]) <= zero)
01546         {
01547           //this variable is always fixed
01548           iwhere[i] = 3;
01549         }
01550         else 
01551           iwhere[i] = 0;
01552       }
01553     }
01554     
01555     if (iprint >= 0)
01556     {
01557       if (prjctd) 
01558         cout << "The initial X is infeasible.  Restart with its projection."
01559              << endl;
01560       if (!cnstnd) cout << "This problem is unconstrained." << endl;
01561     }
01562 
01563     if (iprint > 0) 
01564       cout << "At X0 " << nbdd << " variables are exactly at the bounds" <<endl;
01565   }//active()
01566 
01567 
01568   //   ************
01569   //
01570   //   Subroutine bmv
01571   //
01572   //   This subroutine computes the product of the 2m x 2m middle matrix 
01573   //     in the compact L-BFGS formula of B and a 2m vector v;  
01574   //     it returns the product in p.
01575   //    
01576   //   m is an integer variable.
01577   //     On entry m is the maximum number of variable metric corrections
01578   //       used to define the limited memory matrix.
01579   //     On exit m is unchanged.
01580   //
01581   //   sy is a double precision array of dimension m x m.
01582   //     On entry sy specifies the matrix S'Y.
01583   //     On exit sy is unchanged.
01584   //
01585   //   wt is a double precision array of dimension m x m.
01586   //     On entry wt specifies the upper triangular matrix J' which is 
01587   //       the Cholesky factor of (thetaS'S+LD^(-1)L').
01588   //     On exit wt is unchanged.
01589   //
01590   //   col is an integer variable.
01591   //     On entry col specifies the number of s-vectors (or y-vectors)
01592   //       stored in the compact L-BFGS formula.
01593   //     On exit col is unchanged.
01594   //
01595   //   v is a double precision array of dimension 2col.
01596   //     On entry v specifies vector v.
01597   //     On exit v is unchanged.
01598   //
01599   //   p is a double precision array of dimension 2col.
01600   //     On entry p is unspecified.
01601   //     On exit p is the product Mv.
01602   //
01603   //   info is an integer variable.
01604   //     On entry info is unspecified.
01605   //     On exit info = 0       for normal return,
01606   //                  = nonzero for abnormal return when the system
01607   //                              to be solved by dtrsl is singular.
01608   //
01609   //   Subprograms called:
01610   //
01611   //     Linpack ... dtrsl.
01612   //
01613   //
01614   //                         *  *  *
01615   //
01616   //   NEOS, November 1994. (Latest revision June 1996.)
01617   //   Optimization Technology Center.
01618   //   Argonne National Laboratory and Northwestern University.
01619   //   Written by
01620   //                      Ciyou Zhu
01621   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
01622   //
01623   //
01624   //   ************
01625     //function
01626   void bmv(const int& m, double* const & sy, double* const & wt, 
01627            const int& col, const double* const & v, double* const & p, 
01628            int& info)
01629   {
01630     //int i,k;
01631     int i2;
01632     double sum;
01633  
01634     if (col == 0) return;
01635  
01636     //PART I: solve [  D^(1/2)      O ] [ p1 ] = [ v1 ]
01637     //              [ -L*D^(-1/2)   J ] [ p2 ]   [ v2 ].
01638 
01639     //solve Jp2=v2+LD^(-1)v1.
01640     p[col+1] = v[col+1];
01641 
01642     for (int i = 2; i <= col; i++)
01643     {
01644       i2 = col + i;
01645       sum = 0;
01646       for (int k = 1; k <= i-1; k++)
01647         sum += sy[getIdx(i,k,m)]*v[k]/sy[getIdx(k,k,m)];
01648       
01649       p[i2] = v[i2] + sum;
01650     }
01651 
01652     //Solve the triangular system
01653     dtrsl(wt,m,col,&(p[col+1-1]),11,info);
01654     if (info != 0) return; 
01655  
01656     //solve D^(1/2)p1=v1.
01657     for (int i = 1; i <= col; i++)
01658       p[i] = v[i]/sqrt(sy[getIdx(i,i,m)]);
01659  
01660     //PART II: solve [ -D^(1/2)   D^(-1/2)*L'  ] [ p1 ] = [ p1 ]
01661     //               [  0         J'           ] [ p2 ]   [ p2 ]. 
01662  
01663     //solve J^Tp2=p2. 
01664     dtrsl(wt,m,col,&(p[col+1-1]),1,info);
01665     if (info != 0) return;
01666  
01667     //compute p1=-D^(-1/2)(p1-D^(-1/2)L'p2)
01668     //          =-D^(-1/2)p1+D^(-1)L'p2.  
01669     for (int i = 1; i <= col; i++)
01670       p[i] = -p[i]/sqrt(sy[getIdx(i,i,m)]);
01671     
01672     for (int i = 1; i <= col; i++)
01673     {
01674       sum = 0;
01675       for (int k = i+1; i <= col; i++)
01676         sum += sy[getIdx(k,i,m)]*p[col+k]/sy[getIdx(i,i,m)];
01677       p[i] += sum;
01678     }
01679   }//bmv()
01680 
01681 
01682   //   ************
01683   //
01684   //   Subroutine cauchy
01685   //
01686   //   For given x, l, u, g (with sbgnrm > 0), and a limited memory
01687   //     BFGS matrix B defined in terms of matrices WY, WS, WT, and
01688   //     scalars head, col, and theta, this subroutine computes the
01689   //     generalized Cauchy point (GCP), defined as the first local
01690   //     minimizer of the quadrati//
01691   //
01692   //                Q(x + s) = g's + 1/2 s'Bs
01693   //
01694   //     along the projected gradient direction P(x-tg,l,u).
01695   //     The routine returns the GCP in xcp. 
01696   //     
01697   //   n is an integer variable.
01698   //     On entry n is the dimension of the problem.
01699   //     On exit n is unchanged.
01700   //
01701   //   x is a double precision array of dimension n.
01702   //     On entry x is the starting point for the GCP computation.
01703   //     On exit x is unchanged.
01704   //
01705   //   l is a double precision array of dimension n.
01706   //     On entry l is the lower bound of x.
01707   //     On exit l is unchanged.
01708   //
01709   //   u is a double precision array of dimension n.
01710   //     On entry u is the upper bound of x.
01711   //     On exit u is unchanged.
01712   //
01713   //   nbd is an integer array of dimension n.
01714   //     On entry nbd represents the type of bounds imposed on the
01715   //       variables, and must be specified as follows:
01716   //       nbd(i)=0 if x(i) is unbounded,
01717   //              1 if x(i) has only a lower bound,
01718   //              2 if x(i) has both lower and upper bounds, and
01719   //              3 if x(i) has only an upper bound. 
01720   //     On exit nbd is unchanged.
01721   //
01722   //   g is a double precision array of dimension n.
01723   //     On entry g is the gradient of f(x).  g must be a nonzero vector.
01724   //     On exit g is unchanged.
01725   //
01726   //   iorder is an integer working array of dimension n.
01727   //     iorder will be used to store the breakpoints in the piecewise
01728   //     linear path and free variables encountered. On exit,
01729   //       iorder(1),...,iorder(nleft) are indices of breakpoints
01730   //                              which have not been encountered; 
01731   //       iorder(nleft+1),...,iorder(nbreak) are indices of
01732   //                                   encountered breakpoints; and
01733   //       iorder(nfree),...,iorder(n) are indices of variables which
01734   //               have no bound constraits along the search direction.
01735   //
01736   //   iwhere is an integer array of dimension n.
01737   //     On entry iwhere indicates only the permanently fixed (iwhere=3)
01738   //     or free (iwhere= -1) components of x.
01739   //     On exit iwhere records the status of the current x variables.
01740   //     iwhere(i)=-3  if x(i) is free and has bounds, but is not moved
01741   //               0   if x(i) is free and has bounds, and is moved
01742   //               1   if x(i) is fixed at l(i), and l(i) != u(i)
01743   //               2   if x(i) is fixed at u(i), and u(i) != l(i)
01744   //               3   if x(i) is always fixed, i.e.,  u(i)=x(i)=l(i)
01745   //               -1  if x(i) is always free, i.e., it has no bounds.
01746   //
01747   //   t is a double precision working array of dimension n. 
01748   //     t will be used to store the break points.
01749   //
01750   //   d is a double precision array of dimension n used to store
01751   //     the Cauchy direction P(x-tg)-x.
01752   //
01753   //   xcp is a double precision array of dimension n used to return the
01754   //     GCP on exit.
01755   //
01756   //   m is an integer variable.
01757   //     On entry m is the maximum number of variable metric corrections 
01758   //       used to define the limited memory matrix.
01759   //     On exit m is unchanged.
01760   //
01761   //   ws, wy, sy, and wt are double precision arrays.
01762   //     On entry they store information that defines the
01763   //                           limited memory BFGS matrix:
01764   //       ws(n,m) stores S, a set of s-vectors;
01765   //       wy(n,m) stores Y, a set of y-vectors;
01766   //       sy(m,m) stores S'Y;
01767   //       wt(m,m) stores the
01768   //               Cholesky factorization of (theta*S'S+LD^(-1)L').
01769   //     On exit these arrays are unchanged.
01770   //
01771   //   theta is a double precision variable.
01772   //     On entry theta is the scaling factor specifying B_0 = theta I.
01773   //     On exit theta is unchanged.
01774   //
01775   //   col is an integer variable.
01776   //     On entry col is the actual number of variable metri//
01777   //       corrections stored so far.
01778   //     On exit col is unchanged.
01779   //
01780   //   head is an integer variable.
01781   //     On entry head is the location of the first s-vector (or y-vector)
01782   //       in S (or Y).
01783   //     On exit col is unchanged.
01784   //
01785   //   p is a double precision working array of dimension 2m.
01786   //     p will be used to store the vector p = W^(T)d.
01787   //
01788   //   c is a double precision working array of dimension 2m.
01789   //     c will be used to store the vector c = W^(T)(xcp-x).
01790   //
01791   //   wbp is a double precision working array of dimension 2m.
01792   //     wbp will be used to store the row of W corresponding
01793   //       to a breakpoint.
01794   //
01795   //   v is a double precision working array of dimension 2m.
01796   //
01797   //   nint is an integer variable.
01798   //     On exit nint records the number of quadratic segments explored
01799   //       in searching for the GCP.
01800   //
01801   //   sg and yg are double precision arrays of dimension m.
01802   //     On entry sg  and yg store S'g and Y'g correspondingly.
01803   //     On exit they are unchanged. 
01804   // 
01805   //   iprint is an INTEGER variable that must be set by the user.
01806   //     It controls the frequency and type of output generated:
01807   //      iprint<0    no output is generated;
01808   //      iprint=0    print only one line at the last iteration;
01809   //      0<iprint<99 print also f and |proj g| every iprint iterations;
01810   //      iprint=99   print details of every iteration except n-vectors;
01811   //      iprint=100  print also the changes of active set and final x;
01812   //      iprint>100  print details of every iteration including x and g;
01813   //     When iprint > 0, the file iterate.dat will be created to
01814   //                      summarize the iteration.
01815   //
01816   //   sbgnrm is a double precision variable.
01817   //     On entry sbgnrm is the norm of the projected gradient at x.
01818   //     On exit sbgnrm is unchanged.
01819   //
01820   //   info is an integer variable.
01821   //     On entry info is 0.
01822   //     On exit info = 0       for normal return,
01823   //                  = nonzero for abnormal return when the the system
01824   //                            used in routine bmv is singular.
01825   //
01826   //   Subprograms called:
01827   // 
01828   //     L-BFGS-B Library ... hpsolb, bmv.
01829   //
01830   //     Linpack ... dscal dcopy, daxpy.
01831   //
01832   //
01833   //   References:
01834   //
01835   //     [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
01836   //     memory algorithm for bound constrained optimization'',
01837   //     SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
01838   //
01839   //     [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: FORTRAN
01840   //     Subroutines for Large Scale Bound Constrained Optimization''
01841   //     Tech. Report, NAM-11, EECS Department, Northwestern University,
01842   //     1994.
01843   //
01844   //     (Postscript files of these papers are available via anonymous
01845   //      ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.)
01846   //
01847   //                         *  *  *
01848   //
01849   //   NEOS, November 1994. (Latest revision June 1996.)
01850   //   Optimization Technology Center.
01851   //   Argonne National Laboratory and Northwestern University.
01852   //   Written by
01853   //                      Ciyou Zhu
01854   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
01855   //
01856   //
01857   //   ************  
01858     //function
01859   void cauchy(const int& n, const double* const & x, 
01860               const double* const & l, const double* const & u, 
01861               const int* const & nbd, const double* const & g, 
01862               int* const & iorder, int* const & iwhere, 
01863               double* const & t, double* const & d, double* const & xcp, 
01864               const int& m, double* const & wy, 
01865               double* const & ws, double* const & sy, 
01866               double* const & wt, double& theta, 
01867               const int& col, const int& head, double* const & p, 
01868               double* const & c, double* const & wbp, 
01869               double* const & v, int& nint, const double* const & sg, 
01870               const double* const & yg, const int& iprint, 
01871               const double& sbgnrm, int& info, const double& epsmch)
01872   {
01873     bool xlower,xupper,bnded;
01874     //int i,j;
01875     int col2,nfree,nbreak,pointr,
01876         ibp,nleft,ibkmin,iter;
01877     double f1,f2,dt,dtm,tsum,dibp,zibp,dibp2,bkmin,
01878            tu=0,tl=0,wmc,wmp,wmw,tj,tj0,neggi,
01879            f2_org;
01880     double one=1,zero=0;
01881  
01882     //Check the status of the variables, reset iwhere(i) if necessary;
01883     //compute the Cauchy direction d and the breakpoints t; initialize
01884     //the derivative f1 and the vector p = W'd (for theta = 1).
01885  
01886     if (sbgnrm <= zero)
01887     {
01888       if (iprint >= 0) cout << "Subgnorm = 0.  GCP = X." << endl;
01889       dcopy(n,x,1,xcp,1);
01890       return;
01891     }
01892     bnded = true;
01893     nfree = n + 1;
01894     nbreak = 0;
01895     ibkmin = 0;
01896     bkmin = zero;
01897     col2 = 2*col;
01898     f1 = zero;
01899     if (iprint >= 99) 
01900       cout << "---------------- CAUCHY entered-------------------" << endl;
01901 
01902     //We set p to zero and build it up as we determine d.
01903     for (int i = 1; i <= col2; i++)
01904       p[i] = zero;
01905 
01906     //In the following loop we determine for each variable its bound
01907     //status and its breakpoint, and update p accordingly.
01908     //Smallest breakpoint is identified.
01909 
01910     for (int i = 1; i <= n; i++)      
01911     {
01912       neggi = -g[i];  
01913       if (iwhere[i] != 3 && iwhere[i] != -1)
01914       {
01915         //if x(i) is not a constant and has bounds,
01916         //compute the difference between x(i) and its bounds.
01917         if (nbd[i] <= 2) tl = x[i] - l[i];
01918         if (nbd[i] >= 2) tu = u[i] - x[i];
01919 
01920         //If a variable is close enough to a bound
01921         //we treat it as at bound.
01922         xlower = (nbd[i] <= 2 && tl <= zero);
01923         xupper = (nbd[i] >= 2 && tu <= zero);
01924 
01925         //reset iwhere(i).
01926         iwhere[i] = 0;
01927         if (xlower)
01928         { 
01929           if (neggi <= zero) iwhere[i] = 1;
01930         }
01931         else 
01932         if (xupper)
01933         {
01934           if (neggi >= zero) iwhere[i] = 2;
01935         }
01936         else
01937         {
01938           if (fabs(neggi) <= zero) iwhere[i] = -3;
01939         }
01940       }
01941       pointr = head;
01942       if (iwhere[i] != 0 && iwhere[i] != -1)
01943         d[i] = zero;
01944       else
01945       {
01946         d[i] = neggi;
01947         f1 -= neggi*neggi;
01948         //calculate p := p - W'e_i* (g_i).
01949         for (int j = 1; j <= col; j++)
01950         {
01951           p[j] += wy[getIdx(i,pointr,n)] * neggi;
01952           p[col + j] += ws[getIdx(i,pointr,n)] * neggi;
01953           pointr = pointr%m + 1;
01954         }
01955         if (nbd[i] <= 2 && nbd[i] != 0 && neggi < zero)
01956         {
01957           //x[i] + d[i] is bounded; compute t[i].
01958           nbreak += 1;
01959           iorder[nbreak] = i;
01960           t[nbreak] = tl/(-neggi);
01961           if (nbreak == 1 || t[nbreak] < bkmin)
01962           {
01963             bkmin = t[nbreak];
01964             ibkmin = nbreak;
01965           }
01966         }
01967         else
01968         if (nbd[i] >= 2 && neggi > zero)
01969         {
01970           //x(i) + d(i) is bounded; compute t(i).
01971           nbreak += 1;
01972           iorder[nbreak] = i;
01973           t[nbreak] = tu/neggi;
01974           if (nbreak == 1 || t[nbreak] < bkmin)
01975           {
01976             bkmin = t[nbreak];
01977             ibkmin = nbreak;
01978           }          
01979         }
01980         else
01981         {
01982           //x(i) + d(i) is not bounded.
01983           nfree -= 1;
01984           iorder[nfree] = i;
01985           if (fabs(neggi) > zero) bnded = false;
01986         }
01987       }
01988     } //for (int i = 1; i <= n; i++)      
01989 
01990  
01991     //The indices of the nonzero components of d are now stored
01992     //in iorder(1),...,iorder(nbreak) and iorder(nfree),...,iorder(n).
01993     //The smallest of the nbreak breakpoints is in t(ibkmin)=bkmin.
01994  
01995     if (theta != one)
01996     {
01997       //complete the initialization of p for theta not= one.
01998       dscal(col,theta,&(p[col+1-1]),1);
01999     }
02000  
02001     //Initialize GCP xcp = x.
02002 
02003     dcopy(n,x,1,xcp,1);
02004 
02005     if (nbreak == 0 && nfree == n + 1)
02006     {
02007       //is a zero vector, return with the initial xcp as GCP.
02008       if (iprint > 100) 
02009       {
02010         cout << "Cauchy X = ";
02011         for (int i = 1; i <= n; i++)
02012           cout << xcp[i] << " ";
02013         cout << endl;
02014       }
02015       return;
02016     }    
02017     
02018     //Initialize c = W'(xcp - x) = 0.
02019     
02020     for (int j = 1; j <= col2; j++)
02021       c[j] = zero;
02022     
02023     //Initialize derivative f2.
02024     
02025     f2 = -theta*f1;
02026     f2_org = f2;
02027     if (col > 0) 
02028     {
02029       bmv(m,sy,wt,col,p,v,info);
02030       if (info != 0) return;
02031       f2 -= ddot(col2,v,1,p,1);
02032     }
02033     dtm = -f1/f2;
02034     tsum = zero;
02035     nint = 1;
02036     if (iprint >= 99)
02037       cout << "There are " << nbreak << " breakpoints" << endl;
02038     
02039     //If there are no breakpoints, locate the GCP and return. 
02040     
02041     if (nbreak == 0) goto goto888;
02042     
02043     nleft = nbreak;
02044     iter = 1;
02045     
02046     tj = zero;
02047     
02048     //------------------- the beginning of the loop -------------------------
02049     
02050   goto777:
02051     
02052     //Find the next smallest breakpoint;
02053     //compute dt = t(nleft) - t(nleft + 1).
02054     
02055     tj0 = tj;
02056     if (iter == 1) 
02057     {
02058       //Since we already have the smallest breakpoint we need not do
02059       //heapsort yet. Often only one breakpoint is used and the
02060       //cost of heapsort is avoided.
02061       tj = bkmin;
02062       ibp = iorder[ibkmin];
02063     }
02064     else
02065     {
02066       if (iter == 2)
02067       {
02068         //Replace the already used smallest breakpoint with the
02069         //breakpoint numbered nbreak > nlast, before heapsort call.
02070         if (ibkmin != nbreak)
02071         {
02072           t[ibkmin] = t[nbreak];
02073           iorder[ibkmin] = iorder[nbreak];
02074         }
02075         //Update heap structure of breakpoints
02076         //(if iter=2, initialize heap).
02077       }
02078       
02079       hpsolb(nleft,t,iorder,iter-2);
02080       tj = t[nleft];
02081      ibp = iorder[nleft];    
02082     }    
02083 
02084     dt = tj - tj0;
02085     
02086     if (dt != zero && iprint >= 100)
02087     {
02088       cout << "Piece    " << nint << " --f1, f2 at start point " 
02089            << f1 << "," << f2 << endl;
02090       cout << "Distance to the next break point = " << dt << endl;
02091       cout << "Distance to the stationary point = " << dtm << endl;
02092     }
02093     
02094     //If a minimizer is within this interval, locate the GCP and return. 
02095     
02096     if (dtm < dt) goto goto888;
02097     
02098     //Otherwise fix one variable and
02099     //reset the corresponding component of d to zero.
02100     
02101     tsum += dt;
02102     nleft -= 1;
02103     iter += 1;
02104     dibp = d[ibp];
02105     d[ibp] = zero;
02106     if (dibp > zero) 
02107     {
02108       zibp = u[ibp] - x[ibp];
02109       xcp[ibp] = u[ibp];
02110       iwhere[ibp] = 2;
02111     }
02112     else
02113     {
02114      zibp = l[ibp] - x[ibp];
02115      xcp[ibp] = l[ibp];
02116      iwhere[ibp] = 1;
02117     }
02118     if (iprint >= 100) cout << "Variable  " << ibp << " is fixed." << endl;
02119     if (nleft == 0 && nbreak == n) 
02120     {
02121       //all n variables are fixed, return with xcp as GCP.
02122       dtm = dt;
02123       goto goto999;
02124     }
02125     
02126     //Update the derivative information.
02127     
02128     nint += 1;
02129     dibp2 = dibp*dibp;
02130     
02131    //Update f1 and f2.
02132     
02133    //temporarily set f1 and f2 for col=0.
02134     f1 += dt*f2 + dibp2 - theta*dibp*zibp;
02135     f2 -= theta*dibp2;
02136     
02137     if (col > 0)
02138     {
02139       //update c = c + dt*p.
02140      daxpy(col2,dt,p,1,c,1);
02141      
02142      //choose wbp,
02143      //the row of W corresponding to the breakpoint encountered.
02144      pointr = head;
02145      for (int j = 1; j <= col; j++)
02146      {
02147        wbp[j] = wy[getIdx(ibp,pointr,n)];
02148        wbp[col + j] = theta*ws[getIdx(ibp,pointr,n)];
02149        pointr = pointr%m + 1;
02150      }
02151      //compute (wbp)Mc, (wbp)Mp, and (wbp)M(wbp)'.
02152      bmv(m,sy,wt,col,wbp,v,info);
02153      if (info != 0) return;
02154      wmc = ddot(col2,c,1,v,1);
02155      wmp = ddot(col2,p,1,v,1); 
02156      wmw = ddot(col2,wbp,1,v,1);
02157      
02158      //update p = p - dibp*wbp. 
02159      daxpy(col2,-dibp,wbp,1,p,1);
02160      
02161      //complete updating f1 and f2 while col > 0.
02162      f1 += dibp*wmc;
02163      f2 += 2.0*dibp*wmp - dibp2*wmw;
02164     }
02165     
02166     f2 = max(epsmch*f2_org,f2);
02167     if (nleft > 0)
02168     {
02169      dtm = -f1/f2;
02170      goto goto777;
02171      //to repeat the loop for unsearched intervals. 
02172     }
02173     else
02174     if(bnded)
02175     {
02176       f1 = zero;
02177       f2 = zero;
02178       dtm = zero;
02179     }
02180     else
02181       dtm = -f1/f2;
02182     
02183     //------------------- the end of the loop -------------------------------
02184     
02185   goto888:
02186     if (iprint >= 99)
02187     {
02188       cout << endl << "GCP found in this segment" << endl
02189            << "Piece    " << nint << " --f1, f2 at start point " 
02190            << f1 << ","  << f2 << endl
02191            << "Distance to the stationary point = " << dtm << endl;
02192     }
02193     
02194     if (dtm <= zero) dtm = zero;
02195     tsum += dtm;
02196     
02197     //Move free variables (i.e., the ones w/o breakpoints) and 
02198     //the variables whose breakpoints haven't been reached.
02199     
02200     daxpy(n,tsum,d,1,xcp,1);
02201     
02202   goto999:
02203     
02204     //Update c = c + dtm*p = W'(x^c - x) 
02205     //which will be used in computing r = Z'(B(x^c - x) + g).
02206    
02207     if (col > 0) daxpy(col2,dtm,p,1,c,1);
02208     if (iprint > 100)
02209     {
02210       cout<< "Cauchy X = ";
02211       for (int i = 1; i <=n; i++)
02212         cout << xcp[i] << " ";
02213       cout << endl;
02214     }
02215     if (iprint >= 99) 
02216       cout << "---------------- exit CAUCHY----------------------" << endl;
02217   }//cauchy()
02218 
02219 
02220 //   ************
02221 //
02222 //   Subroutine cmprlb 
02223 //
02224 //     This subroutine computes r=-Z'B(xcp-xk)-Z'g by using 
02225 //       wa(2m+1)=W'(xcp-x) from subroutine cauchy.
02226 //
02227 //   Subprograms called:
02228 //
02229 //     L-BFGS-B Library ... bmv.
02230 //
02231 //
02232 //                         *  *  *
02233 //
02234 //   NEOS, November 1994. (Latest revision June 1996.)
02235 //   Optimization Technology Center.
02236 //   Argonne National Laboratory and Northwestern University.
02237 //   Written by
02238 //                      Ciyou Zhu
02239 //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
02240 //
02241 //
02242 //   ************
02243     //function
02244   void cmprlb(const int& n, const int& m, const double* const & x, 
02245               const double* const & g, double* const & ws, 
02246               double* const & wy, double* const & sy, 
02247               double* const & wt, const double* const & z, 
02248               double* const & r, double* const & wa, 
02249               const int* const & index, const double& theta, 
02250               const int& col, const int& head, const int& nfree, 
02251               const bool& cnstnd, int& info)
02252   {
02253     //int i,j;
02254     int k,pointr,idx;
02255     double a1,a2;
02256 
02257     if (!cnstnd && col > 0)
02258     {
02259       for (int i = 1; i <= n; i++)
02260         r[i] = -g[i];
02261     }
02262     else
02263     {
02264       for (int i = 1; i <= nfree; i++)
02265       {
02266         k = index[i];
02267         r[i] = -theta*(z[k] - x[k]) - g[k];
02268       }
02269       bmv(m,sy,wt,col,&(wa[2*m+1-1]),&(wa[1-1]),info);
02270       if (info != 0)
02271       {
02272         info = -8;
02273         return;
02274       }
02275       pointr = head;
02276       for (int j = 1; j <= col; j++)
02277       {
02278         a1 = wa[j];
02279         a2 = theta*wa[col + j];
02280         for (int i = 1; i <= nfree; i++)
02281         {
02282           k = index[i];
02283           idx = getIdx(k,pointr,n);
02284           r[i] += wy[idx]*a1 + ws[idx]*a2;
02285         }
02286             
02287         pointr = pointr%m + 1;
02288       }
02289     }
02290   }//cmprlb()
02291 
02292 
02293   //   ************
02294   //
02295   //   Subroutine errclb
02296   //
02297   //   This subroutine checks the validity of the input data.
02298   //
02299   //
02300   //                         *  *  *
02301   //
02302   //   NEOS, November 1994. (Latest revision June 1996.)
02303   //   Optimization Technology Center.
02304   //   Argonne National Laboratory and Northwestern University.
02305   //   Written by
02306   //                      Ciyou Zhu
02307   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
02308   //
02309   //
02310   //   ************
02311     //function
02312   void errclb(const int& n, const int& m, const double& factr, 
02313               const double* const & l, const double* const & u, 
02314               const int* const & nbd, char* const & task, int& info, 
02315               int& k)
02316   {
02317     //int i;
02318     //double one=1.0;
02319     double zero=0.0;
02320 
02321     //Check the input arguments for errors.
02322     
02323     if (n <= 0) strcpy(task,"ERROR: N <= 0");
02324     if (m <= 0) strcpy(task,"ERROR: M <= 0");
02325     if (factr < zero) strcpy(task,"ERROR: FACTR < 0");
02326 
02327     //Check the validity of the arrays nbd[i], u[i], and l[i].
02328     for (int i = 1; i <= n; i++)
02329     {
02330       if (nbd[i] < 0 || nbd[i] > 3)
02331       {
02332         //return
02333         strcpy(task,"ERROR: INVALID NBD");
02334         info = -6;
02335         k = i;
02336       }
02337       if (nbd[i] == 2)
02338       {
02339         if (l[i] > u[i])
02340         {
02341           //return
02342           strcpy(task, "ERROR: NO FEASIBLE SOLUTION");
02343           info = -7;
02344           k = i;
02345         }
02346       }
02347     }
02348   }//errclb
02349 
02350 
02351   //   ************
02352   //
02353   //   Subroutine formk 
02354   //
02355   //   This subroutine forms  the LEL^T factorization of the indefinite
02356   //
02357   //     matrix    K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
02358   //                   [L_a -R_z           theta*S'AA'S ]
02359   //                                                  where E = [-I  0]
02360   //                                                            [ 0  I]
02361   //   The matrix K can be shown to be equal to the matrix M^[-1]N
02362   //     occurring in section 5.1 of [1], as well as to the matrix
02363   //     Mbar^[-1] Nbar in section 5.3.
02364   //
02365   //   n is an integer variable.
02366   //     On entry n is the dimension of the problem.
02367   //     On exit n is unchanged.
02368   //
02369   //   nsub is an integer variable
02370   //     On entry nsub is the number of subspace variables in free set.
02371   //     On exit nsub is not changed.
02372   //
02373   //   ind is an integer array of dimension nsub.
02374   //     On entry ind specifies the indices of subspace variables.
02375   //     On exit ind is unchanged. 
02376   //
02377   //   nenter is an integer variable.
02378   //     On entry nenter is the number of variables entering the 
02379   //       free set.
02380   //     On exit nenter is unchanged. 
02381   //
02382   //   ileave is an integer variable.
02383   //     On entry indx2(ileave),...,indx2(n) are the variables leaving
02384   //       the free set.
02385   //     On exit ileave is unchanged. 
02386   //
02387   //   indx2 is an integer array of dimension n.
02388   //     On entry indx2(1),...,indx2(nenter) are the variables entering
02389   //       the free set, while indx2(ileave),...,indx2(n) are the
02390   //       variables leaving the free set.
02391   //     On exit indx2 is unchanged. 
02392   //
02393   //   iupdat is an integer variable.
02394   //     On entry iupdat is the total number of BFGS updates made so far.
02395   //     On exit iupdat is unchanged. 
02396   //
02397   //   updatd is a logical variable.
02398   //     On entry 'updatd' is true if the L-BFGS matrix is updatd.
02399   //     On exit 'updatd' is unchanged. 
02400   //
02401   //   wn is a double precision array of dimension 2m x 2m.
02402   //     On entry wn is unspecified.
02403   //     On exit the upper triangle of wn stores the LEL^T factorization
02404   //       of the 2*col x 2*col indefinite matrix
02405   //                   [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
02406   //                   [L_a -R_z           theta*S'AA'S ]
02407   //
02408   //   wn1 is a double precision array of dimension 2m x 2m.
02409   //     On entry wn1 stores the lower triangular part of 
02410   //                   [Y' ZZ'Y   L_a'+R_z']
02411   //                   [L_a+R_z   S'AA'S   ]
02412   //       in the previous iteration.
02413   //     On exit wn1 stores the corresponding updated matrices.
02414   //     The purpose of wn1 is just to store these inner products
02415   //     so they can be easily updated and inserted into wn.
02416   //
02417   //   m is an integer variable.
02418   //     On entry m is the maximum number of variable metric corrections
02419   //       used to define the limited memory matrix.
02420   //     On exit m is unchanged.
02421   //
02422   //   ws, wy, sy, and wtyy are double precision arrays;
02423   //   theta is a double precision variable;
02424   //   col is an integer variable;
02425   //   head is an integer variable.
02426   //     On entry they store the information defining the
02427   //                                        limited memory BFGS matrix:
02428   //       ws(n,m) stores S, a set of s-vectors;
02429   //       wy(n,m) stores Y, a set of y-vectors;
02430   //       sy(m,m) stores S'Y;
02431   //       wtyy(m,m) stores the Cholesky factorization
02432   //                                 of (theta*S'S+LD^(-1)L')
02433   //       theta is the scaling factor specifying B_0 = theta I;
02434   //       col is the number of variable metric corrections stored;
02435   //       head is the location of the 1st s- (or y-) vector in S (or Y).
02436   //     On exit they are unchanged.
02437   //
02438   //   info is an integer variable.
02439   //     On entry info is unspecified.
02440   //     On exit info =  0 for normal return;
02441   //                  = -1 when the 1st Cholesky factorization failed;
02442   //                  = -2 when the 2st Cholesky factorization failed.
02443   //
02444   //   Subprograms called:
02445   //
02446   //     Linpack ... dcopy, dpofa, dtrsl.
02447   //
02448   //
02449   //   References:
02450   //     [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
02451   //     memory algorithm for bound constrained optimization'',
02452   //     SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
02453   //
02454   //     [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: a
02455   //     limited memory FORTRAN code for solving bound constrained
02456   //     optimization problems'', Tech. Report, NAM-11, EECS Department,
02457   //     Northwestern University, 1994.
02458   //
02459   //     (Postscript files of these papers are available via anonymous
02460   //      ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.)
02461   //
02462   //                         *  *  *
02463   //
02464   //   NEOS, November 1994. (Latest revision June 1996.)
02465   //   Optimization Technology Center.
02466   //   Argonne National Laboratory and Northwestern University.
02467   //   Written by
02468   //                      Ciyou Zhu
02469   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
02470   //
02471   //
02472   //   ************
02473     //function
02474   void formk(const int& n, const int& nsub, const int* const & ind, 
02475              const int& nenter, const int& ileave, 
02476              const int* const & indx2, const int& iupdat, 
02477              const bool& updatd, double* const & wn, 
02478              double* const & wn1, const int& m, 
02479              double* const & ws, double* const & wy, 
02480              double* const & sy, const double& theta, 
02481              const int& col, const int& head, int& info)
02482   {
02483     //int i,k;
02484     int m2,ipntr,jpntr,iy,is,jy,js,is1,js1,k1,
02485         col2,pbegin,pend,dbegin,dend,upcl;
02486     int idx1, idx2;
02487     double temp1,temp2,temp3,temp4;
02488     //double one=1.0;
02489     double zero=0.0;
02490 
02491     m2 = 2*m;
02492 
02493     //Form the lower triangular part of
02494     //WN1 = [Y' ZZ'Y   L_a'+R_z'] 
02495     //      [L_a+R_z   S'AA'S   ]
02496     //where L_a is the strictly lower triangular part of S'AA'Y
02497     //      R_z is the upper triangular part of S'ZZ'Y.
02498       
02499     if (updatd)
02500     {
02501       if (iupdat > m)
02502       { 
02503         //shift old part of WN1.
02504         for (int jy = 1; jy <= m-1; jy++)
02505         { 
02506           js = m + jy;
02507           dcopy(m-jy,&(wn1[getIdx(jy+1,jy+1,m2)-1]),1,
02508                      &(wn1[getIdx(jy,jy,m2)-1]),1);
02509           dcopy(m-jy,&(wn1[getIdx(js+1,js+1,m2)-1]),1,
02510                      &(wn1[getIdx(js,js,m2)-1]), 1);
02511           dcopy(m-1, &(wn1[getIdx(m+2,jy+1,m2)-1]), 1,
02512                      &(wn1[getIdx(m+1,jy,m2)-1]),1);
02513         }
02514       }
02515 
02516       //put new rows in blocks (1,1), (2,1) and (2,2).
02517       pbegin = 1;
02518       pend = nsub;
02519       dbegin = nsub + 1;
02520       dend = n;
02521       iy = col;
02522       is = m + col;
02523       ipntr = head + col - 1;
02524       if (ipntr > m) ipntr -= m ;
02525       jpntr = head;
02526   
02527       for (jy = 1; jy <= col; jy++)
02528       {
02529         js = m + jy;
02530         temp1 = zero;
02531         temp2 = zero;
02532         temp3 = zero;
02533         //compute element jy of row 'col' of Y'ZZ'Y
02534         for (int k = pbegin; k <= pend; k++)
02535         {
02536           k1 = ind[k];
02537           temp1 += wy[getIdx(k1,ipntr,n)]*wy[getIdx(k1,jpntr,n)];
02538         }
02539         //compute elements jy of row 'col' of L_a and S'AA'S
02540         for (int k = dbegin; k <= dend; k++)
02541         {
02542           k1 = ind[k];
02543           idx1 = getIdx(k1,ipntr,n);
02544           idx2 = getIdx(k1,jpntr,n);
02545           temp2 += ws[idx1] * ws[idx2];
02546           temp3 += ws[idx1] * wy[idx2];
02547         }
02548         wn1[getIdx(iy,jy,m2)] = temp1;
02549         wn1[getIdx(is,js,m2)] = temp2;
02550         wn1[getIdx(is,jy,m2)] = temp3;
02551         jpntr = jpntr%m + 1;
02552       }
02553  
02554       //put new column in block (2,1).
02555       jy = col;
02556       jpntr = head + col - 1;
02557       if (jpntr > m) jpntr -= m;
02558       ipntr = head;
02559       for (int i = 1; i <= col; i++)
02560       {
02561         is = m + i;
02562         temp3 = zero;
02563         //compute element i of column 'col' of R_z
02564         for (int k = pbegin; k <= pend; k++)
02565         {
02566           k1 = ind[k];
02567           temp3 += ws[getIdx(k1,ipntr,n)]*wy[getIdx(k1,jpntr,n)];
02568         }
02569         ipntr = ipntr%m + 1;
02570         wn1[getIdx(is,jy,m2)] = temp3;
02571       }
02572       upcl = col - 1;
02573     }
02574     else
02575       upcl = col;
02576 
02577     //modify the old parts in blocks (1,1) and (2,2) due to changes
02578     //in the set of free variables.
02579     ipntr = head;
02580     
02581     for (int iy = 1; iy <= upcl; iy++)
02582     {
02583       is = m + iy;
02584       jpntr = head;
02585 
02586       for (int jy = 1; jy <= iy; jy++)
02587       {
02588         js = m + jy;
02589         temp1 = zero;
02590         temp2 = zero;
02591         temp3 = zero;
02592         temp4 = zero;
02593         for (int k = 1; k <= nenter; k++)
02594         {
02595           k1 = indx2[k];
02596           idx1 = getIdx(k1,ipntr,n);
02597           idx2 = getIdx(k1,jpntr,n);
02598           temp1 += wy[idx1]*wy[idx2];
02599           temp2 += ws[idx1]*ws[idx2];
02600         }
02601         for (int k = ileave; k <= n; k++)
02602         {
02603           k1 = indx2[k];
02604           idx1 = getIdx(k1,ipntr,n);
02605           idx2 = getIdx(k1,jpntr,n);
02606           temp3 += wy[idx1]*wy[idx2];
02607           temp4 += ws[idx1]*ws[idx2];
02608         }
02609         wn1[getIdx(iy,jy,m2)] += temp1 - temp3;
02610         wn1[getIdx(is,js,m2)] += temp4 - temp2;
02611         jpntr = jpntr%m + 1;
02612       }
02613       ipntr = ipntr%m + 1;
02614     } 
02615     //modify the old parts in block (2,1).
02616     ipntr = head;
02617 
02618     for (int is = m+1; is <= m + upcl; is++)
02619     {
02620       jpntr = head;
02621       for (int jy = 1; jy <= upcl; jy++)
02622       {
02623         temp1 = zero;
02624         temp3 = zero;
02625 
02626         for (int k = 1; k <= nenter; k++)
02627         {
02628           k1 = indx2[k];
02629           temp1 += ws[getIdx(k1,ipntr,n)]*wy[getIdx(k1,jpntr,n)];
02630         }
02631         for (int k = ileave; k <= n; k++)
02632         {
02633           k1 = indx2[k];
02634           temp3 += ws[getIdx(k1,ipntr,n)]*wy[getIdx(k1,jpntr,n)];
02635         }
02636         if (is <= jy + m)
02637           wn1[getIdx(is,jy,m2)] += temp1 - temp3;
02638         else
02639           wn1[getIdx(is,jy,m2)] += temp3 - temp1;
02640             
02641         jpntr = jpntr%m + 1;
02642       }
02643       ipntr = ipntr%m + 1;
02644     } 
02645     //Form the upper triangle of WN = [D+Y' ZZ'Y/theta   -L_a'+R_z' ] 
02646     //                                [-L_a +R_z        S'AA'S*theta]
02647 
02648     for (int iy = 1; iy <= col; iy++)
02649     {
02650       is = col + iy;
02651       is1 = m + iy;
02652       for (int jy = 1; jy <= iy; jy++)
02653       {
02654         js = col + jy;
02655         js1 = m + jy;
02656         wn[getIdx(jy,iy,m2)] = wn1[getIdx(iy,jy,m2)]/theta;
02657         wn[getIdx(js,is,m2)] = wn1[getIdx(is1,js1,m2)]*theta;
02658       }
02659 
02660       for (int jy = 1; jy <= iy-1; jy++)
02661         wn[getIdx(jy,is,m2)] = -wn1[getIdx(is1,jy,m2)];
02662 
02663       for (int jy = iy; jy <= col; jy++)
02664         wn[getIdx(jy,is,m2)] = wn1[getIdx(is1,jy,m2)];
02665       wn[getIdx(iy,iy,m2)] += sy[getIdx(iy,iy,m)];
02666     }
02667 
02668     //Form the upper triangle of WN= [  LL'            L^-1(-L_a'+R_z')] 
02669     //                               [(-L_a +R_z)L'^-1   S'AA'S*theta  ]
02670 
02671     //first Cholesky factor (1,1) block of wn to get LL'
02672     //with L' stored in the upper triangle of wn.
02673     dpofa(wn,m2,col,info);
02674     if (info != 0) 
02675     {
02676       info = -1;
02677       return;
02678     }
02679 
02680     //then form L^-1(-L_a'+R_z') in the (1,2) block.
02681     col2 = 2*col;
02682     for (int js = col+1; js <= col2; js++)
02683       dtrsl(wn,m2,col,&(wn[getIdx(1,js,m2)-1]),11,info);
02684 
02685 
02686 
02687     //Form S'AA'S*theta + (L^-1(-L_a'+R_z'))'L^-1(-L_a'+R_z') in the
02688     //upper triangle of (2,2) block of wn.
02689     //HH                      
02690     for (int is = col+1; is <= col2; is++)
02691       for (int js = is; js <= col2; js++)
02692         wn[getIdx(is,js,m2)] += ddot(col,&(wn[getIdx(1,is,m2)-1]),1,
02693                                          &(wn[getIdx(1,js,m2)-1]),1);
02694 
02695     //Cholesky factorization of (2,2) block of wn.
02696     dpofa(&(wn[getIdx(col+1,col+1,m2)-1]),m2,col,info);
02697 
02698     if (info != 0)
02699     {
02700       info = -2;
02701       return;
02702     }
02703   }//formk()
02704 
02705 
02706   //   ************
02707   //
02708   //   Subroutine formt
02709   //
02710   //     This subroutine forms the upper half of the pos. def. and symm.
02711   //       T = theta*SS + L*D^(-1)*L', stores T in the upper triangle
02712   //       of the array wt, and performs the Cholesky factorization of T
02713   //       to produce J*J', with J' stored in the upper triangle of wt.
02714   //
02715   //   Subprograms called:
02716   //
02717   //     Linpack ... dpofa.
02718   //
02719   //
02720   //                         *  *  *
02721   //
02722   //   NEOS, November 1994. (Latest revision June 1996.)
02723   //   Optimization Technology Center.
02724   //   Argonne National Laboratory and Northwestern University.
02725   //   Written by
02726   //                      Ciyou Zhu
02727   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
02728   //
02729   //
02730   //   ***********
02731     //function
02732   void formt(const int& m, double* const & wt, double* const& sy,
02733              double* const &  ss, const int& col, const double& theta, 
02734              int& info)
02735   {
02736     //int i,j,k;
02737     int k1, idx;
02738     double ddum;
02739     double zero=0.0;
02740 
02741     //Form the upper half of  T = theta*SS + L*D^(-1)*L',
02742     //store T in the upper triangle of the array wt.
02743     for (int j = 1; j <= col; j++)
02744     {
02745       idx = getIdx(1,j,m);
02746       wt[idx] = theta*ss[idx];
02747     }
02748 
02749     for (int i = 2; i <= col; i++) 
02750       for (int j = i; j <= col; j++) 
02751       {
02752         k1 = min(i,j) - 1;
02753         ddum = zero;
02754         for (int k = 1; k <= k1; k++) 
02755           ddum  += sy[getIdx(i,k,m)]*sy[getIdx(j,k,m)]/sy[getIdx(k,k,m)];
02756         wt[getIdx(i,j,m)] = ddum + theta*ss[getIdx(i,j,m)];
02757       }
02758  
02759     //Cholesky factorize T to J*J' with 
02760     //J' stored in the upper triangle of wt.
02761  
02762     dpofa(wt,m,col,info);
02763     if (info != 0) info = -3;
02764   }//formt()
02765 
02766 
02767   //   ************
02768   //
02769   //   Subroutine freev 
02770   //
02771   //   This subroutine counts the entering and leaving variables when
02772   //     iter > 0, and finds the index set of free and active variables
02773   //     at the GCP.
02774   //
02775   //   cnstnd is a logical variable indicating whether bounds are present
02776   //
02777   //   index is an integer array of dimension n
02778   //     for i=1,...,nfree, index(i) are the indices of free variables
02779   //     for i=nfree+1,...,n, index(i) are the indices of bound variables
02780   //     On entry after the first iteration, index gives 
02781   //       the free variables at the previous iteration.
02782   //     On exit it gives the free variables based on the determination
02783   //       in cauchy using the array iwhere.
02784   //
02785   //   indx2 is an integer array of dimension n
02786   //     On entry indx2 is unspecified.
02787   //     On exit with iter>0, indx2 indicates which variables
02788   //        have changed status since the previous iteration.
02789   //     For i= 1,...,nenter, indx2(i) have changed from bound to free.
02790   //     For i= ileave+1,...,n, indx2(i) have changed from free to bound.
02791   // 
02792   //
02793   //                         *  *  *
02794   //
02795   //   NEOS, November 1994. (Latest revision June 1996.)
02796   //   Optimization Technology Center.
02797   //   Argonne National Laboratory and Northwestern University.
02798   //   Written by
02799   //                      Ciyou Zhu
02800   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
02801   //
02802   //
02803   //   ************
02804     //function
02805   void freev(const int& n, int& nfree, int* const & index, int& nenter, 
02806              int& ileave, int* const & indx2, int* const & iwhere, 
02807              bool& wrk, const bool& updatd, const bool& cnstnd, 
02808              const int& iprint, const int& iter)
02809   {
02810     //int i;
02811     int iact,k;
02812 
02813     nenter = 0;
02814     ileave = n + 1;
02815     if (iter > 0 && cnstnd) 
02816     {
02817       //count the entering and leaving variables.
02818       for (int i = 1; i <= nfree; i++) 
02819       {
02820         k = index[i];
02821         if (iwhere[k] > 0)
02822         {
02823           ileave -= 1;
02824           indx2[ileave] = k;
02825           if (iprint >= 100) 
02826             cout << "Variable " << k<<" leaves the set of free variables"<<endl;
02827         }
02828       }
02829 
02830       for (int i = 1+nfree; i <= n; i++) 
02831       {
02832         k = index[i];
02833         if (iwhere[k] <= 0)
02834         {
02835           nenter += 1;
02836           indx2[nenter] = k;
02837           if (iprint >= 100) 
02838             cout << "Variable " << k<<" enters the set of free variables"<<endl;
02839         }
02840       }
02841       if (iprint >= 99) 
02842         cout << n+1-ileave << " variables leave; " 
02843              << nenter << " variables enter" << endl;
02844     }
02845     wrk = (ileave < n+1) || (nenter > 0) || updatd;
02846  
02847     //Find the index set of free and active variables at the GCP.
02848  
02849     nfree = 0;
02850     iact = n + 1;
02851     for (int i = 1; i <= n; i++) 
02852     {
02853       if (iwhere[i] <= 0)
02854       {
02855         nfree += 1;
02856         index[nfree] = i;
02857       }
02858       else
02859       {
02860         iact -= 1;
02861         index[iact] = i;
02862       }
02863     }
02864 
02865     if (iprint >= 99) 
02866       cout << nfree << " variables are free at GCP " << iter + 1 << endl;
02867   }//freev()
02868 
02869 
02870   //   ************
02871   //
02872   //   Subroutine hpsolb 
02873   //
02874   //   This subroutine sorts out the least element of t, and puts the
02875   //     remaining elements of t in a heap.
02876   // 
02877   //   n is an integer variable.
02878   //     On entry n is the dimension of the arrays t and iorder.
02879   //     On exit n is unchanged.
02880   //
02881   //   t is a double precision array of dimension n.
02882   //     On entry t stores the elements to be sorted,
02883   //     On exit t(n) stores the least elements of t, and t(1) to t(n-1)
02884   //       stores the remaining elements in the form of a heap.
02885   //
02886   //   iorder is an integer array of dimension n.
02887   //     On entry iorder(i) is the index of t(i).
02888   //     On exit iorder(i) is still the index of t(i), but iorder may be
02889   //       permuted in accordance with t.
02890   //
02891   //   iheap is an integer variable specifying the task.
02892   //     On entry iheap should be set as follows:
02893   //       iheap == 0 if t(1) to t(n) is not in the form of a heap,
02894   //       iheap != 0 if otherwise.
02895   //     On exit iheap is unchanged.
02896   //
02897   //
02898   //   References:
02899   //     Algorithm 232 of CACM (J. W. J. Williams): HEAPSORT.
02900   //
02901   //                         *  *  *
02902   //
02903   //   NEOS, November 1994. (Latest revision June 1996.)
02904   //   Optimization Technology Center.
02905   //   Argonne National Laboratory and Northwestern University.
02906   //   Written by
02907   //                      Ciyou Zhu
02908   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
02909   //
02910   //   ************
02911     //function
02912   void hpsolb(const int& n, double* const & t, int* const & iorder, 
02913               const int& iheap)
02914   {
02915     //int k;
02916     int i,j,indxin,indxou;
02917     double ddum,out;
02918 
02919     if (iheap == 0)
02920     {
02921       //Rearrange the elements t[1] to t[n] to form a heap.
02922       for (int k = 2; k <= n; k++) 
02923       {
02924         ddum  = t[k];
02925         indxin = iorder[k];
02926 
02927         //Add ddum to the heap.
02928         i = k;
02929       goto10:
02930         if (i>1)
02931         {
02932           j = i/2;
02933           if (ddum < t[j])
02934           {
02935             t[i] = t[j];
02936             iorder[i] = iorder[j];
02937             i = j;
02938             goto goto10;
02939           }
02940                  
02941         }  
02942         t[i] = ddum;
02943         iorder[i] = indxin;
02944       }
02945     }
02946  
02947     //Assign to 'out' the value of t(1), the least member of the heap,
02948     //and rearrange the remaining members to form a heap as
02949     //elements 1 to n-1 of t.
02950  
02951     if (n > 1)
02952     {
02953       i = 1;
02954       out = t[1];
02955       indxou = iorder[1];
02956       ddum = t[n];
02957       indxin = iorder[n];
02958 
02959       //Restore the heap 
02960     goto30:
02961       j = i+i;
02962       if (j <= n-1) 
02963       {
02964         if (t[j+1] < t[j]) j = j+1;
02965         if (t[j] < ddum )
02966         {
02967           t[i] = t[j];
02968           iorder[i] = iorder[j];
02969           i = j;
02970           goto goto30;
02971         } 
02972       } 
02973       t[i] = ddum;
02974       iorder[i] = indxin;
02975  
02976       //Put the least member in t(n). 
02977 
02978       t[n] = out;
02979       iorder[n] = indxou;
02980     }
02981   }//hpsolb()
02982 
02983 
02984   //   **********
02985   //
02986   //   Subroutine lnsrlb
02987   //
02988   //   This subroutine calls subroutine dcsrch from the Minpack2 library
02989   //     to perform the line search.  Subroutine dscrch is safeguarded so
02990   //     that all trial points lie within the feasible region.
02991   //
02992   //   Subprograms called:
02993   //
02994   //     Minpack2 Library ... dcsrch.
02995   //
02996   //     Linpack ... dtrsl, ddot.
02997   //
02998   //
02999   //                         *  *  *
03000   //
03001   //   NEOS, November 1994. (Latest revision June 1996.)
03002   //   Optimization Technology Center.
03003   //   Argonne National Laboratory and Northwestern University.
03004   //   Written by
03005   //                      Ciyou Zhu
03006   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
03007   //
03008   //
03009   //   **********
03010     //function
03011   void lnsrlb(const int& n, const double* const & l, const double* const & u, 
03012               const int* const& nbd, double* const & x, double& f, 
03013               double& fold, double& gd, double& gdold, double* const& g, 
03014               double* const& d, double* const& r, double* const& t,
03015               double* const& z, double& stp, double& dnorm, double& dtd, 
03016               double& xstep, double& stpmx, const int& iter, int& ifun,
03017               int& iback, int& nfgv, int& info, char* const & task, 
03018               const bool& boxed, const bool& cnstnd, char* const & csave,
03019               int* const & isave, double* const & dsave)
03020   {
03021     //int i;
03022     double a1,a2;
03023     double one=1.0,zero=0.0,big=1e10;
03024     double ftol=1.0e-3,gtol=0.9,xtol=0.1;
03025 
03026     
03027     if (strncmp(task,"FG_LN",5)==0) goto goto556;
03028 
03029     dtd = ddot(n,d,1,d,1);
03030     dnorm = sqrt(dtd);
03031 
03032     //Determine the maximum step length.
03033 
03034     stpmx = big;
03035     if (cnstnd)
03036     {
03037       if (iter == 0)
03038         stpmx = one;
03039       else
03040       {
03041         for (int i = 1; i <= n; i++) 
03042         {
03043           a1 = d[i];
03044           if (nbd[i] != 0)
03045           {
03046             if (a1 < zero && nbd[i] <= 2)
03047             {
03048               a2 = l[i] - x[i];
03049               if (a2 >= zero)
03050                 stpmx = zero;
03051               else 
03052               if (a1*stpmx < a2)
03053                 stpmx = a2/a1;
03054             }
03055             else 
03056             if (a1 > zero && nbd[i] >= 2)
03057             {
03058               a2 = u[i] - x[i];
03059               if (a2 <= zero)
03060                 stpmx = zero;
03061               else 
03062               if (a1*stpmx > a2)
03063                 stpmx = a2/a1;
03064             }
03065           }
03066         } // for (int i = 1; i <= n; i++) 
03067       }
03068     }
03069  
03070     if (iter == 0 && !boxed)
03071       stp = min(one/dnorm, stpmx);
03072     else
03073       stp = one;
03074 
03075     dcopy(n,x,1,t,1);
03076     dcopy(n,g,1,r,1);
03077     fold = f;
03078     ifun = 0;
03079     iback = 0;
03080     strcpy(csave,"START");
03081   goto556:
03082     gd = ddot(n,g,1,d,1);
03083     if (ifun == 0)
03084     {
03085       gdold=gd;
03086       if (gd >= zero)
03087       {
03088         //the directional derivative >=0.
03089         //Line search is impossible.
03090         info = -4;
03091         return;
03092       }
03093     }
03094 
03095     dcsrch(f,gd,stp,ftol,gtol,xtol,zero,stpmx,csave,isave,dsave);
03096 
03097     xstep = stp*dnorm;
03098     if (strncmp(csave,"CONV",4) != 0 && strncmp(csave,"WARN",4) != 0) 
03099     {
03100       strcpy(task,"FG_LNSRCH");
03101       ifun += 1;
03102       nfgv += 1;
03103       iback = ifun - 1;
03104       if (stp == one)
03105         dcopy(n,z,1,x,1);
03106       else
03107       {
03108         for (int i = 1; i <= n; i++) 
03109           x[i] = stp*d[i] + t[i];
03110       }
03111     }
03112     else
03113       strcpy(task,"NEW_X");    
03114   } //lnsrlb()
03115 
03116 
03117   //   ************
03118   //
03119   //   Subroutine matupd
03120   //
03121   //     This subroutine updates matrices WS and WY, and forms the
03122   //       middle matrix in B.
03123   //
03124   //   Subprograms called:
03125   //
03126   //     Linpack ... dcopy, ddot.
03127   //
03128   //
03129   //                         *  *  *
03130   //
03131   //   NEOS, November 1994. (Latest revision June 1996.)
03132   //   Optimization Technology Center.
03133   //   Argonne National Laboratory and Northwestern University.
03134   //   Written by
03135   //                      Ciyou Zhu
03136   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
03137   //
03138   //
03139   //   ************
03140     //function
03141   void matupd(const int& n, const int& m, double* const & ws, 
03142               double* const & wy, double* const & sy, double* const & ss, 
03143               double* const & d, double* const & r, int& itail, int& iupdat, 
03144               int& col, int& head, double& theta, double& rr, double& dr, 
03145               double& stp, double& dtd)
03146   {
03147     //int j;
03148     int pointr;
03149     double one=1.0;
03150     int idx;
03151 
03152     //Set pointers for matrices WS and WY.
03153     if (iupdat <= m)
03154     {
03155       col = iupdat;
03156       itail = (head+iupdat-2)%m + 1;
03157     }
03158     else
03159     {
03160       itail = itail%m + 1;
03161       head = head%m + 1;
03162     }
03163  
03164     //Update matrices WS and WY.
03165     idx = getIdx(1,itail,n)-1;
03166     dcopy(n,d,1,&(ws[idx]),1);
03167     dcopy(n,r,1,&(wy[idx]),1);
03168  
03169     //Set theta=yy/ys.
03170     theta = rr/dr;
03171  
03172     //Form the middle matrix in B.
03173     //update the upper triangle of SS,
03174     //and the lower triangle of SY:
03175     if (iupdat > m)
03176     {
03177       //move old information
03178       for (int j = 1; j <= col-1; j++)
03179       {
03180         dcopy(j,&(ss[getIdx(2,j+1,m)-1]),1,&(ss[getIdx(1,j,m)-1]),1);
03181         dcopy(col-j,&(sy[getIdx(j+1,j+1,m)-1]),1,&(sy[getIdx(j,j,m)-1]),1);
03182       }
03183     }
03184 
03185     //add new information: the last row of SY
03186     //and the last column of SS:
03187     pointr = head;
03188     for (int j = 1; j <= col-1; j++)
03189     {
03190       idx = getIdx(1,pointr,n)-1;
03191       sy[getIdx(col,j,m)] = ddot(n,d,1,&(wy[idx]),1);
03192       ss[getIdx(j,col,m)] = ddot(n,&(ws[idx]),1,d,1);   
03193       pointr = pointr%m + 1;
03194     }
03195 
03196     idx = getIdx(col,col,m);
03197     if (stp == one)
03198       ss[idx] = dtd;
03199     else
03200       ss[idx] = stp*stp*dtd;
03201     
03202     sy[idx] = dr;
03203   }//matupd() 
03204 
03205 
03206   //   ************
03207   //
03208   //   Subroutine prn1lb
03209   //
03210   //   This subroutine prints the input data, initial point, upper and
03211   //     lower bounds of each variable, machine precision, as well as 
03212   //     the headings of the output.
03213   //
03214   //
03215   //                         *  *  *
03216   //
03217   //   NEOS, November 1994. (Latest revision June 1996.)
03218   //   Optimization Technology Center.
03219   //   Argonne National Laboratory and Northwestern University.
03220   //   Written by
03221   //                      Ciyou Zhu
03222   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
03223   //
03224   //
03225   //   ************
03226     //function
03227   void prn1lb(const int& n, const int& m, const double* const & l, 
03228               const double* const & u, const double* const & x, 
03229               const int& iprint, ofstream* itfile, const double& epsmch)
03230   {
03231     //int i;
03232 
03233     if (iprint >= 0)
03234     {
03235       cout << "RUNNING THE L-BFGS-B CODE, " << endl
03236            << "epsmch = machine precision" << endl
03237            << "it    = iteration number" << endl
03238            << "nf    = number of function evaluations" << endl
03239            << "nint  = number of segments explored during the Cauchy search" 
03240            << endl
03241            << "nact  = number of active bounds at the generalized Cauchy point"
03242            << endl
03243            << "sub   = manner in which the subspace minimization terminated:"
03244            << endl
03245            <<"con = converged, bnd = a bound was reached" << endl
03246            << "itls  = number of iterations performed in the line search" 
03247            << endl
03248            << "stepl = step length used" << endl
03249            << "tstep = norm of the displacement (total step)" << endl
03250            << "projg = norm of the projected gradient" << endl
03251            << "f     = function value" << endl
03252            << "Machine precision = " << epsmch << endl;
03253       cout << "N = " << n << ",    M = " << m << endl;
03254       if (iprint >= 1)
03255       {
03256         *itfile << "RUNNING THE L-BFGS-B CODE, epsmch = " 
03257                 << "it    = iteration number" << endl
03258                 << "nf    = number of function evaluations" << endl
03259                 <<"nint  = number of segments explored during the Cauchy search"
03260                 << endl
03261                 <<"nact  = number of active bounds at generalized Cauchy point"
03262                 << endl
03263                 <<"sub   =manner in which the subspace minimization terminated:"
03264                 << endl
03265                 <<"con = converged, bnd = a bound was reached" << endl
03266                 << "itls  = number of iterations performed in the line search" 
03267                 << endl
03268                 << "stepl = step length used" << endl
03269                 << "tstep = norm of the displacement (total step)" << endl
03270                 << "projg = norm of the projected gradient" << endl
03271                 << "f     = function value" << endl
03272                 << "Machine precision = " << epsmch << endl;
03273         *itfile << "N = " << n << ",    M = " << m << endl;
03274         *itfile << "   it   nf  nint  nact  sub  itls  stepl    tstep     projg"
03275                 << "        f" << endl;
03276         if (iprint > 100)
03277         {
03278           cout << "L = ";
03279           for (int i = 1; i <= n; i++) cout << l[i] << " "; 
03280           cout << endl;
03281           cout << "X0 = ";
03282           for (int i = 1; i <= n; i++) cout << x[i] << " "; 
03283           cout << endl;
03284           cout << "U = ";
03285           for (int i = 1; i <= n; i++) cout << u[i] << " ";
03286           cout << endl;
03287         }
03288       }
03289     }
03290   } //prn2lb()
03291 
03292 
03293   //   ************
03294   //
03295   //   Subroutine prn2lb
03296   //
03297   //   This subroutine prints out new information after a successful
03298   //     line search. 
03299   //
03300   //
03301   //                         *  *  *
03302   //
03303   //   NEOS, November 1994. (Latest revision June 1996.)
03304   //   Optimization Technology Center.
03305   //   Argonne National Laboratory and Northwestern University.
03306   //   Written by
03307   //                      Ciyou Zhu
03308   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
03309   //
03310   //
03311   //   ************
03312     //function
03313   void prn2lb(const int& n, const double* const & x, const double& f, 
03314               const double* const & g, const int& iprint, 
03315               ofstream* itfile, const int& iter, const int& nfgv, 
03316               const int& nact, const double& sbgnrm, const int& nint, 
03317               char* const & word, const int& iword, const int& iback, 
03318               const double& stp, const double& xstep)
03319   {
03320     //int i;
03321     int imod;
03322 
03323     //'word' records the status of subspace solutions.
03324     if (iword == 0)
03325     {
03326       //the subspace minimization converged.
03327       strcpy(word, "con");
03328     }
03329     else 
03330     if (iword == 1)
03331     {
03332       //the subspace minimization stopped at a bound.
03333       strcpy(word, "bnd");
03334     }
03335     else 
03336     if (iword == 5)
03337     {
03338       //the truncated Newton step has been used.
03339       strcpy(word, "TNT");
03340 
03341     }      
03342     else
03343       strcpy(word, "---");
03344 
03345     if (iprint >= 99)
03346     {
03347       cout << "LINE SEARCH " << iback <<" times; norm of step = " <<xstep<<endl;
03348       cout << "At iterate " << iter << " f=" << f <<"  |proj g|="<<sbgnrm<<endl;
03349       if (iprint > 100)
03350       { 
03351         cout << "X = " << endl;
03352         for (int i = 1; i <= n; i++) cout << x[i] << " ";
03353         cout << endl;
03354         cout << "G = " << endl;
03355         for (int i = 1; i <= n; i++) cout << g[i] << " ";
03356         cout << endl;
03357       }
03358     }
03359     else 
03360     if (iprint > 0)
03361     {
03362       imod = iter%iprint;
03363       if (imod == 0) 
03364         cout << "At iterate " << iter << " f="<<f<< "  |proj g|="<<sbgnrm<<endl;
03365     }
03366     if (iprint >= 1)
03367       *itfile << " " << iter << " " << nfgv << " " << nint << " " << nact << " "
03368            << word << " " << iback << " " << stp << " " << xstep << " " 
03369            << sbgnrm << " " << f << endl;
03370   }//prn2lb()
03371 
03372 
03373   //   ************
03374   //
03375   //   Subroutine prn3lb
03376   //
03377   //   This subroutine prints out information when either a built-in
03378   //     convergence test is satisfied or when an error message is
03379   //     generated.
03380   //     
03381   //
03382   //                         *  *  *
03383   //
03384   //   NEOS, November 1994. (Latest revision June 1996.)
03385   //   Optimization Technology Center.
03386   //   Argonne National Laboratory and Northwestern University.
03387   //   Written by
03388   //                      Ciyou Zhu
03389   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
03390   //
03391   //
03392   //   ************
03393     //function
03394   void prn3lb(const int& n, const double* const & x, double& f, 
03395               const char* const & task, const int& iprint, 
03396               const int& info, ofstream* itfile, const int& iter, 
03397               const int& nfgv, const int& nintol, const int& nskip, 
03398               const int& nact, const double& sbgnrm, const double& time, 
03399               const int& nint, const char* const & word, const int& iback, 
03400               const double& stp,const double& xstep, const int& k, 
03401               const double& cachyt, const double& sbtime, const double& lnscht)
03402   {
03403     //int i;
03404     if (strncmp(task,"ERROR",5)==0) goto goto999;
03405 
03406     if (iprint >= 0)
03407     {
03408       cout << "           * * *" 
03409            << "Tit   = total number of iterations" << endl
03410            << "Tnf   = total number of function evaluations" << endl
03411            << "Tnint = total number of segments explored during"
03412            << " Cauchy searches" << endl
03413            << "Skip  = number of BFGS updates skipped" << endl
03414            << "Nact  = number of active bounds at final generalized"
03415            << " Cauchy point" << endl
03416            << "Projg = norm of the final projected gradient" << endl
03417            << "F     = final function value" << endl
03418            << "           * * *" << endl;
03419       
03420       cout << "   N   Tit  Tnf  Tnint  Skip  Nact     Projg        F" << endl;
03421       cout << " " << n << " " << iter << " " << nfgv << " " << nintol << " " 
03422            << nskip << " " << nact << " " << sbgnrm << " " << f << endl;
03423       if (iprint >= 100)
03424       {
03425         cout << "X = ";
03426         for (int i = 1; i <= n; i++)
03427           cout << x[i] << " ";
03428         cout << endl;
03429       }
03430       if (iprint >= 1) cout << " F = " << f << endl;
03431     }
03432        
03433   goto999:
03434 
03435     if (iprint >= 0)
03436     {
03437       cout << task << endl;
03438       if (info != 0)
03439       {
03440         if (info == -1)
03441           cout << "Matrix in 1st Cholesky factorization in formk is not " 
03442                << "Pos. Def." << endl;
03443         if (info == -2)
03444           cout << "Matrix in 2st Cholesky factorization in formk is not "
03445                << "Pos. Def." << endl;
03446         if (info == -3) 
03447           cout << "Matrix in the Cholesky factorization in formt is not "
03448                << "Pos. Def." << endl;
03449         if (info == -4)
03450           cout << "Derivative >= 0, backtracking line search impossible."
03451                << endl << "Previous x, f and g restored." << endl
03452                << "Possible causes: 1 error in function or gradient "
03453                <<"evaluation;" << endl
03454                << "2 rounding errors dominate computation." << endl;
03455         if (info == -5) 
03456           cout << "Warning:  more than 10 function and gradient" << endl
03457                << "evaluations in the last line search.  Termination"
03458                << "may possibly be caused by a bad search direction."<<endl;
03459         if (info == -6) 
03460           cout << " Input nbd(" << k << ") is invalid."<<endl;
03461         if (info == -7)
03462           cout << " l(" << k << ") > u(" << k << ").  No feasible solution."
03463                << endl;
03464         if (info == -8) 
03465           cout << "The triangular system is singular" << endl;
03466         if (info == -9)
03467           cout << " Line search cannot locate an adequate point after"<<endl
03468                << " 20 function and gradient evaluations. Previous x, f and"
03469                << " g restored." << endl
03470                << "Possible causes: 1 error in function or gradient "
03471                << "evaluation; 2 rounding error dominate computation" 
03472                << endl;
03473       }
03474       
03475       if (iprint >= 1) 
03476         cout << "Cauchy                time " << cachyt << " seconds."<<endl
03477              << "Subspace minimization time " << sbtime << " seconds."<<endl
03478              << "Line search           time " << lnscht << " seconds."<<endl;
03479       
03480       cout << "Total User time " << time << " seconds." << endl;
03481 
03482       if (iprint >= 1)
03483       {
03484         if (info == -4 || info == -9)
03485         {              
03486           *itfile << " " << n << " " << iter << " " << nfgv << " " << nintol 
03487                  << " " << nskip << " " << nact << " " << sbgnrm << " " << f
03488                  << endl;
03489         }
03490         *itfile << task << endl;
03491         if (info != 0)
03492         {
03493           if (info == -1)
03494             *itfile << "Matrix in 1st Cholesky factorization in formk is not"
03495                     << " Pos. Def." << endl;
03496           if (info == -2)
03497             *itfile << "Matrix in 2st Cholesky factorization in formk is not"
03498                     << " Pos. Def." << endl;
03499           if (info == -3) 
03500             *itfile << "Matrix in the Cholesky factorization in formt is not"
03501                     << " Pos. Def." << endl;
03502           if (info == -4)
03503             *itfile << "Derivative>=0, backtracking line search impossible."
03504                     << endl << "Previous x, f and g restored." << endl
03505                     << "Possible causes: 1 error in function or gradient "
03506                     <<"evaluation;" << endl
03507                     << "2 rounding errors dominate computation." << endl;
03508           if (info == -5) 
03509             *itfile << "Warning:  more than 10 function and gradient" << endl
03510                     << "evaluations in the last line search.  Termination"
03511                     << "may possibly be caused by a bad search direction."
03512                     << endl;
03513           if (info == -8) 
03514             cout << "The triangular system is singular" << endl;
03515           if (info == -9)
03516             cout << " Line search cannot locate an adequate point after"
03517                  << endl
03518                  << " 20 function and gradient evaluations. Previous x, f "
03519                  << "and g restored." << endl
03520                  << "Possible causes: 1 error in function or gradient "
03521                  << "evaluation; 2 rounding error dominate computation" 
03522                  << endl;
03523         }
03524         *itfile << "Total User time " << time << " seconds." << endl;
03525       }
03526     }    
03527   }//prn3lb()
03528 
03529   
03530   //   ************
03531   //
03532   //   Subroutine projgr
03533   //
03534   //   This subroutine computes the infinity norm of the projected
03535   //     gradient.
03536   //
03537   //
03538   //                         *  *  *
03539   //
03540   //   NEOS, November 1994. (Latest revision June 1996.)
03541   //   Optimization Technology Center.
03542   //   Argonne National Laboratory and Northwestern University.
03543   //   Written by
03544   //                      Ciyou Zhu
03545   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
03546   //
03547   //
03548   //   ************
03549     //functions
03550   void projgr(const int& n, const double* const & l, const double* const & u, 
03551               const int* const & nbd, const double* const & x, 
03552               const double* const & g, double& sbgnrm)
03553   {
03554     //int i;
03555     double gi;
03556     //double one=1.0;
03557     double zero=0.0;
03558 
03559     sbgnrm = zero;
03560     for (int i = 1; i <= n; i++)
03561     {
03562       gi = g[i];
03563       if (nbd[i] != 0)
03564       {
03565         if (gi < zero)
03566         {
03567           if (nbd[i] >= 2) gi = max((x[i]-u[i]),gi);
03568         }
03569         else
03570         {
03571           if (nbd[i] <= 2) gi = min((x[i]-l[i]),gi);
03572         }
03573       }
03574       sbgnrm = max(sbgnrm,fabs(gi));
03575     }
03576   }//projgr()
03577 
03578 
03579   //   ************
03580   //
03581   //   Subroutine subsm
03582   //
03583   //   Given xcp, l, u, r, an index set that specifies
03584   //     the active set at xcp, and an l-BFGS matrix B 
03585   //     (in terms of WY, WS, SY, WT, head, col, and theta), 
03586   //     this subroutine computes an approximate solution
03587   //     of the subspace problem
03588   //
03589   //    (P)   min Q(x) = r'(x-xcp) + 1/2 (x-xcp)' B (x-xcp)
03590   //
03591   //           subject to l<=x<=u
03592   //                    x_i=xcp_i for all i in A(xcp)
03593   //                  
03594   //    along the subspace unconstrained Newton direction 
03595   //    
03596   //       d = -(Z'BZ)^(-1) r.
03597   //
03598   //     The formula for the Newton direction, given the L-BFGS matrix
03599   //     and the Sherman-Morrison formula, is
03600   //
03601   //       d = (1/theta)r + (1/theta*2) Z'WK^(-1)W'Z r.
03602   //  
03603   //     where
03604   //               K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
03605   //                   [L_a -R_z           theta*S'AA'S ]
03606   //
03607   //   Note that this procedure for computing d differs 
03608   //   from that described in [1]. One can show that the matrix K is
03609   //   equal to the matrix M^[-1]N in that paper.
03610   //
03611   //   n is an integer variable.
03612   //     On entry n is the dimension of the problem.
03613   //     On exit n is unchanged.
03614   //
03615   //   m is an integer variable.
03616   //     On entry m is the maximum number of variable metric corrections
03617   //       used to define the limited memory matrix.
03618   //     On exit m is unchanged.
03619   //
03620   //   nsub is an integer variable.
03621   //     On entry nsub is the number of free variables.
03622   //     On exit nsub is unchanged.
03623   //
03624   //   ind is an integer array of dimension nsub.
03625   //     On entry ind specifies the coordinate indices of free variables.
03626   //     On exit ind is unchanged.
03627   //
03628   //   l is a double precision array of dimension n.
03629   //     On entry l is the lower bound of x.
03630   //     On exit l is unchanged.
03631   //
03632   //   u is a double precision array of dimension n.
03633   //     On entry u is the upper bound of x.
03634   //     On exit u is unchanged.
03635   //
03636   //   nbd is a integer array of dimension n.
03637   //     On entry nbd represents the type of bounds imposed on the
03638   //       variables, and must be specified as follows:
03639   //       nbd(i)=0 if x(i) is unbounded,
03640   //              1 if x(i) has only a lower bound,
03641   //              2 if x(i) has both lower and upper bounds, and
03642   //              3 if x(i) has only an upper bound.
03643   //     On exit nbd is unchanged.
03644   //
03645   //   x is a double precision array of dimension n.
03646   //     On entry x specifies the Cauchy point xcp. 
03647   //     On exit x(i) is the minimizer of Q over the subspace of
03648   //                                                      free variables. 
03649   //
03650   //   d is a double precision array of dimension n.
03651   //     On entry d is the reduced gradient of Q at xcp.
03652   //     On exit d is the Newton direction of Q. 
03653   //
03654   //   ws and wy are double precision arrays;
03655   //   theta is a double precision variable;
03656   //   col is an integer variable;
03657   //   head is an integer variable.
03658   //     On entry they store the information defining the
03659   //                                        limited memory BFGS matrix:
03660   //       ws(n,m) stores S, a set of s-vectors;
03661   //       wy(n,m) stores Y, a set of y-vectors;
03662   //       theta is the scaling factor specifying B_0 = theta I;
03663   //       col is the number of variable metric corrections stored;
03664   //       head is the location of the 1st s- (or y-) vector in S (or Y).
03665   //     On exit they are unchanged.
03666   //
03667   //   iword is an integer variable.
03668   //     On entry iword is unspecified.
03669   //     On exit iword specifies the status of the subspace solution.
03670   //       iword = 0 if the solution is in the box,
03671   //               1 if some bound is encountered.
03672   //
03673   //   wv is a double precision working array of dimension 2m.
03674   //
03675   //   wn is a double precision array of dimension 2m x 2m.
03676   //     On entry the upper triangle of wn stores the LEL^T factorization
03677   //       of the indefinite matrix
03678   //
03679   //            k = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
03680   //                [L_a -R_z           theta*S'AA'S ]
03681   //                                                  where E = [-I  0]
03682   //                                                            [ 0  I]
03683   //     On exit wn is unchanged.
03684   //
03685   //   iprint is an INTEGER variable that must be set by the user.
03686   //     It controls the frequency and type of output generated:
03687   //      iprint<0    no output is generated;
03688   //      iprint=0    print only one line at the last iteration;
03689   //      0<iprint<99 print also f and |proj g| every iprint iterations;
03690   //      iprint=99   print details of every iteration except n-vectors;
03691   //      iprint=100  print also the changes of active set and final x;
03692   //      iprint>100  print details of every iteration including x and g;
03693   //     When iprint > 0, the file iterate.dat will be created to
03694   //                      summarize the iteration.
03695   //
03696   //   info is an integer variable.
03697   //     On entry info is unspecified.
03698   //     On exit info = 0       for normal return,
03699   //                  = nonzero for abnormal return 
03700   //                                when the matrix K is ill-conditioned.
03701   //
03702   //   Subprograms called:
03703   //
03704   //     Linpack dtrsl.
03705   //
03706   //
03707   //   References:
03708   //
03709   //     [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
03710   //     memory algorithm for bound constrained optimization'',
03711   //     SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
03712   //
03713   //
03714   //
03715   //                         *  *  *
03716   //
03717   //   NEOS, November 1994. (Latest revision June 1996.)
03718   //   Optimization Technology Center.
03719   //   Argonne National Laboratory and Northwestern University.
03720   //   Written by
03721   //                      Ciyou Zhu
03722   //   in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
03723   //
03724   //
03725   //   ************
03726     //function
03727   void subsm(const int& n, const int& m, const int& nsub, const int* const& ind,
03728              const double* const & l, const double* const & u, 
03729              const int* const & nbd, double* const & x, double* const & d, 
03730              double* const & ws, double* const & wy, const double& theta, 
03731              const int& col, const int& head, int& iword, double* const & wv, 
03732              double* const & wn, const int& iprint, int& info) 
03733   {
03734     //int jy,i,j;
03735     int pointr,m2,col2,ibd=0,js,k;
03736     double alpha,dk,temp1,temp2;
03737     double one=1.0,zero=0.0;
03738     int idx;
03739 
03740     if (nsub <= 0) return;
03741     if (iprint >= 99) 
03742       cout << "----------------SUBSM entered-----------------" << endl;
03743 
03744     //Compute wv = W'Zd.
03745 
03746     pointr = head;
03747     for (int i = 1; i <= col; i++)
03748     {
03749       temp1 = zero;
03750       temp2 = zero;
03751       for (int j = 1; j <= nsub; j++)
03752       {
03753         k = ind[j];
03754         idx = getIdx(k,pointr,n);
03755         temp1 += wy[idx]*d[j];
03756         temp2 += ws[idx]*d[j];
03757       }
03758       wv[i] = temp1;
03759       wv[col + i] = theta*temp2;
03760       pointr = pointr%m + 1;
03761     }
03762 
03763 
03764     //Compute wv:=K^(-1)wv.
03765 
03766     m2 = 2*m;
03767     col2 = 2*col;
03768     dtrsl(wn,m2,col2,wv,11,info);
03769 
03770     if (info != 0) return;
03771     for (int i = 1; i <= col; i++)
03772       wv[i] = -wv[i];
03773     dtrsl(wn,m2,col2,wv,01,info);
03774 
03775     if (info != 0) return;
03776  
03777     //Compute d = (1/theta)d + (1/theta**2)Z'W wv.
03778  
03779     pointr = head;
03780     for (int jy = 1; jy <= col; jy++)
03781     {
03782       js = col + jy;
03783       for (int i = 1; i <= nsub; i++)        
03784       {
03785         k = ind[i];
03786         idx = getIdx(k,pointr,n);
03787         d[i] += wy[idx]*wv[jy]/theta + ws[idx]*wv[js];
03788       }
03789       pointr = pointr%m + 1;
03790     }
03791 
03792     for (int i = 1; i <= nsub; i++)
03793       d[i] /= theta;
03794  
03795     //Backtrack to the feasible region.
03796  
03797     alpha = one;
03798     temp1 = alpha;
03799 
03800     for (int i = 1; i <= nsub; i++)
03801     {
03802       k = ind[i];
03803       dk = d[i];
03804       if (nbd[k] != 0)
03805       {
03806             if (dk < zero && nbd[k] <= 2)
03807         {
03808                 temp2 = l[k] - x[k];
03809                 if (temp2 >= zero)
03810                       temp1 = zero;
03811                 else 
03812           if (dk*alpha < temp2)
03813                         temp1 = temp2/dk;               
03814         }
03815             else 
03816         if (dk > zero && nbd[k] >= 2)
03817         {
03818                 temp2 = u[k] - x[k];
03819                 if (temp2 <= zero)
03820                         temp1 = zero;
03821           else
03822           if (dk*alpha > temp2)
03823                         temp1 = temp2/dk;
03824         }
03825         if (temp1 < alpha)
03826         {
03827                 alpha = temp1;
03828                 ibd = i;
03829         }
03830       }
03831     }
03832 
03833 
03834     if (alpha < one)
03835     {
03836       dk = d[ibd];
03837       k = ind[ibd];
03838       if (dk > zero)
03839       {
03840         x[k] = u[k];
03841         d[ibd] = zero;
03842       }
03843       else 
03844       if (dk < zero)
03845       {
03846         x[k] = l[k];
03847         d[ibd] = zero;
03848       }
03849     }
03850 
03851     for (int i = 1; i <= nsub; i++)
03852     {
03853       k = ind[i];
03854       x[k] += alpha*d[i];
03855     } 
03856     
03857     if (iprint >= 99)
03858     {
03859       if (alpha < one)
03860         cout << "ALPHA = " << alpha << " backtrack to the BOX" << endl;
03861       else
03862         cout  << "SM solution inside the box" << endl;
03863 
03864       if (iprint >100)
03865       {
03866         cout << "Subspace solution X = ";
03867         for (int i = 1; i <= n; i++) cout << x[i] << " ";
03868         cout << endl;
03869       }
03870     }
03871  
03872     if (alpha < one)
03873       iword = 1;
03874     else
03875       iword = 0;
03876 
03877     if (iprint >= 99) 
03878       cout << "----------------exit SUBSM --------------------" << endl;    
03879   }//subsm()
03880 
03881 
03882   //   **********
03883   //
03884   //   Subroutine dcsrch
03885   //
03886   //   This subroutine finds a step that satisfies a sufficient
03887   //   decrease condition and a curvature condition.
03888   //
03889   //   Each call of the subroutine updates an interval with 
03890   //   endpoints stx and sty. The interval is initially chosen 
03891   //   so that it contains a minimizer of the modified function
03892   //
03893   //         psi(stp) = f(stp) - f(0) - ftol*stp*f'(0).
03894   //
03895   //   If psi(stp) <= 0 and f'(stp) >= 0 for some step, then the
03896   //   interval is chosen so that it contains a minimizer of f. 
03897   //
03898   //   The algorithm is designed to find a step that satisfies 
03899   //   the sufficient decrease condition 
03900   //
03901   //         f(stp) <= f(0) + ftol*stp*f'(0),
03902   //
03903   //   and the curvature condition
03904   //
03905   //         abs(f'(stp)) <= gtol*abs(f'(0)).
03906   //
03907   //   If ftol is less than gtol and if, for example, the function
03908   //   is bounded below, then there is always a step which satisfies
03909   //   both conditions. 
03910   //
03911   //   If no step can be found that satisfies both conditions, then 
03912   //   the algorithm stops with a warning. In this case stp only 
03913   //   satisfies the sufficient decrease condition.
03914   //
03915   //   A typical invocation of dcsrch has the following outline:
03916   //
03917   //   task = 'START'
03918   //  10 continue
03919   //      call dcsrch( ... )
03920   //      if (task == 'FG') then
03921   //         Evaluate the function and the gradient at stp 
03922   //         goto 10
03923   //         end if
03924   //
03925   //   NOTE: The user must no alter work arrays between calls.
03926   //
03927   //   The subroutine statement is
03928   //
03929   //      subroutine dcsrch(f,g,stp,ftol,gtol,xtol,stpmin,stpmax,
03930   //                        task,isave,dsave)
03931   //   where
03932   //
03933   //     f is a double precision variable.
03934   //       On initial entry f is the value of the function at 0.
03935   //          On subsequent entries f is the value of the 
03936   //          function at stp.
03937   //       On exit f is the value of the function at stp.
03938   //
03939   //    g is a double precision variable.
03940   //       On initial entry g is the derivative of the function at 0.
03941   //          On subsequent entries g is the derivative of the 
03942   //          function at stp.
03943   //       On exit g is the derivative of the function at stp.
03944   //
03945   //    stp is a double precision variable. 
03946   //       On entry stp is the current estimate of a satisfactory 
03947   //          step. On initial entry, a positive initial estimate 
03948   //          must be provided. 
03949   //       On exit stp is the current estimate of a satisfactory step
03950   //          if task = 'FG'. If task = 'CONV' then stp satisfies
03951   //          the sufficient decrease and curvature condition.
03952   //
03953   //     ftol is a double precision variable.
03954   //       On entry ftol specifies a nonnegative tolerance for the 
03955   //          sufficient decrease condition.
03956   //       On exit ftol is unchanged.
03957   //
03958   //     gtol is a double precision variable.
03959   //       On entry gtol specifies a nonnegative tolerance for the 
03960   //          curvature condition. 
03961   //       On exit gtol is unchanged.
03962   //
03963   //    xtol is a double precision variable.
03964   //       On entry xtol specifies a nonnegative relative tolerance
03965   //          for an acceptable step. The subroutine exits with a
03966   //          warning if the relative difference between sty and stx
03967   //          is less than xtol.
03968   //       On exit xtol is unchanged.
03969   //
03970   //    stpmin is a double precision variable.
03971   //       On entry stpmin is a nonnegative lower bound for the step.
03972   //       On exit stpmin is unchanged.
03973   //
03974   //    stpmax is a double precision variable.
03975   //       On entry stpmax is a nonnegative upper bound for the step.
03976   //       On exit stpmax is unchanged.
03977   //
03978   //     task is a character variable of length at least 60.
03979   //       On initial entry task must be set to 'START'.
03980   //       On exit task indicates the required action:
03981   //
03982   //          If task(1:2) = 'FG' then evaluate the function and 
03983   //          derivative at stp and call dcsrch again.
03984   //
03985   //          If task(1:4) = 'CONV' then the search is successful.
03986   //
03987   //          If task(1:4) = 'WARN' then the subroutine is not able
03988   //          to satisfy the convergence conditions. The exit value of
03989   //          stp contains the best point found during the search.
03990   //
03991   //          If task(1:5) = 'ERROR' then there is an error in the
03992   //          input arguments.
03993   //
03994   //       On exit with convergence, a warning or an error, the
03995   //          variable task contains additional information.
03996   //
03997   //     isave is an integer work array of dimension 2.
03998   //       
03999   //     dsave is a double precision work array of dimension 13.
04000   //
04001   //   Subprograms called
04002   //
04003   //     MINPACK-2 ... dcstep
04004   //
04005   //   MINPACK-1 Project. June 1983.
04006   //   Argonne National Laboratory. 
04007   //   Jorge J. More' and David J. Thuente.
04008   //
04009   //   MINPACK-2 Project. October 1993.
04010   //   Argonne National Laboratory and University of Minnesota. 
04011   //   Brett M. Averick, Richard G. Carter, and Jorge J. More'. 
04012   //
04013   //   **********
04014     //function
04015   void dcsrch(double& f, double& g, double& stp, const double& ftol, 
04016               const double& gtol, const double& xtol, const double& stpmin, 
04017               const double& stpmax, char* const & task, int* const & isave, 
04018               double* const & dsave)
04019   {
04020     double zero=0.0,p5=0.5,p66=0.66;
04021     double xtrapl=1.1,xtrapu=4.0;
04022     
04023     bool brackt;
04024     int stage;
04025     double finit,ftest,fm,fx,fxm,fy,fym,ginit,gtest,
04026            gm,gx,gxm,gy,gym,stx,sty,stmin,stmax,width,width1;
04027 
04028     //Initialization block.
04029 
04030     if (strncmp(task,"START",5)==0)
04031     {
04032       //Check the input arguments for errors.
04033 
04034       if (stp < stpmin)    strcpy(task, "ERROR: STP < STPMIN");
04035       if (stp > stpmax)    strcpy(task, "ERROR: STP > STPMAX");
04036       if (g >zero)         strcpy(task, "ERROR: INITIAL G >ZERO");
04037       if (ftol < zero)     strcpy(task, "ERROR: FTOL < ZERO");
04038       if (gtol < zero)     strcpy(task, "ERROR: GTOL < ZERO");
04039       if (xtol < zero)     strcpy(task, "ERROR: XTOL < ZERO");
04040       if (stpmin < zero)   strcpy(task, "ERROR: STPMIN < ZERO");
04041       if (stpmax < stpmin) strcpy(task, "ERROR: STPMAX < STPMIN");
04042 
04043       //Exit if there are errors on input.
04044       if (strncmp(task,"ERROR",5)==0) return;
04045       
04046       //Initialize local variables.
04047 
04048       brackt = false;
04049       stage = 1;
04050       finit = f;
04051       ginit = g;
04052       gtest = ftol*ginit;
04053       width = stpmax - stpmin;
04054       width1 = width/p5;
04055 
04056       //The variables stx, fx, gx contain the values of the step, 
04057       //function, and derivative at the best step. 
04058       //The variables sty, fy, gy contain the value of the step, 
04059       //function, and derivative at sty.
04060       //The variables stp, f, g contain the values of the step, 
04061       //function, and derivative at stp.
04062       
04063       stx = zero;
04064       fx = finit;
04065       gx = ginit;
04066       sty = zero;
04067       fy = finit;
04068       gy = ginit;
04069       stmin = zero;
04070       stmax = stp + xtrapu*stp;
04071       strcpy(task, "FG");
04072 
04073       goto goto1000;
04074     }
04075     else
04076     {
04077       //Restore local variables.
04078       
04079       if (isave[1] == 1)
04080         brackt = true;
04081       else
04082         brackt = false;
04083       
04084       stage  = isave[2]; 
04085       ginit  = dsave[1]; 
04086       gtest  = dsave[2]; 
04087       gx     = dsave[3]; 
04088       gy     = dsave[4]; 
04089       finit  = dsave[5]; 
04090       fx     = dsave[6]; 
04091       fy     = dsave[7]; 
04092       stx    = dsave[8]; 
04093       sty    = dsave[9]; 
04094       stmin  = dsave[10]; 
04095       stmax  = dsave[11]; 
04096       width  = dsave[12]; 
04097       width1 = dsave[13]; 
04098     }
04099 
04100     //If psi(stp) <= 0 and f'(stp) >= 0 for some step, then the
04101     //algorithm enters the second stage.
04102 
04103     ftest = finit + stp*gtest;
04104     if (stage == 1 && f <= ftest && g >= zero) stage = 2;
04105 
04106     //Test for warnings.
04107 
04108     if (brackt && (stp <= stmin || stp >= stmax))
04109       strcpy(task, "WARNING: ROUNDING ERRORS PREVENT PROGRESS");
04110     if (brackt && stmax - stmin <= xtol*stmax) 
04111       strcpy(task, "WARNING: XTOL TEST SATISFIED");
04112     if (stp == stpmax && f <= ftest && g <= gtest) 
04113       strcpy(task, "WARNING: STP = STPMAX");
04114     if (stp == stpmin && (f > ftest || g >= gtest)) 
04115       strcpy(task, "WARNING: STP = STPMIN");
04116     
04117     //Test for convergence.
04118     
04119     if (f <= ftest && fabs(g) <= gtol*(-ginit)) 
04120       strcpy(task, "CONVERGENCE");
04121     
04122     //Test for termination.
04123     
04124     if (strncmp(task,"WARN",4)==0 || strncmp(task,"CONV",4)==0) goto goto1000;
04125     
04126     //A modified function is used to predict the step during the
04127     //first stage if a lower function value has been obtained but 
04128     //the decrease is not sufficient.
04129     
04130     if (stage == 1 && f <= fx && f > ftest)
04131     {
04132       //Define the modified function and derivative values.
04133       
04134       fm = f - stp*gtest;
04135       fxm = fx - stx*gtest;
04136       fym = fy - sty*gtest;
04137       gm = g - gtest;
04138       gxm = gx - gtest;
04139       gym = gy - gtest;
04140       
04141       //Call dcstep to update stx, sty, and to compute the new step.
04142       
04143       dcstep(stx,fxm,gxm,sty,fym,gym,stp,fm,gm,
04144              brackt,stmin,stmax);
04145       
04146       //Reset the function and derivative values for f.
04147       
04148       fx = fxm + stx*gtest;
04149       fy = fym + sty*gtest;
04150       gx = gxm + gtest;
04151       gy = gym + gtest;
04152     }
04153     else
04154     {
04155       //Call dcstep to update stx, sty, and to compute the new step.
04156       
04157       dcstep(stx,fx,gx,sty,fy,gy,stp,f,g,
04158              brackt,stmin,stmax);
04159     }
04160     
04161     //Decide if a bisection step is needed.
04162     
04163     if (brackt)
04164     {
04165       if (fabs(sty-stx) >= p66*width1) stp = stx + p5*(sty - stx);
04166       width1 = width;
04167       width = fabs(sty-stx);
04168     }
04169     
04170     //Set the minimum and maximum steps allowed for stp.
04171     
04172     if (brackt)
04173     {
04174       stmin = min(stx,sty);
04175       stmax = max(stx,sty);
04176     }
04177     else
04178     {
04179       stmin = stp + xtrapl*(stp - stx);
04180       stmax = stp + xtrapu*(stp - stx);
04181     }
04182     
04183     //Force the step to be within the bounds stpmax and stpmin.
04184     
04185     stp = max(stp,stpmin);
04186     stp = min(stp,stpmax);
04187     
04188     //If further progress is not possible, let stp be the best
04189     //point obtained during the search.
04190 
04191     if (brackt && (stp <= stmin || stp >= stmax)
04192         || (brackt && stmax-stmin <= xtol*stmax)) stp = stx;
04193     
04194     //Obtain another function and derivative.
04195     strcpy(task,"FG");
04196     
04197   goto1000:
04198     
04199     //Save local variables.
04200     
04201     if (brackt)
04202       isave[1]  = 1;
04203     else    
04204       isave[1]  = 0;
04205 
04206     isave[2]  = stage;
04207     dsave[1]  = ginit;
04208     dsave[2]  = gtest;
04209     dsave[3]  = gx;
04210     dsave[4]  = gy;
04211     dsave[5]  = finit;
04212     dsave[6]  = fx;
04213     dsave[7]  = fy;
04214     dsave[8]  = stx;
04215     dsave[9]  = sty;
04216     dsave[10] = stmin;
04217     dsave[11] = stmax;
04218     dsave[12] = width;
04219     dsave[13] = width1;
04220   }//dcsrch()
04221 
04222 
04223   //   **********
04224   //
04225   //   Subroutine dcstep
04226   //
04227   //   This subroutine computes a safeguarded step for a search
04228   //   procedure and updates an interval that contains a step that
04229   //   satisfies a sufficient decrease and a curvature condition.
04230   //
04231   //   The parameter stx contains the step with the least function
04232   //   value. If brackt is set to true then a minimizer has
04233   //   been bracketed in an interval with endpoints stx and sty.
04234   //   The parameter stp contains the current step. 
04235   //   The subroutine assumes that if brackt is set to true then
04236   //
04237   //         min(stx,sty) < stp < max(stx,sty),
04238   //
04239   //   and that the derivative at stx is negative in the direction 
04240   //   of the step.
04241   //
04242   //   The subroutine statement is
04243   //
04244   //     subroutine dcstep(stx,fx,dx,sty,fy,dy,stp,fp,dp,brackt,
04245   //                       stpmin,stpmax)
04246   //
04247   //   where
04248   //
04249   //     stx is a double precision variable.
04250   //       On entry stx is the best step obtained so far and is an
04251   //          endpoint of the interval that contains the minimizer. 
04252   //       On exit stx is the updated best step.
04253   //
04254   //     fx is a double precision variable.
04255   //       On entry fx is the function at stx.
04256   //       On exit fx is the function at stx.
04257   //
04258   //     dx is a double precision variable.
04259   //       On entry dx is the derivative of the function at 
04260   //          stx. The derivative must be negative in the direction of 
04261   //          the step, that is, dx and stp - stx must have opposite 
04262   //          signs.
04263   //       On exit dx is the derivative of the function at stx.
04264   //
04265   //     sty is a double precision variable.
04266   //       On entry sty is the second endpoint of the interval that 
04267   //          contains the minimizer.
04268   //       On exit sty is the updated endpoint of the interval that 
04269   //          contains the minimizer.
04270   //
04271   //     fy is a double precision variable.
04272   //       On entry fy is the function at sty.
04273   //       On exit fy is the function at sty.
04274   //
04275   //     dy is a double precision variable.
04276   //       On entry dy is the derivative of the function at sty.
04277   //       On exit dy is the derivative of the function at the exit sty.
04278   //
04279   //     stp is a double precision variable.
04280   //       On entry stp is the current step. If brackt is set to true
04281   //          then on input stp must be between stx and sty. 
04282   //       On exit stp is a new trial step.
04283   //
04284   //     fp is a double precision variable.
04285   //       On entry fp is the function at stp
04286   //       On exit fp is unchanged.
04287   //
04288   //     dp is a double precision variable.
04289   //       On entry dp is the the derivative of the function at stp.
04290   //       On exit dp is unchanged.
04291   //
04292   //     brackt is an logical variable.
04293   //       On entry brackt specifies if a minimizer has been bracketed.
04294   //          Initially brackt must be set to false
04295   //       On exit brackt specifies if a minimizer has been bracketed.
04296   //          When a minimizer is bracketed brackt is set to true
04297   //
04298   //     stpmin is a double precision variable.
04299   //       On entry stpmin is a lower bound for the step.
04300   //       On exit stpmin is unchanged.
04301   //
04302   //     stpmax is a double precision variable.
04303   //       On entry stpmax is an upper bound for the step.
04304   //       On exit stpmax is unchanged.
04305   //
04306   //   MINPACK-1 Project. June 1983
04307   //   Argonne National Laboratory. 
04308   //   Jorge J. More' and David J. Thuente.
04309   //
04310   //   MINPACK-2 Project. October 1993.
04311   //   Argonne National Laboratory and University of Minnesota. 
04312   //   Brett M. Averick and Jorge J. More'.
04313   //
04314   //   **********
04315     //function
04316   void dcstep(double& stx, double& fx, double& dx, double& sty, double& fy, 
04317               double& dy, double& stp, const double& fp, const double& dp, 
04318               bool& brackt, const double& stpmin, const double& stpmax)
04319   {
04320     double zero=0.0,p66=0.66,two=2.0,three=3.0;
04321     double gamma,p,q,r,s,sgnd,stpc,stpf,stpq,theta;
04322 
04323     sgnd = dp*(dx/fabs(dx));
04324 
04325     //First case: A higher function value. The minimum is bracketed. 
04326     //If the cubic step is closer to stx than the quadratic step, the 
04327     //cubic step is taken, otherwise the average of the cubic and 
04328     //quadratic steps is taken.
04329 
04330     if (fp > fx)
04331     {
04332       theta = three*(fx - fp)/(stp - stx) + dx + dp;
04333       s = max(fabs(theta),fabs(dx),fabs(dp));
04334       gamma = s*sqrt( (theta/s)*(theta/s) - (dx/s)*(dp/s) );
04335       if (stp < stx) gamma = -gamma;
04336       p = (gamma - dx) + theta;
04337       q = ((gamma - dx) + gamma) + dp;
04338       r = p/q;
04339       stpc = stx + r*(stp - stx);
04340       stpq = stx + ((dx/((fx - fp)/(stp - stx) + dx))/two)*(stp - stx);
04341       if (fabs(stpc-stx) < fabs(stpq-stx))
04342         stpf = stpc;
04343       else
04344         stpf = stpc + (stpq - stpc)/two;
04345       brackt = true;
04346     }
04347 
04348     //Second case: A lower function value and derivatives of opposite 
04349     //sign. The minimum is bracketed. If the cubic step is farther from 
04350     //stp than the secant step, the cubic step is taken, otherwise the 
04351     //secant step is taken.
04352 
04353     else 
04354     if (sgnd < zero)
04355     {
04356       theta = three*(fx - fp)/(stp - stx) + dx + dp;
04357       s = max(fabs(theta),fabs(dx),fabs(dp));
04358       gamma = s*sqrt( (theta/s)*(theta/s) - (dx/s)*(dp/s) );
04359       if (stp > stx) gamma = -gamma;
04360       p = (gamma - dp) + theta;
04361       q = ((gamma - dp) + gamma) + dx;
04362       r = p/q;
04363       stpc = stp + r*(stx - stp);
04364       stpq = stp + (dp/(dp - dx))*(stx - stp);
04365       if (fabs(stpc-stp) > fabs(stpq-stp))
04366         stpf = stpc;
04367       else
04368         stpf = stpq;
04369       brackt = true;
04370     }
04371 
04372     //Third case: A lower function value, derivatives of the same sign,
04373     //and the magnitude of the derivative decreases.
04374 
04375     else 
04376     if (fabs(dp) < fabs(dx))
04377     {
04378       //The cubic step is computed only if the cubic tends to infinity 
04379       //in the direction of the step or if the minimum of the cubic
04380       //is beyond stp. Otherwise the cubic step is defined to be the 
04381       //secant step.
04382 
04383       theta = three*(fx - fp)/(stp - stx) + dx + dp;
04384       s = max(fabs(theta),fabs(dx),fabs(dp));
04385 
04386       //The case gamma = 0 only arises if the cubic does not tend
04387       //to infinity in the direction of the step.
04388       
04389       gamma = s*sqrt(max(zero, (theta/s)*(theta/s)-(dx/s)*(dp/s)));
04390       if (stp > stx) gamma = -gamma;
04391       p = (gamma - dp) + theta;
04392       q = (gamma + (dx - dp)) + gamma;
04393       r = p/q;
04394       if (r < zero && gamma != zero)
04395         stpc = stp + r*(stx - stp);
04396       else 
04397       if (stp > stx)
04398         stpc = stpmax;
04399       else
04400         stpc = stpmin;
04401       
04402       stpq = stp + (dp/(dp - dx))*(stx - stp);
04403 
04404       if (brackt)
04405       {
04406 
04407         //A minimizer has been bracketed. If the cubic step is 
04408         //closer to stp than the secant step, the cubic step is 
04409         //taken, otherwise the secant step is taken.
04410 
04411         if (fabs(stpc-stp) < fabs(stpq-stp))
04412           stpf = stpc;
04413         else
04414           stpf = stpq;
04415 
04416         if (stp > stx) 
04417           stpf = min(stp+p66*(sty-stp),stpf);
04418         else
04419           stpf = max(stp+p66*(sty-stp),stpf);
04420       }
04421       else
04422       {
04423         //A minimizer has not been bracketed. If the cubic step is 
04424         //farther from stp than the secant step, the cubic step is 
04425         //taken, otherwise the secant step is taken.
04426 
04427         if (fabs(stpc-stp) > fabs(stpq-stp))
04428           stpf = stpc;
04429         else
04430           stpf = stpq;
04431         
04432         stpf = min(stpmax,stpf);
04433         stpf = max(stpmin,stpf);
04434       }
04435     }
04436     //Fourth case: A lower function value, derivatives of the same sign, 
04437     //and the magnitude of the derivative does not decrease. If the 
04438     //minimum is not bracketed, the step is either stpmin or stpmax, 
04439     //otherwise the cubic step is taken.
04440     else
04441     {
04442       if (brackt)
04443       {
04444         theta = three*(fp - fy)/(sty - stp) + dy + dp;
04445         s = max(fabs(theta),fabs(dy),fabs(dp));
04446         gamma = s*sqrt((theta/s)*(theta/s) - (dy/s)*(dp/s));
04447         if (stp > sty) gamma = -gamma;
04448         p = (gamma - dp) + theta;
04449         q = ((gamma - dp) + gamma) + dy;
04450         r = p/q;
04451         stpc = stp + r*(sty - stp);
04452         stpf = stpc;
04453       }
04454       else 
04455       if (stp > stx)
04456         stpf = stpmax;
04457       else
04458         stpf = stpmin;
04459     }
04460 
04461     //Update the interval which contains a minimizer.
04462 
04463     if (fp > fx)
04464     {
04465       sty = stp;
04466       fy = fp;
04467       dy = dp;
04468     }
04469     else
04470     {
04471       if (sgnd < zero)
04472       {
04473         sty = stx;
04474         fy = fx;
04475         dy = dx;
04476       }
04477       stx = stp;
04478       fx = fp;
04479       dx = dp;
04480     }
04481 
04482     //Compute the new step.
04483 
04484     stp = stpf;    
04485   }//dcstep()
04486 
04487 
04488   //   **********
04489   //
04490   //   Function dnrm2
04491   //
04492   //   Given a vector x of length n, this function calculates the
04493   //   Euclidean norm of x with stride incx.
04494   //
04495   //   The function statement is
04496   //
04497   //     double precision function dnrm2(n,x,incx)
04498   //
04499   //   where
04500   //
04501   //     n is a positive integer input variable.
04502   //
04503   //     x is an input array of length n.
04504   //
04505   //     incx is a positive integer variable that specifies the 
04506   //       stride of the vector.
04507   //
04508   //   Subprograms called
04509   //
04510   //     FORTRAN-supplied ... abs, max, sqrt
04511   //
04512   //   MINPACK-2 Project. February 1991.
04513   //   Argonne National Laboratory.
04514   //   Brett M. Averick.
04515   //
04516   //   **********
04517     //function
04518   double dnrm2(int& n,double* const & x, int& incx)
04519   {
04520     //int i;
04521     double scale = 0.0;
04522     double ddnrm2 = 0.0;
04523 
04524     for (int i = 1; i <= n; i+=incx)
04525       scale = max(scale, fabs(x[i]));
04526 
04527     if (scale == 0.0) return ddnrm2;
04528 
04529     for (int i = 1; i <= n; i+=incx)  
04530       ddnrm2 += (x[i]/scale)*(x[i]/scale);
04531 
04532     ddnrm2 = scale*sqrt(ddnrm2);
04533     return ddnrm2;
04534   }
04535 
04536 
04537   //   **********
04538   //
04539   //   Subroutine dpeps
04540   //
04541   //   This subroutine computes the machine precision parameter
04542   //   dpmeps as the smallest floating point number such that
04543   //   1 + dpmeps differs from 1.
04544   //
04545   //   This subroutine is based on the subroutine machar described in
04546   //
04547   //   W. J. Cody,
04548   //   MACHAR: A subroutine to dynamically determine machine parameters,
04549   //   ACM Transactions on Mathematical Software, 14, 1988, pages 303-311.
04550   //
04551   //   The subroutine statement is:
04552   //
04553   //     subroutine dpeps(dpmeps)
04554   //
04555   //   where
04556   //
04557   //     dpmeps is a double precision variable.
04558   //       On entry dpmeps need not be specified.
04559   //       On exit dpmeps is the machine precision.
04560   //
04561   //   MINPACK-2 Project. February 1991.
04562   //   Argonne National Laboratory and University of Minnesota.
04563   //   Brett M. Averick.
04564   //
04565   //   *******
04566     //function
04567   double dpmeps()
04568   {
04569     //int i ;
04570     long int ibeta,irnd,it,itemp,negep;
04571     long double a,b,beta,betain,betah,temp,tempa,temp1,
04572            zero=0.0,one=1.0,two=2.0;
04573     long double ddpmeps;
04574  
04575     //determine ibeta, beta ala malcolm.
04576 
04577     a = one;
04578     b = one;
04579   goto10:
04580     a = a + a;
04581     temp = a + one;
04582     temp1 = temp - a;
04583     if (temp1 - one == zero) goto goto10;
04584    
04585   goto20:
04586     b = b + b;
04587     temp = a + b;
04588     itemp = int(temp - a);
04589     if (itemp == 0) goto goto20;
04590     ibeta = itemp;
04591     beta = double(ibeta);
04592 
04593     //determine it, irnd.
04594 
04595     it = 0;
04596     b = one;
04597   goto30:
04598     it += 1;
04599     b *= beta;
04600     temp = b + one;
04601     temp1 = temp - b;
04602     if (temp1 - one == zero) goto goto30;
04603     irnd = 0;
04604     betah = beta/two;
04605     temp = a + betah;
04606     if (temp - a != zero) irnd = 1;
04607     tempa = a + beta;
04608     temp = tempa + betah;
04609     if ((irnd == 0) && (temp - tempa != zero)) irnd = 2;
04610 
04611     //determine ddpmeps.
04612 
04613     negep = it + 3;
04614     betain = one/beta;
04615     a = one;
04616     for (int i = 1; i <= negep; i++)
04617       a *= betain;
04618 
04619   goto50:
04620     temp = one + a;
04621     if (temp - one != zero) goto goto60;
04622     a *= beta;
04623     goto goto50;
04624 
04625   goto60:
04626     ddpmeps = a;
04627     if ((ibeta == 2) || (irnd == 0)) goto goto70;
04628     a = (a*(one + a))/two;
04629     temp = one + a;
04630     if (temp - one != zero) ddpmeps = a;
04631 
04632   goto70:
04633     return ddpmeps;
04634   }//dpmeps()
04635 
04636 
04637   //   constant times a vector plus a vector.
04638   //   uses unrolled loops for increments equal to one.
04639   //   jack dongarra, linpack, 3/11/78.
04640     //function
04641   void daxpy(const int& n, const double& da, const double* const & dx, 
04642              const int& incx, double* const & dy, const int& incy)
04643   {
04644     //int i;
04645     int ix,iy,m,mp1;
04646     if (n <= 0) return;
04647     if (da == 0.0) return;
04648     if(incx==1 && incy==1) goto goto20;
04649 
04650     //code for unequal increments or equal increments
04651     //not equal to 1
04652 
04653     ix = 1;
04654     iy = 1;
04655     if(incx < 0) ix = (-n+1)*incx + 1;
04656     if(incy < 0) iy = (-n+1)*incy + 1;
04657 
04658     for (int i = 1; i <= n; i++)
04659     {    
04660       dy[iy] += da*dx[ix];
04661       ix += incx;
04662       iy += incy;
04663     }
04664     return;
04665 
04666     //code for both increments equal to 1
04667     //clean-up loop
04668 
04669   goto20:
04670     m = n%4;
04671     if (m == 0) goto goto40;
04672     
04673     for (int i = 1; i <= m; i++)
04674       dy[i] += da*dx[i];
04675 
04676     if (n < 4) return;
04677 
04678   goto40:
04679     mp1 = m + 1;
04680 
04681     for (int i = mp1; i <= n; i+=4)
04682     {
04683       dy[i] += da*dx[i];
04684       dy[i + 1] += da*dx[i + 1];
04685       dy[i + 2] += da*dx[i + 2];
04686       dy[i + 3] += da*dx[i + 3];
04687     }
04688   }//daxpy()
04689 
04690 
04691   //   copies a vector, x, to a vector, y.
04692   //   uses unrolled loops for increments equal to one.
04693   //   jack dongarra, linpack, 3/11/78.
04694     //function  
04695   void dcopy(const int& n, const double* const & dx, const int& incx, 
04696              double* const & dy,const int& incy)
04697   {
04698     //int i;
04699     int ix,iy,m,mp1;
04700 
04701     if (n <= 0) return;
04702     if(incx==1 && incy==1) goto goto20;
04703 
04704     //code for unequal increments or equal increments
04705     //not equal to 1
04706     
04707     ix = 1;
04708     iy = 1;
04709     if (incx < 0) ix = (-n+1)*incx + 1;
04710     if (incy < 0) iy = (-n+1)*incy + 1;
04711     for (int i = 1; i <= n; i++)
04712     {
04713       dy[iy] = dx[ix];
04714       ix += incx;
04715       iy += incy;
04716     }
04717     return;
04718 
04719     //code for both increments equal to 1
04720 
04721     //clean-up loop
04722 
04723   goto20:
04724     m = n%7;
04725     if (m == 0) goto goto40;
04726     for (int i = 1; i <= m; i++)
04727       dy[i] = dx[i];
04728 
04729     if (n < 7) return;
04730 
04731   goto40:
04732     mp1 = m + 1;
04733     for (int i = mp1; i <= n; i+=7)
04734     {
04735       dy[i] = dx[i];
04736       dy[i + 1] = dx[i + 1];
04737       dy[i + 2] = dx[i + 2];
04738       dy[i + 3] = dx[i + 3];
04739       dy[i + 4] = dx[i + 4];
04740       dy[i + 5] = dx[i + 5];
04741       dy[i + 6] = dx[i + 6];
04742     }      
04743   }//dcopy()
04744 
04745 
04746   //forms the dot product of two vectors.
04747   //uses unrolled loops for increments equal to one.
04748   //jack dongarra, linpack, 3/11/78.
04749     //function
04750   double ddot(const int& n, const double* const & dx, const int& incx, 
04751               const double* const & dy, const int& incy)
04752   {
04753     double dtemp;
04754     //int i;
04755     int ix,iy,m,mp1;
04756 
04757     double dddot = 0.0;
04758     dtemp = 0.0;
04759     if (n <= 0) return dddot;
04760     if (incx==1 && incy==1) goto goto20;
04761 
04762     //code for unequal increments or equal increments
04763     //not equal to 1
04764     
04765     ix = 1;
04766     iy = 1;
04767     if (incx < 0) ix = (-n+1)*incx + 1;
04768     if (incy < 0) iy = (-n+1)*incy + 1;
04769 
04770     for (int i = 1; i <= n; i++)
04771     {
04772       dtemp += dx[ix]*dy[iy];
04773       ix += incx;
04774       iy += incy;
04775     }
04776     dddot = dtemp;
04777     return dddot;
04778 
04779     //code for both increments equal to 1
04780 
04781     //clean-up loop
04782 
04783   goto20:
04784     m = n%5;
04785     if (m == 0) goto goto40;
04786 
04787     for (int i = 1; i <= m; i++)
04788       dtemp += dx[i]*dy[i];
04789 
04790     if( n < 5 ) goto goto60;
04791 
04792   goto40:
04793     mp1 = m + 1;
04794 
04795 
04796     for (int i = mp1; i <= n; i+=5)
04797     {
04798       dtemp += dx[i]*dy[i] + dx[i + 1]*dy[i + 1] +
04799                dx[i + 2]*dy[i + 2] + dx[i + 3]*dy[i + 3] + dx[i + 4]*dy[i + 4];
04800     }
04801 
04802   goto60:
04803     dddot = dtemp;
04804     return dddot;
04805   }//ddot()
04806 
04807 
04808   //   dpofa factors a double precision symmetric positive definite
04809   //   matrix.
04810   //
04811   //   dpofa is usually called by dpoco, but it can be called
04812   //   directly with a saving in time if  rcond  is not needed.
04813   //   (time for dpoco) = (1 + 18/n)*(time for dpofa) .
04814   //
04815   //   on entry
04816   //
04817   //      a       double precision(lda, n)
04818   //              the symmetric matrix to be factored.  only the
04819   //              diagonal and upper triangle are used.
04820   //
04821   //      lda     integer
04822   //              the leading dimension of the array  a .
04823   //
04824   //      n       integer
04825   //              the order of the matrix  a .
04826   //
04827   //   on return
04828   //
04829   //      a       an upper triangular matrix  r  so that  a = trans(r)*r
04830   //              where  trans(r)  is the transpose.
04831   //              the strict lower triangle is unaltered.
04832   //              if  info != 0 , the factorization is not complete.
04833   //
04834   //      info    integer
04835   //              = 0  for normal return.
04836   //              = k  signals an error condition.  the leading minor
04837   //                   of order  k  is not positive definite.
04838   //
04839   //   linpack.  this version dated 08/14/78 .
04840   //   cleve moler, university of new mexico, argonne national lab.
04841   //
04842   //   subroutines and functions
04843   //
04844   //   blas ddot
04845   //   fortran sqrt
04846   //
04847   //   internal variables
04848   //  
04849     //function
04850   void dpofa(double* const & a, const int& lda, const int& n, int& info,
04851              bool smallerMatrix=false)
04852   {
04853     double t;
04854     double s;
04855     //int j,k
04856     int jm1;
04857     int idx;
04858     //begin block with ...exits to 40
04859 
04860     for (int j = 1; j <= n; j++)
04861     {
04862       info = j;
04863       s = 0.0;
04864       jm1 = j - 1;
04865       if (jm1 < 1) goto goto20;
04866       for (int k = 1; k <= jm1; k++)
04867       {
04868         idx = getIdx(k,j,lda);
04869         t = a[idx] - ddot(k-1,&(a[getIdx(1,k,lda)-1]),1,
04870                               &(a[getIdx(1,j,lda)-1]),1);
04871         t = t/a[getIdx(k,k,lda)];
04872         a[idx] = t;
04873         s += t*t;
04874       }
04875 
04876     goto20:
04877       idx = getIdx(j,j,lda);
04878       s = a[idx] - s;
04879 
04880       //......exit
04881       if (s <= 0.0) goto goto40;
04882       a[idx] = sqrt(s);
04883     }
04884     info = 0;
04885   goto40:
04886     t = 0;
04887   }//dpofa()
04888 
04889 
04890   //scales a vector by a constant.
04891   //uses unrolled loops for increment equal to one.
04892   //jack dongarra, linpack, 3/11/78.
04893   //modified 3/93 to return if incx <= 0.
04894     //function    
04895   void dscal(const int& n, const double& da, double* const & dx, 
04896              const int& incx)
04897   {
04898     //int i;
04899     int m,mp1,nincx;
04900 
04901     if (n <= 0 || incx <= 0) return;
04902     if (incx == 1) goto goto20;
04903 
04904     //code for increment not equal to 1
04905 
04906     nincx = n*incx;
04907 
04908     for (int i = 1; i <= nincx; i+=incx)
04909       dx[i] = da*dx[i];
04910     return;
04911 
04912     //code for increment equal to 1
04913 
04914     //clean-up loop
04915 
04916   goto20:
04917     m = n%5;
04918     if (m == 0) goto goto40;
04919 
04920     for (int i = 1; i <= m; i++)
04921       dx[i] = da*dx[i];
04922 
04923     if (n < 5) return;
04924 
04925   goto40:
04926     mp1 = m + 1;
04927     for (int i = mp1; i <= n; i+=5)
04928     {
04929       dx[i] = da*dx[i];
04930       dx[i + 1] = da*dx[i + 1];
04931       dx[i + 2] = da*dx[i + 2];
04932       dx[i + 3] = da*dx[i + 3];
04933       dx[i + 4] = da*dx[i + 4];
04934     }
04935   }//dscal()
04936 
04937   //
04938   //
04939   //   dtrsl solves systems of the form
04940   //
04941   //                 t * x = b
04942   //   or
04943   //                 trans(t) * x = b
04944   //
04945   //   where t is a triangular matrix of order n. here trans(t)
04946   //   denotes the transpose of the matrix t.
04947   //
04948   //   on entry
04949   //
04950   //       t         double precision(ldt,n)
04951   //                 t contains the matrix of the system. the zero
04952   //                 elements of the matrix are not referenced, and
04953   //                 the corresponding elements of the array can be
04954   //                 used to store other information.
04955   //
04956   //       ldt       integer
04957   //                 ldt is the leading dimension of the array t.
04958   //
04959   //       n         integer
04960   //                 n is the order of the system.
04961   //
04962   //       b         double precision(n).
04963   //                 b contains the right hand side of the system.
04964   //
04965   //       job       integer
04966   //                 job specifies what kind of system is to be solved.
04967   //                 if job is
04968   //
04969   //                      00   solve t*x=b, t lower triangular,
04970   //                      01   solve t*x=b, t upper triangular,
04971   //                      10   solve trans(t)*x=b, t lower triangular,
04972   //                      11   solve trans(t)*x=b, t upper triangular.
04973   //
04974   //   on return
04975   //
04976   //       b         b contains the solution, if info == 0.
04977   //                 otherwise b is unaltered.
04978   //
04979   //       info      integer
04980   //                 info contains zero if the system is nonsingular.
04981   //                 otherwise info contains the index of
04982   //                 the first zero diagonal element of t.
04983   //
04984   //   linpack. this version dated 08/14/78 .
04985   //   g. w. stewart, university of maryland, argonne national lab.
04986   //
04987   //   subroutines and functions
04988   //
04989   //   blas daxpy,ddot
04990   //   fortran mod
04991     //function
04992   void dtrsl(double* const & t, const int& ldt, const int& n, 
04993              double* const &b, const int& job, int& info)
04994   {
04995     double temp;
04996     int ccase,j;
04997     //int jj;
04998 
04999     //begin block permitting ...exits to 150
05000     
05001     //check for zero diagonal elements.
05002     
05003     for (info = 1; info <= n; info++)
05004     {
05005       //......exit
05006       if (t[getIdx(info,info,ldt)] == 0.0) goto goto150;
05007     }
05008     info = 0;
05009 
05010     //determine the task and go to it.
05011 
05012     ccase = 1;
05013     if (job%10 != 0) ccase = 2;
05014     if ((job%100)/10 != 0) ccase += 2;
05015     if (ccase==1) goto goto20;
05016     if (ccase==2) goto goto50;
05017     if (ccase==3) goto goto80;
05018     if (ccase==4) goto goto110;
05019 
05020     //solve t*x=b for t lower triangular
05021 
05022   goto20:
05023     b[1] /= t[getIdx(1,1,ldt)];
05024     if (n < 2) goto goto40;
05025     for (int j = 2; j <= n; j++)
05026     {
05027       temp = -b[j-1];
05028       daxpy(n-j+1,temp,&(t[getIdx(j,j-1,ldt)-1]),1,&(b[j-1]),1);
05029       b[j] /= t[getIdx(j,j,ldt)];
05030     }
05031   goto40:
05032     goto goto140;
05033 
05034     //solve t*x=b for t upper triangular.
05035 
05036   goto50:    
05037     b[n] /= t[getIdx(n,n,ldt)];
05038     if (n < 2) goto goto70;
05039     for (int jj = 2; jj <= n; jj++)
05040     {
05041       j = n - jj + 1;
05042       temp = -b[j+1];
05043       daxpy(j,temp,&(t[getIdx(1,j+1,ldt)-1]),1,&(b[1-1]),1);
05044       b[j] /= t[getIdx(j,j,ldt)];
05045     }
05046 
05047   goto70:
05048     goto goto140;
05049 
05050     //solve trans(t)*x=b for t lower triangular.
05051 
05052   goto80:
05053     b[n] /= t[getIdx(n,n,ldt)];
05054     if (n < 2) goto goto100;
05055     for (int jj = 2; jj <= n; jj++)
05056     {
05057       j = n - jj + 1;
05058       b[j] = b[j] - ddot(jj-1,&(t[getIdx(j+1,j,ldt)-1]),1,&(b[j+1-1]),1);
05059       b[j] /= t[getIdx(j,j,ldt)];
05060     }
05061   goto100:
05062     goto goto140;
05063 
05064     //solve trans(t)*x=b for t upper triangular.
05065 
05066   goto110:
05067     b[1] /= t[getIdx(1,1,ldt)];
05068     if (n < 2) goto goto130;
05069     for (int j = 2; j <= n; j++)
05070     {
05071       b[j] = b[j] - ddot(j-1,&(t[getIdx(1,j,ldt)-1]),1,&(b[1-1]),1);
05072       b[j] /= t[getIdx(j,j,ldt)];
05073     }
05074 
05075   goto130:
05076     
05077     if (false);
05078 
05079   goto140:
05080 
05081     if (false);
05082 
05083   goto150:
05084 
05085     if (false);
05086     
05087   }//dtrsl()
05088 
05089  private:
05090   Timer timer_;
05091 
05092 };
05093 
05094 #endif

Generated on Sun Jun 7 11:55:14 2009 for Alchemy by  doxygen 1.5.1