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

Generated on Tue Jan 16 05:30:03 2007 for Alchemy by  doxygen 1.5.1