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