ROOT logo
// @(#)root/tmva $Id: MethodFDA.cxx 29195 2009-06-24 10:39:49Z brun $    
// Author: Andreas Hoecker, Peter Speckmayer, Joerg Stelzer

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : MethodFDA                                                             *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Implementation                                                            *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Andreas Hoecker  <Andreas.Hocker@cern.ch> - CERN, Switzerland             *
 *      Peter Speckmayer <speckmay@mail.cern.ch>  - CERN, Switzerland             *
 *      Joerg Stelzer    <stelzer@cern.ch>        - DESY, Germany                 *
 *      Maciej Kruk      <mkruk@cern.ch>          - IFJ PAN & AGH, Poland         *
 *                                                                                *
 * Copyright (c) 2005-2006:                                                       *
 *      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)                                          *
 **********************************************************************************/

//_______________________________________________________________________
//                                                                      
// Function discriminant analysis (FDA). This simple classifier         //
// fits any user-defined TFormula (via option configuration string) to  //
// the training data by requiring a formula response of 1 (0) to signal //
// (background) events. The parameter fitting is done via the abstract  //
// class FitterBase, featuring Monte Carlo sampling, Genetic            //
// Algorithm, Simulated Annealing, MINUIT and combinations of these.    //
//                                                                      //
// Can compute regression value for one dimensional output              //
//_______________________________________________________________________

#include "Riostream.h"
#include "TList.h"
#include "TFormula.h"
#include "TString.h"
#include "TObjString.h"
#include "TRandom3.h"
#include "TMath.h"
#include <sstream>

#include "TMVA/ClassifierFactory.h"
#include "TMVA/MethodFDA.h"
#include "TMVA/Tools.h"
#include "TMVA/Interval.h"
#include "TMVA/Timer.h"
#include "TMVA/GeneticFitter.h"
#include "TMVA/SimulatedAnnealingFitter.h"
#include "TMVA/MinuitFitter.h"
#include "TMVA/MCFitter.h"
#include "TMVA/Config.h"

REGISTER_METHOD(FDA)

ClassImp(TMVA::MethodFDA)

//_______________________________________________________________________
TMVA::MethodFDA::MethodFDA( const TString& jobName,
                            const TString& methodTitle,
                            DataSetInfo& theData, 
                            const TString& theOption,
                            TDirectory* theTargetDir )
   : MethodBase( jobName, Types::kFDA, methodTitle, theData, theOption, theTargetDir ), 
     IFitterTarget   (),
     fFormula        ( 0 ),
     fFitter         ( 0 ),
     fConvergerFitter( 0 )
{
   // standard constructor
}

//_______________________________________________________________________
TMVA::MethodFDA::MethodFDA( DataSetInfo& theData, 
                            const TString& theWeightFile,  
                            TDirectory* theTargetDir )
   : MethodBase( Types::kFDA, theData, theWeightFile, theTargetDir ), 
     IFitterTarget   (),
     fFormula        ( 0 ),
     fFitter         ( 0 ),
     fConvergerFitter( 0 )
{
   // constructor from weight file
}

//_______________________________________________________________________
void TMVA::MethodFDA::Init( void )
{
   // default initialisation	
   fNPars    = 0;

   fBestPars.clear();

   fSumOfWeights    = 0;
   fSumOfWeightsSig = 0;
   fSumOfWeightsBkg = 0;

   fFormulaStringP  = "";
   fParRangeStringP = "";
   fFormulaStringT  = "";
   fParRangeStringT = "";

   fFitMethod       = "";
   fConverger       = "";
}

//_______________________________________________________________________
void TMVA::MethodFDA::DeclareOptions() 
{
   // define the options (their key words) that can be set in the option string 
   //
   // format of function string:
   //    "x0*(0)+((1)/x1)**(2)..."
   // where "[i]" are the parameters, and "xi" the input variables
   //
   // format of parameter string:
   //    "(-1.2,3.4);(-2.3,4.55);..."
   // where the numbers in "(a,b)" correspond to the a=min, b=max parameter ranges;
   // each parameter defined in the function string must have a corresponding range
   //
   DeclareOptionRef( fFormulaStringP  = "(0)", "Formula",   "The discrimination formula" );
   DeclareOptionRef( fParRangeStringP = "()", "ParRanges", "Parameter ranges" );

   // fitter
   DeclareOptionRef( fFitMethod = "MINUIT", "FitMethod", "Optimisation Method");
   AddPreDefVal(TString("MC"));
   AddPreDefVal(TString("GA"));
   AddPreDefVal(TString("SA"));
   AddPreDefVal(TString("MINUIT"));

   DeclareOptionRef( fConverger = "None", "Converger", "FitMethod uses Converger to improve result");
   AddPreDefVal(TString("None"));
   AddPreDefVal(TString("MINUIT"));
}

//_______________________________________________________________________
void TMVA::MethodFDA::CreateFormula() 
{
   // translate formula string into TFormula, and parameter string into par ranges

   // process transient strings
   fFormulaStringT  = fFormulaStringP;

   // intepret formula string

   // replace the parameters "(i)" by the TFormula style "[i]"
   for (Int_t ipar=0; ipar<fNPars; ipar++) {
      fFormulaStringT.ReplaceAll( Form("(%i)",ipar), Form("[%i]",ipar) );
   }

   // sanity check, there should be no "(i)", with 'i' a number anymore
   for (Int_t ipar=fNPars; ipar<1000; ipar++) {
      if (fFormulaStringT.Contains( Form("(%i)",ipar) ))
         Log() << kFATAL 
                 << "<CreateFormula> Formula contains expression: \"" << Form("(%i)",ipar) << "\", "
                 << "which cannot be attributed to a parameter; " 
                 << "it may be that the number of variable ranges given via \"ParRanges\" "
                 << "does not match the number of parameters in the formula expression, please verify!"
                 << Endl;
   }

   // write the variables "xi" as additional parameters "[npar+i]"
   for (Int_t ivar=GetNvar()-1; ivar >= 0; ivar--) {
      fFormulaStringT.ReplaceAll( Form("x%i",ivar), Form("[%i]",ivar+fNPars) );
   }

   // sanity check, there should be no "xi", with 'i' a number anymore
   for (UInt_t ivar=GetNvar(); ivar<1000; ivar++) {
      if (fFormulaStringT.Contains( Form("x%i",ivar) ))
         Log() << kFATAL 
                 << "<CreateFormula> Formula contains expression: \"" << Form("x%i",ivar) << "\", "
                 << "which cannot be attributed to an input variable" << Endl;
   }
   
   Log() << "User-defined formula string       : \"" << fFormulaStringP << "\"" << Endl;
   Log() << "TFormula-compatible formula string: \"" << fFormulaStringT << "\"" << Endl;
   Log() << "Creating and compiling formula" << Endl;
   
   // create TF1
   if (fFormula) delete fFormula;
   fFormula = new TFormula( "FDA_Formula", fFormulaStringT );
   
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,2,0)
   fFormula->Optimize();
#endif

   // is formula correct ?
   if (fFormula->Compile() != 0)
      Log() << kFATAL << "<ProcessOptions> Formula expression could not be properly compiled" << Endl;

   // other sanity checks
   if (fFormula->GetNpar() > fNPars + (Int_t)GetNvar())
      Log() << kFATAL << "<ProcessOptions> Dubious number of parameters in formula expression: " 
              << fFormula->GetNpar() << " - compared to maximum allowed: " << fNPars + GetNvar() << Endl;
}

//_______________________________________________________________________
void TMVA::MethodFDA::ProcessOptions() 
{
   // the option string is decoded, for availabel options see "DeclareOptions"

   // process transient strings
   fParRangeStringT = fParRangeStringP;

   // interpret parameter string   
   fParRangeStringT.ReplaceAll( " ", "" );
   fNPars = fParRangeStringT.CountChar( ')' );

   TList* parList = gTools().ParseFormatLine( fParRangeStringT, ";" );
   if (parList->GetSize() != fNPars) {
      Log() << kFATAL << "<ProcessOptions> Mismatch in parameter string: " 
              << "the number of parameters: " << fNPars << " != ranges defined: " 
              << parList->GetSize() << "; the format of the \"ParRanges\" string "
              << "must be: \"(-1.2,3.4);(-2.3,4.55);...\", "
              << "where the numbers in \"(a,b)\" correspond to the a=min, b=max parameter ranges; "
              << "each parameter defined in the function string must have a corresponding rang."
              << Endl;
   }

   fParRange.resize( fNPars );
   for (Int_t ipar=0; ipar<fNPars; ipar++) fParRange[ipar] = 0;

   for (Int_t ipar=0; ipar<fNPars; ipar++) {
      // parse (a,b)
      TString str = ((TObjString*)parList->At(ipar))->GetString();
      Ssiz_t istr = str.First( ',' );
      TString pminS(str(1,istr-1));
      TString pmaxS(str(istr+1,str.Length()-2-istr));

      stringstream stmin; Float_t pmin; stmin << pminS.Data(); stmin >> pmin;       
      stringstream stmax; Float_t pmax; stmax << pmaxS.Data(); stmax >> pmax;

      // sanity check
      if (pmin > pmax) Log() << kFATAL << "<ProcessOptions> max > min in interval for parameter: [" 
                               << ipar << "] : [" << pmin  << ", " << pmax << "] " << Endl;

      fParRange[ipar] = new Interval( pmin, pmax );
   }
   delete parList;

   // create formula
   CreateFormula();

   // create minimiser
   fConvergerFitter = (IFitterTarget*)this;
   if (fConverger == "MINUIT") {
      fConvergerFitter = new MinuitFitter( *this, Form("%s_Converger_Minuit", GetName()), fParRange, GetOptions() );
      SetOptions(dynamic_cast<Configurable*>(fConvergerFitter)->GetOptions());
   }

   if      (fFitMethod == "MC")     
      fFitter = new MCFitter( *fConvergerFitter, Form("%s_Fitter_MC", GetName()), fParRange, GetOptions() );
   else if (fFitMethod == "GA")     
      fFitter = new GeneticFitter( *fConvergerFitter, Form("%s_Fitter_GA", GetName()), fParRange, GetOptions() );
   else if (fFitMethod == "SA")     
      fFitter = new SimulatedAnnealingFitter( *fConvergerFitter, Form("%s_Fitter_SA", GetName()), fParRange, GetOptions() );
   else if (fFitMethod == "MINUIT") 
      fFitter = new MinuitFitter( *fConvergerFitter, Form("%s_Fitter_Minuit", GetName()), fParRange, GetOptions() );
   else {
      Log() << kFATAL << "<Train> Do not understand fit method:" << fFitMethod << Endl;
   }
   
   fFitter->CheckForUnusedOptions();
}

//_______________________________________________________________________
TMVA::MethodFDA::~MethodFDA( void )
{
   // destructor
   ClearAll();
}

//_______________________________________________________________________
Bool_t TMVA::MethodFDA::HasAnalysisType( Types::EAnalysisType type, UInt_t numberClasses, UInt_t numberTargets )
{
   // FDA can handle classification with 2 classes and regression with one regression-target
   if (type == Types::kClassification && numberClasses == 2) return kTRUE;
   if (type == Types::kRegression     && numberTargets == 1) return kTRUE;
   return kFALSE;
}


//_______________________________________________________________________
void TMVA::MethodFDA::ClearAll( void )
{
   // delete and clear all class members
   for (UInt_t ipar=0; ipar<fParRange.size(); ipar++) {
      if (fParRange[ipar] != 0) { delete fParRange[ipar]; fParRange[ipar] = 0; }
   }
   fParRange.clear(); 
   
   if (fFormula  != 0) { delete fFormula; fFormula = 0; }
   fBestPars.clear();
}

//_______________________________________________________________________
void TMVA::MethodFDA::Train( void )
{
   // FDA training 

   // cache training events
   fSumOfWeights    = 0;
   fSumOfWeightsSig = 0;
   fSumOfWeightsBkg = 0;

   for (UInt_t ievt=0; ievt<GetNEvents(); ievt++) {

      // read the training event 
      const Event* ev = GetEvent(ievt);

      // true event copy
      Float_t w  = GetTWeight(ev);
	
      if (!DoRegression()) {
         if (ev->IsSignal()) { fSumOfWeightsSig += w; }
         else                { fSumOfWeightsBkg += w; }
      }
      fSumOfWeights += w;
	
   }

   // sanity check
   if (!DoRegression()) {
      if (fSumOfWeightsSig <= 0 || fSumOfWeightsBkg <= 0) {
         Log() << kFATAL << "<Train> Troubles in sum of weights: " 
                 << fSumOfWeightsSig << " (S) : " << fSumOfWeightsBkg << " (B)" << Endl;
      }
   }
   else if (fSumOfWeights <= 0) {
      Log() << kFATAL << "<Train> Troubles in sum of weights: " 
              << fSumOfWeights << Endl;
   }

   // starting values (not used by all fitters)
   fBestPars.clear();
   for (std::vector<Interval*>::const_iterator parIt = fParRange.begin(); parIt != fParRange.end(); parIt++) {
      fBestPars.push_back( (*parIt)->GetMean() );
   }

   // execute the fit
   Double_t estimator = fFitter->Run( fBestPars );
      
   // print results
   PrintResults( fFitMethod, fBestPars, estimator );

   delete fFitter; fFitter = 0;
   if (fConvergerFitter!=0 && fConvergerFitter!=(IFitterTarget*)this) {
      delete fConvergerFitter;
      fConvergerFitter = 0;
   }
}

//_______________________________________________________________________
void TMVA::MethodFDA::PrintResults( const TString& fitter, std::vector<Double_t>& pars, const Double_t estimator ) const
{
   // display fit parameters
   // check maximum length of variable name
   Log() << kINFO;
   Log() << "Results for parameter fit using \"" << fitter << "\" fitter:" << Endl;
   vector<TString>  parNames;
   for (UInt_t ipar=0; ipar<pars.size(); ipar++) parNames.push_back( Form("Par(%i)",ipar ) );
   gTools().FormattedOutput( pars, parNames, "Parameter" , "Fit result", Log(), "%g" );   
   Log() << "Discriminator expression: \"" << fFormulaStringP << "\"" << Endl;
   Log() << "Value of estimator at minimum: " << estimator << Endl;
}


//_______________________________________________________________________
Double_t TMVA::MethodFDA::EstimatorFunction( std::vector<Double_t>& pars )
{
   // compute estimator for given parameter set (to be minimised)
   //   const Double_t sumOfWeights[]                = { fSumOfWeightsSig, fSumOfWeightsBkg, fSumOfWeights };
   const Double_t sumOfWeights[]                = { fSumOfWeightsBkg, fSumOfWeightsSig, fSumOfWeights };
   Double_t estimator[]                         = { 0, 0, 0 };

   Double_t result, deviation;
   Double_t desired = 0.0;
   for (UInt_t ievt=0; ievt<GetNEvents(); ievt++) {

      // read the training event 
      const Event* ev = GetEvent(ievt);

      // calculate the deviation from the desired value

      if (!DoRegression()) desired = (ev->IsSignal() ? 1.0 : 0.0);
      else                 desired = ev->GetTarget( 0 );

      result    = InterpretFormula( ev, pars );
      deviation = TMath::Power(result - desired, 2);

      if (!DoRegression())  estimator[Int_t(desired)] += deviation * ev->GetWeight();
      else                  estimator[2]              += deviation * ev->GetWeight();

   }
   estimator[0] /= sumOfWeights[0];
   estimator[1] /= sumOfWeights[1];
   if (DoRegression()) estimator[2] /= sumOfWeights[2];
   // return value is sum over normalised signal and background contributions

   if (!DoRegression()) return estimator[0] + estimator[1];
   else                 return estimator[2];
}

//_______________________________________________________________________
Double_t TMVA::MethodFDA::InterpretFormula( const Event* event, std::vector<Double_t>& pars )
{
   // formula interpretation
   for (UInt_t ipar=0; ipar<pars.size(); ipar++) fFormula->SetParameter( ipar, pars[ipar] );
   for (UInt_t ivar=0;  ivar<GetNvar();  ivar++) fFormula->SetParameter( fNPars+ivar, event->GetVal(ivar) );

   return fFormula->Eval( 0 );
}

//_______________________________________________________________________
Double_t TMVA::MethodFDA::GetMvaValue( Double_t* err )
{
   // returns MVA value for given event
   const Event* ev = GetEvent();

   // cannot determine error
   if (err != 0) *err = -1;
   
   return InterpretFormula( ev, fBestPars );
}

//_______________________________________________________________________
std::vector<Float_t>& TMVA::MethodFDA::GetRegressionValues()
{
   if (fRegressionReturnVal == NULL) fRegressionReturnVal = new std::vector<Float_t>();
   fRegressionReturnVal->clear();

   const Event* ev = GetEvent();

   Event* evT = new Event(*ev);
   evT->SetTarget(0,InterpretFormula( ev, fBestPars ));
   const Event* evT2 = GetTransformationHandler().InverseTransform( evT );
   fRegressionReturnVal->push_back(evT2->GetTarget(0));

   delete evT;

   return (*fRegressionReturnVal);
}

//_______________________________________________________________________
void  TMVA::MethodFDA::WriteWeightsToStream( ostream& o ) const
{  
   // write the weight from the training to a file (stream)

   // save fitted function parameters
   o << fNPars << endl;
   for (Int_t ipar=0; ipar<fNPars; ipar++) o << fBestPars[ipar] << endl;
}
  
//_______________________________________________________________________
void  TMVA::MethodFDA::ReadWeightsFromStream( istream& istr )
{
   // read back the training results from a file (stream)

   // retrieve best function parameters
   istr >> fNPars;

   fBestPars.clear();
   fBestPars.resize( fNPars );
   for (Int_t ipar=0; ipar<fNPars; ipar++) istr >> fBestPars[ipar];
}

//_______________________________________________________________________
void TMVA::MethodFDA::AddWeightsXMLTo( void* parent ) const 
{
   // create XML description for LD classification and regression 
   // (for arbitrary number of output classes/targets)

   void* wght = gTools().xmlengine().NewChild(parent, 0, "Weights");
   gTools().AddAttr( wght, "NPars",  fNPars );
   for (Int_t ipar=0; ipar<fNPars; ipar++) {
      void* coeffxml = gTools().xmlengine().NewChild( wght, 0, "Parameter" );
      gTools().AddAttr( coeffxml, "Index", ipar   );
      gTools().AddAttr( coeffxml, "Value", fBestPars[ipar] );
   }

   // write formula
   gTools().AddAttr( wght, "Formula", fFormulaStringP );
}
  
//_______________________________________________________________________
void TMVA::MethodFDA::ReadWeightsFromXML( void* wghtnode ) 
{
   // read coefficients from xml weight file
   gTools().ReadAttr( wghtnode, "NPars", fNPars );

   fBestPars.clear();
   fBestPars.resize( fNPars );
   
   void* ch = gTools().xmlengine().GetChild(wghtnode);
   Double_t par;
   Int_t    ipar;
   while (ch) {
      gTools().ReadAttr( ch, "Index", ipar );
      gTools().ReadAttr( ch, "Value", par  );

      // sanity check
      if (ipar >= fNPars) Log() << kFATAL << "<ReadWeightsFromXML> index out of range: "
                                  << ipar << " >= " << fNPars << Endl;
      fBestPars[ipar] = par;

      ch = gTools().xmlengine().GetNext(ch);
   }

   // read formula
   gTools().ReadAttr( wghtnode, "Formula", fFormulaStringP );

   // create the TFormula
   CreateFormula();
}

//_______________________________________________________________________
void TMVA::MethodFDA::MakeClassSpecific( std::ostream& fout, const TString& className ) const
{
   // write FDA-specific classifier response
   fout << "   double              fParameter[" << fNPars << "];" << endl;
   fout << "};" << endl;
   fout << "" << endl;
   fout << "inline void " << className << "::Initialize() " << endl;
   fout << "{" << endl;
   for (Int_t ipar=0; ipar<fNPars; ipar++) {
      fout << "   fParameter[" << ipar << "] = " << fBestPars[ipar] << ";" << endl;
   }
   fout << "}" << endl;
   fout << endl;
   fout << "inline double " << className << "::GetMvaValue__( const std::vector<double>& inputValues ) const" << endl;
   fout << "{" << endl;
   fout << "   // interpret the formula" << endl;

   // replace parameters
   TString str = fFormulaStringT;
   for (Int_t ipar=0; ipar<fNPars; ipar++) {
      str.ReplaceAll( Form("[%i]", ipar), Form("fParameter[%i]", ipar) );
   }
   
   // replace input variables
   for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
      str.ReplaceAll( Form("[%i]", ivar+fNPars), Form("inputValues[%i]", ivar) );
   }

   fout << "   double retval = " << str << ";" << endl;
   fout << endl;
   fout << "   return retval; " << endl;
   fout << "}" << endl;
   fout << endl;
   fout << "// Clean up" << endl;
   fout << "inline void " << className << "::Clear() " << endl;
   fout << "{" << endl;
   fout << "   // nothing to clear" << endl;
   fout << "}" << endl;
}

//_______________________________________________________________________
void TMVA::MethodFDA::GetHelpMessage() const
{
   // get help message text
   //
   // typical length of text line: 
   //         "|--------------------------------------------------------------|"
   Log() << Endl;
   Log() << gTools().Color("bold") << "--- Short description:" << gTools().Color("reset") << Endl;
   Log() << Endl;
   Log() << "The function discriminant analysis (FDA) is a classifier suitable " << Endl;
   Log() << "to solve linear or simple nonlinear discrimination problems." << Endl; 
   Log() << Endl;
   Log() << "The user provides the desired function with adjustable parameters" << Endl;
   Log() << "via the configuration option string, and FDA fits the parameters to" << Endl;
   Log() << "it, requiring the signal (background) function value to be as close" << Endl;
   Log() << "as possible to 1 (0). Its advantage over the more involved and" << Endl;
   Log() << "automatic nonlinear discriminators is the simplicity and transparency " << Endl;
   Log() << "of the discrimination expression. A shortcoming is that FDA will" << Endl;
   Log() << "underperform for involved problems with complicated, phase space" << Endl;
   Log() << "dependent nonlinear correlations." << Endl;
   Log() << Endl;
   Log() << "Please consult the Users Guide for the format of the formula string" << Endl;
   Log() << "and the allowed parameter ranges:" << Endl;
   if (gConfig().WriteOptionsReference()) {
      Log() << "<a href=\"http://tmva.sourceforge.net/docu/TMVAUsersGuide.pdf\">" 
              << "http://tmva.sourceforge.net/docu/TMVAUsersGuide.pdf</a>" << Endl;
   }
   else Log() << "http://tmva.sourceforge.net/docu/TMVAUsersGuide.pdf" << Endl;
   Log() << Endl;
   Log() << gTools().Color("bold") << "--- Performance optimisation:" << gTools().Color("reset") << Endl;
   Log() << Endl;
   Log() << "The FDA performance depends on the complexity and fidelity of the" << Endl;
   Log() << "user-defined discriminator function. As a general rule, it should" << Endl;
   Log() << "be able to reproduce the discrimination power of any linear" << Endl;
   Log() << "discriminant analysis. To reach into the nonlinear domain, it is" << Endl;
   Log() << "useful to inspect the correlation profiles of the input variables," << Endl;
   Log() << "and add quadratic and higher polynomial terms between variables as" << Endl;
   Log() << "necessary. Comparison with more involved nonlinear classifiers can" << Endl;
   Log() << "be used as a guide." << Endl;
   Log() << Endl;
   Log() << gTools().Color("bold") << "--- Performance tuning via configuration options:" << gTools().Color("reset") << Endl;
   Log() << Endl;
   Log() << "Depending on the function used, the choice of \"FitMethod\" is" << Endl;
   Log() << "crucial for getting valuable solutions with FDA. As a guideline it" << Endl;
   Log() << "is recommended to start with \"FitMethod=MINUIT\". When more complex" << Endl;
   Log() << "functions are used where MINUIT does not converge to reasonable" << Endl;
   Log() << "results, the user should switch to non-gradient FitMethods such" << Endl;
   Log() << "as GeneticAlgorithm (GA) or Monte Carlo (MC). It might prove to be" << Endl;
   Log() << "useful to combine GA (or MC) with MINUIT by setting the option" << Endl;
   Log() << "\"Converger=MINUIT\". GA (MC) will then set the starting parameters" << Endl;
   Log() << "for MINUIT such that the basic quality of GA (MC) of finding global" << Endl;
   Log() << "minima is combined with the efficacy of MINUIT of finding local" << Endl;
   Log() << "minima." << Endl;
}
 MethodFDA.cxx:1
 MethodFDA.cxx:2
 MethodFDA.cxx:3
 MethodFDA.cxx:4
 MethodFDA.cxx:5
 MethodFDA.cxx:6
 MethodFDA.cxx:7
 MethodFDA.cxx:8
 MethodFDA.cxx:9
 MethodFDA.cxx:10
 MethodFDA.cxx:11
 MethodFDA.cxx:12
 MethodFDA.cxx:13
 MethodFDA.cxx:14
 MethodFDA.cxx:15
 MethodFDA.cxx:16
 MethodFDA.cxx:17
 MethodFDA.cxx:18
 MethodFDA.cxx:19
 MethodFDA.cxx:20
 MethodFDA.cxx:21
 MethodFDA.cxx:22
 MethodFDA.cxx:23
 MethodFDA.cxx:24
 MethodFDA.cxx:25
 MethodFDA.cxx:26
 MethodFDA.cxx:27
 MethodFDA.cxx:28
 MethodFDA.cxx:29
 MethodFDA.cxx:30
 MethodFDA.cxx:31
 MethodFDA.cxx:32
 MethodFDA.cxx:33
 MethodFDA.cxx:34
 MethodFDA.cxx:35
 MethodFDA.cxx:36
 MethodFDA.cxx:37
 MethodFDA.cxx:38
 MethodFDA.cxx:39
 MethodFDA.cxx:40
 MethodFDA.cxx:41
 MethodFDA.cxx:42
 MethodFDA.cxx:43
 MethodFDA.cxx:44
 MethodFDA.cxx:45
 MethodFDA.cxx:46
 MethodFDA.cxx:47
 MethodFDA.cxx:48
 MethodFDA.cxx:49
 MethodFDA.cxx:50
 MethodFDA.cxx:51
 MethodFDA.cxx:52
 MethodFDA.cxx:53
 MethodFDA.cxx:54
 MethodFDA.cxx:55
 MethodFDA.cxx:56
 MethodFDA.cxx:57
 MethodFDA.cxx:58
 MethodFDA.cxx:59
 MethodFDA.cxx:60
 MethodFDA.cxx:61
 MethodFDA.cxx:62
 MethodFDA.cxx:63
 MethodFDA.cxx:64
 MethodFDA.cxx:65
 MethodFDA.cxx:66
 MethodFDA.cxx:67
 MethodFDA.cxx:68
 MethodFDA.cxx:69
 MethodFDA.cxx:70
 MethodFDA.cxx:71
 MethodFDA.cxx:72
 MethodFDA.cxx:73
 MethodFDA.cxx:74
 MethodFDA.cxx:75
 MethodFDA.cxx:76
 MethodFDA.cxx:77
 MethodFDA.cxx:78
 MethodFDA.cxx:79
 MethodFDA.cxx:80
 MethodFDA.cxx:81
 MethodFDA.cxx:82
 MethodFDA.cxx:83
 MethodFDA.cxx:84
 MethodFDA.cxx:85
 MethodFDA.cxx:86
 MethodFDA.cxx:87
 MethodFDA.cxx:88
 MethodFDA.cxx:89
 MethodFDA.cxx:90
 MethodFDA.cxx:91
 MethodFDA.cxx:92
 MethodFDA.cxx:93
 MethodFDA.cxx:94
 MethodFDA.cxx:95
 MethodFDA.cxx:96
 MethodFDA.cxx:97
 MethodFDA.cxx:98
 MethodFDA.cxx:99
 MethodFDA.cxx:100
 MethodFDA.cxx:101
 MethodFDA.cxx:102
 MethodFDA.cxx:103
 MethodFDA.cxx:104
 MethodFDA.cxx:105
 MethodFDA.cxx:106
 MethodFDA.cxx:107
 MethodFDA.cxx:108
 MethodFDA.cxx:109
 MethodFDA.cxx:110
 MethodFDA.cxx:111
 MethodFDA.cxx:112
 MethodFDA.cxx:113
 MethodFDA.cxx:114
 MethodFDA.cxx:115
 MethodFDA.cxx:116
 MethodFDA.cxx:117
 MethodFDA.cxx:118
 MethodFDA.cxx:119
 MethodFDA.cxx:120
 MethodFDA.cxx:121
 MethodFDA.cxx:122
 MethodFDA.cxx:123
 MethodFDA.cxx:124
 MethodFDA.cxx:125
 MethodFDA.cxx:126
 MethodFDA.cxx:127
 MethodFDA.cxx:128
 MethodFDA.cxx:129
 MethodFDA.cxx:130
 MethodFDA.cxx:131
 MethodFDA.cxx:132
 MethodFDA.cxx:133
 MethodFDA.cxx:134
 MethodFDA.cxx:135
 MethodFDA.cxx:136
 MethodFDA.cxx:137
 MethodFDA.cxx:138
 MethodFDA.cxx:139
 MethodFDA.cxx:140
 MethodFDA.cxx:141
 MethodFDA.cxx:142
 MethodFDA.cxx:143
 MethodFDA.cxx:144
 MethodFDA.cxx:145
 MethodFDA.cxx:146
 MethodFDA.cxx:147
 MethodFDA.cxx:148
 MethodFDA.cxx:149
 MethodFDA.cxx:150
 MethodFDA.cxx:151
 MethodFDA.cxx:152
 MethodFDA.cxx:153
 MethodFDA.cxx:154
 MethodFDA.cxx:155
 MethodFDA.cxx:156
 MethodFDA.cxx:157
 MethodFDA.cxx:158
 MethodFDA.cxx:159
 MethodFDA.cxx:160
 MethodFDA.cxx:161
 MethodFDA.cxx:162
 MethodFDA.cxx:163
 MethodFDA.cxx:164
 MethodFDA.cxx:165
 MethodFDA.cxx:166
 MethodFDA.cxx:167
 MethodFDA.cxx:168
 MethodFDA.cxx:169
 MethodFDA.cxx:170
 MethodFDA.cxx:171
 MethodFDA.cxx:172
 MethodFDA.cxx:173
 MethodFDA.cxx:174
 MethodFDA.cxx:175
 MethodFDA.cxx:176
 MethodFDA.cxx:177
 MethodFDA.cxx:178
 MethodFDA.cxx:179
 MethodFDA.cxx:180
 MethodFDA.cxx:181
 MethodFDA.cxx:182
 MethodFDA.cxx:183
 MethodFDA.cxx:184
 MethodFDA.cxx:185
 MethodFDA.cxx:186
 MethodFDA.cxx:187
 MethodFDA.cxx:188
 MethodFDA.cxx:189
 MethodFDA.cxx:190
 MethodFDA.cxx:191
 MethodFDA.cxx:192
 MethodFDA.cxx:193
 MethodFDA.cxx:194
 MethodFDA.cxx:195
 MethodFDA.cxx:196
 MethodFDA.cxx:197
 MethodFDA.cxx:198
 MethodFDA.cxx:199
 MethodFDA.cxx:200
 MethodFDA.cxx:201
 MethodFDA.cxx:202
 MethodFDA.cxx:203
 MethodFDA.cxx:204
 MethodFDA.cxx:205
 MethodFDA.cxx:206
 MethodFDA.cxx:207
 MethodFDA.cxx:208
 MethodFDA.cxx:209
 MethodFDA.cxx:210
 MethodFDA.cxx:211
 MethodFDA.cxx:212
 MethodFDA.cxx:213
 MethodFDA.cxx:214
 MethodFDA.cxx:215
 MethodFDA.cxx:216
 MethodFDA.cxx:217
 MethodFDA.cxx:218
 MethodFDA.cxx:219
 MethodFDA.cxx:220
 MethodFDA.cxx:221
 MethodFDA.cxx:222
 MethodFDA.cxx:223
 MethodFDA.cxx:224
 MethodFDA.cxx:225
 MethodFDA.cxx:226
 MethodFDA.cxx:227
 MethodFDA.cxx:228
 MethodFDA.cxx:229
 MethodFDA.cxx:230
 MethodFDA.cxx:231
 MethodFDA.cxx:232
 MethodFDA.cxx:233
 MethodFDA.cxx:234
 MethodFDA.cxx:235
 MethodFDA.cxx:236
 MethodFDA.cxx:237
 MethodFDA.cxx:238
 MethodFDA.cxx:239
 MethodFDA.cxx:240
 MethodFDA.cxx:241
 MethodFDA.cxx:242
 MethodFDA.cxx:243
 MethodFDA.cxx:244
 MethodFDA.cxx:245
 MethodFDA.cxx:246
 MethodFDA.cxx:247
 MethodFDA.cxx:248
 MethodFDA.cxx:249
 MethodFDA.cxx:250
 MethodFDA.cxx:251
 MethodFDA.cxx:252
 MethodFDA.cxx:253
 MethodFDA.cxx:254
 MethodFDA.cxx:255
 MethodFDA.cxx:256
 MethodFDA.cxx:257
 MethodFDA.cxx:258
 MethodFDA.cxx:259
 MethodFDA.cxx:260
 MethodFDA.cxx:261
 MethodFDA.cxx:262
 MethodFDA.cxx:263
 MethodFDA.cxx:264
 MethodFDA.cxx:265
 MethodFDA.cxx:266
 MethodFDA.cxx:267
 MethodFDA.cxx:268
 MethodFDA.cxx:269
 MethodFDA.cxx:270
 MethodFDA.cxx:271
 MethodFDA.cxx:272
 MethodFDA.cxx:273
 MethodFDA.cxx:274
 MethodFDA.cxx:275
 MethodFDA.cxx:276
 MethodFDA.cxx:277
 MethodFDA.cxx:278
 MethodFDA.cxx:279
 MethodFDA.cxx:280
 MethodFDA.cxx:281
 MethodFDA.cxx:282
 MethodFDA.cxx:283
 MethodFDA.cxx:284
 MethodFDA.cxx:285
 MethodFDA.cxx:286
 MethodFDA.cxx:287
 MethodFDA.cxx:288
 MethodFDA.cxx:289
 MethodFDA.cxx:290
 MethodFDA.cxx:291
 MethodFDA.cxx:292
 MethodFDA.cxx:293
 MethodFDA.cxx:294
 MethodFDA.cxx:295
 MethodFDA.cxx:296
 MethodFDA.cxx:297
 MethodFDA.cxx:298
 MethodFDA.cxx:299
 MethodFDA.cxx:300
 MethodFDA.cxx:301
 MethodFDA.cxx:302
 MethodFDA.cxx:303
 MethodFDA.cxx:304
 MethodFDA.cxx:305
 MethodFDA.cxx:306
 MethodFDA.cxx:307
 MethodFDA.cxx:308
 MethodFDA.cxx:309
 MethodFDA.cxx:310
 MethodFDA.cxx:311
 MethodFDA.cxx:312
 MethodFDA.cxx:313
 MethodFDA.cxx:314
 MethodFDA.cxx:315
 MethodFDA.cxx:316
 MethodFDA.cxx:317
 MethodFDA.cxx:318
 MethodFDA.cxx:319
 MethodFDA.cxx:320
 MethodFDA.cxx:321
 MethodFDA.cxx:322
 MethodFDA.cxx:323
 MethodFDA.cxx:324
 MethodFDA.cxx:325
 MethodFDA.cxx:326
 MethodFDA.cxx:327
 MethodFDA.cxx:328
 MethodFDA.cxx:329
 MethodFDA.cxx:330
 MethodFDA.cxx:331
 MethodFDA.cxx:332
 MethodFDA.cxx:333
 MethodFDA.cxx:334
 MethodFDA.cxx:335
 MethodFDA.cxx:336
 MethodFDA.cxx:337
 MethodFDA.cxx:338
 MethodFDA.cxx:339
 MethodFDA.cxx:340
 MethodFDA.cxx:341
 MethodFDA.cxx:342
 MethodFDA.cxx:343
 MethodFDA.cxx:344
 MethodFDA.cxx:345
 MethodFDA.cxx:346
 MethodFDA.cxx:347
 MethodFDA.cxx:348
 MethodFDA.cxx:349
 MethodFDA.cxx:350
 MethodFDA.cxx:351
 MethodFDA.cxx:352
 MethodFDA.cxx:353
 MethodFDA.cxx:354
 MethodFDA.cxx:355
 MethodFDA.cxx:356
 MethodFDA.cxx:357
 MethodFDA.cxx:358
 MethodFDA.cxx:359
 MethodFDA.cxx:360
 MethodFDA.cxx:361
 MethodFDA.cxx:362
 MethodFDA.cxx:363
 MethodFDA.cxx:364
 MethodFDA.cxx:365
 MethodFDA.cxx:366
 MethodFDA.cxx:367
 MethodFDA.cxx:368
 MethodFDA.cxx:369
 MethodFDA.cxx:370
 MethodFDA.cxx:371
 MethodFDA.cxx:372
 MethodFDA.cxx:373
 MethodFDA.cxx:374
 MethodFDA.cxx:375
 MethodFDA.cxx:376
 MethodFDA.cxx:377
 MethodFDA.cxx:378
 MethodFDA.cxx:379
 MethodFDA.cxx:380
 MethodFDA.cxx:381
 MethodFDA.cxx:382
 MethodFDA.cxx:383
 MethodFDA.cxx:384
 MethodFDA.cxx:385
 MethodFDA.cxx:386
 MethodFDA.cxx:387
 MethodFDA.cxx:388
 MethodFDA.cxx:389
 MethodFDA.cxx:390
 MethodFDA.cxx:391
 MethodFDA.cxx:392
 MethodFDA.cxx:393
 MethodFDA.cxx:394
 MethodFDA.cxx:395
 MethodFDA.cxx:396
 MethodFDA.cxx:397
 MethodFDA.cxx:398
 MethodFDA.cxx:399
 MethodFDA.cxx:400
 MethodFDA.cxx:401
 MethodFDA.cxx:402
 MethodFDA.cxx:403
 MethodFDA.cxx:404
 MethodFDA.cxx:405
 MethodFDA.cxx:406
 MethodFDA.cxx:407
 MethodFDA.cxx:408
 MethodFDA.cxx:409
 MethodFDA.cxx:410
 MethodFDA.cxx:411
 MethodFDA.cxx:412
 MethodFDA.cxx:413
 MethodFDA.cxx:414
 MethodFDA.cxx:415
 MethodFDA.cxx:416
 MethodFDA.cxx:417
 MethodFDA.cxx:418
 MethodFDA.cxx:419
 MethodFDA.cxx:420
 MethodFDA.cxx:421
 MethodFDA.cxx:422
 MethodFDA.cxx:423
 MethodFDA.cxx:424
 MethodFDA.cxx:425
 MethodFDA.cxx:426
 MethodFDA.cxx:427
 MethodFDA.cxx:428
 MethodFDA.cxx:429
 MethodFDA.cxx:430
 MethodFDA.cxx:431
 MethodFDA.cxx:432
 MethodFDA.cxx:433
 MethodFDA.cxx:434
 MethodFDA.cxx:435
 MethodFDA.cxx:436
 MethodFDA.cxx:437
 MethodFDA.cxx:438
 MethodFDA.cxx:439
 MethodFDA.cxx:440
 MethodFDA.cxx:441
 MethodFDA.cxx:442
 MethodFDA.cxx:443
 MethodFDA.cxx:444
 MethodFDA.cxx:445
 MethodFDA.cxx:446
 MethodFDA.cxx:447
 MethodFDA.cxx:448
 MethodFDA.cxx:449
 MethodFDA.cxx:450
 MethodFDA.cxx:451
 MethodFDA.cxx:452
 MethodFDA.cxx:453
 MethodFDA.cxx:454
 MethodFDA.cxx:455
 MethodFDA.cxx:456
 MethodFDA.cxx:457
 MethodFDA.cxx:458
 MethodFDA.cxx:459
 MethodFDA.cxx:460
 MethodFDA.cxx:461
 MethodFDA.cxx:462
 MethodFDA.cxx:463
 MethodFDA.cxx:464
 MethodFDA.cxx:465
 MethodFDA.cxx:466
 MethodFDA.cxx:467
 MethodFDA.cxx:468
 MethodFDA.cxx:469
 MethodFDA.cxx:470
 MethodFDA.cxx:471
 MethodFDA.cxx:472
 MethodFDA.cxx:473
 MethodFDA.cxx:474
 MethodFDA.cxx:475
 MethodFDA.cxx:476
 MethodFDA.cxx:477
 MethodFDA.cxx:478
 MethodFDA.cxx:479
 MethodFDA.cxx:480
 MethodFDA.cxx:481
 MethodFDA.cxx:482
 MethodFDA.cxx:483
 MethodFDA.cxx:484
 MethodFDA.cxx:485
 MethodFDA.cxx:486
 MethodFDA.cxx:487
 MethodFDA.cxx:488
 MethodFDA.cxx:489
 MethodFDA.cxx:490
 MethodFDA.cxx:491
 MethodFDA.cxx:492
 MethodFDA.cxx:493
 MethodFDA.cxx:494
 MethodFDA.cxx:495
 MethodFDA.cxx:496
 MethodFDA.cxx:497
 MethodFDA.cxx:498
 MethodFDA.cxx:499
 MethodFDA.cxx:500
 MethodFDA.cxx:501
 MethodFDA.cxx:502
 MethodFDA.cxx:503
 MethodFDA.cxx:504
 MethodFDA.cxx:505
 MethodFDA.cxx:506
 MethodFDA.cxx:507
 MethodFDA.cxx:508
 MethodFDA.cxx:509
 MethodFDA.cxx:510
 MethodFDA.cxx:511
 MethodFDA.cxx:512
 MethodFDA.cxx:513
 MethodFDA.cxx:514
 MethodFDA.cxx:515
 MethodFDA.cxx:516
 MethodFDA.cxx:517
 MethodFDA.cxx:518
 MethodFDA.cxx:519
 MethodFDA.cxx:520
 MethodFDA.cxx:521
 MethodFDA.cxx:522
 MethodFDA.cxx:523
 MethodFDA.cxx:524
 MethodFDA.cxx:525
 MethodFDA.cxx:526
 MethodFDA.cxx:527
 MethodFDA.cxx:528
 MethodFDA.cxx:529
 MethodFDA.cxx:530
 MethodFDA.cxx:531
 MethodFDA.cxx:532
 MethodFDA.cxx:533
 MethodFDA.cxx:534
 MethodFDA.cxx:535
 MethodFDA.cxx:536
 MethodFDA.cxx:537
 MethodFDA.cxx:538
 MethodFDA.cxx:539
 MethodFDA.cxx:540
 MethodFDA.cxx:541
 MethodFDA.cxx:542
 MethodFDA.cxx:543
 MethodFDA.cxx:544
 MethodFDA.cxx:545
 MethodFDA.cxx:546
 MethodFDA.cxx:547
 MethodFDA.cxx:548
 MethodFDA.cxx:549
 MethodFDA.cxx:550
 MethodFDA.cxx:551
 MethodFDA.cxx:552
 MethodFDA.cxx:553
 MethodFDA.cxx:554
 MethodFDA.cxx:555
 MethodFDA.cxx:556
 MethodFDA.cxx:557
 MethodFDA.cxx:558
 MethodFDA.cxx:559
 MethodFDA.cxx:560
 MethodFDA.cxx:561
 MethodFDA.cxx:562
 MethodFDA.cxx:563
 MethodFDA.cxx:564
 MethodFDA.cxx:565
 MethodFDA.cxx:566
 MethodFDA.cxx:567
 MethodFDA.cxx:568
 MethodFDA.cxx:569
 MethodFDA.cxx:570
 MethodFDA.cxx:571
 MethodFDA.cxx:572
 MethodFDA.cxx:573
 MethodFDA.cxx:574
 MethodFDA.cxx:575
 MethodFDA.cxx:576
 MethodFDA.cxx:577
 MethodFDA.cxx:578
 MethodFDA.cxx:579
 MethodFDA.cxx:580
 MethodFDA.cxx:581
 MethodFDA.cxx:582
 MethodFDA.cxx:583
 MethodFDA.cxx:584
 MethodFDA.cxx:585
 MethodFDA.cxx:586
 MethodFDA.cxx:587
 MethodFDA.cxx:588
 MethodFDA.cxx:589
 MethodFDA.cxx:590
 MethodFDA.cxx:591
 MethodFDA.cxx:592
 MethodFDA.cxx:593
 MethodFDA.cxx:594
 MethodFDA.cxx:595
 MethodFDA.cxx:596
 MethodFDA.cxx:597
 MethodFDA.cxx:598
 MethodFDA.cxx:599
 MethodFDA.cxx:600
 MethodFDA.cxx:601
 MethodFDA.cxx:602
 MethodFDA.cxx:603
 MethodFDA.cxx:604
 MethodFDA.cxx:605
 MethodFDA.cxx:606
 MethodFDA.cxx:607
 MethodFDA.cxx:608
 MethodFDA.cxx:609
 MethodFDA.cxx:610
 MethodFDA.cxx:611
 MethodFDA.cxx:612
 MethodFDA.cxx:613
 MethodFDA.cxx:614
 MethodFDA.cxx:615
 MethodFDA.cxx:616
 MethodFDA.cxx:617