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