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