GSLSimAnnealing.cxx

Go to the documentation of this file.
00001 // @(#)root/mathmore:$Id: GSLSimAnnealing.cxx 20882 2007-11-19 11:31:26Z rdm $
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  *                                                                    *
00009  **********************************************************************/
00010 
00011 // Implementation file for class GSLSimAnnealing
00012 
00013 #include "Math/GSLSimAnnealing.h"
00014 
00015 #include "gsl/gsl_siman.h"
00016 
00017 #include "Math/IFunction.h"
00018 #include "Math/GSLRndmEngines.h"
00019 #include "GSLRngWrapper.h"
00020 
00021 
00022 #include <cassert> 
00023 #include <iostream> 
00024 #include <cmath> 
00025 #include <vector>
00026 
00027 namespace ROOT { 
00028 
00029    namespace Math { 
00030 
00031 
00032 // implementation of GSLSimAnFunc
00033 
00034 GSLSimAnFunc::GSLSimAnFunc(const ROOT::Math::IMultiGenFunction & func, const double * x) : 
00035    fX( std::vector<double>(x, x + func.NDim() ) ), 
00036    fScale( std::vector<double>(func.NDim() )), 
00037    fFunc(&func)
00038 {
00039    // set scale factors to 1
00040    fScale.assign(fScale.size(), 1.);
00041 }
00042 
00043 GSLSimAnFunc::GSLSimAnFunc(const ROOT::Math::IMultiGenFunction & func, const double * x, const double * scale) : 
00044    fX( std::vector<double>(x, x + func.NDim() ) ), 
00045    fScale( std::vector<double>(scale, scale + func.NDim() ) ), 
00046    fFunc(&func) 
00047 {}
00048 
00049       
00050 double GSLSimAnFunc::Energy() const { 
00051    // evaluate the energy
00052    return   (*fFunc)(&fX.front() );
00053 }
00054 
00055 void GSLSimAnFunc::Step(const GSLRandomEngine & random, double maxstep) { 
00056    // x  -> x + Random[-step,step]     for each coordinate
00057    unsigned int ndim = NDim();
00058    for (unsigned int i = 0; i < ndim; ++i) { 
00059       double urndm = random(); 
00060       double sstep = maxstep * fScale[i];
00061       fX[i] +=  2 * sstep * urndm - sstep; 
00062    }
00063 }
00064 
00065 
00066 double GSLSimAnFunc::Distance(const GSLSimAnFunc & f) const { 
00067    // calculate the distance with respect onother configuration
00068    const std::vector<double> & x = fX;
00069    const std::vector<double> & y = f.X();
00070    unsigned int n = x.size();
00071    assert (n == y.size());
00072    if (n > 1) { 
00073       double d2 = 0; 
00074       for (unsigned int i = 0; i < n; ++i) 
00075          d2 += ( x[i] - y[i] ) * ( x[i] - y[i] ); 
00076       return std::sqrt(d2); 
00077    }
00078    else 
00079       // avoid doing a sqrt for 1 dim
00080       return std::abs( x[0] - y[0] );
00081 } 
00082 
00083 void GSLSimAnFunc::Print() { 
00084    // print the position  x in standard ostream 
00085    // GSL prints also niter-  ntrials - temperature and then the energy and energy min value (from 1.10)
00086    std::cout << "\tx = ( "; 
00087    unsigned n = NDim(); 
00088    for (unsigned int i = 0; i < n-1; ++i) { 
00089       std::cout << fX[i] << " , "; 
00090    }
00091    std::cout << fX.back() << " )\t";
00092    // energy us printed by GSL (and also end-line) 
00093    std::cout << "E  / E_best = ";   // GSL print then E and E best  
00094 }
00095 
00096 GSLSimAnFunc &  GSLSimAnFunc::FastCopy(const GSLSimAnFunc & rhs) { 
00097    // copy only the information which is changed during the process 
00098    // in this case only the x values 
00099    std::copy(rhs.fX.begin(), rhs.fX.end(), fX.begin() ); 
00100    return *this;
00101 }
00102 
00103 
00104 
00105 // definition and implementations of the static functions required by GSL 
00106 
00107 namespace GSLSimAn { 
00108 
00109 
00110    double E( void * xp) { 
00111       // evaluate the energy given a state xp 
00112       GSLSimAnFunc * fx = reinterpret_cast<GSLSimAnFunc *> (xp); 
00113       assert (fx != 0);
00114       return fx->Energy(); 
00115    }
00116 
00117    void Step( const gsl_rng * r, void * xp, double step_size) { 
00118       // change xp according to  the random step 
00119       GSLSimAnFunc * fx = reinterpret_cast<GSLSimAnFunc *> (xp); 
00120       assert (fx != 0);      
00121       // create GSLRandomEngine class 
00122       // cast away constness (we make sure we don't delete (no call to Terminate() )
00123       GSLRngWrapper  rng(const_cast<gsl_rng *>(r));
00124       GSLRandomEngine random(&rng);
00125       // wrapper classes random and rng must exist during call to Step()
00126       fx->Step(random, step_size);
00127    }
00128  
00129    double Dist( void * xp, void * yp) { 
00130       // calculate the distance between two configuration
00131       GSLSimAnFunc * fx = reinterpret_cast<GSLSimAnFunc *> (xp); 
00132       GSLSimAnFunc * fy = reinterpret_cast<GSLSimAnFunc *> (yp); 
00133       
00134       assert (fx != 0);
00135       assert (fy != 0);
00136       return fx->Distance(*fy);
00137    }
00138 
00139    void Print(void * xp) { 
00140       // print the position  xp
00141       // GSL prints also first niter-  ntrials - temperature and then the energy 
00142       GSLSimAnFunc * fx = reinterpret_cast<GSLSimAnFunc *> (xp); 
00143       assert (fx != 0);
00144       fx->Print();
00145    }   
00146 
00147 // static function to pass to GSL copy - create and destroy the object 
00148    
00149    void Copy( void * source, void * dest) { 
00150       GSLSimAnFunc * fx = reinterpret_cast<GSLSimAnFunc *> (source); 
00151       assert (fx != 0);
00152       GSLSimAnFunc * gx = reinterpret_cast<GSLSimAnFunc *> (dest); 
00153       assert (gx != 0);
00154       gx->FastCopy(*fx); 
00155    }
00156 
00157    void * CopyCtor( void * xp) { 
00158       GSLSimAnFunc * fx = reinterpret_cast<GSLSimAnFunc *> (xp); 
00159       assert (fx != 0);
00160       return static_cast<void *> ( fx->Clone() ); 
00161    }
00162 
00163    void Destroy( void * xp) { 
00164       GSLSimAnFunc * fx = reinterpret_cast<GSLSimAnFunc *> (xp); 
00165       assert (fx != 0);
00166       delete fx; 
00167    }
00168 
00169 }
00170 
00171 // implementation of GSLSimAnnealing class 
00172 
00173 
00174 GSLSimAnnealing::GSLSimAnnealing() 
00175 {
00176    // Default constructor implementation.
00177 }
00178 
00179 
00180 
00181 // function for solving (from a Genfunction interface)  
00182 
00183 int GSLSimAnnealing::Solve(const ROOT::Math::IMultiGenFunction & func, const double * x0, const double * scale, double * xmin, bool debug) { 
00184    // solve the simulated annealing problem given starting point and objective function interface
00185     
00186 
00187    // initial conditions
00188    GSLSimAnFunc   fx(func, x0, scale); 
00189 
00190    int iret =  Solve(fx, debug); 
00191 
00192    if (iret == 0) { 
00193       // copy value of the minimum in xmin
00194       std::copy(fx.X().begin(), fx.X().end(), xmin);
00195    }
00196    return iret; 
00197 
00198 }
00199 
00200 int GSLSimAnnealing::Solve(GSLSimAnFunc & fx, bool debug) { 
00201    // solve the simulated annealing problem given starting point and GSLSimAnfunc object
00202     
00203    gsl_rng * r = gsl_rng_alloc(gsl_rng_mt19937); 
00204 
00205 
00206 
00207    gsl_siman_params_t simanParams; 
00208 
00209    // parameters for the simulated annealing
00210    // copy them in GSL structure
00211 
00212    simanParams.n_tries =        fParams.n_tries;     /* how many points to try for each step */
00213    simanParams.iters_fixed_T =  fParams.iters_fixed_T;  /* how many iterations at each temperature? */ 
00214    simanParams.step_size =      fParams.step_size;     /* max step size in the random walk */
00215    // the following parameters are for the Boltzmann distribution */
00216    simanParams.k =              fParams.k;  
00217    simanParams.t_initial =      fParams.t_initial; 
00218    simanParams.mu_t =           fParams.mu;
00219    simanParams.t_min =          fParams.t_min;
00220 
00221 
00222    if (debug) 
00223       gsl_siman_solve(r, &fx, &GSLSimAn::E, &GSLSimAn::Step, &GSLSimAn::Dist, 
00224                    &GSLSimAn::Print, &GSLSimAn::Copy, &GSLSimAn::CopyCtor , &GSLSimAn::Destroy, 0, simanParams );
00225 
00226    else 
00227       gsl_siman_solve(r, &fx, &GSLSimAn::E, &GSLSimAn::Step, &GSLSimAn::Dist, 
00228                    0, &GSLSimAn::Copy, &GSLSimAn::CopyCtor , &GSLSimAn::Destroy, 0, simanParams );
00229 
00230    return 0; 
00231 
00232 }
00233 
00234 
00235 
00236 
00237    } // end namespace Math
00238 
00239 } // end namespace ROOT
00240 

Generated on Tue Jul 5 14:34:57 2011 for ROOT_528-00b_version by  doxygen 1.5.1