00001 // @(#)root/tmva $Id: TMVAGAexample.cxx 31458 2009-11-30 13:58:20Z stelzer $ 00002 /********************************************************************************** 00003 * Project : TMVA - a Root-integrated toolkit for multivariate data analysis * 00004 * Package : TMVA * 00005 * Exectuable: TMVAGAexample * 00006 * * 00007 * This exectutable gives an example of a very simple use of the genetic algorithm* 00008 * of TMVA * 00009 * * 00010 **********************************************************************************/ 00011 00012 #include <iostream> // Stream declarations 00013 #include <vector> 00014 00015 #include "TMVA/GeneticAlgorithm.h" 00016 #include "TMVA/GeneticFitter.h" 00017 #include "TMVA/IFitterTarget.h" 00018 00019 using namespace std; 00020 00021 namespace TMVA { 00022 00023 00024 class MyFitness : public IFitterTarget { 00025 public: 00026 MyFitness() : IFitterTarget() { 00027 } 00028 00029 // the fitness-function goes here 00030 // the factors are optimized such that the return-value of this function is minimized 00031 // take care!! the fitness-function must never fail, .. means: you have to prevent 00032 // the function from reaching undefined values (such as x=0 for 1/x or so) 00033 // 00034 // HINT: to use INTEGER variables, it is sufficient to cast the "factor" in the fitness-function 00035 // to (int). In this case the variable-range has to be chosen +1 ( to get 0..5, take Interval(0,6) ) 00036 // since the introduction of "Interval" ranges can be defined with a third parameter 00037 // which gives the number of bins within the interval. With that technique discrete values 00038 // can be achieved easier. The random selection out of this discrete numbers is completly uniform. 00039 // 00040 Double_t EstimatorFunction( std::vector<Double_t> & factors ){ 00041 //return (10.- (int)factors.at(0) *factors.at(1) + (int)factors.at(2)); 00042 return (10.- factors.at(0) *factors.at(1) + factors.at(2)); 00043 00044 //return 100.- (10 + factors.at(1)) *factors.at(2)* TMath::Abs( TMath::Sin(factors.at(0)) ); 00045 } 00046 }; 00047 00048 00049 class MyGA2nd : public GeneticAlgorithm { 00050 public: 00051 MyGA2nd( IFitterTarget& target, Int_t size, vector<Interval*>& ranges ) : GeneticAlgorithm(target, 00052 size, ranges ){ 00053 } 00054 00055 00056 // this method has to be activated if one wants to change the behaviour of the evolution 00057 // works only with the head version 00058 //void Evolution(){ 00059 // fSexual = true; 00060 // if (fSexual) { 00061 // fPopulation.MakeCopies( 5 ); 00062 // fPopulation.MakeChildren(); 00063 // fPopulation.NextGeneration(); 00064 00065 // fPopulation.Mutate( 10, 3, kTRUE, fSpread, fMirror ); 00066 // fPopulation.Mutate( 40, fPopulation.GetPopulationSize()*3/4 ); 00067 // } else { 00068 // fPopulation.MakeCopies( 3 ); 00069 // fPopulation.MakeMutants(100,true, 0.1, true); 00070 // fPopulation.NextGeneration(); 00071 // } 00072 // } 00073 }; 00074 00075 00076 00077 void exampleGA2nd(){ 00078 std::cout << "\n2nd EXAMPLE" << std::endl; 00079 // define all the parameters by their minimum and maximum value 00080 // in this example 3 parameters are defined. 00081 vector<Interval*> ranges; 00082 ranges.push_back( new Interval(0,15,30) ); 00083 ranges.push_back( new Interval(0,13) ); 00084 ranges.push_back( new Interval(0,5,3) ); 00085 00086 for( std::vector<Interval*>::iterator it = ranges.begin(); it != ranges.end(); it++ ){ 00087 std::cout << " range: " << (*it)->GetMin() << " " << (*it)->GetMax() << std::endl; 00088 } 00089 00090 IFitterTarget* myFitness = new MyFitness(); 00091 00092 // prepare the genetic algorithm with an initial population size of 20 00093 // mind: big population sizes will help in searching the domain space of the solution 00094 // but you have to weight this out to the number of generations 00095 // the extreme case of 1 generation and populationsize n is equal to 00096 // a Monte Carlo calculation with n tries 00097 00098 MyGA2nd mg( *myFitness, 100, ranges ); 00099 // mg.SetParameters( 4, 30, 200, 10,5, 0.95, 0.001 ); 00100 00101 #define CONVSTEPS 20 00102 #define CONVCRIT 0.0001 00103 #define SCSTEPS 10 00104 #define SCRATE 5 00105 #define SCFACTOR 0.95 00106 00107 do { 00108 // prepares the new generation and does evolution 00109 mg.Init(); 00110 00111 // assess the quality of the individuals 00112 mg.CalculateFitness(); 00113 00114 mg.GetGeneticPopulation().Print(0); 00115 // std::cout << "---" << std::endl; 00116 00117 // reduce the population size to the initially defined one 00118 mg.GetGeneticPopulation().TrimPopulation(); 00119 00120 // tricky thing: control the speed of how fast the "solution space" is searched through 00121 // this function basically influences the sigma of a gaussian around the actual value 00122 // of the parameter where the new value will be randomly thrown. 00123 // when the number of improvements within the last SCSTEPS 00124 // A) smaller than SCRATE: divide the preset sigma by SCFACTOR 00125 // B) equal to SCRATE: do nothing 00126 // C) greater than SCRATE: multiply the preset sigma by SCFACTOR 00127 // if you don't know what to do, leave it unchanged or even delete this function call 00128 mg.SpreadControl( SCSTEPS, SCRATE, SCFACTOR ); 00129 00130 } while (!mg.HasConverged( CONVSTEPS, CONVCRIT )); // converged if: fitness-improvement < CONVCRIT within the last CONVSTEPS loops 00131 00132 GeneticGenes* genes = mg.GetGeneticPopulation().GetGenes( 0 ); 00133 std::vector<Double_t> gvec; 00134 gvec = genes->GetFactors(); 00135 int n = 0; 00136 for( std::vector<Double_t>::iterator it = gvec.begin(); it<gvec.end(); it++ ){ 00137 std::cout << "FACTOR " << n << " : " << (*it) << std::endl; 00138 n++; 00139 } 00140 } 00141 00142 00143 00144 } // namespace TMVA 00145 00146 int main( int argc, char** argv ) 00147 { 00148 cout << "Start Test TMVAGAexample" << endl 00149 << "========================" << endl 00150 << endl; 00151 00152 TMVA::exampleGA2nd(); 00153 }