00001 /*! \file Uncmin.h 00002 00003 \brief 00004 C++ implementation of UNCMIN routines for unconstrained minimization 00005 00006 This software is available at 00007 http://www.smallwaters.com/software/cpp/uncmin.html 00008 00009 Version 0080309 00010 This release updates original work by Brad Hanson (http://www.b-a-h.com/) in 2001. 00011 00012 The UNCMIN routines are based on Appendix A of: 00013 00014 Dennis, J. E., & Schnabel, R. B. (1996). Numerical methods for 00015 unconstrained optimization and nonlinear equations. Philadelphia: 00016 Society for Industrual and Applied Mathematics. 00017 00018 The original UNCMIN routines in FORTRAN are available from GAMS 00019 (http://gams.nist.gov/) as OPTIF9 and OPTIF0. 00020 00021 FORTRAN UNCMIN routines were translated to java (Uncmin_f77.java) by 00022 Steve Verrill (steve@ws13.fpl.fs.fed.us). 00023 Uncmin_F77.java is available at http://www1.fpl.fs.fed.us/optimization.html 00024 00025 The routines in Uncmin_f77.java were translated to C++ by 00026 Brad Hanson. 00027 00028 (c) 2008, Werner Wothke, maintenance programming and documentation. 00029 00030 00031 Uncmin is a templated class with template parameters: 00032 00033 V - A vector class of double precision numbers. Member functions 00034 that should be defined for class V are: 00035 00036 V& operator=(const V &A); // assignment 00037 00038 V& operator=(const double& scalar); // assign a value to all elements 00039 00040 double& operator()(int i); // FORTRAN style one-offset subscripting 00041 00042 int size(); // returns number of elements in vector 00043 00044 M - A matrix class of double precision numbers. Member functions that 00045 should be defined for class M are: 00046 00047 double operator()(int i, int j); // FORTRAN style one-offset subscripting 00048 00049 int num_rows(); // returns number of rows in matrix 00050 int num_cols(); // returns number of columns in matrix 00051 00052 FUNC - A class defining the function to minimize, its gradient and hessian. 00053 An example of how this class should be defined is: 00054 00055 // V is vector class, M is matrix class 00056 template <class V, class M> 00057 class minclass 00058 { 00059 double f_to_minimize(V &x); 00060 // Returns value of function to minimize 00061 00062 void gradient(V &x, V &g); 00063 // Returns gradient of function in g. This does not have 00064 // to be defined, in which case the gradient is approximated. 00065 // If the gradient is not defined Analytic_Gradient should 00066 // return 0; 00067 00068 void hessian(V &x, M &h); 00069 // Returns hessian of function in h. This does not have 00070 // to be defined, in which case the hessian is approximated. 00071 // If the hessian is not defined Analytic_Hessian should 00072 // return 0; 00073 00074 int HasAnalyticGradient(); 00075 // Returns 1 if gradient is defined, otherwise returns 0 00076 00077 int HasAnalyticHessian(); 00078 // Returns 1 if hessian is defined, otherwise returns 0 00079 00080 int ValidParameters(V &x); 00081 // Returns 1 if f_to_minimize(x) is defined for argument x. 00082 00083 int dim(); 00084 // Returns dimension of problem (number of elements in vector x 00085 // passed to f_to_minimize) 00086 } 00087 00088 An example of how to use Uncmin to minimize a function defined in 00089 a class minclass with vector and matrix classes from the Simple 00090 C++ Numerical Toolkit (http://www.smallwaters.com/software/cpp/scppnt.html): 00091 00092 #include "Uncmin.h" 00093 #include "vec.h" // Simple C++ Numeric Toolkit (SCPPNT) vector class 00094 #include "cmat.h" // Simple C++ Numeric Toolkit (SCPPNT) matrix class 00095 #include <cstdio> 00096 00097 using namespace SCPPNT; 00098 00099 // Dimension of problem (number of parameters) 00100 const int dim = 4; 00101 00102 // Create function object 00103 minclass<Vector<double>, Matrix<double> > test; 00104 00105 // create Uncmin object 00106 Uncmin<Vector<double>, Matrix<double>, minclass> min(&test); 00107 00108 // Starting values 00109 double start_values[4] = {1.0, 1.0, 1.0, 1.0}; // use some appropriate values here 00110 Vector<double> start(start_values, start_values+dim); 00111 00112 // xpls will contain solution, gpls will contain 00113 // gradient at solution after call to min.Minimize 00114 Vector<double> xpls(dim), gpls(dim); 00115 00116 // fpls contains the value of the function at 00117 // the solution given by xpls. 00118 double fpls; 00119 00120 // Minimize function. 00121 // Minimize returns zero if successful (0, 1, 2, 3 00122 // returned by GetMessage), non-zero if not successful. 00123 if (min.Minimize(start, xpls, fpls, gpls)) 00124 { 00125 int msg = min.GetMessage(); // find out what went wrong 00126 std::printf("\nMessage returned from Uncmin: %d\n", msg); 00127 } 00128 00129 The GetMessage member function returns the status of the solution found 00130 by the last call to the Minimize member function. 00131 Possible values returned by GetMessage are: 00132 00133 0 = Optimal solution found, terminated with gradient small 00134 1 = Terminated with gradient small, xpls is probably optimal. 00135 2 = Terminated with stepsize small, xpls is probably optimal. 00136 3 = Lower point cannot be found, xpls is probably optimal. 00137 4 = Iteration limit (default 150) exceeded. 00138 5 = Too many large steps, function may be unbounded. 00139 -1 = Analytic gradient check requested, but no analytic gradient supplied 00140 -2 = Analytic hessian check requested, but no analytic hessian supplied 00141 -3 = Illegal dimension 00142 -4 = Illegal tolerance 00143 -5 = Illegal iteration limit 00144 -6 = Minimization function has no good digits 00145 -7 = Iteration limit exceeded in lnsrch 00146 -20 = Function not defined at starting value 00147 -21 = Check of analytic gradient failed 00148 -22 = Check of analytic hessian failed 00149 00150 00151 The symbol BOOST_NO_STDC_NAMESPACE should be defined if the C++ compiler 00152 does not put the standard C library functions in the std namespace 00153 (this is needed for Visual C++ 6). 00154 00155 The symbol BOOST_NO_LIMITS should be defined if the standard C++ 00156 library header file <limits> is not available. 00157 (this is needed for Visual C++ 6). 00158 00159 00160 Version History 00161 00162 Version 080309 (March 9, 2008) 00163 00164 Edited doxygen-compatible documentation, second pass. Added descriptive comments, 00165 much as possible, incorporated any useful information from the existing FORTRAN 00166 and Java documentation sets and removed these out-dated documentations afterwards. 00167 00168 Version 071226 (December 26, 2007) 00169 00170 Refactored num_cols property to num_columns in UNCMIN::minimize(). 00171 Tagged all public methods and properties with doxygen-compatible comments. 00172 00173 Version 0.001206 (February 10, 2001) 00174 00175 Added BOOST_NO_STDC_NAMESPACE and BOOST_NO_LIMITS symbols which 00176 need to be defined to compile Uncmin.h using Microsoft Visual C++ 6. 00177 00178 */ 00179 00180 #ifndef UNCMIN_H_ 00181 #define UNCMIN_H_ 00182 00183 #include <cstdio> 00184 #include <cmath> 00185 00186 #ifdef BOOST_NO_STDC_NAMESPACE 00187 // If the standard C library functions are not in the std namespace (like Microsoft Visual C++ 6) 00188 namespace std 00189 { using ::sqrt; using ::pow; using ::fabs; using ::log; using ::FILE; using ::fprintf;} 00190 #endif 00191 00192 #ifndef BOOST_NO_LIMITS 00193 // include limits for epsilon function used in SetTolerances. 00194 #include <limits> 00195 #else 00196 // If there is no limits header. 00197 #include <float.h> 00198 #endif 00199 00200 /*! Documentation of member functions is given in their definitions which follow 00201 the Uncmin class definition */ 00202 template<class V, class M, class FUNC> class Uncmin 00203 { 00204 00205 public: 00206 00207 typedef FUNC function_type; //!< Type definition of function object to minimize. 00208 00209 /* Constructor. */ 00210 Uncmin(FUNC *f); 00211 00212 /* Constructor. */ 00213 Uncmin(int d = 1); 00214 00215 /* Destructor */ 00216 ~Uncmin(); 00217 00218 /* Calculate function minimum. */ 00219 int Minimize(V &start, V &xpls, double &fpls, V &gpls, M &hpls); 00220 00221 /* Version of Minimize where hessian matrix is allocated locally rather 00222 than passed as an argument to the function. */ 00223 int Minimize(V &start, V &xpls, double &fpls, V &gpls); 00224 00225 /* Get object containing function to minimize, gradient, and hessian. */ 00226 FUNC *GetFunction(); 00227 00228 /* Set object containing function to minimize, gradient, and hessian. */ 00229 void SetFunction(FUNC *f); 00230 00231 /* Methods to set options. */ 00232 void SetFuncExpensive(int iexp); 00233 00234 /* Set typical magnitude of each argument to function. */ 00235 int SetScaleArg(V typsiz); 00236 00237 /* Set typical magnitude of function near minimum. */ 00238 void SetScaleFunc(double fscale); 00239 00240 /* Set the number of reliable digits returned by f_to_minimize. */ 00241 void SetNumDigits(double ndigit); 00242 00243 /* Set maximum number of iterations. */ 00244 void SetMaxIter(int maxiter); 00245 00246 /* Set step tolerance, gradient tolerance, and machine epsilon. */ 00247 void SetTolerances(double step, double grad, double macheps = -1.0); 00248 00249 /* Set maximum allowable scaled step length at any iteration. */ 00250 void SetMaxStep(double stepmx); 00251 00252 /* Set initial trust region radius. */ 00253 void SetTrustRegionRadius(double dlt); 00254 00255 /* Set flags to check analytic gradient and hessian. */ 00256 void SetChecks(int check_gradient, int check_hessian = 0); 00257 00258 /* Set flags to indicate whether results are printed. */ 00259 void SetPrint(std::FILE *file, int print_results, int print_iterations = 0); 00260 00261 /* Set method to use to solve minimization problem. 00262 1 = line search, 2 = double dogleg, 3 = More-Hebdon. */ 00263 void SetMethod(int method); 00264 00265 /* Return stopping criteria computed at the end of the last call to Minimize. */ 00266 void GetStoppingCriteria(double &gradtol, double &steptol, int &iterations); 00267 00268 /*! Returns message generated in the last call to Minimize. */ 00269 int GetMessage(); 00270 00271 private: 00272 00273 FUNC *minclass; //!< Class that contains function to miminize, gradient, and hessian. 00274 00275 00276 int algorithm; //!< Indicates algorithm to use to solve minimization problem: 1 = line search, 2 = double dogleg, 3 = More-Hebdon. 00277 00278 std::FILE *mfile; //!< File to print messages to. 00279 00280 int n; //!< Dimension of problem, provided in minclass by minclass->dim(). 00281 00282 double epsm; //!< Machine epsilon. 00283 00284 00285 double mLastGradCrit; //!< Stopping criterion for gradient. 00286 00287 00288 double mLastStepCrit; //!< Stopping criterion for argument change. 00289 00290 00291 int mLastIteration; //!< Stopping criterion by number of iterations. 00292 00293 00294 int mLastMessage; //!< Message generated by last call to Minimize. 00295 00296 /* Options */ 00297 00298 int iexp; //!< Flag indicating computational complexity. Set iexp = 1, for expensive calculations, iexp = 0 otherwise. If iexp = 1, the Hessian will be evaluated by secant (BFGS) update. 00299 00300 /* These two flags are set from minclass using minclass.Analytic_Gradient() and 00301 minclass.Analytic_Methods() */ 00302 int iagflg; //!< Flag: iagflag = 0 if an analytic gradient is not supplied, provided by minclass. 00303 int iahflg; //!< Flag: iahflag = 0 if an analytic Hessian is not supplied, provided by minclass. 00304 00305 int fCheckGradient; //!< fCheckGradient = 0 if analytic gradient is not checked. 00306 00307 int fCheckHessian; //!< fCheckHessian = 0 if analytic hessian is not checked. 00308 00309 int fPrintResults; //!< fPrintResults = 0 if results are not printed to mfile. 00310 00311 int fPrintIterationResults; //!< fPrintIterationResults = 0 if results of each iteration are not printed to mfile. 00312 00313 /* Tolerances */ 00314 00315 V typsiz; //!< Typical size of of each argument of function to minimize. 00316 00317 double fscale; //!< Estimate of scale of objective function. 00318 00319 int ndigit; //!< Number of good digits in the minimization function. Special case, set ndigit = -1, for function providing within 1 or 2 of full number of significant digits. 00320 00321 int itnlim; //!< Maximum number of allowable iterations. 00322 00323 double mdlt; //!< Trust region radius. Special case, mdlt = -1, uses length of initial scaled gradient instead. 00324 00325 double gradtl; //!< Tolerance at which the gradient is considered close enough to zero to terminate the algorithm. 00326 00327 double steptl; //!< Tolerance at which scaled distance between two successive iterates is considered close enough to zero to terminate algorithm. 00328 00329 double stepmx; //!< Maximum allowable step size. 00330 00331 /* Private functions used in minimization. */ 00332 00333 void dfault(); 00334 00335 int optchk(V &x, V &sx, int &msg, int &method); 00336 00337 void fstofd(V &xpls, double fpls, V &g, V &sx, double rnoise); 00338 00339 void fstofd(V &xpls, V &fpls, M &a, V &sx, double rnoise, V &fhat); 00340 00341 int grdchk(V &x, double f, V &g, V &typsiz, V &sx, double fscale, double rnf, double analtl, 00342 V &gest, int &msg); 00343 00344 void optstp(V &xpls, double fpls, V &gpls, V &x, int &itncnt, int &icscmx, int &itrmcd, V &sx, 00345 double &fscale, int &itnlim, int &iretcd, bool &mxtake, int &msg); 00346 00347 void hsnint(M &a, V &sx, int method); 00348 00349 void sndofd(V &xpls, double &fpls, M &a, V &sx, double &rnoise, V &stepsz, V &anbr); 00350 00351 int heschk(V &x, double &f, V &g, M &a, V &typsiz, V &sx, double rnf, double analtl, int &iagflg, 00352 V &udiag, V &wrk1, V &wrk2, int &msg); 00353 00354 void result(V &x, double &f, V &g, M &a, V &p, int &itncnt, int iflg); 00355 00356 void bakslv(M &a, V &x, V &b); 00357 00358 void chlhsn(M &a, V &sx, V &udiag); 00359 00360 void choldc(M &a, double diagmx, double tol, double &addmax); 00361 00362 void dogdrv(V &x, double &f, V &g, M &a, V &p, V &xpls, double &fpls, V &sx, double &dlt, 00363 int &iretcd, bool &mxtake, V &sc, V &wrk1, V &wrk2, V &wrk3); 00364 00365 void dogstp(V &g, M &a, V &p, V &sx, double rnwtln, double &dlt, bool &nwtake, bool &fstdog, 00366 V &ssd, V &v, double &cln, double &eta, V &sc); 00367 00368 void forslv(M &a, V &x, V &b); 00369 00370 void fstocd(V &x, V &sx, double rnoise, V &g); 00371 00372 void hookdr(V &x, double &f, V &g, M &a, V &udiag, V &p, V &xpls, double &fpls, V &sx, 00373 double &dlt, int &iretcd, bool &mxtake, double &amu, double &dltp, double &phi, 00374 double &phip0, V &sc, V &xplsp, V &wrk0, int &itncnt); 00375 00376 void hookst(V &g, M &a, V &udiag, V &p, V &sx, double rnwtln, double &dlt, double &amu, 00377 double &dltp, double &phi, double &phip0, bool &fstime, V &sc, bool &nwtake, V &wrk0); 00378 00379 void lltslv(M &a, V &x, V &b); 00380 00381 void lnsrch(V &x, double &f, V &g, V &p, V &xpls, double &fpls, bool &mxtake, int &iretcd, V &sx); 00382 00383 void mvmltl(M &a, V &x, V &y); 00384 00385 void mvmlts(M &a, V &x, V &y); 00386 00387 void mvmltu(M &a, V &x, V &y); 00388 00389 void qraux1(M &r, int i); 00390 00391 void qraux2(M &r, int i, double a, double b); 00392 00393 void qrupdt(M &a, V &u, V &v); 00394 00395 void secfac(V &x, V &g, M &a, V &xpls, V &gpls, int &itncnt, double rnf, int &iagflg, 00396 bool &noupdt, V &s, V &y, V &u, V &w); 00397 00398 void secunf(V &x, V &g, M &a, V &udiag, V &xpls, V &gpls, int &itncnt, double rnf, int &iagflg, 00399 bool &noupdt, V &s, V &y, V &t); 00400 00401 void tregup(V &x, double &f, V &g, M &a, V &sc, V &sx, bool &nwtake, double &dlt, int &iretcd, 00402 V &xplsp, double &fplsp, V &xpls, double &fpls, bool &mxtake, int method, V &udiag); 00403 00404 double ddot(V &x, V &y); 00405 00406 double dnrm2(V &x); 00407 00408 double max(double a, double b); 00409 00410 double min(double a, double b); 00411 00412 }; 00413 00414 /*! 00415 \brief 00416 Constructor that sets dimension and function to minimize. 00417 00418 The minclass function object must define: 00419 00420 1. a method, f_to_minimize, to minimize. f_to_minimize must have the form 00421 public static double f_to_minimize(double x[]) 00422 where x is the vector of arguments to the function and the return value is the 00423 value of the function evaluated at x. 00424 00425 2. a method, gradient, that has the form 00426 public static void gradient(double x[], double g[]) 00427 where g is the gradient of f evaluated at x. This method will have an empty body if 00428 the user does not wish to provide an analytic estimate of the gradient. 00429 00430 3. a method, hessian, that has the form 00431 public static void hessian(double x[],double h[][]) 00432 where h is the Hessian of f evaluated at x. This method will have an empty body if the 00433 user does not wish to provide an analytic estimate of the Hessian. If the user wants 00434 Uncmin++ to check the Hessian, then the hessian method should only fill the lower 00435 triangle (and diagonal)of h. 00436 00437 Minimization parameters are set at default values. 00438 00439 \section template_args Template Parameters 00440 00441 \param M SCPPNT Matrix type. 00442 \param V SCPPNT Vector type. 00443 \param FUNC Type of function to minimize. 00444 00445 \section function_args Function Parameters 00446 00447 \param[in] *f Pointer to function object f. 00448 */ 00449 template<class V, class M, class FUNC> Uncmin<V, M, FUNC>::Uncmin(FUNC *f) : 00450 minclass(f) 00451 { 00452 if (minclass) 00453 n = minclass->dim(); 00454 else 00455 n = 0; 00456 00457 mfile = 0; 00458 00459 mLastGradCrit = 0.0; 00460 mLastStepCrit = 0.0; 00461 mLastIteration = 0; 00462 mLastMessage = 0; 00463 00464 /* Set default parameter values */ 00465 dfault(); 00466 } 00467 00468 /*! 00469 \brief 00470 Constructor that sets dimension, but not function to minimize. 00471 00472 Note: Function to minimize must be set by calling SetFunction. 00473 Minimization parameters are set to default values. 00474 00475 \section template_args Template Parameters 00476 00477 \param M SCPPNT Matrix type. 00478 \param V SCPPNT Vector type. 00479 \param FUNC Type of function to minimize. 00480 00481 \section function_args Function Parameters 00482 00483 \param[in] d Dimension d (number of function arguments). 00484 */ 00485 template<class V, class M, class FUNC> Uncmin<V, M, FUNC>::Uncmin(int d) : 00486 minclass(0), typsiz(d) 00487 { 00488 00489 n = d; 00490 00491 mfile = 0; 00492 00493 mLastGradCrit = 0.0; 00494 mLastStepCrit = 0.0; 00495 mLastIteration = 0; 00496 mLastMessage = 0; 00497 00498 /* Set default parameter values */ 00499 dfault(); 00500 00501 } 00502 00503 /*! 00504 \brief Destructor of uncmin. 00505 */ 00506 template<class V, class M, class FUNC> Uncmin<V, M, FUNC>::~Uncmin() 00507 { 00508 00509 } 00510 00511 /*! 00512 \brief 00513 Assigns flag indicating whether function is expensive to evaluate. 00514 00515 Set iexp =1 if function is expensive to evaluate, = 0 otherwise. 00516 If iexp = 1, then the Hessian will be evaluated by secant (BFGS) update 00517 rather than analytically or by finite differences. 00518 00519 Default value is 0 if this function is not called. 00520 00521 \section template_args Template Parameters 00522 00523 \param M SCPPNT Matrix type. 00524 \param V SCPPNT Vector type. 00525 \param FUNC Type of function to minimize. 00526 00527 \section function_args Function Parameters 00528 00529 \param[in] iexp Set iexp =1 if function is expensive to evaluate, iexp = 0 otherwise. 00530 */ 00531 template<class V, class M, class FUNC> void Uncmin<V, M, FUNC>::SetFuncExpensive(int iexp) 00532 { 00533 this->iexp = iexp; 00534 } 00535 00536 /*! 00537 \brief 00538 Assigns typical magnitude of each argument to function. 00539 00540 Returns zero if dimension matches, otherwise returns 1. 00541 00542 The default is to set all elements of typsiz to 1 if this function is not called. 00543 00544 \section template_args Template Parameters 00545 00546 \param M SCPPNT Matrix type. 00547 \param V SCPPNT Vector type. 00548 \param FUNC Type of function to minimize. 00549 00550 \section function_args Function Parameters 00551 00552 \param[in] typsiz Vector describing the magnitude of all function arguments. 00553 */ 00554 template<class V, class M, class FUNC> int Uncmin<V, M, FUNC>::SetScaleArg(V typsiz) 00555 { 00556 if (typsiz.size() != n) 00557 return 1; 00558 00559 this->typsiz = typsiz; 00560 00561 return 0; 00562 } 00563 00564 /*! 00565 \brief 00566 Assigns typical magnitude of function near minimum. 00567 00568 \section template_args Template Parameters 00569 00570 \param M SCPPNT Matrix type. 00571 \param V SCPPNT Vector type. 00572 \param FUNC Type of function to minimize. 00573 00574 \section function_args Function Parameters 00575 00576 \param[in] fscale Magnitude of function values near minimum. 00577 A default value of 1 is used for fscale if this 00578 function is not called. 00579 */ 00580 template<class V, class M, class FUNC> void Uncmin<V, M, FUNC>::SetScaleFunc(double fscale) 00581 { 00582 this->fscale = fscale; 00583 } 00584 00585 /*! 00586 \brief 00587 Assigns the number of reliable digits returned by f_to_minimize. 00588 00589 If the argument to the function is -1 this 00590 means that f_to_minimize is expected to 00591 provide within one or two of the full number of 00592 significant digits available. 00593 00594 The default value of -1 is used for ndigit when 00595 this function is not called. 00596 00597 \section template_args Template Parameters 00598 00599 \param M SCPPNT Matrix type. 00600 \param V SCPPNT Vector type. 00601 \param FUNC Type of function to minimize. 00602 00603 \section function_args Function Parameters 00604 00605 \param[in] ndigit Number of digits precision required for the solution. 00606 */ 00607 template<class V, class M, class FUNC> void Uncmin<V, M, FUNC>::SetNumDigits(double ndigit) 00608 { 00609 this->ndigit = ndigit; 00610 } 00611 00612 /*! 00613 \brief 00614 Assigns the maximum number of iterations. 00615 00616 The default value of 150 is used if this function is not called. 00617 00618 \section template_args Template Parameters 00619 00620 \param M SCPPNT Matrix type. 00621 \param V SCPPNT Vector type. 00622 \param FUNC Type of function to minimize. 00623 00624 \section function_args Function Parameters 00625 00626 \param[in] maxiter Maximum number of iterations. 00627 */ 00628 template<class V, class M, class FUNC> void Uncmin<V, M, FUNC>::SetMaxIter(int maxiter) 00629 { 00630 this->itnlim = maxiter; 00631 } 00632 00633 /*! 00634 \brief 00635 Assigns step tolerance, gradient tolerance, and the machine epsilon. 00636 00637 Note: For any of these values <= zero, default values are used. 00638 00639 \section template_args Template Parameters 00640 00641 \param M SCPPNT Matrix type. 00642 \param V SCPPNT Vector type. 00643 \param FUNC Type of function to minimize. 00644 00645 \section function_args Function Parameters 00646 00647 \param[in] step Tolerance at which scaled distance between two successive iterates 00648 is considered close enough to zero to terminate algorithm. If the value of 00649 step is <= zero a default value is used. 00650 \param[in] grad Tolerance at which gradient is considered close enough 00651 to zero to terminate algorithm. If the value of 00652 grad is <= zero a default value is used. 00653 \param[in] macheps Largest relative spacing. Machine epsilon == 2**(-T+1) where 00654 (1 + 2**-T) == 1. This argument has a default value of -1 if not included 00655 in function call. 00656 */ 00657 template<class V, class M, class FUNC> void Uncmin<V, M, FUNC>::SetTolerances(double step, 00658 double grad, double macheps) 00659 { 00660 if (macheps <= 0.0) // use default value 00661 { 00662 00663 #ifdef BOOST_NO_LIMITS 00664 epsm = DBL_EPSILON; // from float.h 00665 #else 00666 // use epsilon from numeric_limits in standard C++ library 00667 epsm = std::numeric_limits<double>::epsilon(); 00668 #endif 00669 00670 } 00671 else 00672 { 00673 epsm = macheps; 00674 } 00675 00676 if (grad <= 0.0) 00677 { 00678 gradtl = std::pow(epsm, 1.0/3.0); // default value 00679 } 00680 else 00681 { 00682 gradtl = grad; 00683 } 00684 00685 if (step <= 0.0) 00686 { 00687 steptl = std::sqrt(epsm); // default value 00688 } 00689 else 00690 { 00691 steptl = step; 00692 } 00693 00694 } 00695 00696 /*! 00697 \brief 00698 Assigns maximum allowable scaled step length at any iteration. 00699 00700 The maximum step length is used to prevent steps that would cause the 00701 optimization algorithm to overflow or leave the domain of iterest, 00702 as well as to detect divergence. It should be chosen small enough 00703 to prevent the first two of these occurrences, but larger 00704 than any anticipated reasonable step size. The algorithm will 00705 halt if it takes steps larger than the maximum allowable step 00706 length on 5 consecutive iterations. 00707 00708 If the argument to the function is <= 0 then a default value of 00709 stepmx will be computed in optchk. 00710 00711 A default value of 0 is used for stepmx when this function is 00712 not called. 00713 00714 \section template_args Template Parameters 00715 00716 \param M SCPPNT Matrix type. 00717 \param V SCPPNT Vector type. 00718 \param FUNC Type of function to minimize. 00719 00720 \section function_args Function Parameters 00721 00722 \param[in] stepmx Maximum (scaled) step size. 00723 */ 00724 template<class V, class M, class FUNC> void Uncmin<V, M, FUNC>::SetMaxStep(double stepmx) 00725 { 00726 this->stepmx = stepmx; 00727 } 00728 00729 /*! 00730 \brief 00731 Assigns initial trust region radius. 00732 00733 Used when method = 2 or 3, ignored when method = 1. 00734 The value should be what the user considers a reasonable 00735 scaled step length for the first iteration, and should be 00736 less than the maximum step length. 00737 00738 If dlt = -1, then the length of the initial scaled gradient is used instead. 00739 00740 A default value of -1 is used if this function is not called. 00741 00742 \section template_args Template Parameters 00743 00744 \param M SCPPNT Matrix type. 00745 \param V SCPPNT Vector type. 00746 \param FUNC Type of function to minimize. 00747 00748 \section function_args Function Parameters 00749 00750 \param[in] dlt Maximum (scaled) step size of first iteration. 00751 */ 00752 template<class V, class M, class FUNC> void Uncmin<V, M, FUNC>::SetTrustRegionRadius(double dlt) 00753 { 00754 this->mdlt = dlt; 00755 } 00756 00757 /*! 00758 \brief 00759 Returns pointer to object containing function to minimize, gradient, and hessian. 00760 00761 \section template_args Template Parameters 00762 00763 \param M SCPPNT Matrix type. 00764 \param V SCPPNT Vector type. 00765 \param FUNC Type of function to minimize. 00766 */ 00767 template<class V, class M, class FUNC> FUNC * Uncmin<V, M, FUNC>::GetFunction() 00768 { 00769 return minclass; 00770 } 00771 00772 00773 /*! 00774 \brief 00775 Assigns pointer to object containing function to minimize, gradient, and hessian. 00776 00777 \section template_args Template Parameters 00778 00779 \param M SCPPNT Matrix type. 00780 \param V SCPPNT Vector type. 00781 \param FUNC Type of function to minimize. 00782 00783 \section function_args Function Parameters 00784 00785 \param[in] *f Pointer to function object f. 00786 */ 00787 template<class V, class M, class FUNC> void Uncmin<V, M, FUNC>::SetFunction(FUNC *f) 00788 { 00789 minclass = f; 00790 00791 /* If dimension does not match change n and re-intialize typsiz */ 00792 if (n != f->dim()) 00793 { 00794 n = f->dim(); 00795 V defaultTypSiz(n, 1.0); 00796 typsiz = defaultTypSiz; 00797 } 00798 } 00799 00800 /*! 00801 \brief 00802 Assigns flags to check analytic gradient and hessian. 00803 00804 The default is to not check the gradient and hessian, if this function is not called 00805 (fCheckGradient = 0 and fCheckHessian = 0). 00806 00807 Note that check_hessian can be left off function call in which case default value of 00808 0 is used. 00809 00810 \section template_args Template Parameters 00811 00812 \param M SCPPNT Matrix type. 00813 \param V SCPPNT Vector type. 00814 \param FUNC Type of function to minimize. 00815 00816 \section function_args Function Parameters 00817 00818 \param[in] check_gradient Flag to check analytic gradient of function: 1 = yes, 0 = no. 00819 \param[in] check_hessian Flag to check analytic hessian of function: 1 = yes, 0 = no. 00820 */ 00821 template<class V, class M, class FUNC> void Uncmin<V, M, FUNC>::SetChecks(int check_gradient, 00822 int check_hessian) 00823 { 00824 fCheckGradient = check_gradient; 00825 fCheckHessian = check_hessian; 00826 } 00827 00828 /*! 00829 \brief 00830 Assigns flags to indicate whether results are printed and specify which file is 00831 receive the print output. 00832 00833 Printing is done to open file indicated by first argument. 00834 00835 The default action is not to print any output. 00836 00837 \section template_args Template Parameters 00838 00839 \param M SCPPNT Matrix type. 00840 \param V SCPPNT Vector type. 00841 \param FUNC Type of function to minimize. 00842 \param FILE Type of file for writing print output to. 00843 00844 \section function_args Function Parameters 00845 00846 \param[in] *file Pointer to the open file that will receive the printed results. 00847 \param[in] print_results Flag (if non-zero) to print standard results. 00848 \param[in] print_iterations Flag (if non-zero) to print intermediate results at each 00849 iteration (this argument can be left off function call in which case the 00850 default value of 0 is used). 00851 */ 00852 template<class V, class M, class FUNC> void Uncmin<V, M, FUNC>::SetPrint(std::FILE *file, 00853 int print_results, int print_iterations) 00854 { 00855 00856 mfile = file; 00857 00858 if (!file) 00859 { 00860 fPrintResults = 0; 00861 fPrintIterationResults = 0; 00862 } 00863 else 00864 { 00865 fPrintResults = print_results; 00866 fPrintIterationResults = print_iterations; 00867 } 00868 00869 } 00870 00871 /*! 00872 \brief 00873 Assigns method to use to solve minimization problem. 00874 00875 A default value is 1 (line search) if SetMethod is not called. 00876 00877 \section template_args Template Parameters 00878 00879 \param M SCPPNT Matrix type. 00880 \param V SCPPNT Vector type. 00881 \param FUNC Type of function to minimize. 00882 00883 \section function_args Function Parameters 00884 00885 \param[in] method Method indicator: 1 = line search, 2 = double dogleg, 3 = More-Hebdon. 00886 */ 00887 template<class V, class M, class FUNC> void Uncmin<V, M, FUNC>::SetMethod(int method) 00888 { 00889 if (method == 2 || method == 3) 00890 algorithm = method; 00891 else 00892 algorithm = 1; // use default value of 1 for any values of argument other than 2 or 3 00893 } 00894 00895 /*! 00896 \brief 00897 Returns stopping criteria computed at the end of the last call to Minimize. 00898 00899 \section template_args Template Parameters 00900 00901 \param M SCPPNT Matrix type. 00902 \param V SCPPNT Vector type. 00903 \param FUNC Type of function to minimize. 00904 00905 \section function_args Function Parameters 00906 00907 \param[out] &gradtol Address of gradient tolerance, i.e., how close the gradient is to zero. 00908 \param[out] &steptol Address of maximum scaled difference between function parameters in 00909 consecutive iterations. 00910 \param[out] &iterations Address of number of iterations used. 00911 */ 00912 template<class V, class M, class FUNC> void Uncmin<V, M, FUNC>::GetStoppingCriteria( 00913 double &gradtol, double &steptol, int &iterations) 00914 { 00915 gradtol = mLastGradCrit; 00916 steptol = mLastStepCrit; 00917 iterations = mLastIteration; 00918 } 00919 00920 /*! 00921 \brief 00922 Returns message index generated in the last call to Minimize. 00923 00924 Possible values of message are: 00925 00926 0 = Optimal solution found, terminated with gradient small. 00927 1 = Terminated with gradient small, xpls is probably optimal. 00928 2 = Terminated with stepsize small, xpls is probably optimal. 00929 3 = Lower point cannot be found, xpls is probably optimal. 00930 4 = Iteration limit (default 150) exceeded. 00931 5 = Too many large steps, function may be unbounded. 00932 -1 = Analytic gradient check requested, but no analytic gradient supplied 00933 -2 = Analytic hessian check requested, but no analytic hessian supplied 00934 -3 = Illegal dimension 00935 -4 = Illegal tolerance 00936 -5 = Illegal iteration limit 00937 -6 = Minimization function has no good digits 00938 -7 = Iteration limit exceeded in lnsrch 00939 -20 = Function not defined at starting value 00940 -21 = Check of analytic gradient failed 00941 -22 = Check of analytic hessian failed 00942 00943 \section template_args Template Parameters 00944 00945 \param M SCPPNT Matrix type. 00946 \param V SCPPNT Vector type. 00947 \param FUNC Type of function to minimize. 00948 */ 00949 template<class V, class M, class FUNC> inline int Uncmin<V, M, FUNC>::GetMessage() 00950 { 00951 return mLastMessage; 00952 } 00953 00954 /*! 00955 \brief 00956 Method to compute values that minimize the function. 00957 00958 Translated by Brad Hanson from optdrv_f77 by Steve Verrill. 00959 00960 Returns 0 if mLastMessage is 0, 1, 2, or 3 (indicating optimal solution probably found), 00961 otherwise returns non-zero. 00962 00963 On exit data member mLastMessage is set to indicate status of solution. 00964 00965 Possible values of mLastMessage are: 00966 0 = Optimal solution found, terminated with gradient small. 00967 1 = Terminated with gradient small, xpls is probably optimal. 00968 2 = Terminated with stepsize small, xpls is probably optimal. 00969 3 = Lower point cannot be found, xpls is probably optimal. 00970 4 = Iteration limit (default 150) exceeded. 00971 5 = Too many large steps, function may be unbounded. 00972 -1 = Analytic gradient check requested, but no analytic gradient supplied. 00973 -2 = Analytic hessian check requested, but no analytic hessian supplied. 00974 -3 = Illegal dimension. 00975 -4 = Illegal tolerance. 00976 -5 = Illegal iteration limit. 00977 -6 = Minimization function has no good digits. 00978 -7 = Iteration limit exceeded in lnsrch. 00979 -20 = Function not defined at starting value. 00980 -21 = Check of analytic gradient failed. 00981 -22 = Check of analytic hessian failed. 00982 00983 \section template_args Template Parameters 00984 00985 \param M SCPPNT Matrix type. 00986 \param V SCPPNT Vector type. 00987 \param FUNC Type of function to minimize. 00988 00989 \section function_args Function Parameters 00990 00991 \param[in] &start Address of vector containing initial estimate of location of minimum. 00992 \param[out] &xpls Address of vector containing local minimum (size must be n on input). 00993 \param[out] &fpls Address of function value at local minimum. 00994 \param[out] &gpls Address of vector containing gradient at local minimum (size must be 00995 n on input). 00996 \param[out] &hpls Address of matrix containing hessian at local minimum (size must be 00997 n X n on input). Only the lower half should be input; the upper off-diagonal entries 00998 can be set to zero. On return, the lower half of hpls contains the Cholesky factor 00999 of the Hessian, evaluated at the solution (i.e., H = LL'). 01000 */ 01001 template<class V, class M, class FUNC> int Uncmin<V, M, FUNC>::Minimize(V &start, V &xpls, 01002 double &fpls, V &gpls, M &hpls) 01003 { 01004 01005 bool noupdt; 01006 bool mxtake; 01007 01008 int i, j, num5, remain, ilow, ihigh; 01009 int icscmx; 01010 int iretcd; 01011 int itncnt; 01012 01013 /* 01014 Return code. 01015 itrmcd = 0: Optimal solution found 01016 itrmcd = 1: Terminated with gradient small, X is probably optimal 01017 itrmcd = 2: Terminated with stepsize small, X is probably optimal 01018 itrmcd = 3: Lower point cannot be found, X is probably optimal 01019 itrmcd = 4: Iteration limit (150) exceeded 01020 itrmcd = 5: Too many large steps, function may be unbounded. 01021 */ 01022 int itrmcd; 01023 01024 double rnf, analtl, dltsav, amusav, dlpsav, phisav, phpsav; 01025 01026 double f; 01027 01028 double amu = 0.0; 01029 double dltp = 0.0; 01030 double phi = 0.0; 01031 double phip0 = 0.0; 01032 01033 int method = algorithm; 01034 01035 mLastGradCrit = 0.0; 01036 mLastStepCrit = 0.0; 01037 mLastIteration = 0; 01038 mLastMessage = -9999; 01039 01040 iagflg = minclass->HasAnalyticGradient(); 01041 iahflg = minclass->HasAnalyticHessian(); 01042 01043 /* 01044 msg 01045 Flag to set various options. 01046 Bits which indicate flags which control checks of gradient and hessian and what output is printed. 01047 msg should be zero or a sum of the following values which indicate which flags to set or not set. 01048 01049 1 = Turn off check of analytic gradient. 01050 2 = Turn off check of analytic hessian. 01051 4 = Turn off printing of results. 01052 8 = Turn on printing of results at each iteration. 01053 */ 01054 int msg = (fCheckGradient == 0) * 1 + (fCheckHessian == 0) * 2 + (fPrintResults == 0) * 4 01055 + (fPrintIterationResults != 0) * 8; 01056 01057 /* Check that dimensions match */ 01058 if (start.size() != n || xpls.size() != n || gpls.size() != n || hpls.num_rows() != n 01059 || hpls.num_columns() != n) // Refactored function "num_columns", ww, 12-22-2007 01060 { 01061 mLastMessage = -3; 01062 return -1; 01063 } 01064 01065 /* Check that starting values are valid */ 01066 if (!(minclass->ValidParameters(start))) 01067 { 01068 mLastMessage = -20; 01069 return -1; 01070 } 01071 01072 /* Workspace */ 01073 M &a = hpls; 01074 V udiag(n); //workspace (for diagonal of Hessian) 01075 V g(n); // workspace (for gradient at current iterate) 01076 V p(n); // workspace for step 01077 V sx(n); // workspace (for scaling vector) 01078 V wrk0(n), wrk1(n), wrk2(n), wrk3(n); 01079 01080 V x(start); 01081 01082 double dlt = mdlt; 01083 01084 dltsav = amusav = dlpsav = phisav = phpsav = 0.0; 01085 01086 // INITIALIZATION 01087 01088 for (i = 1; i <= n; i++) 01089 { 01090 p(i) = 0.0; 01091 } 01092 01093 itncnt = 0; 01094 iretcd = -1; 01095 01096 /* Check for valid options */ 01097 if (optchk(x, sx, msg, method)) 01098 { 01099 mLastMessage = msg; 01100 return -1; 01101 } 01102 01103 rnf = max(std::pow(10.0, -ndigit), epsm); 01104 analtl = max(.01, std::sqrt(rnf)); 01105 01106 if (!(msg & 4)) 01107 { 01108 num5 = n/5; 01109 remain = n%5; 01110 01111 std::fprintf(mfile, "\n\nOPTDRV Typical x\n\n"); 01112 01113 ilow = -4; 01114 ihigh = 0; 01115 01116 for (i = 1; i <= num5; i++) 01117 { 01118 ilow += 5; 01119 ihigh += 5; 01120 01121 std::fprintf(mfile, "%d--%d ", ilow, ihigh); 01122 01123 for (j = 1; j <= 5; j++) 01124 { 01125 std::fprintf(mfile, "%lf ", (double) typsiz(ilow+j-1)); 01126 } 01127 std::fprintf(mfile, "\n"); 01128 } 01129 01130 ilow += 5; 01131 ihigh = ilow + remain - 1; 01132 01133 std::fprintf(mfile, "%d--%d ", ilow, ihigh); 01134 01135 for (j = 1; j <= remain; j++) 01136 { 01137 std::fprintf(mfile, "%lf ", (double) typsiz(ilow+j-1)); 01138 } 01139 01140 std::fprintf(mfile, "\n"); 01141 01142 std::fprintf(mfile, "\n\nOPTDRV Scaling vector for x\n\n"); 01143 01144 ilow = -4; 01145 ihigh = 0; 01146 01147 for (i = 1; i <= num5; i++) 01148 { 01149 ilow += 5; 01150 ihigh += 5; 01151 01152 std::fprintf(mfile, "%d--%d ", ilow, ihigh); 01153 01154 for (j = 1; j <= 5; j++) 01155 { 01156 std::fprintf(mfile, "%lf ", (double) sx(ilow+j-1)); 01157 } 01158 std::fprintf(mfile, "\n"); 01159 } 01160 01161 ilow += 5; 01162 ihigh = ilow + remain - 1; 01163 01164 std::fprintf(mfile, "%d--%d ", ilow, ihigh); 01165 01166 for (j = 1; j <= remain; j++) 01167 { 01168 std::fprintf(mfile, "%lf ", (double) sx(ilow+j-1)); 01169 } 01170 01171 std::fprintf(mfile, "\n"); 01172 01173 std::fprintf(mfile, "\n\nOPTDRV Typical f = %f\n", fscale); 01174 std::fprintf(mfile, "OPTDRV Number of good digits in"); 01175 std::fprintf(mfile, " f_to_minimize = %d\n", ndigit); 01176 std::fprintf(mfile, "OPTDRV Gradient flag"); 01177 std::fprintf(mfile, " = %d\n", iagflg); 01178 std::fprintf(mfile, "OPTDRV Hessian flag"); 01179 std::fprintf(mfile, " = %d\n", iahflg); 01180 std::fprintf(mfile, "OPTDRV Expensive function calculation flag"); 01181 std::fprintf(mfile, " = %d\n", iexp); 01182 std::fprintf(mfile, "OPTDRV Method to use"); 01183 std::fprintf(mfile, " = %d\n", method); 01184 std::fprintf(mfile, "OPTDRV Iteration limit"); 01185 std::fprintf(mfile, " = %d\n", itnlim); 01186 std::fprintf(mfile, "OPTDRV Machine epsilon"); 01187 std::fprintf(mfile, " = %e\n", epsm); 01188 std::fprintf(mfile, "OPTDRV Maximum step size"); 01189 std::fprintf(mfile, " = %f\n", stepmx); 01190 std::fprintf(mfile, "OPTDRV Step tolerance"); 01191 std::fprintf(mfile, " = %e\n", steptl); 01192 std::fprintf(mfile, "OPTDRV Gradient tolerance"); 01193 std::fprintf(mfile, " = %e\n", gradtl); 01194 std::fprintf(mfile, "OPTDRV Trust region radius"); 01195 std::fprintf(mfile, " = %f\n", dlt); 01196 std::fprintf(mfile, "OPTDRV Relative noise in"); 01197 std::fprintf(mfile, " f_to_minimize = %e\n", rnf); 01198 std::fprintf(mfile, "OPTDRV Analytical fd tolerance"); 01199 std::fprintf(mfile, " = %e\n", analtl); 01200 } 01201 01202 // EVALUATE FCN(X) 01203 f = minclass->f_to_minimize(x); 01204 01205 // EVALUATE ANALYTIC OR FINITE DIFFERENCE GRADIENT AND CHECK ANALYTIC 01206 // GRADIENT, IF REQUESTED. 01207 if (iagflg == 0) 01208 { 01209 fstofd(x, f, g, sx, rnf); 01210 } 01211 else 01212 { 01213 minclass->gradient(x, g); 01214 01215 if (!(msg & 1)) 01216 { 01217 if (grdchk(x, f, g, typsiz, sx, fscale, rnf, analtl, wrk1, msg)) 01218 { 01219 mLastMessage = msg; 01220 return -1; // msg = -21 01221 } 01222 } 01223 } 01224 01225 optstp(x, f, g, wrk1, itncnt, icscmx, itrmcd, sx, fscale, itnlim, iretcd, mxtake, msg); 01226 01227 if (itrmcd != 0) 01228 { 01229 fpls = f; 01230 01231 for (i = 1; i <= n; i++) 01232 { 01233 xpls(i) = x(i); 01234 gpls(i) = g(i); 01235 } 01236 } 01237 else 01238 { 01239 if (iexp == 1) 01240 { 01241 // IF OPTIMIZATION FUNCTION EXPENSIVE TO EVALUATE (IEXP=1), THEN 01242 // HESSIAN WILL BE OBTAINED BY SECANT (BFGS) UPDATES. GET INITIAL HESSIAN. 01243 01244 hsnint(a, sx, method); 01245 } 01246 else 01247 { 01248 // EVALUATE ANALYTIC OR FINITE DIFFERENCE HESSIAN AND CHECK ANALYTIC 01249 // HESSIAN IF REQUESTED (ONLY IF USER-SUPPLIED ANALYTIC HESSIAN 01250 // ROUTINE minclass->hessian FILLS ONLY LOWER TRIANGULAR PART AND DIAGONAL OF A). 01251 01252 if (iahflg == 0) 01253 { 01254 if (iagflg == 1) 01255 { 01256 fstofd(x, g, a, sx, rnf, wrk1); 01257 } 01258 else 01259 { 01260 sndofd(x, f, a, sx, rnf, wrk1, wrk2); 01261 } 01262 } 01263 else 01264 { 01265 if (msg & 2) 01266 { 01267 minclass->hessian(x, a); 01268 } 01269 else 01270 { 01271 if (heschk(x, f, g, a, typsiz, sx, rnf, analtl, iagflg, udiag, wrk1, wrk2, msg)) 01272 { 01273 mLastMessage = msg; 01274 return -1; // msg = -22 01275 } 01276 // HESCHK EVALUATES minclass->hessian AND CHECKS IT AGAINST THE FINITE 01277 // DIFFERENCE HESSIAN WHICH IT CALCULATES BY CALLING FSTOFD 01278 // (IF IAGFLG .EQ. 1) OR SNDOFD (OTHERWISE). 01279 } 01280 } 01281 } 01282 01283 if (!(msg & 4)) 01284 result(x, f, g, a, p, itncnt, 1); 01285 01286 // ITERATION 01287 while (itrmcd == 0) 01288 { 01289 itncnt++; 01290 mLastIteration = itncnt; // BAH 01291 01292 // FIND PERTURBED LOCAL MODEL HESSIAN AND ITS LL+ DECOMPOSITION 01293 // (SKIP THIS STEP IF LINE SEARCH OR DOGSTEP TECHNIQUES BEING USED WITH 01294 // SECANT UPDATES. CHOLESKY DECOMPOSITION L ALREADY OBTAINED FROM 01295 // SECFAC.) 01296 if (iexp != 1 || method == 3) 01297 { 01298 chlhsn(a, sx, udiag); 01299 } 01300 01301 // SOLVE FOR NEWTON STEP: AP=-G 01302 for (i = 1; i <= n; i++) 01303 { 01304 wrk1(i) = -g(i); 01305 } 01306 01307 lltslv(a, p, wrk1); 01308 01309 // DECIDE WHETHER TO ACCEPT NEWTON STEP XPLS=X + P 01310 // OR TO CHOOSE XPLS BY A GLOBAL STRATEGY. 01311 if (iagflg == 0 && method != 1) 01312 { 01313 dltsav = dlt; 01314 01315 if (method != 2) 01316 { 01317 amusav = amu; 01318 dlpsav = dltp; 01319 phisav = phi; 01320 phpsav = phip0; 01321 } 01322 } 01323 01324 if (method == 1) 01325 { 01326 lnsrch(x, f, g, p, xpls, fpls, mxtake, iretcd, sx); 01327 if (iretcd == -7) // BAH 01328 { 01329 mLastMessage = iretcd; 01330 return -1; 01331 } 01332 } 01333 else if (method == 2) 01334 { 01335 dogdrv(x, f, g, a, p, xpls, fpls, sx, dlt, iretcd, mxtake, wrk0, wrk1, wrk2, wrk3); 01336 } 01337 else 01338 { 01339 hookdr(x, f, g, a, udiag, p, xpls, fpls, sx, dlt, iretcd, mxtake, amu, dltp, phi, phip0, 01340 wrk0, wrk1, wrk2, itncnt); 01341 } 01342 01343 // IF COULD NOT FIND SATISFACTORY STEP AND FORWARD DIFFERENCE 01344 // GRADIENT WAS USED, RETRY USING CENTRAL DIFFERENCE GRADIENT. 01345 if (iretcd == 1 && iagflg == 0) 01346 { 01347 // SET IAGFLG FOR CENTRAL DIFFERENCES 01348 iagflg = -1; 01349 01350 if (!(msg & 4)) 01351 { 01352 std::fprintf(mfile, "\nOPTDRV Shift from forward to central"); 01353 std::fprintf(mfile, " differences"); 01354 std::fprintf(mfile, "\nOPTDRV in iteration %d", itncnt); 01355 std::fprintf(mfile, "\n"); 01356 } 01357 01358 fstocd(x, sx, rnf, g); 01359 01360 if (method == 1) 01361 { 01362 // SOLVE FOR NEWTON STEP: AP=-G 01363 for (i = 1; i <= n; i++) 01364 { 01365 wrk1(i) = -g(i); 01366 } 01367 01368 lltslv(a, p, wrk1); 01369 01370 lnsrch(x, f, g, p, xpls, fpls, mxtake, iretcd, sx); 01371 if (iretcd == -7) // BAH 01372 { 01373 mLastMessage = iretcd; 01374 return -1; 01375 } 01376 } 01377 else 01378 { 01379 dlt = dltsav; 01380 if (method == 2) 01381 { 01382 // SOLVE FOR NEWTON STEP: AP=-G 01383 for (i = 1; i <= n; i++) 01384 { 01385 wrk1(i) = -g(i); 01386 } 01387 01388 lltslv(a, p, wrk1); 01389 01390 dogdrv(x, f, g, a, p, xpls, fpls, sx, dlt, iretcd, mxtake, wrk0, wrk1, wrk2, wrk3); 01391 } 01392 else 01393 { 01394 amu = amusav; 01395 dltp = dlpsav; 01396 phi = phisav; 01397 phip0 = phpsav; 01398 01399 chlhsn(a, sx, udiag); 01400 01401 // SOLVE FOR NEWTON STEP: AP=-G 01402 for (i = 1; i <= n; i++) 01403 { 01404 wrk1(i) = -g(i); 01405 } 01406 01407 lltslv(a, p, wrk1); 01408 01409 hookdr(x, f, g, a, udiag, p, xpls, fpls, sx, dlt, iretcd, mxtake, amu, dltp, phi, 01410 phip0, wrk0, wrk1, wrk2, itncnt); 01411 } 01412 } 01413 } 01414 // CALCULATE STEP FOR OUTPUT 01415 for (i = 1; i <= n; i++) 01416 { 01417 p(i) = xpls(i) - x(i); 01418 } 01419 01420 // CALCULATE GRADIENT AT XPLS 01421 if (iagflg == -1) 01422 { 01423 // CENTRAL DIFFERENCE GRADIENT 01424 fstocd(xpls, sx, rnf, gpls); 01425 } 01426 else if (iagflg == 0) 01427 { 01428 // FORWARD DIFFERENCE GRADIENT 01429 fstofd(xpls, fpls, gpls, sx, rnf); 01430 } 01431 else 01432 { 01433 // ANALYTIC GRADIENT 01434 minclass->gradient(xpls, gpls); 01435 } 01436 01437 // CHECK WHETHER STOPPING CRITERIA SATISFIED 01438 optstp(xpls, fpls, gpls, x, itncnt, icscmx, itrmcd, sx, fscale, itnlim, iretcd, mxtake, msg); 01439 01440 if (itrmcd == 0) 01441 { 01442 // EVALUATE HESSIAN AT XPLS 01443 if (iexp != 0) 01444 { 01445 if (method == 3) 01446 { 01447 secunf(x, g, a, udiag, xpls, gpls, itncnt, rnf, iagflg, noupdt, wrk1, wrk2, wrk3); 01448 } 01449 else 01450 { 01451 secfac(x, g, a, xpls, gpls, itncnt, rnf, iagflg, noupdt, wrk0, wrk1, wrk2, wrk3); 01452 } 01453 } 01454 else 01455 { 01456 if (iahflg == 1) 01457 { 01458 minclass->hessian(xpls, a); 01459 } 01460 else 01461 { 01462 if (iagflg == 1) 01463 { 01464 fstofd(xpls, gpls, a, sx, rnf, wrk1); 01465 } 01466 else 01467 { 01468 sndofd(xpls, fpls, a, sx, rnf, wrk1, wrk2); 01469 } 01470 } 01471 } 01472 01473 if