00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 2009, Andrew W. Steiner 00005 00006 This file is part of O2scl. 00007 00008 O2scl is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 O2scl is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with O2scl. If not, see <http://www.gnu.org/licenses/>. 00020 00021 ------------------------------------------------------------------- 00022 */ 00023 #ifndef O2SCL_MULTI_MIN_H 00024 #define O2SCL_MULTI_MIN_H 00025 00026 #include <o2scl/text_file.h> 00027 #include <o2scl/ovector_tlate.h> 00028 #include <o2scl/multi_funct.h> 00029 #include <o2scl/string_conv.h> 00030 00031 #ifndef DOXYGENP 00032 namespace o2scl { 00033 #endif 00034 00035 /** \brief Gradient function [abstract base] 00036 00037 Default template arguments 00038 - \c param_t - (no default) 00039 - \c vec_t - \ref ovector_base 00040 00041 */ 00042 template<class param_t, class vec_t=ovector_base> 00043 class grad_funct { 00044 00045 public: 00046 00047 virtual ~grad_funct() {} 00048 00049 /// Compute the gradient \c g at the point \c x 00050 virtual int operator()(size_t nv, vec_t &x, vec_t &g, param_t &pa)=0; 00051 00052 }; 00053 00054 /** \brief Function pointer to a gradient 00055 00056 Default template arguments 00057 - \c param_t - (no default) 00058 - \c vec_t - \ref ovector_base 00059 */ 00060 template <class param_t, class vec_t=ovector_base> 00061 class grad_funct_fptr : public grad_funct<param_t,vec_t> { 00062 00063 public: 00064 00065 /** \brief Specify the function pointer 00066 */ 00067 grad_funct_fptr(int (*fp)(size_t nv, vec_t &x, vec_t &g, param_t &pa)) { 00068 fptr=fp; 00069 } 00070 00071 virtual ~grad_funct_fptr() {}; 00072 00073 /** \brief Compute the gradient \c g at the point \c x 00074 */ 00075 virtual int operator()(size_t nv, vec_t &x, vec_t &g, param_t &pa) { 00076 return (*fptr)(nv,x,g,pa); 00077 } 00078 00079 #ifndef DOXYGEN_INTERNAL 00080 00081 protected: 00082 00083 /// The function pointer 00084 int (*fptr)(size_t nv, vec_t &x, vec_t &g, param_t &pa); 00085 00086 #endif 00087 00088 #ifndef DOXYGENP 00089 00090 private: 00091 00092 grad_funct_fptr(const grad_funct_fptr &); 00093 grad_funct_fptr& operator=(const grad_funct_fptr&); 00094 00095 #endif 00096 00097 }; 00098 00099 /** \brief Member function pointer to a gradient 00100 00101 Default template arguments 00102 - \c tclass - (no default) 00103 - \c param_t - (no default) 00104 - \c vec_t - \ref ovector_base 00105 */ 00106 template <class tclass, class param_t, class vec_t=ovector_base> 00107 class grad_funct_mfptr : public grad_funct<param_t,vec_t> { 00108 00109 public: 00110 00111 /** \brief Specify the member function pointer 00112 */ 00113 grad_funct_mfptr(tclass *tp, int (tclass::*fp) 00114 (size_t nv, vec_t &x, vec_t &g, param_t &pa)) { 00115 tptr=tp; 00116 fptr=fp; 00117 } 00118 00119 virtual ~grad_funct_mfptr() {}; 00120 00121 /** \brief Compute the gradient \c g at the point \c x 00122 */ 00123 virtual int operator()(size_t nv, vec_t &x, vec_t &g, param_t &pa) { 00124 return (*tptr.*fptr)(nv,x,g,pa); 00125 } 00126 00127 #ifndef DOXYGEN_INTERNAL 00128 00129 protected: 00130 00131 /// Member function pointer 00132 int (tclass::*fptr)(size_t nv, vec_t &x, vec_t &g, param_t &pa); 00133 00134 /// Class pointer 00135 tclass *tptr; 00136 00137 #endif 00138 00139 #ifndef DOXYGENP 00140 00141 private: 00142 00143 grad_funct_mfptr(const grad_funct_mfptr &); 00144 grad_funct_mfptr& operator=(const grad_funct_mfptr&); 00145 00146 #endif 00147 00148 }; 00149 00150 /** \brief Const member function pointer to a gradient 00151 00152 Default template arguments 00153 - \c tclass - (no default) 00154 - \c param_t - (no default) 00155 - \c vec_t - \ref ovector_base 00156 */ 00157 template <class tclass, class param_t, class vec_t=ovector_base> 00158 class grad_funct_cmfptr : public grad_funct<param_t,vec_t> { 00159 00160 public: 00161 00162 /** \brief Specify the member function pointer 00163 */ 00164 grad_funct_cmfptr(tclass *tp, int (tclass::*fp) 00165 (size_t nv, vec_t &x, vec_t &g, param_t &pa) const) { 00166 tptr=tp; 00167 fptr=fp; 00168 } 00169 00170 virtual ~grad_funct_cmfptr() {}; 00171 00172 /** \brief Compute the gradient \c g at the point \c x 00173 */ 00174 virtual int operator()(size_t nv, vec_t &x, vec_t &g, param_t &pa) { 00175 return (*tptr.*fptr)(nv,x,g,pa); 00176 } 00177 00178 #ifndef DOXYGEN_INTERNAL 00179 00180 protected: 00181 00182 /// Member function pointer 00183 int (tclass::*fptr)(size_t nv, vec_t &x, vec_t &g, param_t &pa) const; 00184 00185 /// Class pointer 00186 tclass *tptr; 00187 00188 #endif 00189 00190 #ifndef DOXYGENP 00191 00192 private: 00193 00194 grad_funct_cmfptr(const grad_funct_cmfptr &); 00195 grad_funct_cmfptr& operator=(const grad_funct_cmfptr&); 00196 00197 #endif 00198 00199 }; 00200 00201 /** \brief Class for automatically computing gradients [abstract base] 00202 00203 Default template arguments 00204 - \c param_t - (no default) 00205 - \c func_t - (no default) 00206 - \c vec_t - \ref ovector_base 00207 */ 00208 template<class param_t, class func_t, class vec_t=ovector_base> 00209 class gradient : public grad_funct<param_t,vec_t> { 00210 00211 public: 00212 00213 virtual ~gradient() {} 00214 00215 /// Set the function to compute the gradient of 00216 virtual int set_function(func_t &f) { 00217 func=&f; 00218 return 0; 00219 } 00220 00221 /** \brief Compute the gradient \c g at the point \c x 00222 */ 00223 virtual int operator()(size_t nv, vec_t &x, vec_t &g, param_t &pa)=0; 00224 00225 #ifndef DOXYGEN_INTERNAL 00226 00227 protected: 00228 00229 /// A pointer to the user-specified function 00230 func_t *func; 00231 00232 #endif 00233 00234 }; 00235 00236 /** \brief Simple automatic computation of gradient by finite 00237 differencing 00238 */ 00239 template<class param_t, class func_t, class vec_t> class simple_grad : 00240 public gradient<param_t,func_t,vec_t> { 00241 00242 public: 00243 00244 simple_grad() { 00245 epsrel=1.0e-6; 00246 epsmin=1.0e-15; 00247 } 00248 00249 virtual ~simple_grad() {} 00250 00251 /** \brief The relative stepsize for finite-differencing 00252 (default \f$ 10^{-6} \f$ ) 00253 */ 00254 double epsrel; 00255 00256 /// The minimum stepsize (default \f$ 10^{-15} \f$) 00257 double epsmin; 00258 00259 /** \brief Compute the gradient \c g at the point \c x 00260 */ 00261 virtual int operator()(size_t nv, vec_t &x, vec_t &g, param_t &pa) { 00262 double fv1, fv2, h; 00263 00264 (*this->func)(nv,x,fv1,pa); 00265 00266 for(size_t i=0;i<nv;i++) { 00267 00268 h=epsrel*fabs(x[i]); 00269 if (fabs(h)<=epsmin) h=epsrel; 00270 00271 x[i]+=h; 00272 (*this->func)(nv,x,fv2,pa); 00273 x[i]-=h; 00274 g[i]=(fv2-fv1)/h; 00275 00276 } 00277 00278 return 0; 00279 } 00280 00281 }; 00282 00283 /// Base class for a gradient function using arrays [abstract base] 00284 template<class param_t, size_t nv> class grad_vfunct { 00285 00286 public: 00287 00288 virtual ~grad_vfunct() {} 00289 00290 /** \brief Compute the gradient \c g at the point \c x 00291 */ 00292 virtual int operator()(size_t nvar, double x[nv], double g[nv], 00293 param_t &pa)=0; 00294 00295 }; 00296 00297 /** 00298 \brief Function pointer to a gradient 00299 00300 \note \c nv should be greater than zero 00301 */ 00302 template <class param_t, size_t nv> 00303 class grad_vfunct_fptr : public grad_vfunct<param_t,nv> { 00304 00305 public: 00306 00307 /** \brief Specify the member function pointer 00308 */ 00309 grad_vfunct_fptr(int (*fp)(size_t nvar, double x[nv], double g[nv], 00310 param_t &pa)) { 00311 fptr=fp; 00312 } 00313 00314 virtual ~grad_vfunct_fptr() {}; 00315 00316 /** \brief Compute the gradient \c g at the point \c x 00317 */ 00318 virtual int operator()(size_t nvar, double x[nv], double g[nv], 00319 param_t &pa) { 00320 return (*fptr)(nvar,x,g,pa); 00321 } 00322 00323 #ifndef DOXYGEN_INTERNAL 00324 00325 protected: 00326 00327 /// Function pointer 00328 int (*fptr)(size_t nvar, double x[nv], double g[nv], param_t &pa); 00329 00330 #endif 00331 00332 #ifndef DOXYGENP 00333 00334 private: 00335 00336 grad_vfunct_fptr(const grad_vfunct_fptr &); 00337 grad_vfunct_fptr& operator=(const grad_vfunct_fptr&); 00338 00339 #endif 00340 00341 }; 00342 00343 /** \brief Member function pointer to a gradient 00344 */ 00345 template <class tclass, class param_t, size_t nv> 00346 class grad_vfunct_mfptr : public grad_vfunct<param_t,nv> { 00347 00348 public: 00349 00350 /** \brief Specify the member function pointer 00351 */ 00352 grad_vfunct_mfptr(tclass *tp, int (tclass::*fp) 00353 (size_t nvar, double x[nv], double g[nv], param_t &pa)) { 00354 tptr=tp; 00355 fptr=fp; 00356 } 00357 00358 virtual ~grad_vfunct_mfptr() {}; 00359 00360 /** \brief Compute the gradient \c g at the point \c x 00361 */ 00362 virtual int operator()(size_t nvar, double x[nv], double g[nv], 00363 param_t &pa) { 00364 return (*tptr.*fptr)(nvar,x,g,pa); 00365 } 00366 00367 #ifndef DOXYGEN_INTERNAL 00368 00369 protected: 00370 00371 /// Member function pointer 00372 int (tclass::*fptr)(size_t nvar, double x[nv], double g[nv], param_t &pa); 00373 00374 /// Class pointer 00375 tclass *tptr; 00376 00377 #endif 00378 00379 #ifndef DOXYGENP 00380 00381 private: 00382 00383 grad_vfunct_mfptr(const grad_vfunct_mfptr &); 00384 grad_vfunct_mfptr& operator=(const grad_vfunct_mfptr&); 00385 00386 #endif 00387 00388 }; 00389 00390 /** \brief Const member function pointer to a gradient 00391 */ 00392 template <class tclass, class param_t, size_t nv> 00393 class grad_vfunct_cmfptr : public grad_vfunct<param_t,nv> { 00394 00395 public: 00396 00397 /** \brief Specify the member function pointer 00398 */ 00399 grad_vfunct_cmfptr(tclass *tp, int (tclass::*fp) 00400 (size_t nvar, double x[nv], double g[nv], 00401 param_t &pa) const) { 00402 tptr=tp; 00403 fptr=fp; 00404 } 00405 00406 virtual ~grad_vfunct_cmfptr() {}; 00407 00408 /** \brief Compute the gradient \c g at the point \c x 00409 */ 00410 virtual int operator()(size_t nvar, double x[nv], double g[nv], 00411 param_t &pa) { 00412 return (*tptr.*fptr)(nvar,x,g,pa); 00413 } 00414 00415 #ifndef DOXYGEN_INTERNAL 00416 00417 protected: 00418 00419 /// Member function pointer 00420 int (tclass::*fptr)(size_t nvar, double x[nv], double g[nv], 00421 param_t &pa) const; 00422 00423 /// Class pointer 00424 tclass *tptr; 00425 00426 #endif 00427 00428 #ifndef DOXYGENP 00429 00430 private: 00431 00432 grad_vfunct_cmfptr(const grad_vfunct_cmfptr &); 00433 grad_vfunct_cmfptr& operator=(const grad_vfunct_cmfptr&); 00434 00435 #endif 00436 00437 }; 00438 00439 /** 00440 \brief Base class for automatically computing gradients with arrays 00441 [abstract base] 00442 */ 00443 template<class param_t, class func_t, size_t nv> 00444 class gradient_array : public grad_vfunct<param_t,nv> { 00445 00446 public: 00447 00448 virtual ~gradient_array() {} 00449 00450 /// Set the function to compute the gradient of 00451 virtual int set_function(func_t &f) { 00452 func=&f; 00453 return 0; 00454 } 00455 00456 /** \brief Compute the gradient \c g at the point \c x 00457 */ 00458 virtual int operator()(size_t nvar, double x[nv], double g[nv], 00459 param_t &pa)=0; 00460 00461 #ifndef DOXYGEN_INTERNAL 00462 00463 protected: 00464 00465 /// A pointer to the user-specified function 00466 func_t *func; 00467 00468 #endif 00469 00470 }; 00471 00472 /** \brief Simple automatic computation of gradient by finite 00473 differencing with arrays 00474 */ 00475 template<class param_t, class func_t, size_t nv> class simple_grad_array : 00476 public gradient_array<param_t,func_t,nv> { 00477 00478 public: 00479 00480 simple_grad_array() { 00481 epsrel=1.0e-6; 00482 epsmin=1.0e-15; 00483 } 00484 00485 virtual ~simple_grad_array() {} 00486 00487 /** \brief The relative stepsize for finite-differencing 00488 (default \f$ 10^{-4} \f$ ) 00489 */ 00490 double epsrel; 00491 00492 /// The minimum stepsize (default \f$ 10^{-15} \f$) 00493 double epsmin; 00494 00495 /** \brief Compute the gradient \c g at the point \c x 00496 */ 00497 virtual int operator()(size_t nvar, double x[nv], double g[nv], 00498 param_t &pa) { 00499 double fv1, fv2, h; 00500 00501 (*this->func)(nv,x,fv1,pa); 00502 00503 for(size_t i=0;i<nvar;i++) { 00504 00505 h=epsrel*fabs(x[i]); 00506 if (fabs(h)<=epsmin) h=epsrel; 00507 00508 x[i]+=h; 00509 (*this->func)(nvar,x,fv2,pa); 00510 x[i]-=h; 00511 g[i]=(fv2-fv1)/h; 00512 00513 } 00514 00515 return 0; 00516 } 00517 00518 }; 00519 00520 /** 00521 \brief Multidimensional minimization [abstract base] 00522 00523 <b>The template parameters:</b> 00524 The template parameter \c func_t specifies the function to 00525 minimize and should be a class containing a definition 00526 \code 00527 func_t::operator()(size_t nv, const vec_t &x, double &f, param_t &pa); 00528 \endcode 00529 where \c f is the value of the function at \c x with parameter \c pa 00530 where \c x is a array-like class defining \c operator[] of size \c nv. 00531 The parameter \c dfunc_t (if used) should provide the gradient with 00532 \code 00533 func_t::operator()(size_t nv, const vec_t &x, vec_t &g, param_t &pa); 00534 \endcode 00535 where \c g is the gradient of the function at \c x. 00536 */ 00537 template<class param_t, class func_t, class dfunc_t=func_t, 00538 class vec_t=ovector_base> class multi_min { 00539 00540 #ifndef DOXYGEN_INTERNAL 00541 00542 protected: 00543 00544 /// Stream for verbose output 00545 std::ostream *outs; 00546 00547 /// Stream for verbose input 00548 std::istream *ins; 00549 00550 #endif 00551 00552 public: 00553 00554 multi_min() { 00555 verbose=0; 00556 ntrial=100; 00557 tolf=1.0e-4; 00558 tolx=1.0e-4; 00559 last_ntrial=0; 00560 err_nonconv=true; 00561 last_conv=0; 00562 outs=&std::cout; 00563 ins=&std::cin; 00564 } 00565 00566 virtual ~multi_min() {} 00567 00568 /// Output control 00569 int verbose; 00570 00571 /// Maximum number of iterations 00572 int ntrial; 00573 00574 /// Function value tolerance 00575 double tolf; 00576 00577 /// The independent variable tolerance 00578 double tolx; 00579 00580 /// The number of iterations for in the most recent minimization 00581 int last_ntrial; 00582 00583 /// If true, call the error handler if the routine does not "converge" 00584 bool err_nonconv; 00585 00586 /** 00587 \brief Zero if last call to mmin() or mmin_de() converged. 00588 00589 This is particularly useful if err_nonconv is false to test 00590 if the last call to mmin() or mmin_de() converged. 00591 */ 00592 int last_conv; 00593 00594 /// Set streams for verbose I/O 00595 int set_verbose_stream(std::ostream &out, std::istream &in) { 00596 outs=&out; 00597 ins=∈ 00598 return 0; 00599 } 00600 00601 /** \brief Calculate the minimum \c min of \c func w.r.t. the 00602 array \c x of size \c nvar. 00603 */ 00604 virtual int mmin(size_t nvar, vec_t &x, double &fmin, param_t &pa, 00605 func_t &func)=0; 00606 00607 /** \brief Calculate the minimum \c min of \c func 00608 w.r.t. the array \c x of size \c nvar with gradient 00609 \c dfunc 00610 */ 00611 virtual int mmin_de(size_t nvar, vec_t &x, double &fmin, param_t &pa, 00612 func_t &func, dfunc_t &dfunc) 00613 { 00614 return mmin(nvar,x,fmin,pa,func); 00615 } 00616 00617 /** 00618 \brief Print out iteration information. 00619 00620 Depending on the value of the variable verbose, this prints out 00621 the iteration information. If verbose=0, then no information is 00622 printed, while if verbose>1, then after each iteration, the 00623 present values of x and y are output to std::cout along with the 00624 iteration number. If verbose>=2 then each iteration waits for a 00625 character. 00626 */ 00627 template<class vec2_t> 00628 int print_iter(size_t nv, vec2_t &x, double y, int iter, 00629 double value, double limit, std::string comment) 00630 { 00631 00632 if (verbose<=0) return 0; 00633 00634 int i; 00635 char ch; 00636 00637 (*outs) << comment << " Iteration: " << iter << std::endl; 00638 { 00639 text_out_file outsf(outs,79); 00640 outsf.word_out("x:"); 00641 for(i=0;i<((int)nv);i++) outsf.double_out(x[i]); 00642 outsf.end_line(); 00643 } 00644 (*outs) << "y: " << y << " Val: " << value << " Lim: " 00645 << limit << std::endl; 00646 if (verbose>1) { 00647 (*outs) << "Press a key and type enter to continue. "; 00648 (*ins) >> ch; 00649 } 00650 00651 return 0; 00652 } 00653 00654 /// Return string denoting type ("multi_min") 00655 const char *type() { return "multi_min"; } 00656 00657 }; 00658 00659 #ifndef DOXYGENP 00660 } 00661 #endif 00662 00663 #endif 00664
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page