// @(#)root/tmva $Id$    
// Author: Peter Speckmayer

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : TMVA::GeneticPopulation                                               *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Implementation (see header for description)                               *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Peter Speckmayer <speckmay@mail.cern.ch> - CERN, Switzerland              *
 *                                                                                *
 * Copyright (c) 2005:                                                            *
 *      CERN, Switzerland                                                         *
 *      MPI-K Heidelberg, Germany                                                 *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without             *
 * modification, are permitted according to the terms listed in LICENSE           *
 * (http://tmva.sourceforge.net/LICENSE)                                          *
 **********************************************************************************/

#include <iostream>
#include <iomanip>

#include "Rstrstream.h"
#include "TSystem.h"
#include "TRandom3.h"
#include "TH1.h"
#include <algorithm>

#include "TMVA/GeneticPopulation.h"
#include "TMVA/GeneticGenes.h"
#include "TMVA/MsgLogger.h"

ClassImp(TMVA::GeneticPopulation)

using namespace std;
   
//_______________________________________________________________________
//                                                                      
// Population definition for genetic algorithm                          
//_______________________________________________________________________

//_______________________________________________________________________
TMVA::GeneticPopulation::GeneticPopulation(const std::vector<Interval*>& ranges, Int_t size, UInt_t seed) 
   : fGenePool(size),
     fRanges(ranges.size()),
     fLogger( new MsgLogger("GeneticPopulation") )
{
   // Constructor
   
   // create a randomGenerator for this population and set a seed
   // create the genePools
   //
   fRandomGenerator = new TRandom3( 100 ); //please check
   fRandomGenerator->Uniform(0.,1.);
   fRandomGenerator->SetSeed( seed );

   for ( unsigned int i = 0; i < ranges.size(); ++i )
      fRanges[i] = new TMVA::GeneticRange( fRandomGenerator, ranges[i] );

   vector<Double_t> newEntry( fRanges.size() );
   for ( int i = 0; i < size; ++i )
      {
         for ( unsigned int rIt = 0; rIt < fRanges.size(); ++rIt )
            newEntry[rIt] = fRanges[rIt]->Random();
         fGenePool[i] = TMVA::GeneticGenes( newEntry);
      }

   fPopulationSizeLimit = size;
}

//_______________________________________________________________________
TMVA::GeneticPopulation::~GeneticPopulation() 
{
   // destructor
   if (fRandomGenerator != NULL) delete fRandomGenerator;

   std::vector<GeneticRange*>::iterator it = fRanges.begin();
   for (;it!=fRanges.end(); it++) delete *it;

   delete fLogger;
}



//_______________________________________________________________________
void TMVA::GeneticPopulation::SetRandomSeed( UInt_t seed ) 
{
   // the random seed of the random generator
   fRandomGenerator->SetSeed( seed );
}

//_______________________________________________________________________
void TMVA::GeneticPopulation::MakeCopies( int number )
{
   // produces offspring which is are copies of their parents
   // Parameters:
   //         int number : the number of the last individual to be copied
   //
   
   int i=0; 
   for (std::vector<TMVA::GeneticGenes>::iterator it = fGenePool.begin();
        it != fGenePool.end() && i < number; 
        ++it, ++i ) {
      GiveHint( it->GetFactors(), it->GetFitness() );
   }
}

//_______________________________________________________________________
void TMVA::GeneticPopulation::MakeChildren()
{
   // does what the name says,... it creates children out of members of the
   // current generation
   // children have a combination of the coefficients of their parents
   //

#ifdef _GLIBCXX_PARALLEL
#pragma omp parallel
#pragma omp for
#endif
   for ( int it = 0; it < (int) (fGenePool.size() / 2); ++it )
      {
         Int_t pos = (Int_t)fRandomGenerator->Integer( fGenePool.size()/2 );
         fGenePool[(fGenePool.size() / 2) + it] = MakeSex( fGenePool[it], fGenePool[pos] );
      }
}

//_______________________________________________________________________
TMVA::GeneticGenes TMVA::GeneticPopulation::MakeSex( TMVA::GeneticGenes male, 
                                                     TMVA::GeneticGenes female ) 
{
   // this function takes two individuals and produces offspring by mixing (recombining) their
   // coefficients
   //
   vector< Double_t > child(fRanges.size());
   for (unsigned int i = 0; i < fRanges.size(); ++i) {
      if (fRandomGenerator->Integer( 2 ) == 0) {
         child[i] = male.GetFactors()[i];
      }else{
         child[i] = female.GetFactors()[i];
      }
   }
   return TMVA::GeneticGenes( child );
}

//_______________________________________________________________________
void TMVA::GeneticPopulation::Mutate( Double_t probability , Int_t startIndex, 
                                      Bool_t near, Double_t spread, Bool_t mirror ) 
{
   // mutates the individuals in the genePool
   // Parameters:
   //         double probability : gives the probability (in percent) of a mutation of a coefficient
   //         int startIndex : leaves unchanged (without mutation) the individuals which are better ranked
   //                     than indicated by "startIndex". This means: if "startIndex==3", the first (and best)
   //                     three individuals are not mutaded. This allows to preserve the best result of the 
   //                     current Generation for the next generation. 
   //         Bool_t near : if true, the mutation will produce a new coefficient which is "near" the old one
   //                     (gaussian around the current value)
   //         double spread : if near==true, spread gives the sigma of the gaussian
   //         Bool_t mirror : if the new value obtained would be outside of the given constraints
   //                    the value is mapped between the constraints again. This can be done either
   //                    by a kind of periodic boundary conditions or mirrored at the boundary.
   //                    (mirror = true seems more "natural")
   //

   vector< Double_t>::iterator vec;
   vector< TMVA::GeneticRange* >::iterator vecRange;

   //#ifdef _GLIBCXX_PARALLEL
   // #pragma omp parallel
   // #pragma omp for
   //#endif
   // The range methods are not thread safe!
   for (int it = startIndex; it < (int) fGenePool.size(); ++it) {
      vecRange = fRanges.begin();
      for (vec = (fGenePool[it].GetFactors()).begin(); vec < (fGenePool[it].GetFactors()).end(); ++vec) {
         if (fRandomGenerator->Uniform( 100 ) <= probability) {
            (*vec) = (*vecRange)->Random( near, (*vec), spread, mirror );
         }
         ++vecRange;
      }
   }
}


//_______________________________________________________________________
TMVA::GeneticGenes* TMVA::GeneticPopulation::GetGenes( Int_t index )
{
   // gives back the "Genes" of the population with the given index.
   //
   return &(fGenePool[index]);
}

//_______________________________________________________________________
void TMVA::GeneticPopulation::Print( Int_t untilIndex )
{
   // make a little printout of the individuals up to index "untilIndex"
   // this means, .. write out the best "untilIndex" individuals.
   //

   for ( unsigned int it = 0; it < fGenePool.size(); ++it )
      {
         Int_t n=0;
         if (untilIndex >= -1 ) {
            if (untilIndex == -1 ) return;
            untilIndex--;
         }
         Log() << "fitness: " << fGenePool[it].GetFitness() << "    ";
         for (vector< Double_t >::iterator vec = fGenePool[it].GetFactors().begin(); 
              vec < fGenePool[it].GetFactors().end(); vec++ ) {
            Log() << "f_" << n++ << ": " << (*vec) << "     ";
         }
         Log() << Endl;
      }
}

//_______________________________________________________________________
void TMVA::GeneticPopulation::Print( ostream & out, Int_t untilIndex )
{
   // make a little printout to the stream "out" of the individuals up to index "untilIndex"
   // this means, .. write out the best "untilIndex" individuals.
   //

   for ( unsigned int it = 0; it < fGenePool.size(); ++it ) {
      Int_t n=0;
      if (untilIndex >= -1 ) {
         if (untilIndex == -1 ) return;
         untilIndex--;
      }
      out << "fitness: " << fGenePool[it].GetFitness() << "    ";
      for (vector< Double_t >::iterator vec = fGenePool[it].GetFactors().begin(); 
           vec < fGenePool[it].GetFactors().end(); vec++ ) {
         out << "f_" << n++ << ": " << (*vec) << "     ";
      }
      out << std::endl;
   }
}

//_______________________________________________________________________
TH1F* TMVA::GeneticPopulation::VariableDistribution( Int_t varNumber, Int_t bins, 
                                                     Int_t min, Int_t max ) 
{
   // give back a histogram with the distribution of the coefficients
   // parameters:
   //          int bins : number of bins of the histogram
   //          int min : histogram minimum 
   //          int max : maximum value of the histogram
   //

   std::cout << "FAILED! TMVA::GeneticPopulation::VariableDistribution" << std::endl;

   std::stringstream histName;
   histName.clear();
   histName.str("v");
   histName << varNumber;
   TH1F *hist = new TH1F( histName.str().c_str(),histName.str().c_str(), bins,min,max );

   return hist;
}

//_______________________________________________________________________
vector<Double_t> TMVA::GeneticPopulation::VariableDistribution( Int_t /*varNumber*/ ) 
{
   // gives back all the values of coefficient "varNumber" of the current generation
   //

   std::cout << "FAILED! TMVA::GeneticPopulation::VariableDistribution" << std::endl;

   vector< Double_t > varDist;

   return varDist;
}

//_______________________________________________________________________
void TMVA::GeneticPopulation::AddPopulation( GeneticPopulation *strangers )
{
   // add another population (strangers) to the one of this GeneticPopulation
   for (std::vector<TMVA::GeneticGenes>::iterator it = strangers->fGenePool.begin(); 
        it != strangers->fGenePool.end(); it++ ) {
      GiveHint( it->GetFactors(), it->GetFitness() );
   }
}

//_______________________________________________________________________
void TMVA::GeneticPopulation::AddPopulation( GeneticPopulation &strangers )
{
   // add another population (strangers) to the one of this GeneticPopulation
   AddPopulation(&strangers);
}

//_______________________________________________________________________
void TMVA::GeneticPopulation::TrimPopulation()
{
   // trim the population to the predefined size
   std::sort(fGenePool.begin(), fGenePool.end());
   while ( fGenePool.size() > (unsigned int) fPopulationSizeLimit )
      fGenePool.pop_back();
}

//_______________________________________________________________________
void TMVA::GeneticPopulation::GiveHint( std::vector< Double_t >& hint, Double_t fitness )
{
   // add an individual (a set of variables) to the population
   // if there is a set of variables which is known to perform good, they can be given as a hint to the population
   TMVA::GeneticGenes g(hint);
   g.SetFitness(fitness);

   fGenePool.push_back( g );
}

//_______________________________________________________________________
void TMVA::GeneticPopulation::Sort()
{
   // sort the genepool according to the fitness of the individuals
   std::sort(fGenePool.begin(), fGenePool.end());
}

 GeneticPopulation.cxx:1
 GeneticPopulation.cxx:2
 GeneticPopulation.cxx:3
 GeneticPopulation.cxx:4
 GeneticPopulation.cxx:5
 GeneticPopulation.cxx:6
 GeneticPopulation.cxx:7
 GeneticPopulation.cxx:8
 GeneticPopulation.cxx:9
 GeneticPopulation.cxx:10
 GeneticPopulation.cxx:11
 GeneticPopulation.cxx:12
 GeneticPopulation.cxx:13
 GeneticPopulation.cxx:14
 GeneticPopulation.cxx:15
 GeneticPopulation.cxx:16
 GeneticPopulation.cxx:17
 GeneticPopulation.cxx:18
 GeneticPopulation.cxx:19
 GeneticPopulation.cxx:20
 GeneticPopulation.cxx:21
 GeneticPopulation.cxx:22
 GeneticPopulation.cxx:23
 GeneticPopulation.cxx:24
 GeneticPopulation.cxx:25
 GeneticPopulation.cxx:26
 GeneticPopulation.cxx:27
 GeneticPopulation.cxx:28
 GeneticPopulation.cxx:29
 GeneticPopulation.cxx:30
 GeneticPopulation.cxx:31
 GeneticPopulation.cxx:32
 GeneticPopulation.cxx:33
 GeneticPopulation.cxx:34
 GeneticPopulation.cxx:35
 GeneticPopulation.cxx:36
 GeneticPopulation.cxx:37
 GeneticPopulation.cxx:38
 GeneticPopulation.cxx:39
 GeneticPopulation.cxx:40
 GeneticPopulation.cxx:41
 GeneticPopulation.cxx:42
 GeneticPopulation.cxx:43
 GeneticPopulation.cxx:44
 GeneticPopulation.cxx:45
 GeneticPopulation.cxx:46
 GeneticPopulation.cxx:47
 GeneticPopulation.cxx:48
 GeneticPopulation.cxx:49
 GeneticPopulation.cxx:50
 GeneticPopulation.cxx:51
 GeneticPopulation.cxx:52
 GeneticPopulation.cxx:53
 GeneticPopulation.cxx:54
 GeneticPopulation.cxx:55
 GeneticPopulation.cxx:56
 GeneticPopulation.cxx:57
 GeneticPopulation.cxx:58
 GeneticPopulation.cxx:59
 GeneticPopulation.cxx:60
 GeneticPopulation.cxx:61
 GeneticPopulation.cxx:62
 GeneticPopulation.cxx:63
 GeneticPopulation.cxx:64
 GeneticPopulation.cxx:65
 GeneticPopulation.cxx:66
 GeneticPopulation.cxx:67
 GeneticPopulation.cxx:68
 GeneticPopulation.cxx:69
 GeneticPopulation.cxx:70
 GeneticPopulation.cxx:71
 GeneticPopulation.cxx:72
 GeneticPopulation.cxx:73
 GeneticPopulation.cxx:74
 GeneticPopulation.cxx:75
 GeneticPopulation.cxx:76
 GeneticPopulation.cxx:77
 GeneticPopulation.cxx:78
 GeneticPopulation.cxx:79
 GeneticPopulation.cxx:80
 GeneticPopulation.cxx:81
 GeneticPopulation.cxx:82
 GeneticPopulation.cxx:83
 GeneticPopulation.cxx:84
 GeneticPopulation.cxx:85
 GeneticPopulation.cxx:86
 GeneticPopulation.cxx:87
 GeneticPopulation.cxx:88
 GeneticPopulation.cxx:89
 GeneticPopulation.cxx:90
 GeneticPopulation.cxx:91
 GeneticPopulation.cxx:92
 GeneticPopulation.cxx:93
 GeneticPopulation.cxx:94
 GeneticPopulation.cxx:95
 GeneticPopulation.cxx:96
 GeneticPopulation.cxx:97
 GeneticPopulation.cxx:98
 GeneticPopulation.cxx:99
 GeneticPopulation.cxx:100
 GeneticPopulation.cxx:101
 GeneticPopulation.cxx:102
 GeneticPopulation.cxx:103
 GeneticPopulation.cxx:104
 GeneticPopulation.cxx:105
 GeneticPopulation.cxx:106
 GeneticPopulation.cxx:107
 GeneticPopulation.cxx:108
 GeneticPopulation.cxx:109
 GeneticPopulation.cxx:110
 GeneticPopulation.cxx:111
 GeneticPopulation.cxx:112
 GeneticPopulation.cxx:113
 GeneticPopulation.cxx:114
 GeneticPopulation.cxx:115
 GeneticPopulation.cxx:116
 GeneticPopulation.cxx:117
 GeneticPopulation.cxx:118
 GeneticPopulation.cxx:119
 GeneticPopulation.cxx:120
 GeneticPopulation.cxx:121
 GeneticPopulation.cxx:122
 GeneticPopulation.cxx:123
 GeneticPopulation.cxx:124
 GeneticPopulation.cxx:125
 GeneticPopulation.cxx:126
 GeneticPopulation.cxx:127
 GeneticPopulation.cxx:128
 GeneticPopulation.cxx:129
 GeneticPopulation.cxx:130
 GeneticPopulation.cxx:131
 GeneticPopulation.cxx:132
 GeneticPopulation.cxx:133
 GeneticPopulation.cxx:134
 GeneticPopulation.cxx:135
 GeneticPopulation.cxx:136
 GeneticPopulation.cxx:137
 GeneticPopulation.cxx:138
 GeneticPopulation.cxx:139
 GeneticPopulation.cxx:140
 GeneticPopulation.cxx:141
 GeneticPopulation.cxx:142
 GeneticPopulation.cxx:143
 GeneticPopulation.cxx:144
 GeneticPopulation.cxx:145
 GeneticPopulation.cxx:146
 GeneticPopulation.cxx:147
 GeneticPopulation.cxx:148
 GeneticPopulation.cxx:149
 GeneticPopulation.cxx:150
 GeneticPopulation.cxx:151
 GeneticPopulation.cxx:152
 GeneticPopulation.cxx:153
 GeneticPopulation.cxx:154
 GeneticPopulation.cxx:155
 GeneticPopulation.cxx:156
 GeneticPopulation.cxx:157
 GeneticPopulation.cxx:158
 GeneticPopulation.cxx:159
 GeneticPopulation.cxx:160
 GeneticPopulation.cxx:161
 GeneticPopulation.cxx:162
 GeneticPopulation.cxx:163
 GeneticPopulation.cxx:164
 GeneticPopulation.cxx:165
 GeneticPopulation.cxx:166
 GeneticPopulation.cxx:167
 GeneticPopulation.cxx:168
 GeneticPopulation.cxx:169
 GeneticPopulation.cxx:170
 GeneticPopulation.cxx:171
 GeneticPopulation.cxx:172
 GeneticPopulation.cxx:173
 GeneticPopulation.cxx:174
 GeneticPopulation.cxx:175
 GeneticPopulation.cxx:176
 GeneticPopulation.cxx:177
 GeneticPopulation.cxx:178
 GeneticPopulation.cxx:179
 GeneticPopulation.cxx:180
 GeneticPopulation.cxx:181
 GeneticPopulation.cxx:182
 GeneticPopulation.cxx:183
 GeneticPopulation.cxx:184
 GeneticPopulation.cxx:185
 GeneticPopulation.cxx:186
 GeneticPopulation.cxx:187
 GeneticPopulation.cxx:188
 GeneticPopulation.cxx:189
 GeneticPopulation.cxx:190
 GeneticPopulation.cxx:191
 GeneticPopulation.cxx:192
 GeneticPopulation.cxx:193
 GeneticPopulation.cxx:194
 GeneticPopulation.cxx:195
 GeneticPopulation.cxx:196
 GeneticPopulation.cxx:197
 GeneticPopulation.cxx:198
 GeneticPopulation.cxx:199
 GeneticPopulation.cxx:200
 GeneticPopulation.cxx:201
 GeneticPopulation.cxx:202
 GeneticPopulation.cxx:203
 GeneticPopulation.cxx:204
 GeneticPopulation.cxx:205
 GeneticPopulation.cxx:206
 GeneticPopulation.cxx:207
 GeneticPopulation.cxx:208
 GeneticPopulation.cxx:209
 GeneticPopulation.cxx:210
 GeneticPopulation.cxx:211
 GeneticPopulation.cxx:212
 GeneticPopulation.cxx:213
 GeneticPopulation.cxx:214
 GeneticPopulation.cxx:215
 GeneticPopulation.cxx:216
 GeneticPopulation.cxx:217
 GeneticPopulation.cxx:218
 GeneticPopulation.cxx:219
 GeneticPopulation.cxx:220
 GeneticPopulation.cxx:221
 GeneticPopulation.cxx:222
 GeneticPopulation.cxx:223
 GeneticPopulation.cxx:224
 GeneticPopulation.cxx:225
 GeneticPopulation.cxx:226
 GeneticPopulation.cxx:227
 GeneticPopulation.cxx:228
 GeneticPopulation.cxx:229
 GeneticPopulation.cxx:230
 GeneticPopulation.cxx:231
 GeneticPopulation.cxx:232
 GeneticPopulation.cxx:233
 GeneticPopulation.cxx:234
 GeneticPopulation.cxx:235
 GeneticPopulation.cxx:236
 GeneticPopulation.cxx:237
 GeneticPopulation.cxx:238
 GeneticPopulation.cxx:239
 GeneticPopulation.cxx:240
 GeneticPopulation.cxx:241
 GeneticPopulation.cxx:242
 GeneticPopulation.cxx:243
 GeneticPopulation.cxx:244
 GeneticPopulation.cxx:245
 GeneticPopulation.cxx:246
 GeneticPopulation.cxx:247
 GeneticPopulation.cxx:248
 GeneticPopulation.cxx:249
 GeneticPopulation.cxx:250
 GeneticPopulation.cxx:251
 GeneticPopulation.cxx:252
 GeneticPopulation.cxx:253
 GeneticPopulation.cxx:254
 GeneticPopulation.cxx:255
 GeneticPopulation.cxx:256
 GeneticPopulation.cxx:257
 GeneticPopulation.cxx:258
 GeneticPopulation.cxx:259
 GeneticPopulation.cxx:260
 GeneticPopulation.cxx:261
 GeneticPopulation.cxx:262
 GeneticPopulation.cxx:263
 GeneticPopulation.cxx:264
 GeneticPopulation.cxx:265
 GeneticPopulation.cxx:266
 GeneticPopulation.cxx:267
 GeneticPopulation.cxx:268
 GeneticPopulation.cxx:269
 GeneticPopulation.cxx:270
 GeneticPopulation.cxx:271
 GeneticPopulation.cxx:272
 GeneticPopulation.cxx:273
 GeneticPopulation.cxx:274
 GeneticPopulation.cxx:275
 GeneticPopulation.cxx:276
 GeneticPopulation.cxx:277
 GeneticPopulation.cxx:278
 GeneticPopulation.cxx:279
 GeneticPopulation.cxx:280
 GeneticPopulation.cxx:281
 GeneticPopulation.cxx:282
 GeneticPopulation.cxx:283
 GeneticPopulation.cxx:284
 GeneticPopulation.cxx:285
 GeneticPopulation.cxx:286
 GeneticPopulation.cxx:287
 GeneticPopulation.cxx:288
 GeneticPopulation.cxx:289
 GeneticPopulation.cxx:290
 GeneticPopulation.cxx:291
 GeneticPopulation.cxx:292
 GeneticPopulation.cxx:293
 GeneticPopulation.cxx:294
 GeneticPopulation.cxx:295
 GeneticPopulation.cxx:296
 GeneticPopulation.cxx:297
 GeneticPopulation.cxx:298
 GeneticPopulation.cxx:299
 GeneticPopulation.cxx:300
 GeneticPopulation.cxx:301
 GeneticPopulation.cxx:302
 GeneticPopulation.cxx:303
 GeneticPopulation.cxx:304
 GeneticPopulation.cxx:305
 GeneticPopulation.cxx:306
 GeneticPopulation.cxx:307
 GeneticPopulation.cxx:308
 GeneticPopulation.cxx:309
 GeneticPopulation.cxx:310
 GeneticPopulation.cxx:311
 GeneticPopulation.cxx:312
 GeneticPopulation.cxx:313
 GeneticPopulation.cxx:314
 GeneticPopulation.cxx:315
 GeneticPopulation.cxx:316
 GeneticPopulation.cxx:317
 GeneticPopulation.cxx:318
 GeneticPopulation.cxx:319
 GeneticPopulation.cxx:320
 GeneticPopulation.cxx:321