00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 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_NAIVE_METROPOLIS_H 00024 #define O2SCL_NAIVE_METROPOLIS_H 00025 00026 #include <iostream> 00027 #include <o2scl/collection.h> 00028 #include <o2scl/funct.h> 00029 #include <o2scl/mcarlo_inte.h> 00030 #include <o2scl/gsl_rnga.h> 00031 00032 #ifndef DOXYGENP 00033 namespace o2scl { 00034 #endif 00035 00036 /** 00037 \brief Naive metropolis monte carlo integration 00038 00039 Very experimental. 00040 00041 This returns the ratio of n-dimensional integrals 00042 \f[ 00043 I = \frac{\int f(\vec{x}) \exp\left[-\beta~w(\vec{x})\right] d \vec{x}} 00044 {\int \exp\left[-\beta~w(\vec{x})\right] d \vec{x}} 00045 \f] 00046 for function \f$ f \f$ specified in \c func and \f$ w \f$ 00047 specified in \c weight. 00048 00049 A "Metropolis step" (or simply a "step") is defined by 00050 the following procedure: The step \f$ \vec{x}_0 \rightarrow 00051 \vec{x}_1 \f$ is accepted if 00052 \f[ 00053 w(\vec{x}_1)<w_(\vec{x}_0) 00054 \f] 00055 or if 00056 \f[ 00057 e^{-\beta \left[w(\vec{x}_1)-w_(\vec{x}_0)\right]}>r 00058 \f] 00059 where \f$ r \f$ is a uniform random number \f$ [0,1) \f$ newly 00060 generated for each step. 00061 00062 \ref nstart steps are taken initially to ensure the first point 00063 is created with the correct probability. Afterwards, the 00064 average value of the function is stored over \ref niter steps. 00065 This average value is computed \ref nblock times to get 00066 an overall average and an estimate of the uncertainity. 00067 00068 \todo Talk about how accurate this is with \f$ \beta \f$ . 00069 \todo Redo statistics, talk about how many times the integral 00070 is evaluated. 00071 \todo Offer an option of giving more results 00072 than just the final averange and error? 00073 00074 \b Minimization 00075 00076 There is a connection between integration over functions of this 00077 type and minimization. The expression 00078 \f[ 00079 \lim_{T \rightarrow 0} 00080 \frac{\int_{x=a}^{x=b} f(x) e^{-f(x)/T}} 00081 {\int_{x=a}^{x=b} e^{-f(x)/T}} 00082 \f] 00083 gives the minimum of the function \f$ f(x) \f$ in the region 00084 \f$ x \in (a,b) \f$ . 00085 00086 */ 00087 template<class param_t, class func_t, class rng_t, 00088 class vec_t, class alloc_vec_t> class naive_metropolis : 00089 public mcarlo_inte<param_t,func_t,rng_t,vec_t> 00090 00091 { 00092 public: 00093 00094 rng_t rng; 00095 00096 naive_metropolis() { 00097 nblock=10; 00098 niter=10000; 00099 nstart=1000; 00100 } 00101 00102 virtual ~naive_metropolis() {} 00103 00104 /** 00105 \brief Calculate the integral returning result in \c value 00106 00107 Calculates the integral given the functions \c func and \c weight 00108 over the region specified by \c a and \c b, both of side \c ndim. 00109 The value of \f$ \beta \f$ is specified in \c beta, and the 00110 result is returned in \c value, with the uncertainty given 00111 in \c err. 00112 */ 00113 virtual int minteg_err(func_t &func, func_t &energy, size_t ndim, 00114 const vec_t &a, const vec_t &b, 00115 const double beta, double &value, double &err, 00116 param_t &pa) 00117 { 00118 double value2=0.0, bvalue; 00119 alloc_vec_t x, xnew; 00120 00121 value=0.0; 00122 00123 // Choose a random starting point 00124 for(size_t i=0;i<ndim;i++) { 00125 x[i]=rng.random()*(b[i]-a[i])+a[i]; 00126 } 00127 00128 // Take several steps to ensure independence 00129 // from the starting point 00130 for(size_t n=0;n<nstart;n++) { 00131 00132 // Pick a new point 00133 for(size_t i=0;i<ndim;i++) { 00134 xnew[i]=rng.random()*(b[i]-a[i])+a[i]; 00135 } 00136 00137 // Take a step 00138 double dw=energy(ndim,xnew,pa)-energy(ndim,x,pa); 00139 if (dw<0 || exp(-beta*dw)>rng.random()) { 00140 for(size_t i=0;i<ndim;i++) { 00141 x[i]=xnew[i]; 00142 } 00143 } 00144 00145 } 00146 00147 for(unsigned long int ib=0;ib<nblock;ib++) { 00148 00149 bvalue=0.0; 00150 00151 // Integrate the function 00152 for(size_t n=0;n<niter;n++) { 00153 double t=func(ndim,x,pa); 00154 bvalue+=t; 00155 00156 // Pick a new point 00157 for(size_t i=0;i<ndim;i++) { 00158 xnew[i]=rng.random()*(b[i]-a[i])+a[i]; 00159 } 00160 00161 // Decide to accept or reject 00162 double dw=energy(ndim,xnew,pa)-energy(ndim,x,pa); 00163 if (dw<0 || exp(-beta*dw)>rng.random()) { 00164 for(size_t i=0;i<ndim;i++) { 00165 x[i]=xnew[i]; 00166 } 00167 } 00168 } 00169 00170 bvalue/=((double)niter); 00171 value+=bvalue; 00172 value2+=bvalue*bvalue; 00173 00174 } 00175 00176 value/=((double)nblock); 00177 value2/=((double)nblock); 00178 err=sqrt(fabs(value2-value*value)); 00179 00180 return 0; 00181 } 00182 00183 /** 00184 \brief Calculate the integral returning result in \c value 00185 00186 Calculates the integral given the functions \c func and \c weight 00187 over the region specified by \c a and \c b, both of side \c ndim. 00188 The value of \f$ \beta \f$ is specified in \c beta, and the 00189 result is returned in \c value, with the uncertainty given 00190 in \c err. 00191 */ 00192 virtual int minteg_array(func_t &func, func_t &energy, size_t ndim, 00193 const vec_t &a, const vec_t &b, 00194 const double beta, vec_t &results, param_t &pa) 00195 { 00196 double value2=0.0, bvalue; 00197 alloc_vec_t x, xnew; 00198 00199 unsigned long int ix=0; 00200 00201 // Choose a random starting point 00202 for(size_t i=0;i<ndim;i++) { 00203 x[i]=rng.random()*(b[i]-a[i])+a[i]; 00204 } 00205 00206 // Take several steps to ensure independence 00207 // from the starting point 00208 for(size_t n=0;n<nstart;n++) { 00209 00210 // Pick a new point 00211 for(size_t i=0;i<ndim;i++) { 00212 xnew[i]=rng.random()*(b[i]-a[i])+a[i]; 00213 } 00214 00215 // Take a step 00216 double dw=energy(ndim,xnew,pa)-energy(ndim,x,pa); 00217 if (dw<0 || exp(-beta*dw)>rng.random()) { 00218 for(size_t i=0;i<ndim;i++) { 00219 x[i]=xnew[i]; 00220 } 00221 } 00222 00223 } 00224 00225 for(unsigned long int ib=0;ib<nblock;ib++) { 00226 00227 bvalue=0.0; 00228 00229 // Integrate the function 00230 for(size_t n=0;n<niter;n++) { 00231 double t=func(ndim,x,pa); 00232 bvalue+=t; 00233 00234 // Pick a new point 00235 for(size_t i=0;i<ndim;i++) { 00236 xnew[i]=rng.random()*(b[i]-a[i])+a[i]; 00237 } 00238 00239 // Decide to accept or reject 00240 double dw=energy(ndim,xnew,pa)-energy(ndim,x,pa); 00241 if (dw<0 || exp(-beta*dw)>rng.random()) { 00242 for(size_t i=0;i<ndim;i++) { 00243 x[i]=xnew[i]; 00244 } 00245 } 00246 } 00247 00248 results[ix]=bvalue; 00249 ix++; 00250 00251 } 00252 00253 return 0; 00254 } 00255 00256 /// The number of iterations (default 10000) 00257 unsigned long int niter; 00258 00259 /// The number of warm-up iterations (default 1000) 00260 unsigned long int nstart; 00261 00262 /// Number of blocks (default 10) 00263 unsigned long int nblock; 00264 }; 00265 00266 #ifndef DOXYGENP 00267 } 00268 #endif 00269 00270 #endif 00271 00272 00273 00274 00275 00276
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