GeneticAlgorithm.cxx

Go to the documentation of this file.
00001 // @(#)root/tmva $Id: GeneticAlgorithm.cxx 35719 2010-09-24 17:32:57Z stelzer $    
00002 // Author: Peter Speckmayer
00003 
00004 /**********************************************************************************
00005  * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
00006  * Package: TMVA                                                                  *
00007  * Class  : TMVA::GeneticAlgorithm                                                *
00008  * Web    : http://tmva.sourceforge.net                                           *
00009  *                                                                                *
00010  * Description:                                                                   *
00011  *      Implementation (see header for description)                               *
00012  *                                                                                *
00013  * Authors (alphabetical):                                                        *
00014  *      Peter Speckmayer <speckmay@mail.cern.ch> - CERN, Switzerland              *
00015  *                                                                                *
00016  * Copyright (c) 2005:                                                            *
00017  *      CERN, Switzerland                                                         *
00018  *      MPI-K Heidelberg, Germany                                                 *
00019  *                                                                                *
00020  * Redistribution and use in source and binary forms, with or without             *
00021  * modification, are permitted according to the terms listed in LICENSE           *
00022  * (http://tmva.sourceforge.net/LICENSE)                                          *
00023  **********************************************************************************/
00024 
00025 //_______________________________________________________________________
00026 //                                                                      
00027 // Base definition for genetic algorithm                                
00028 //_______________________________________________________________________
00029 
00030 #include <iostream>
00031 #include <algorithm>
00032 #include <float.h>
00033 
00034 #ifdef _GLIBCXX_PARALLEL
00035 #include <omp.h>
00036 #endif
00037 
00038 #include "TMVA/GeneticAlgorithm.h"
00039 #include "TMVA/Interval.h"
00040 #include "TMVA/IFitterTarget.h"
00041 
00042 #include "TMVA/MsgLogger.h"
00043 
00044 namespace TMVA {
00045    const Bool_t GeneticAlgorithm__DEBUG__ = kFALSE;
00046 }
00047 
00048 ClassImp(TMVA::GeneticAlgorithm)
00049    
00050 //_______________________________________________________________________
00051 TMVA::GeneticAlgorithm::GeneticAlgorithm( IFitterTarget& target, Int_t populationSize, 
00052                                           const std::vector<Interval*>& ranges, UInt_t seed )
00053    : fConvCounter(-1),
00054      fFitterTarget( target ),
00055      fConvValue(0.),
00056      fLastResult(DBL_MAX),
00057      fSpread(0.1),
00058      fMirror(kTRUE),
00059      fFirstTime(kTRUE),
00060      fMakeCopies(kFALSE),
00061      fPopulationSize(populationSize),
00062      fRanges( ranges ),
00063      fPopulation(ranges, populationSize, seed),
00064      fBestFitness(DBL_MAX),
00065      fLogger( new MsgLogger("GeneticAlgorithm") )
00066 {
00067    // Constructor
00068    // Parameters: 
00069    //     int populationSize : defines the number of "Individuals" which are created and tested 
00070    //                          within one Generation (Iteration of the Evolution)
00071    //     vector<TMVA::Interval*> ranges : Interval holds the information of an interval, where the GetMin 
00072    //                          gets the low and GetMax gets the high constraint of the variable
00073    //                          the size of "ranges" is the number of coefficients which are optimised
00074    // Purpose: 
00075    //     Creates a random population with individuals of the size ranges.size()
00076    fPopulation.SetRandomSeed( seed );
00077 }
00078 
00079 TMVA::GeneticAlgorithm::~GeneticAlgorithm() 
00080 {
00081    // destructor; deletes fLogger
00082    delete fLogger;
00083 }
00084 
00085 
00086 //_______________________________________________________________________
00087 void TMVA::GeneticAlgorithm::Init()
00088 {
00089    // calls evolution, but if it is not the first time. 
00090    // If it's the first time, the random population created by the
00091    // constructor is still not evaluated, .. therefore we wait for the 
00092    // second time init is called. 
00093    if ( fFirstTime ) fFirstTime = kFALSE;
00094    else {
00095       Evolution();
00096    }
00097 }
00098 
00099 //_______________________________________________________________________
00100 Double_t TMVA::GeneticAlgorithm::NewFitness( Double_t /*oldValue*/, Double_t newValue )
00101 {
00102    // if the "fitnessFunction" is called multiple times for one set of 
00103    // factors (because i.e. each event of a TTree has to be assessed with 
00104    // each set of Factors proposed by the Genetic Algorithm) the value 
00105    // of the current calculation has to be added(? or else) to the value
00106    // obtained up to now. 
00107    // example: some chi-square is calculated for every event, 
00108    // after every event the new chi-square (newValue) has to be simply
00109    // added to the oldValue. 
00110    //
00111    // this function has to be overridden eventually 
00112    // it might contain only the following return statement.
00113    //        return oldValue + newValue;
00114    return newValue;
00115 }
00116 
00117 //_______________________________________________________________________
00118 Double_t TMVA::GeneticAlgorithm::CalculateFitness()
00119 {
00120    // starts the evaluation of the fitness of all different individuals of
00121    // the population. 
00122    //
00123    // this function calls implicitly (many times) the "fitnessFunction" which
00124    // has been overridden by the user. 
00125    fBestFitness = DBL_MAX;
00126 #ifdef _GLIBCXX_PARALLEL
00127 
00128    const int nt = omp_get_num_threads();
00129    Double_t bests[nt];
00130    for ( int i =0; i < nt; ++i )
00131       bests[i] = fBestFitness;
00132 
00133 #pragma omp parallel
00134    {
00135       int thread_number = omp_get_thread_num();
00136 #pragma omp for
00137       for ( int index = 0; index < fPopulation.GetPopulationSize(); ++index )
00138       {
00139          GeneticGenes* genes = fPopulation.GetGenes(index);
00140          Double_t fitness = NewFitness( genes->GetFitness(), 
00141                                         fFitterTarget.EstimatorFunction(genes->GetFactors()) );
00142          genes->SetFitness( fitness );
00143          
00144          if ( bests[thread_number] > fitness )
00145             bests[thread_number] = fitness;
00146       }
00147    }
00148    
00149    fBestFitness = *std::min_element(bests, bests+nt);
00150 
00151 #else 
00152 
00153    for ( int index = 0; index < fPopulation.GetPopulationSize(); ++index ) {
00154       GeneticGenes* genes = fPopulation.GetGenes(index);
00155       Double_t fitness = NewFitness( genes->GetFitness(),
00156                                      fFitterTarget.EstimatorFunction(genes->GetFactors()) );
00157       genes->SetFitness( fitness );
00158       
00159       if ( fBestFitness  > fitness )
00160          fBestFitness = fitness;
00161       
00162    }
00163 
00164 #endif
00165 
00166    fPopulation.Sort();
00167 
00168    return fBestFitness; 
00169 }
00170 
00171 //_______________________________________________________________________
00172 void TMVA::GeneticAlgorithm::Evolution()
00173 {
00174    // this function is called from "init" and controls the evolution of the 
00175    // individuals. 
00176    // the function can be overridden to change the parameters for mutation rate
00177    // sexual reproduction and so on.
00178    if ( fMakeCopies ) 
00179       fPopulation.MakeCopies( 5 );
00180    fPopulation.MakeChildren();
00181 
00182    fPopulation.Mutate( 10, 3, kTRUE, fSpread, fMirror );
00183    fPopulation.Mutate( 40, fPopulation.GetPopulationSize()*3/4 );
00184 }
00185 
00186 //_______________________________________________________________________
00187 Double_t TMVA::GeneticAlgorithm::SpreadControl( Int_t ofSteps, Int_t successSteps, Double_t factor )
00188 {
00189    // this function provides the ability to change the stepSize of a mutation according to
00190    // the success of the last generations. 
00191    // 
00192    // Parameters:
00193    //      int ofSteps :  = if OF the number of STEPS given in this variable (ofSteps)
00194    //      int successSteps : >sucessSteps Generations could improve the result
00195    //      double factor : than multiply the stepSize ( spread ) by this factor
00196    // (if ofSteps == successSteps nothing is changed, if ofSteps < successSteps, the spread
00197    // is divided by the factor) 
00198    //
00199    // using this function one can increase the stepSize of the mutation when we have 
00200    // good success (to pass fast through the easy phase-space) and reduce the stepSize
00201    // if we are in a difficult "territory" of the phase-space. 
00202    //
00203 
00204    // < is valid for "less" comparison
00205    if ( fBestFitness < fLastResult || fSuccessList.size() <=0 ) { 
00206       fLastResult = fBestFitness;
00207       fSuccessList.push_front( 1 ); // it got better
00208    } 
00209    else {
00210       fSuccessList.push_front( 0 ); // it stayed the same
00211    }
00212    Int_t n = 0;
00213    Int_t sum = 0;
00214    std::deque<Int_t>::iterator vec = fSuccessList.begin();
00215    for (; vec<fSuccessList.end() ; vec++) {
00216       sum += *vec;
00217       n++;
00218    }
00219 
00220    if ( n >= ofSteps ) {
00221       fSuccessList.pop_back();
00222       if ( sum > successSteps ) { // too much success
00223          fSpread /= factor;
00224          if (GeneticAlgorithm__DEBUG__) Log() << kINFO << ">" << std::flush;
00225       }
00226       else if ( sum == successSteps ) { // on the optimal path
00227          if (GeneticAlgorithm__DEBUG__) Log() << "=" << std::flush;
00228       }
00229       else {        // not very successful
00230          fSpread *= factor;
00231          if (GeneticAlgorithm__DEBUG__) Log() << "<" << std::flush;
00232       }
00233    }
00234 
00235    return fSpread;
00236 }
00237 
00238 //_______________________________________________________________________
00239 Bool_t TMVA::GeneticAlgorithm::HasConverged( Int_t steps, Double_t improvement )
00240 {
00241    // gives back true if the last "steps" steps have lead to an improvement of the
00242    // "fitness" of the "individuals" of at least "improvement"
00243    // 
00244    // this gives a simple measure of if the fitness of the individuals is
00245    // converging and no major improvement is to be expected soon. 
00246    //
00247    if (fConvCounter < 0) {
00248       fConvValue = fBestFitness;
00249    }
00250    if (TMath::Abs(fBestFitness - fConvValue) <= improvement || steps<0) {
00251       fConvCounter ++;
00252    } 
00253    else {
00254       fConvCounter = 0;
00255       fConvValue = fBestFitness;
00256    }
00257    if (GeneticAlgorithm__DEBUG__) Log() << "." << std::flush;
00258    if (fConvCounter < steps) return kFALSE;
00259    return kTRUE;
00260 }

Generated on Tue Jul 5 15:25:00 2011 for ROOT_528-00b_version by  doxygen 1.5.1