lbfgsp.h

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

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