Object-oriented Scientific Computing Library: Version 0.910
multi_min.h
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=&in;
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 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.