Object-oriented Scientific Computing Library: Version 0.910
cern_minimize.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_CERN_MINIMIZE_H
00024 #define O2SCL_CERN_MINIMIZE_H
00025 
00026 #include <o2scl/funct.h>
00027 #include <o2scl/minimize.h>
00028 
00029 #ifndef DOXYGENP
00030 namespace o2scl {
00031 #endif
00032 
00033   /** \brief One-dimensional minimization (CERNLIB)
00034 
00035       The golden section search is applied in the interval \f$ (a,b) \f$ 
00036       using a fixed number \f$ n \f$ of function evaluations where 
00037       \f[
00038       n=\left[ 2.08 \ln(|a-b|/\mathrm{tol\_abs})+\frac{1}{2}\right]+1 
00039       \f]
00040       
00041       The accuracy depends on the function. A choice of \f$
00042       \mathrm{tol\_abs}>10^{-8} \f$ usually results in a relative error of
00043       $x$ which is smaller than or of the order of \f$ \mathrm{tol\_abs}
00044       \f$ .
00045       
00046       This routine strictly searches the interval \f$ (a,b) \f$ . If
00047       the function is nowhere flat in this interval, then min_bkt()
00048       will return either \f$ a \f$ or \f$ b \f$ and \ref min_type
00049       is set to 1. Note that if there are more than 1 local minima
00050       in the specified interval, there is no guarantee that this
00051       method will find the global minimum. 
00052       
00053       \note The number of function evaluations can be quite large if
00054       multi_min::tol_abs is sufficiently small. If multi_min::tol_abs is 
00055       exactly zero, then the error handler will be called.
00056 
00057       \comment
00058       If multi_min::tol_abs is exactly zero, then \f$ 10^{-8} \f$ 
00059       will be used instead.
00060       [5/23/11 - Changed this consistent with the policy of
00061       throwing on incorrect input.]
00062       \endcomment
00063 
00064       Based on the CERNLIB routines RMINFC and DMINFC, which was 
00065       based on \ref Fletcher87, and \ref Krabs83 and is documented at
00066       http://wwwasdoc.web.cern.ch/wwwasdoc/shortwrupsdir/d503/top.html
00067   */
00068 #ifdef DOXYGENP
00069   template<class func_t=funct> class cern_minimize : 
00070   public minimize_bkt
00071 #else
00072     template<class func_t=funct > class cern_minimize :
00073   public minimize_bkt<func_t> 
00074 #endif
00075     {
00076       
00077 #ifndef DOXGYEN_INTERNAL
00078 
00079       protected:
00080 
00081       /// C analog of Fortran's "Nearest integer" function 
00082       inline int nint(double x) {
00083         if (x<0.0) return ((int)(x-0.5));
00084         else return ((int)(x+0.5));
00085       }
00086     
00087 #endif      
00088 
00089     public:
00090       
00091       cern_minimize() {
00092         delta_set=false;
00093         min_type=0;
00094       }
00095     
00096       /** \brief Calculate the minimum \c min of \c func between
00097           \c a and \c b
00098           
00099           The initial value of \c x is ignored.
00100           
00101           If there is no minimum in the given interval, then on exit
00102           \c x will be equal to either \c a or \c b and \ref min_type
00103           will be set to 1 instead of zero. The error handler is not
00104           called, as this need not be interpreted as an error.
00105       */
00106       virtual int min_bkt(double &x, double a, double b, double &y,
00107                           func_t &func) {
00108       
00109         // The square root of 5
00110         static const double w5=2.23606797749979;
00111         static const double hv=(3.0-w5)/2.0, hw=(w5-1.0)/2.0;
00112         double c, d, v=0.0, fv=0.0, w=0.0, fw=0.0, h;
00113       
00114         if (!delta_set) delta=10.0*this->tol_abs;
00115         
00116         int n=-1;
00117         if (this->tol_abs==0.0) {
00118           O2SCL_ERR_RET("Tolerance zero in cern_minimize::min_bkt().",
00119                         gsl_einval);
00120         } else {
00121           if (a!=b) n=nint(2.0*log(fabs((a-b)/this->tol_abs)));
00122         }
00123         this->last_ntrial=n;
00124         c=a;
00125         d=b;
00126         if (a>b) {
00127           c=b;
00128           d=a;
00129         }
00130         bool llt=true, lge=true;
00131       
00132         // This is never an infinite loop so long as 'n' is finite. We
00133         // should maybe check somehow that 'n' is not too large
00134         while (true) {
00135           h=d-c;
00136           if (this->verbose>0) {
00137             x=(c+d)/2.0;
00138             y=func(x);
00139             this->print_iter(x,y,this->last_ntrial-n,((double)n),this->tol_abs,
00140                              "cern_minimize");
00141           }
00142           if (n<0) {
00143             x=(c+d)/2.0;
00144             y=func(x);
00145             if ((fabs(x-a)>delta && fabs(x-b)>delta)) min_type=0;
00146             min_type=1;
00147             return 0;
00148           }
00149           if (llt) {
00150             v=c+hv*h;
00151             fv=func(v);
00152           }
00153           if (lge) {
00154             w=c+hw*h;
00155             fw=func(w);
00156           }
00157           if (fv<fw) {
00158             llt=true;
00159             lge=false;
00160             d=w;
00161             w=v;
00162             fw=fv;
00163           } else {
00164             llt=false;
00165             lge=true;
00166             c=v;
00167             v=w;
00168             fv=fw;
00169           }
00170           n--;
00171         }
00172 
00173         O2SCL_ERR("Failed sanity check in cern_minimize::min_bkt().",
00174                   gsl_esanity);
00175         return gsl_esanity;
00176       }
00177     
00178       /** \brief Set the value of \f$ \delta \f$ 
00179           
00180           If this is not called before min_bkt() is used, then the
00181           suggested value \f$ \delta=10 \mathrm{tol_abs} \f$ is used.
00182       */
00183       int set_delta(double d) {
00184         if (d>0.0) {
00185           delta=d;
00186           delta_set=true;
00187         }
00188         return 0;
00189       }
00190     
00191       /// Return string denoting type ("cern_minimize")
00192       virtual const char *type() { return "cern_minimize"; }
00193 
00194       /// Type of minimum found
00195       int min_type;
00196 
00197     protected:
00198 
00199 #ifndef DOXYGEN_INTERNAL
00200 
00201       /// The value of delta as specified by the user
00202       double delta;
00203 
00204       /// True if the value of delta has been set
00205       bool delta_set;
00206 
00207 #endif
00208 
00209     };
00210 
00211 #ifndef DOXYGENP
00212 }
00213 #endif
00214 
00215 #endif
 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.