00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 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 00030 #ifndef DOXYGENP 00031 namespace o2scl { 00032 #endif 00033 00034 /// Gradient function [abstract base] 00035 template<class param_t, class vec_t=ovector_view> 00036 class grad_funct { 00037 00038 public: 00039 00040 virtual ~grad_funct() {} 00041 00042 /// Compute the gradient \c g at the point \c x 00043 virtual int operator()(size_t nv, vec_t &x, vec_t &g, param_t &pa)=0; 00044 00045 }; 00046 00047 /** \brief Function pointer to a gradient 00048 */ 00049 template <class param_t, class vec_t=ovector_view> 00050 class grad_funct_fptr : public grad_funct<param_t,vec_t> { 00051 00052 public: 00053 00054 /** \brief Specify the function pointer 00055 */ 00056 grad_funct_fptr(int (*fp)(size_t nv, vec_t &x, vec_t &g, param_t &pa)) { 00057 fptr=fp; 00058 } 00059 00060 virtual ~grad_funct_fptr() {}; 00061 00062 /** \brief Compute the gradient \c g at the point \c x 00063 */ 00064 virtual int operator()(size_t nv, vec_t &x, vec_t &g, param_t &pa) { 00065 return (*fptr)(nv,x,g,pa); 00066 } 00067 00068 #ifndef DOXYGEN_INTERNAL 00069 00070 protected: 00071 00072 /// The function pointer 00073 int (*fptr)(size_t nv, vec_t &x, vec_t &g, param_t &pa); 00074 00075 #endif 00076 00077 #ifndef DOXYGENP 00078 00079 private: 00080 00081 grad_funct_fptr(const grad_funct_fptr &); 00082 grad_funct_fptr& operator=(const grad_funct_fptr&); 00083 00084 #endif 00085 00086 }; 00087 00088 /** \brief Member function pointer to a gradient 00089 */ 00090 template <class tclass, class param_t, class vec_t=ovector_view> 00091 class grad_funct_mfptr : public grad_funct<param_t,vec_t> { 00092 00093 public: 00094 00095 /** \brief Specify the member function pointer 00096 */ 00097 grad_funct_mfptr(tclass *tp, int (tclass::*fp) 00098 (size_t nv, vec_t &x, vec_t &g, param_t &pa)) { 00099 tptr=tp; 00100 fptr=fp; 00101 } 00102 00103 virtual ~grad_funct_mfptr() {}; 00104 00105 /** \brief Compute the gradient \c g at the point \c x 00106 */ 00107 virtual int operator()(size_t nv, vec_t &x, vec_t &g, param_t &pa) { 00108 return (*tptr.*fptr)(nv,x,g,pa); 00109 } 00110 00111 #ifndef DOXYGEN_INTERNAL 00112 00113 protected: 00114 00115 /// Member function pointer 00116 int (tclass::*fptr)(size_t nv, vec_t &x, vec_t &g, param_t &pa); 00117 00118 /// Class pointer 00119 tclass *tptr; 00120 00121 #endif 00122 00123 #ifndef DOXYGENP 00124 00125 private: 00126 00127 grad_funct_mfptr(const grad_funct_mfptr &); 00128 grad_funct_mfptr& operator=(const grad_funct_mfptr&); 00129 00130 #endif 00131 00132 }; 00133 00134 /// Class for automatically computing gradients [abstract base] 00135 template<class param_t, class func_t, class vec_t=ovector_view> 00136 class gradient : public grad_funct<param_t,vec_t> { 00137 00138 public: 00139 00140 virtual ~gradient() {} 00141 00142 /// Set the function to compute the gradient of 00143 virtual int set_function(func_t &f) { 00144 func=&f; 00145 return 0; 00146 } 00147 00148 /** \brief Compute the gradient \c g at the point \c x 00149 */ 00150 virtual int operator()(size_t nv, vec_t &x, vec_t &g, param_t &pa)=0; 00151 00152 #ifndef DOXYGEN_INTERNAL 00153 00154 protected: 00155 00156 /// A pointer to the user-specified function 00157 func_t *func; 00158 00159 #endif 00160 00161 }; 00162 00163 /// Simple automatic computation of gradient by finite differencing 00164 template<class param_t, class func_t, class vec_t> class simple_grad : 00165 public gradient<param_t,func_t,vec_t> { 00166 00167 public: 00168 00169 simple_grad() { 00170 epsrel=1.0e-4; 00171 epsmin=1.0e-15; 00172 } 00173 00174 virtual ~simple_grad() {} 00175 00176 /** \brief The relative stepsize for finite-differencing 00177 (default \f$ 10^{-4} \f$ ) 00178 */ 00179 double epsrel; 00180 00181 /// The minimum stepsize (default \f$ 10^{-15} \f$) 00182 double epsmin; 00183 00184 /** \brief Compute the gradient \c g at the point \c x 00185 */ 00186 virtual int operator()(size_t nv, vec_t &x, vec_t &g, param_t &pa) { 00187 double fv1, fv2, h; 00188 00189 (*this->func)(nv,x,fv1,pa); 00190 00191 for(size_t i=0;i<nv;i++) { 00192 00193 h=epsrel*fabs(x[i]); 00194 if (fabs(h)<=epsmin) h=epsrel; 00195 00196 x[i]+=h; 00197 (*this->func)(nv,x,fv2,pa); 00198 x[i]-=h; 00199 g[i]=(fv2-fv1)/h; 00200 } 00201 00202 return 0; 00203 } 00204 00205 }; 00206 00207 /// Base class for a gradient function using arrays [abstract base] 00208 template<class param_t, size_t nv> class grad_vfunct { 00209 00210 public: 00211 00212 virtual ~grad_vfunct() {} 00213 00214 /** \brief Compute the gradient \c g at the point \c x 00215 */ 00216 virtual int operator()(size_t nvar, double x[nv], double g[nv], 00217 param_t &pa)=0; 00218 00219 }; 00220 00221 /** \brief Function pointer to a gradient 00222 */ 00223 template <class param_t, size_t nv> 00224 class grad_vfunct_fptr : public grad_vfunct<param_t,nv> { 00225 00226 public: 00227 00228 /** \brief Specify the member function pointer 00229 */ 00230 grad_vfunct_fptr(int (*fp)(size_t nv, double x[nv], double g[nv], 00231 param_t &pa)) { 00232 fptr=fp; 00233 } 00234 00235 virtual ~grad_vfunct_fptr() {}; 00236 00237 /** \brief Compute the gradient \c g at the point \c x 00238 */ 00239 virtual int operator()(size_t nvar, double x[nv], double g[nv], 00240 param_t &pa) { 00241 return (*fptr)(nvar,x,g,pa); 00242 } 00243 00244 #ifndef DOXYGEN_INTERNAL 00245 00246 protected: 00247 00248 /// Function pointer 00249 int (*fptr)(size_t nvar, double x[nv], double g[nv], param_t &pa); 00250 00251 #endif 00252 00253 #ifndef DOXYGENP 00254 00255 private: 00256 00257 grad_vfunct_fptr(const grad_vfunct_fptr &); 00258 grad_vfunct_fptr& operator=(const grad_vfunct_fptr&); 00259 00260 #endif 00261 00262 }; 00263 00264 /** \brief Member function pointer to a gradient 00265 */ 00266 template <class tclass, class param_t, size_t nv> 00267 class grad_vfunct_mfptr : public grad_vfunct<param_t,nv> { 00268 00269 public: 00270 00271 /** \brief Specify the member function pointer 00272 */ 00273 grad_vfunct_mfptr(tclass *tp, int (tclass::*fp) 00274 (size_t nvar, double x[nv], double g[nv], param_t &pa)) { 00275 tptr=tp; 00276 fptr=fp; 00277 } 00278 00279 virtual ~grad_vfunct_mfptr() {}; 00280 00281 /** \brief Compute the gradient \c g at the point \c x 00282 */ 00283 virtual int operator()(size_t nvar, double x[nv], double g[nv], 00284 param_t &pa) { 00285 return (*tptr.*fptr)(nvar,x,g,pa); 00286 } 00287 00288 #ifndef DOXYGEN_INTERNAL 00289 00290 protected: 00291 00292 /// Member function pointer 00293 int (tclass::*fptr)(size_t nvar, double x[nv], double g[nv], param_t &pa); 00294 00295 /// Class pointer 00296 tclass *tptr; 00297 00298 #endif 00299 00300 #ifndef DOXYGENP 00301 00302 private: 00303 00304 grad_vfunct_mfptr(const grad_vfunct_mfptr &); 00305 grad_vfunct_mfptr& operator=(const grad_vfunct_mfptr&); 00306 00307 #endif 00308 00309 }; 00310 00311 /** 00312 \brief Base class for automatically computing gradients with arrays 00313 [abstract base] 00314 */ 00315 template<class param_t, class func_t, size_t nv> 00316 class gradient_array : public grad_vfunct<param_t,nv> { 00317 00318 public: 00319 00320 virtual ~gradient_array() {} 00321 00322 /// Set the function to compute the gradient of 00323 virtual int set_function(func_t &f) { 00324 func=&f; 00325 return 0; 00326 } 00327 00328 /** \brief Compute the gradient \c g at the point \c x 00329 */ 00330 virtual int operator()(size_t nvar, double x[nv], double g[nv], 00331 param_t &pa)=0; 00332 00333 #ifndef DOXYGEN_INTERNAL 00334 00335 protected: 00336 00337 /// A pointer to the user-specified function 00338 func_t *func; 00339 00340 #endif 00341 00342 }; 00343 00344 /** \brief Simple automatic computation of gradient by finite 00345 differencing with arrays 00346 */ 00347 template<class param_t, class func_t, size_t nv> class simple_grad_array : 00348 public gradient_array<param_t,func_t,nv> { 00349 00350 public: 00351 00352 simple_grad_array() { 00353 epsrel=1.0e-4; 00354 epsmin=1.0e-15; 00355 } 00356 00357 virtual ~simple_grad_array() {} 00358 00359 /** \brief The relative stepsize for finite-differencing 00360 (default \f$ 10^{-4} \f$ ) 00361 */ 00362 double epsrel; 00363 00364 /// The minimum stepsize (default \f$ 10^{-15} \f$) 00365 double epsmin; 00366 00367 /** \brief Compute the gradient \c g at the point \c x 00368 */ 00369 virtual int operator()(size_t nvar, double x[nv], double g[nv], 00370 param_t &pa) { 00371 double fv1, fv2, h; 00372 00373 (*this->func)(nv,x,fv1,pa); 00374 00375 for(size_t i=0;i<nvar;i++) { 00376 00377 h=epsrel*fabs(x[i]); 00378 if (fabs(h)<=epsmin) h=epsrel; 00379 00380 x[i]+=h; 00381 (*this->func)(nvar,x,fv2,pa); 00382 x[i]-=h; 00383 g[i]=(fv2-fv1)/h; 00384 } 00385 00386 return 0; 00387 } 00388 00389 }; 00390 00391 /** 00392 \brief Multidimensional minimization [abstract base] 00393 00394 <b>The template parameters:</b> 00395 The template parameter \c func_t specifies the function to 00396 minimize and should be a class containing a definition 00397 \code 00398 func_t::operator()(size_t nv, const vec_t &x, double &f, param_t &pa); 00399 \endcode 00400 where \c f is the value of the function at \c x with parameter \c pa 00401 where \c x is a array-like class defining \c operator[] of size \c nv. 00402 The parameter \c dfunc_t (if used) should provide the gradient with 00403 \code 00404 func_t::operator()(size_t nv, const vec_t &x, vec_t &g, param_t &pa); 00405 \endcode 00406 where \c g is the gradient of the function at \c x. 00407 */ 00408 template<class param_t, class func_t, class dfunc_t=func_t, 00409 class vec_t=ovector_view> class multi_min { 00410 00411 public: 00412 00413 /// Output control 00414 int verbose; 00415 00416 /// Maximum number of iterations 00417 int ntrial; 00418 00419 /// Tolerance 00420 double tolf; 00421 00422 /// The minimum allowable stepsize 00423 double tolx; 00424 00425 /// The number of iterations for in the most recent minimization 00426 int last_ntrial; 00427 00428 multi_min() { 00429 verbose=0; 00430 ntrial=100; 00431 tolf=1.0e-4; 00432 tolx=1.0e-4; 00433 last_ntrial=0; 00434 } 00435 00436 virtual ~multi_min() {} 00437 00438 /** \brief Calculate the minimum \c min of \c func w.r.t. the 00439 array \c x of size \c nvar. 00440 */ 00441 virtual int mmin(size_t nvar, vec_t &x, double &fmin, param_t &pa, 00442 func_t &func)=0; 00443 00444 /** \brief Calculate the minimum \c min of \c func 00445 w.r.t. the array \c x of size \c nvar with gradient 00446 \c dfunc 00447 */ 00448 virtual int mmin_de(size_t nvar, vec_t &x, double &fmin, param_t &pa, 00449 func_t &func, dfunc_t &dfunc) 00450 { 00451 return mmin(nvar,x,fmin,pa,func); 00452 } 00453 00454 /** 00455 \brief Print out iteration information. 00456 00457 Depending on the value of the variable verbose, this prints out 00458 the iteration information. If verbose=0, then no information is 00459 printed, while if verbose>1, then after each iteration, the 00460 present values of x and y are output to std::cout along with the 00461 iteration number. If verbose>=2 then each iteration waits for a 00462 character. 00463 */ 00464 template<class vec2_t> 00465 int print_iter(size_t nv, vec2_t &x, double y, int iter, 00466 double value, double limit, 00467 std::string comment) 00468 { 00469 if (verbose<=0) return 0; 00470 00471 int i; 00472 char ch; 00473 00474 std::cout << comment << " Iteration: " << iter << std::endl; 00475 text_out_file outs(&std::cout,79); 00476 outs.word_out("x:"); 00477 for(i=0;i<((int)nv);i++) outs.double_out(x[i]); 00478 outs.end_line(); 00479 std::cout << "y: " << y << " Val: " << value << " Lim: " 00480 << limit << std::endl; 00481 if (verbose>1) { 00482 std::cout << "Press a key and type enter to continue. "; 00483 std::cin >> ch; 00484 } 00485 00486 return 0; 00487 } 00488 00489 /// Return string denoting type ("multi_min") 00490 const char *type() { return "multi_min"; } 00491 00492 }; 00493 00494 #ifndef DOXYGENP 00495 } 00496 #endif 00497 00498 #endif 00499
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