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