![]() |
Object-oriented Scientific Computing Library: Version 0.910
|
00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006-2012, 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/ovector_tlate.h> 00027 #include <o2scl/multi_funct.h> 00028 #include <o2scl/mm_funct.h> 00029 #include <o2scl/string_conv.h> 00030 00031 #ifndef DOXYGENP 00032 namespace o2scl { 00033 #endif 00034 00035 /** \brief Array of multi-dimensional functions [abstract base] 00036 00037 This class generalizes \c nv functions of \c nv variables, i.e. 00038 \f$ y_j(x_0,x_1,...,x_{nv-1}) \f$ for \f$ 0\leq j \leq 00039 nv-1 \f$ . 00040 00041 This class is one of a large number of function object classes 00042 in \o2 designed to provide a mechanism for the user to 00043 supply functions to solvers, minimizers, integrators, etc. 00044 See \ref funct_section for a general description. 00045 00046 \note This class is different from \ref mm_funct in that 00047 the first vector argument is not const. 00048 */ 00049 template<class vec_t=ovector_base> class grad_funct { 00050 public: 00051 00052 grad_funct() {} 00053 00054 virtual ~grad_funct() {} 00055 00056 /** \brief Compute \c nv functions, \c y, of \c nv variables 00057 stored in \c x with parameter \c pa. 00058 */ 00059 virtual int operator()(size_t nv, vec_t &x, vec_t &y)=0; 00060 00061 #ifndef DOXYGENP 00062 00063 private: 00064 00065 grad_funct(const grad_funct &); 00066 grad_funct& operator=(const grad_funct&); 00067 00068 #endif 00069 00070 }; 00071 00072 /** \brief Function pointer to array of multi-dimensional functions 00073 */ 00074 template<class vec_t=ovector_base> class grad_funct_fptr : 00075 public grad_funct<vec_t> { 00076 00077 public: 00078 00079 grad_funct_fptr() {} 00080 00081 virtual ~grad_funct_fptr() {} 00082 00083 /** \brief Specify the function pointer 00084 */ 00085 grad_funct_fptr(int (*fp)(size_t nv, vec_t &x, vec_t &y)) { 00086 fptr=fp; 00087 } 00088 00089 /** \brief Specify the function pointer 00090 */ 00091 int set_function(int (*fp)(size_t nv, vec_t &x, vec_t &y)) { 00092 fptr=fp; 00093 return 0; 00094 } 00095 00096 /** \brief Compute \c nv functions, \c y, of \c nv variables 00097 stored in \c x with parameter \c pa. 00098 */ 00099 virtual int operator()(size_t nv, vec_t &x, vec_t &y) { 00100 return fptr(nv,x,y); 00101 } 00102 00103 00104 #ifndef DOXYGEN_INTERNAL 00105 00106 protected: 00107 00108 /// The function pointer to the user-supplied function 00109 int (*fptr)(size_t nv, vec_t &x, vec_t &y); 00110 00111 private: 00112 00113 grad_funct_fptr(const grad_funct_fptr &); 00114 grad_funct_fptr& operator=(const grad_funct_fptr&); 00115 00116 #endif 00117 00118 }; 00119 00120 /** \brief Function pointer to array of multi-dimensional functions 00121 */ 00122 template<class param_t, class vec_t=ovector_base> 00123 class grad_funct_fptr_param : 00124 public grad_funct<vec_t> { 00125 00126 public: 00127 00128 grad_funct_fptr_param() {} 00129 00130 virtual ~grad_funct_fptr_param() {} 00131 00132 /** \brief Specify the function pointer 00133 */ 00134 grad_funct_fptr_param(int (*fp) 00135 (size_t nv, vec_t &x, vec_t &y, param_t &), 00136 param_t &pa) { 00137 fptr=fp; 00138 pp=&pa; 00139 } 00140 00141 /** \brief Specify the function pointer 00142 */ 00143 int set_function(int (*fp)(size_t nv, vec_t &x, vec_t &y, param_t &), 00144 param_t &pa) { 00145 fptr=fp; 00146 pp=&pa; 00147 return 0; 00148 } 00149 00150 /** \brief Compute \c nv functions, \c y, of \c nv variables 00151 stored in \c x with parameter \c pa. 00152 */ 00153 virtual int operator()(size_t nv, vec_t &x, vec_t &y) { 00154 return fptr(nv,x,y,*pp); 00155 } 00156 00157 00158 #ifndef DOXYGEN_INTERNAL 00159 00160 protected: 00161 00162 /// The function pointer to the user-supplied function 00163 int (*fptr)(size_t nv, vec_t &x, vec_t &y, param_t &); 00164 00165 /// The parameter 00166 param_t *pp; 00167 00168 private: 00169 00170 grad_funct_fptr_param(const grad_funct_fptr_param &); 00171 grad_funct_fptr_param& operator=(const grad_funct_fptr_param&); 00172 00173 #endif 00174 00175 }; 00176 00177 /** \brief Member function pointer to an array of 00178 multi-dimensional functions 00179 */ 00180 template<class tclass, class vec_t=ovector_base> 00181 class grad_funct_mfptr : public grad_funct<vec_t> { 00182 public: 00183 00184 /** \brief Empty constructor 00185 */ 00186 grad_funct_mfptr() { 00187 } 00188 00189 /** \brief Specify the member function pointer 00190 */ 00191 grad_funct_mfptr(tclass *tp, int (tclass::*fp) 00192 (size_t nv, vec_t &x, vec_t &y)) { 00193 tptr=tp; 00194 fptr=fp; 00195 } 00196 00197 /** \brief Specify the member function pointer 00198 */ 00199 int set_function(tclass *tp, int (tclass::*fp) 00200 (size_t nv, vec_t &x, vec_t &y)) 00201 { 00202 tptr=tp; 00203 fptr=fp; 00204 return 0; 00205 } 00206 00207 virtual ~grad_funct_mfptr() {}; 00208 00209 /** \brief Compute \c nv functions, \c y, of \c nv variables 00210 stored in \c x with parameter \c pa. 00211 */ 00212 virtual int operator()(size_t nv, vec_t &x, vec_t &y) { 00213 return (*tptr.*fptr)(nv,x,y); 00214 } 00215 00216 #ifndef DOXYGEN_INTERNAL 00217 00218 protected: 00219 00220 /// The member function pointer 00221 int (tclass::*fptr)(size_t nv, vec_t &x, vec_t &y); 00222 00223 /// The class pointer 00224 tclass *tptr; 00225 00226 private: 00227 00228 grad_funct_mfptr(const grad_funct_mfptr &); 00229 grad_funct_mfptr& operator=(const grad_funct_mfptr&); 00230 00231 #endif 00232 00233 }; 00234 00235 /** \brief Member function pointer to an array of 00236 multi-dimensional functions 00237 */ 00238 template<class tclass, class param_t, class vec_t=ovector_base> 00239 class grad_funct_mfptr_param : public grad_funct<vec_t> { 00240 public: 00241 00242 /** \brief Empty constructor 00243 */ 00244 grad_funct_mfptr_param() { 00245 } 00246 00247 /** \brief Specify the member function pointer 00248 */ 00249 grad_funct_mfptr_param(tclass *tp, int (tclass::*fp) 00250 (size_t nv, vec_t &x, vec_t &y, param_t &), 00251 param_t &pa) { 00252 tptr=tp; 00253 fptr=fp; 00254 pp=&pa; 00255 } 00256 00257 /** \brief Specify the member function pointer 00258 */ 00259 int set_function(tclass *tp, int (tclass::*fp) 00260 (size_t nv, vec_t &x, vec_t &y, param_t &), 00261 param_t &pa) { 00262 tptr=tp; 00263 fptr=fp; 00264 pp=&pa; 00265 return 0; 00266 } 00267 00268 virtual ~grad_funct_mfptr_param() {}; 00269 00270 /** \brief Compute \c nv functions, \c y, of \c nv variables 00271 stored in \c x with parameter \c pa. 00272 */ 00273 virtual int operator()(size_t nv, vec_t &x, vec_t &y) { 00274 return (*tptr.*fptr)(nv,x,y,*pp); 00275 } 00276 00277 #ifndef DOXYGEN_INTERNAL 00278 00279 protected: 00280 00281 /// The member function pointer 00282 int (tclass::*fptr)(size_t nv, vec_t &x, vec_t &y, param_t &pa); 00283 00284 /// The class pointer 00285 tclass *tptr; 00286 00287 /// Parameter 00288 param_t *pp; 00289 00290 private: 00291 00292 grad_funct_mfptr_param(const grad_funct_mfptr_param &); 00293 grad_funct_mfptr_param& operator=(const grad_funct_mfptr_param&); 00294 00295 #endif 00296 00297 }; 00298 00299 /** \brief Const member function pointer to an array of 00300 multi-dimensional functions 00301 */ 00302 template<class tclass, class vec_t=ovector_base> 00303 class grad_funct_cmfptr : public grad_funct<vec_t> { 00304 00305 public: 00306 00307 /** \brief Empty constructor 00308 */ 00309 grad_funct_cmfptr() { 00310 } 00311 00312 /** \brief Specify the member function pointer 00313 */ 00314 grad_funct_cmfptr(tclass *tp, int (tclass::*fp) 00315 (size_t nv, vec_t &x, vec_t &y) const) { 00316 tptr=tp; 00317 fptr=fp; 00318 } 00319 00320 /** \brief Specify the member function pointer 00321 */ 00322 int set_function(tclass *tp, int (tclass::*fp) 00323 (size_t nv, vec_t &x, vec_t &y) const) 00324 { 00325 tptr=tp; 00326 fptr=fp; 00327 return 0; 00328 } 00329 00330 virtual ~grad_funct_cmfptr() {}; 00331 00332 /** \brief Compute \c nv functions, \c y, of \c nv variables 00333 stored in \c x with parameter \c pa. 00334 */ 00335 virtual int operator()(size_t nv, vec_t &x, vec_t &y) { 00336 return (*tptr.*fptr)(nv,x,y); 00337 } 00338 00339 #ifndef DOXYGEN_INTERNAL 00340 00341 protected: 00342 00343 /// The member function pointer 00344 int (tclass::*fptr)(size_t nv, vec_t &x, vec_t &y) const; 00345 00346 /// The class pointer 00347 tclass *tptr; 00348 00349 private: 00350 00351 grad_funct_cmfptr(const grad_funct_cmfptr &); 00352 grad_funct_cmfptr& operator=(const grad_funct_cmfptr&); 00353 00354 #endif 00355 00356 }; 00357 00358 /** \brief Class for automatically computing gradients [abstract base] 00359 00360 Default template arguments 00361 - \c func_t - (no default) 00362 - \c vec_t - \ref ovector_base 00363 00364 \future Consider making an exact_grad class for computing exact 00365 gradients. 00366 */ 00367 template<class func_t, class vec_t=ovector_base> 00368 class gradient : public grad_funct<vec_t> { 00369 00370 public: 00371 00372 virtual ~gradient() {} 00373 00374 /// Set the function to compute the gradient of 00375 virtual int set_function(func_t &f) { 00376 func=&f; 00377 return 0; 00378 } 00379 00380 /** \brief Compute the gradient \c g at the point \c x 00381 */ 00382 virtual int operator()(size_t nv, vec_t &x, vec_t &g)=0; 00383 00384 #ifndef DOXYGEN_INTERNAL 00385 00386 protected: 00387 00388 /// A pointer to the user-specified function 00389 func_t *func; 00390 00391 #endif 00392 00393 }; 00394 00395 /** \brief Simple automatic computation of gradient by finite 00396 differencing 00397 */ 00398 template<class func_t, class vec_t> class simple_grad : 00399 public gradient<func_t,vec_t> { 00400 00401 public: 00402 00403 simple_grad() { 00404 epsrel=1.0e-6; 00405 epsmin=1.0e-15; 00406 } 00407 00408 virtual ~simple_grad() {} 00409 00410 /** \brief The relative stepsize for finite-differencing 00411 (default \f$ 10^{-6} \f$ ) 00412 */ 00413 double epsrel; 00414 00415 /// The minimum stepsize (default \f$ 10^{-15} \f$) 00416 double epsmin; 00417 00418 /** \brief Compute the gradient \c g at the point \c x 00419 */ 00420 virtual int operator()(size_t nv, vec_t &x, vec_t &g) { 00421 double fv1, fv2, h; 00422 00423 fv1=(*this->func)(nv,x); 00424 00425 for(size_t i=0;i<nv;i++) { 00426 00427 h=epsrel*fabs(x[i]); 00428 if (fabs(h)<=epsmin) h=epsrel; 00429 00430 x[i]+=h; 00431 fv2=(*this->func)(nv,x); 00432 x[i]-=h; 00433 g[i]=(fv2-fv1)/h; 00434 00435 } 00436 00437 return 0; 00438 } 00439 00440 }; 00441 00442 /** \brief Multidimensional minimization [abstract base] 00443 00444 <b>The template parameters:</b> 00445 The template parameter \c func_t specifies the function to 00446 minimize and should be a class containing a definition 00447 \code 00448 func_t::operator()(size_t nv, const vec_t &x, double &f); 00449 \endcode 00450 where \c f is the value of the function at \c x , 00451 where \c x is a array-like class defining \c operator[] of size \c nv. 00452 The parameter \c dfunc_t (if used) should provide the gradient with 00453 \code 00454 func_t::operator()(size_t nv, vec_t &x, vec_t &g); 00455 \endcode 00456 where \c g is the gradient of the function at \c x. 00457 00458 Verbose I/O is sent through \c std::cout and \c std::cin by 00459 default, but this can be modified using \ref 00460 set_verbose_stream(). 00461 */ 00462 template<class func_t, class dfunc_t=func_t, 00463 class vec_t=ovector_base> class multi_min { 00464 00465 #ifndef DOXYGEN_INTERNAL 00466 00467 protected: 00468 00469 /// Stream for verbose output 00470 std::ostream *outs; 00471 00472 /// Stream for verbose input 00473 std::istream *ins; 00474 00475 #endif 00476 00477 public: 00478 00479 multi_min() { 00480 verbose=0; 00481 ntrial=100; 00482 tol_rel=1.0e-4; 00483 tol_abs=1.0e-4; 00484 last_ntrial=0; 00485 err_nonconv=true; 00486 last_conv=0; 00487 outs=&std::cout; 00488 ins=&std::cin; 00489 } 00490 00491 virtual ~multi_min() {} 00492 00493 /// Output control 00494 int verbose; 00495 00496 /// Maximum number of iterations 00497 int ntrial; 00498 00499 /// Function value tolerance 00500 double tol_rel; 00501 00502 /// The independent variable tolerance 00503 double tol_abs; 00504 00505 /// The number of iterations for in the most recent minimization 00506 int last_ntrial; 00507 00508 /// If true, call the error handler if the routine does not "converge" 00509 bool err_nonconv; 00510 00511 /** \brief Zero if last call to mmin() or mmin_de() converged. 00512 00513 This is particularly useful if err_nonconv is false to test 00514 if the last call to mmin() or mmin_de() converged. 00515 */ 00516 int last_conv; 00517 00518 /// Set streams for verbose I/O 00519 int set_verbose_stream(std::ostream &out, std::istream &in) { 00520 outs=&out; 00521 ins=∈ 00522 return 0; 00523 } 00524 00525 /** \brief Calculate the minimum \c min of \c func w.r.t. the 00526 array \c x of size \c nvar. 00527 */ 00528 virtual int mmin(size_t nvar, vec_t &x, double &fmin, 00529 func_t &func)=0; 00530 00531 /** \brief Calculate the minimum \c min of \c func 00532 w.r.t. the array \c x of size \c nvar with gradient 00533 \c dfunc 00534 */ 00535 virtual int mmin_de(size_t nvar, vec_t &x, double &fmin, 00536 func_t &func, dfunc_t &dfunc) 00537 { 00538 return mmin(nvar,x,fmin,func); 00539 } 00540 00541 /** \brief Print out iteration information. 00542 00543 Depending on the value of the variable verbose, this prints out 00544 the iteration information. If verbose=0, then no information is 00545 printed, while if verbose>1, then after each iteration, the 00546 present values of x and y are output to std::cout along with the 00547 iteration number. If verbose>=2 then each iteration waits for a 00548 character. 00549 */ 00550 template<class vec2_t> 00551 int print_iter(size_t nv, vec2_t &x, double y, int iter, 00552 double value, double limit, std::string comment) 00553 { 00554 00555 if (verbose<=0) return 0; 00556 00557 int i; 00558 char ch; 00559 00560 (*outs) << comment << " Iteration: " << iter << std::endl; 00561 { 00562 (*outs) << "x: " << std::endl; 00563 for(i=0;i<((int)nv);i++) (*outs) << x[i] << " "; 00564 (*outs) << std::endl; 00565 } 00566 (*outs) << "y: " << y << " Val: " << value << " Lim: " 00567 << limit << std::endl; 00568 if (verbose>1) { 00569 (*outs) << "Press a key and type enter to continue. "; 00570 (*ins) >> ch; 00571 } 00572 00573 return 0; 00574 } 00575 00576 /// Return string denoting type ("multi_min") 00577 const char *type() { return "multi_min"; } 00578 00579 }; 00580 00581 #ifndef DOXYGENP 00582 } 00583 #endif 00584 00585 #endif 00586
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).