00001 // @(#)root/mathmore:$Id: GSLSimAnnealing.h 21553 2007-12-21 10:55:46Z moneta $ 00002 // Author: L. Moneta Thu Jan 25 11:13:48 2007 00003 00004 /********************************************************************** 00005 * * 00006 * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT * 00007 * * 00008 * This library is free software; you can redistribute it and/or * 00009 * modify it under the terms of the GNU General Public License * 00010 * as published by the Free Software Foundation; either version 2 * 00011 * of the License, or (at your option) any later version. * 00012 * * 00013 * This library 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 GNU * 00016 * General Public License for more details. * 00017 * * 00018 * You should have received a copy of the GNU General Public License * 00019 * along with this library (see file COPYING); if not, write * 00020 * to the Free Software Foundation, Inc., 59 Temple Place, Suite * 00021 * 330, Boston, MA 02111-1307 USA, or contact the author. * 00022 * * 00023 **********************************************************************/ 00024 00025 // Header file for class GSLSimAnnealing 00026 00027 #ifndef ROOT_Math_GSLSimAnnealing 00028 #define ROOT_Math_GSLSimAnnealing 00029 00030 #include "Math/IFunctionfwd.h" 00031 00032 #include <vector> 00033 00034 namespace ROOT { 00035 00036 namespace Math { 00037 00038 class GSLRandomEngine; 00039 00040 //_____________________________________________________________________________ 00041 /** 00042 GSLSimAnFunc class description. 00043 Interface class for the objetive function to be used in simulated annealing 00044 If user wants to re-implement some of the methods (like the one defining the metric) which are used by the 00045 the simulated annealing algorithm must build a user derived class. 00046 NOTE: Derived classes must re-implement the assignment and copy constructor to call them of the parent class 00047 00048 @ingroup MultiMin 00049 */ 00050 class GSLSimAnFunc { 00051 public: 00052 00053 /** 00054 construct from an interface of a multi-dimensional function 00055 */ 00056 GSLSimAnFunc(const ROOT::Math::IMultiGenFunction & func, const double * x); 00057 00058 /** 00059 construct from an interface of a multi-dimensional function 00060 Use optionally a scale factor (for each coordinate) which can be used to scale the step sizes 00061 (this is used for example by the minimization algorithm) 00062 */ 00063 GSLSimAnFunc(const ROOT::Math::IMultiGenFunction & func, const double * x, const double * scale); 00064 00065 protected: 00066 00067 /** 00068 derived classes might need to re-define completly the class 00069 */ 00070 GSLSimAnFunc() : 00071 fFunc(0) 00072 {} 00073 00074 public: 00075 00076 00077 /// virtual distructor (no operations) 00078 virtual ~GSLSimAnFunc() { } // 00079 00080 00081 /** 00082 fast copy method called by GSL simuated annealing internally 00083 copy only the things which have been changed 00084 must be re-implemented by derived classes if needed 00085 */ 00086 virtual GSLSimAnFunc & FastCopy(const GSLSimAnFunc & f); 00087 00088 00089 /** 00090 clone method. Needs to be re-implemented by the derived classes for deep copying 00091 */ 00092 virtual GSLSimAnFunc * Clone() const { 00093 return new GSLSimAnFunc(*this); 00094 } 00095 00096 /** 00097 evaluate the energy ( objective function value) 00098 re-implement by derived classes if needed to be modified 00099 */ 00100 virtual double Energy() const; 00101 00102 /** 00103 change the x[i] value using a random value urndm generated between [0,1] 00104 up to a maximum value maxstep 00105 re-implement by derived classes if needed to be modified 00106 */ 00107 virtual void Step(const GSLRandomEngine & r, double maxstep); 00108 00109 /** 00110 calculate the distance (metric) between this one and another configuration 00111 Presently a cartesian metric is used. 00112 re-implement by derived classes if needed to be modified 00113 */ 00114 virtual double Distance(const GSLSimAnFunc & func) const; 00115 00116 /** 00117 print the position in the standard output ostream 00118 GSL prints in addition n iteration, n function calls, temperature and energy 00119 re-implement by derived classes if necessary 00120 */ 00121 virtual void Print(); 00122 00123 /** 00124 change the x values (used by sim annealing to take a step) 00125 */ 00126 void SetX(const double * x) { 00127 std::copy(x, x+ fX.size(), fX.begin() ); 00128 } 00129 00130 template <class IT> 00131 void SetX(IT begin, IT end) { 00132 std::copy(begin, end, fX.begin() ); 00133 } 00134 00135 unsigned int NDim() const { return fX.size(); } 00136 00137 double X(unsigned int i) const { return fX[i]; } 00138 00139 const std::vector<double> & X() const { return fX; } 00140 00141 double Scale(unsigned int i) const { return fScale[i]; } 00142 00143 void SetX(unsigned int i, double x) { fX[i] = x; } 00144 00145 // use compiler generated copy ctror and assignment operators 00146 00147 private: 00148 00149 std::vector<double> fX; 00150 std::vector<double> fScale; 00151 const ROOT::Math::IMultiGenFunction * fFunc; 00152 00153 }; 00154 00155 //_____________________________________________________ 00156 /** 00157 structure holding the simulated annealing parameters 00158 00159 @ingroup MultiMin 00160 */ 00161 struct GSLSimAnParams { 00162 00163 // constructor with some default values 00164 GSLSimAnParams() { 00165 n_tries = 200; 00166 iters_fixed_T = 10; 00167 step_size = 10; 00168 // the following parameters are for the Boltzmann distribution */ 00169 k = 1.0; 00170 t_initial = 0.002; 00171 mu = 1.005; 00172 t_min = 2.0E-6; 00173 } 00174 00175 00176 int n_tries; // number of points to try for each step 00177 int iters_fixed_T; // number of iterations at each temperature 00178 double step_size; // max step size used in random walk 00179 /// parameters for the Boltzman distribution 00180 double k; 00181 double t_initial; 00182 double mu; 00183 double t_min; 00184 }; 00185 00186 //___________________________________________________________________________ 00187 /** 00188 GSLSimAnnealing class for performing a simulated annealing search of 00189 a multidimensional function 00190 00191 @ingroup MultiMin 00192 */ 00193 class GSLSimAnnealing { 00194 00195 public: 00196 00197 /** 00198 Default constructor 00199 */ 00200 GSLSimAnnealing (); 00201 00202 /** 00203 Destructor (no operations) 00204 */ 00205 ~GSLSimAnnealing () {} 00206 00207 private: 00208 // usually copying is non trivial, so we make this unaccessible 00209 00210 /** 00211 Copy constructor 00212 */ 00213 GSLSimAnnealing(const GSLSimAnnealing &) {} 00214 00215 /** 00216 Assignment operator 00217 */ 00218 GSLSimAnnealing & operator = (const GSLSimAnnealing & rhs) { 00219 if (this == &rhs) return *this; // time saving self-test 00220 return *this; 00221 } 00222 00223 public: 00224 00225 00226 /** 00227 solve the simulated annealing given a multi-dim function, the initial vector parameters 00228 and a vector containing the scaling factors for the parameters 00229 */ 00230 int Solve(const ROOT::Math::IMultiGenFunction & func, const double * x0, const double * scale, double * xmin, bool debug = false); 00231 00232 /** 00233 solve the simulated annealing given a GSLSimAnFunc object 00234 The object will contain the initial state at the beginning and the final minimum state at the end 00235 */ 00236 int Solve(GSLSimAnFunc & func, bool debug = false); 00237 00238 00239 GSLSimAnParams & Params() { return fParams; } 00240 const GSLSimAnParams & Params() const { return fParams; } 00241 00242 00243 protected: 00244 00245 00246 private: 00247 00248 GSLSimAnParams fParams; // parameters for GSLSimAnnealig 00249 00250 }; 00251 00252 } // end namespace Math 00253 00254 } // end namespace ROOT 00255 00256 00257 #endif /* ROOT_Math_GSLSimAnnealing */