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{stepsize} (2 u_i - 1) + x_{i,\mathrm{old}}
00041       \f]
00042       where the \f$u_i\f$ are random numbers between 0 and 1.  The
00043       random number generator and temperature schedule are set in the
00044       parent, sim_anneal.  The variables minimize::tolx and
00045       minimize::tolf are not used
00046 
00047       \todo Implement different stepsizes for the different dimensions
00048 
00049       \future Implement a more general routine which would allow
00050       the solution of discrete problems like the Traveling Salesman
00051       problem.
00052       
00053   */
00054   template<class param_t, class func_t, class vec_t=ovector_view,
00055     class rng_t=gsl_rnga> class gsl_anneal :
00056     public sim_anneal<param_t,func_t,vec_t,rng_t> {
00057       public:
00058 
00059       virtual ~gsl_anneal() {}
00060       
00061       /** \brief Calculate the minimum \c fmin of \c func w.r.t the 
00062           array \c x0 of size \c nvar.
00063       */
00064       virtual int mmin(size_t nvar, vec_t &x0, double &fmin, param_t &pa,
00065                        func_t &func) 
00066       {
00067         
00068         fmin=0.0;
00069 
00070         allocate(nvar);
00071 
00072         double E, new_E, best_E, T;
00073         int i, iter=0;
00074         bool done;
00075         size_t j;
00076 
00077         for(j=0;j<nvar;j++) {
00078           x[j]=x0[j];
00079           best_x[j]=x0[j];
00080         }
00081     
00082         E=func(nvar,x,pa);
00083         best_E=E;
00084   
00085         T=this->tp->start(0.0,0,x0,NULL);
00086         done=false;
00087 
00088         while (!done) {
00089           for (i=0;i<this->ntrial;++i) {
00090             for (j=0;j<nvar;j++) new_x[j]=x[j];
00091       
00092             step(new_x,nvar);
00093             new_E=func(nvar,new_x,pa);
00094       
00095             if(new_E<=best_E){
00096               for(j=0;j<nvar;j++) best_x[j]=new_x[j];
00097               best_E=new_E;
00098             }
00099       
00100             // Take the crucial step: see if the new point is accepted
00101             // or not, as determined by the boltzman probability
00102             if (new_E<E) {
00103               for(j=0;j<nvar;j++) x[j]=new_x[j];
00104               E=new_E;
00105             } else if (this->def_rng.random() < exp(-(new_E-E)/(boltz*T)) ) {
00106               for(j=0;j<nvar;j++) x[j]=new_x[j];
00107               E=new_E;
00108             }
00109           }
00110     
00111           if (this->verbose>0) {
00112             this->print_iter(nvar,best_x,best_E,iter,T,"gsl_anneal");
00113             iter++;
00114           }
00115     
00116           // apply the cooling schedule to the temperature
00117           T=this->tp->next(0.0,0,x0,NULL);
00118           if (this->tp->done(0.0,0,x0,NULL)) {
00119             done=true;
00120           }
00121         }
00122   
00123         for(j=0;j<nvar;j++) x0[j]=best_x[j];
00124         fmin=best_E;
00125 
00126         free();
00127   
00128         return 0;
00129       }
00130       
00131       /// Return string denoting type ("gsl_anneal")
00132       virtual const char *type() { return "gsl_anneal"; }
00133 
00134       /// Size of step (default 10.0).
00135       double step_size;
00136 
00137       /// Boltzmann factor (default 1.0).
00138       double boltz;
00139 
00140 #ifndef DOXYGEN_INTERNAL
00141       
00142       protected:
00143       
00144       /// \name Storage for present, next, and best vectors
00145       //@{
00146       ovector x, new_x, best_x;
00147       //@}
00148 
00149       /** \brief Allocate memory for a minimizer over \c n dimensions
00150           with stepsize \c step and Boltzmann factor \c boltz_factor 
00151       */
00152       int allocate(size_t n, double ustep=10.0, double boltz_factor=1.0) {
00153         x.allocate(n);
00154         new_x.allocate(n);
00155         best_x.allocate(n);
00156         step_size=ustep;
00157         boltz=boltz_factor;
00158         return 0;
00159       }
00160 
00161       /// Free allocated memory
00162       int free() {
00163         x.free();
00164         new_x.free();
00165         best_x.free();
00166         return 0;
00167       }
00168 
00169       /// Make a step to a new attempted minimum
00170       int step(vec_t &sx, int nvar) {
00171         for(int i=0;i<nvar;i++) {
00172           double u=this->def_rng.random();
00173           sx[i]=2.0*u*step_size-step_size+sx[i];
00174         }
00175         return 0;
00176       }
00177   
00178 #endif
00179 
00180     };
00181 
00182 #ifndef DOXYGENP
00183 }
00184 #endif
00185 
00186 #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