GeneticMinimizer.cxx

Go to the documentation of this file.
00001 #include "Math/GeneticMinimizer.h"
00002 
00003 #include "TMVA/GeneticAlgorithm.h"
00004 #include "TMVA/IFitterTarget.h"
00005 
00006 #include "Math/IFunction.h"
00007 #include "Math/GenAlgoOptions.h"
00008 
00009 #include "TError.h"
00010 
00011 #include <cassert>
00012 
00013 namespace ROOT {
00014 namespace Math {
00015    
00016 
00017 // wrapper class for TMVA interface to evaluate objective function
00018 class MultiGenFunctionFitness : public TMVA::IFitterTarget {
00019 private:
00020    unsigned int fNCalls;
00021    const ROOT::Math::IMultiGenFunction& fFunc;
00022 
00023 public:
00024    MultiGenFunctionFitness(const ROOT::Math::IMultiGenFunction& function) : fFunc(function) { fNCalls = 0; }
00025 
00026    unsigned int NCalls() const { return fNCalls; }
00027    unsigned int NDims() const { return fFunc.NDim(); }
00028 
00029    Double_t Evaluate(const std::vector<double> & factors ) const {
00030       return fFunc(&factors[0]);
00031    }
00032 
00033    Double_t EstimatorFunction(std::vector<double> & factors ){
00034       fNCalls += 1;
00035       return fFunc(&factors[0]);
00036    }
00037 };
00038 
00039 GeneticMinimizerParameters::GeneticMinimizerParameters() 
00040 { 
00041    // constructor of parameters with default values
00042    fNsteps   = 40;
00043    fPopSize  =300;
00044    fCycles   = 3;
00045    fSC_steps =10;
00046    fSC_rate  =5;
00047    fSC_factor=0.95;
00048    fConvCrit =10.0 * ROOT::Math::MinimizerOptions::DefaultTolerance(); // default is 0.001
00049    if (fConvCrit <=0 ) fConvCrit = 0.001; 
00050 
00051 }
00052 
00053    GeneticMinimizer::GeneticMinimizer(int ): 
00054       fFitness(0), 
00055       fParameters(GeneticMinimizerParameters() )
00056 {
00057 
00058    // check with default minimizer options
00059    ROOT::Math::IOptions * geneticOpt = ROOT::Math::MinimizerOptions::FindDefault("Genetic");
00060    if (geneticOpt) { 
00061       ROOT::Math::MinimizerOptions opt; // create using default options
00062       opt.SetExtraOptions(*geneticOpt);
00063       this->SetOptions(opt);
00064    } 
00065  }
00066 
00067 GeneticMinimizer::~GeneticMinimizer()
00068 {
00069    if ( fFitness )
00070    {
00071       delete fFitness;
00072       fFitness = 0;
00073    }
00074 }
00075 
00076 void GeneticMinimizer::Clear() 
00077 {
00078    fRanges.clear();
00079    fResult.clear();
00080    if ( fFitness )
00081    {
00082       delete fFitness;
00083       fFitness = 0;
00084    }
00085 }
00086 
00087 void GeneticMinimizer::SetFunction(const ROOT::Math::IMultiGenFunction & func) 
00088 {
00089    Clear();
00090 
00091    fFitness = new MultiGenFunctionFitness(func);
00092 }  
00093 
00094 bool GeneticMinimizer::SetLimitedVariable(unsigned int , const std::string & , double , double , double lower , double upper ) 
00095 { 
00096    fRanges.push_back( new TMVA::Interval(lower,upper) );
00097 
00098    return true;
00099 }
00100 
00101 bool GeneticMinimizer::SetVariable(unsigned int, const std::string&, double value, double step) 
00102 {
00103    //It does nothing! As there is no variable if it has no limits!
00104    Info("GeneticMinimizer::SetVariable", "Variables should be limited on a Genetic Minimizer - set automatic range to 50 times step size");
00105    fRanges.push_back( new TMVA::Interval(value - (50 * step), value + (50 * step)) );
00106    
00107    return true;
00108 }
00109 
00110 void GeneticMinimizer::SetParameters(const GeneticMinimizerParameters & params )
00111 {
00112    fParameters  = params; 
00113 }
00114 
00115 ROOT::Math::MinimizerOptions GeneticMinimizer::Options() const { 
00116    ROOT::Math::MinimizerOptions opt; 
00117    GetGeneticOptions(opt);
00118    return opt; 
00119 }
00120 
00121 void  GeneticMinimizer::GetGeneticOptions(ROOT::Math::MinimizerOptions & opt) const { 
00122    // get  the genetic options of the class and return them in the MinimizerOptions class
00123    opt.SetTolerance(fParameters.fConvCrit/10); // use a factor of 10 to have default as Minuit
00124    opt.SetPrintLevel(PrintLevel() );   
00125    opt.SetMaxFunctionCalls(MaxIterations());  // this is different than nsteps
00126    // use fixed or dammy value for the other options
00127    opt.SetMinimizerType("Genetic");
00128    opt.SetMaxFunctionCalls(0);
00129    opt.SetStrategy(-1);
00130    opt.SetErrorDef(0);
00131    opt.SetPrecision(0);
00132    opt.SetMinimizerAlgorithm("");
00133 
00134    ROOT::Math::GenAlgoOptions geneticOpt; 
00135    geneticOpt.SetValue("PopSize",fParameters.fPopSize);
00136    geneticOpt.SetValue("Steps",fParameters.fNsteps);
00137    geneticOpt.SetValue("Cycles",fParameters.fCycles);
00138    geneticOpt.SetValue("SC_steps",fParameters.fSC_steps);
00139    geneticOpt.SetValue("SC_rate",fParameters.fSC_rate);
00140    geneticOpt.SetValue("SC_factor",fParameters.fSC_factor);
00141    geneticOpt.SetValue("ConvCrit",fParameters.fConvCrit);
00142 
00143    opt.SetExtraOptions(geneticOpt);   
00144 }
00145 
00146 void GeneticMinimizer::SetOptions(const ROOT::Math::MinimizerOptions & opt) 
00147 {
00148    SetTolerance(opt.Tolerance() );
00149    SetPrintLevel(opt.PrintLevel() );
00150    //SetMaxFunctionCalls(opt.MaxFunctionCalls() );
00151    SetMaxIterations(opt.MaxIterations() );
00152 
00153    fParameters.fConvCrit = 10.*opt.Tolerance(); // use a factor of 10 to have default as Minuit
00154 
00155    // set genetic parameter from minimizer options 
00156    ROOT::Math::IOptions * geneticOpt = opt.ExtraOptions(); 
00157    if (!geneticOpt) { 
00158       Warning("GeneticMinimizer::SetOptions", "No specific genetic minimizer options have been set"); 
00159       return; 
00160    }
00161 
00162    // if options are not existing values will not be set
00163    geneticOpt->GetValue("PopSize",fParameters.fPopSize);
00164    geneticOpt->GetValue("Steps",fParameters.fNsteps);
00165    geneticOpt->GetValue("Cycles",fParameters.fCycles);
00166    geneticOpt->GetValue("SC_steps",fParameters.fSC_steps);
00167    geneticOpt->GetValue("SC_rate",fParameters.fSC_rate);
00168    geneticOpt->GetValue("SC_factor",fParameters.fSC_factor);
00169    geneticOpt->GetValue("ConvCrit",fParameters.fConvCrit);
00170 
00171    // use same of options in base class
00172    int maxiter = MaxIterations();
00173    if ( maxiter > 0 &&  maxiter < fParameters.fNsteps )    {
00174       Warning("GeneticMinimizer::SetOptions", "max iterations smaller than Steps - set equal to steps %d",fParameters.fNsteps); 
00175       SetMaxIterations(fParameters.fNsteps);
00176    }
00177 
00178 
00179 }
00180 
00181 bool GeneticMinimizer::Minimize() 
00182 {
00183 
00184    if (!fFitness) {
00185       Error("GeneticMinimizer::Minimize","Fitness function has not been set"); 
00186       return false; 
00187    }
00188 
00189    TMVA::GeneticAlgorithm mg( *fFitness, fParameters.fPopSize, fRanges );
00190 
00191    if (PrintLevel() > 0) { 
00192       Info("GeneticMinimizer::Minimize","Start iterating - max iterations = %d , conv criteria (tolerance) = %10e6 ",
00193            MaxIterations() ,  fParameters.fConvCrit );
00194    }
00195    
00196    fStatus = 0;
00197    unsigned int niter = 0; 
00198    do {
00199       mg.Init();
00200       
00201       mg.CalculateFitness();
00202       
00203       // Just for debugging options
00204       //mg.GetGeneticPopulation().Print(0);
00205       
00206       mg.GetGeneticPopulation().TrimPopulation();
00207       
00208       mg.SpreadControl( fParameters.fSC_steps, fParameters.fSC_rate, fParameters.fSC_factor );
00209 
00210       if (PrintLevel() > 2) { 
00211          std::cout << "New Iteration " << niter << " with  parameter values :" << std::endl;
00212          TMVA::GeneticGenes* genes = mg.GetGeneticPopulation().GetGenes( 0 );
00213          if (genes) { 
00214             std::vector<Double_t> gvec;
00215             gvec = genes->GetFactors(); 
00216             for (unsigned int i = 0; i < gvec.size(); ++i) {
00217                std::cout << gvec[i] << "    ";
00218             }
00219             std::cout << std::endl;
00220             std::cout << "\tFitness function value = " <<  static_cast<MultiGenFunctionFitness*>(fFitness)->Evaluate(gvec) << std::endl;
00221          }                     
00222       } 
00223       niter++;
00224       if ( niter > MaxIterations() && MaxIterations() > 0) { 
00225          if (PrintLevel() > 0) { 
00226             Info("GeneticMinimizer::Minimize","Max number of iterations %d reached - stop iterating",MaxIterations());
00227          }
00228          fStatus = 1; 
00229          break;
00230       }
00231       
00232    } while (!mg.HasConverged( fParameters.fNsteps, fParameters.fConvCrit ));  // converged if: fitness-improvement < CONVCRIT within the last CONVSTEPS loops
00233    
00234    TMVA::GeneticGenes* genes = mg.GetGeneticPopulation().GetGenes( 0 );
00235    std::vector<Double_t> gvec;
00236    gvec = genes->GetFactors();
00237 
00238    fResult = gvec;   
00239 
00240 
00241    if (PrintLevel() > 0) { 
00242       if (PrintLevel() > 2) std::cout << std::endl;
00243           std::cout << "Finished Iteration (niter = " << niter << "  with fitness function value = " << MinValue() << std::endl;
00244       for (unsigned int i = 0; i < fResult.size(); ++i) {
00245          std::cout << " Parameter-" << i << "\t=\t" << fResult[i] << std::endl;
00246       }
00247    }
00248 
00249    return true;
00250 }  
00251 
00252 double GeneticMinimizer::MinValue() const 
00253 {
00254    if ( fFitness )
00255       return static_cast<MultiGenFunctionFitness*>(fFitness)->Evaluate(fResult);
00256    else
00257       return 0;
00258 }  
00259 
00260 const double *  GeneticMinimizer::X() const { return &fResult[0]; }  
00261 
00262 unsigned int GeneticMinimizer::NCalls() const 
00263 {
00264    if ( fFitness )
00265       return static_cast<MultiGenFunctionFitness*>(fFitness)->NCalls();
00266    else
00267       return 0;
00268 }
00269 
00270 unsigned int GeneticMinimizer::NDim() const 
00271 {
00272    if ( fFitness )
00273       return static_cast<MultiGenFunctionFitness*>(fFitness)->NDims();
00274    else
00275       return 0;
00276 }   
00277 unsigned int GeneticMinimizer::NFree() const 
00278 {
00279    // They should be the same in this case!
00280    return NDim();
00281 }   
00282 
00283 // Functions we don't need...
00284 const double *  GeneticMinimizer::MinGradient() const { return 0; }   
00285 bool GeneticMinimizer::ProvidesError() const { return false; }  
00286 const double * GeneticMinimizer::Errors() const { return 0; }
00287 double GeneticMinimizer::Edm() const { return 0; }
00288 double GeneticMinimizer::CovMatrix(unsigned int, unsigned int) const { return 0; }
00289 
00290 }
00291 }

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