gsl_anneal.h

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 SourceForge.net Logo, O2scl Sourceforge Project Page