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_GSL_ANNEAL_H 00024 #define O2SCL_GSL_ANNEAL_H 00025 00026 #include <o2scl/sim_anneal.h> 00027 #include <gsl/gsl_rng.h> 00028 #include <gsl/gsl_siman.h> 00029 00030 #ifndef DOXYGENP 00031 namespace o2scl { 00032 #endif 00033 00034 /** 00035 \brief Multidimensional minimization by simulated annealing (GSL) 00036 00037 Minimize by simulated annealing for an arbitrary temperature 00038 schedule and random number generator. A move is defined by 00039 \f[ 00040 x_{i,\mathrm{new}} = \mathrm{step\_size}_i 00041 (2 u_i - 1) + x_{i,\mathrm{old}} 00042 \f] 00043 where the \f$u_i\f$ are random numbers between 0 and 1. The 00044 random number generator and temperature schedule are set in the 00045 parent, sim_anneal. The variables minimize::tolx and 00046 minimize::tolf are not used 00047 00048 The step size for each dimension is specified in \ref 00049 set_stepsize(). The number of stepsizes specified need not be 00050 the same as the number of dimensions. If \c nstep is the number 00051 of stepsizes, then the stepsize for dimension \c i is 00052 \code 00053 step_size[i % nstep] 00054 \endcode 00055 00056 \comment 00057 Note that I don't make a direct reference to "nstep" here 00058 since it's protected, and I want the documentation to 00059 work even if the protected part is hidden. 00060 \endcomment 00061 00062 \future Implement a more general simulated annealing routine 00063 which would allow the solution of discrete problems like the 00064 Traveling Salesman problem. 00065 \future Implement a method which automatically minimizes 00066 within some specified tolerance? 00067 00068 */ 00069 template<class param_t, class func_t, class vec_t=ovector_view, 00070 class alloc_vec_t=ovector, class alloc_t=ovector_alloc, 00071 class rng_t=gsl_rnga> class gsl_anneal : 00072 public sim_anneal<param_t,func_t,vec_t,rng_t> { 00073 public: 00074 00075 gsl_anneal() { 00076 nstep=1; 00077 step_sizes=new double[1]; 00078 step_sizes[0]=10.0; 00079 } 00080 00081 virtual ~gsl_anneal() { 00082 delete[] step_sizes; 00083 } 00084 00085 /** \brief Calculate the minimum \c fmin of \c func w.r.t the 00086 array \c x0 of size \c nvar. 00087 */ 00088 virtual int mmin(size_t nvar, vec_t &x0, double &fmin, param_t &pa, 00089 func_t &func) 00090 { 00091 00092 fmin=0.0; 00093 00094 allocate(nvar); 00095 00096 double E, new_E, best_E, T; 00097 int i, iter=0; 00098 bool done; 00099 size_t j; 00100 00101 for(j=0;j<nvar;j++) { 00102 x[j]=x0[j]; 00103 best_x[j]=x0[j]; 00104 } 00105 00106 E=func(nvar,x,pa); 00107 best_E=E; 00108 00109 T=this->tp->start(0.0,0,x0,NULL); 00110 done=false; 00111 00112 while (!done) { 00113 for (i=0;i<this->ntrial;++i) { 00114 for (j=0;j<nvar;j++) new_x[j]=x[j]; 00115 00116 step(new_x,nvar); 00117 new_E=func(nvar,new_x,pa); 00118 00119 if(new_E<=best_E){ 00120 for(j=0;j<nvar;j++) best_x[j]=new_x[j]; 00121 best_E=new_E; 00122 } 00123 00124 // Take the crucial step: see if the new point is accepted 00125 // or not, as determined by the boltzman probability 00126 if (new_E<E) { 00127 for(j=0;j<nvar;j++) x[j]=new_x[j]; 00128 E=new_E; 00129 } else if (this->def_rng.random() < exp(-(new_E-E)/(boltz*T)) ) { 00130 for(j=0;j<nvar;j++) x[j]=new_x[j]; 00131 E=new_E; 00132 } 00133 } 00134 00135 if (this->verbose>0) { 00136 this->print_iter(nvar,best_x,best_E,iter,T,"gsl_anneal"); 00137 iter++; 00138 } 00139 00140 // apply the cooling schedule to the temperature 00141 T=this->tp->next(0.0,0,x0,NULL); 00142 if (this->tp->done(0.0,0,x0,NULL)) { 00143 done=true; 00144 } 00145 } 00146 00147 for(j=0;j<nvar;j++) x0[j]=best_x[j]; 00148 fmin=best_E; 00149 00150 free(); 00151 00152 return 0; 00153 } 00154 00155 /// Return string denoting type ("gsl_anneal") 00156 virtual const char *type() { return "gsl_anneal"; } 00157 00158 /// Set the step 00159 template<class vec2_t> int set_stepsize(size_t n, vec2_t &ss) { 00160 if (n!=0) { 00161 delete[] step_sizes; 00162 step_sizes=new double[n]; 00163 for(size_t i=0;i<n;i++) { 00164 step_sizes[i]=ss[i]; 00165 } 00166 nstep=n; 00167 return 0; 00168 } 00169 set_err_ret("Cannot set zero stepsizes in set_stepsize().",gsl_einval); 00170 } 00171 00172 /// Boltzmann factor (default 1.0). 00173 double boltz; 00174 00175 #ifndef DOXYGEN_INTERNAL 00176 00177 protected: 00178 00179 /// \name Storage for present, next, and best vectors 00180 //@{ 00181 alloc_vec_t x, new_x, best_x; 00182 //@} 00183 00184 /// Allocation object 00185 alloc_t ao; 00186 00187 /// Number of step sizes 00188 size_t nstep; 00189 00190 /// Step sizes 00191 double *step_sizes; 00192 00193 /** \brief Allocate memory for a minimizer over \c n dimensions 00194 with stepsize \c step and Boltzmann factor \c boltz_factor 00195 */ 00196 virtual int allocate(size_t n, double boltz_factor=1.0) { 00197 ao.allocate(x,n); 00198 ao.allocate(new_x,n); 00199 ao.allocate(best_x,n); 00200 boltz=boltz_factor; 00201 return 0; 00202 } 00203 00204 /// Free allocated memory 00205 virtual int free() { 00206 ao.free(x); 00207 ao.free(new_x); 00208 ao.free(best_x); 00209 return 0; 00210 } 00211 00212 /// Make a step to a new attempted minimum 00213 virtual int step(vec_t &sx, int nvar) { 00214 for(int i=0;i<nvar;i++) { 00215 double u=this->def_rng.random(); 00216 sx[i]=(2.0*u-1.0)*step_sizes[i%nstep]+sx[i]; 00217 } 00218 return 0; 00219 } 00220 00221 #endif 00222 00223 }; 00224 00225 #ifndef DOXYGENP 00226 } 00227 #endif 00228 00229 #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