ROOT logo
// @(#)root/tmva $Id: MethodTMlpANN.cxx 31458 2009-11-30 13:58:20Z stelzer $ 
// Author: Andreas Hoecker, Joerg Stelzer, Helge Voss, Kai Voss 
/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : MethodTMlpANN                                                         *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Implementation (see header for description)                               *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland              *
 *      Helge Voss      <Helge.Voss@cern.ch>     - MPI-K Heidelberg, Germany      *
 *      Kai Voss        <Kai.Voss@cern.ch>       - U. of Victoria, Canada         *
 *                                                                                *
 * Copyright (c) 2005:                                                            *
 *      CERN, Switzerland                                                         * 
 *      U. of Victoria, Canada                                                    * 
 *      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)                                          *
 **********************************************************************************/

//_______________________________________________________________________
/* Begin_Html

  This is the TMVA TMultiLayerPerceptron interface class. It provides the 
  training and testing the ROOT internal MLP class in the TMVA framework.<be>

  Available learning methods:<br>
  <ul>
  <li>Stochastic      </li> 
  <li>Batch           </li>
  <li>SteepestDescent </li>
  <li>RibierePolak    </li>
  <li>FletcherReeves  </li>
  <li>BFGS            </li>
  </ul>
End_Html */
//
//  See the TMultiLayerPerceptron class description
//  for details on this ANN.
//
//_______________________________________________________________________

#include <cstdlib>
#include <iostream>
#include <fstream>

#include "Riostream.h"
#include "TLeaf.h"
#include "TEventList.h"
#include "TObjString.h"
#include "TROOT.h"
#include "TMultiLayerPerceptron.h"

#include "TMVA/Config.h"
#include "TMVA/MethodTMlpANN.h"

#include "TMVA/ClassifierFactory.h"
#ifndef ROOT_TMVA_Tools
#include "TMVA/Tools.h"
#endif

// some additional TMlpANN options
const Bool_t EnforceNormalization__=kTRUE;
#if ROOT_VERSION_CODE > ROOT_VERSION(5,13,06)
const TMultiLayerPerceptron::ELearningMethod LearningMethod__= TMultiLayerPerceptron::kStochastic;
// const TMultiLayerPerceptron::ELearningMethod LearningMethod__= TMultiLayerPerceptron::kBatch;
#else
const TMultiLayerPerceptron::LearningMethod LearningMethod__= TMultiLayerPerceptron::kStochastic;
#endif

REGISTER_METHOD(TMlpANN)

ClassImp(TMVA::MethodTMlpANN)

//_______________________________________________________________________
TMVA::MethodTMlpANN::MethodTMlpANN( const TString& jobName,
                                    const TString& methodTitle,
                                    DataSetInfo& theData, 
                                    const TString& theOption,
                                    TDirectory* theTargetDir) :
   TMVA::MethodBase( jobName, Types::kTMlpANN, methodTitle, theData, theOption, theTargetDir ),
   fMLP(0),
   fLearningMethod( "" )
{
   // standard constructor 
}

//_______________________________________________________________________
TMVA::MethodTMlpANN::MethodTMlpANN( DataSetInfo& theData, 
                                    const TString& theWeightFile,  
                                    TDirectory* theTargetDir ) :
   TMVA::MethodBase( Types::kTMlpANN, theData, theWeightFile, theTargetDir ),
   fMLP(0),
   fLearningMethod( "" )
{
   // constructor from weight file
}

//_______________________________________________________________________
Bool_t TMVA::MethodTMlpANN::HasAnalysisType( Types::EAnalysisType type, UInt_t numberClasses, 
                                             UInt_t /*numberTargets*/ )
{
   // TMlpANN can handle classification with 2 classes 
   if (type == Types::kClassification && numberClasses == 2) return kTRUE;
   return kFALSE;
}


//_______________________________________________________________________
void TMVA::MethodTMlpANN::Init( void )
{
   // default initialisations
}

//_______________________________________________________________________
TMVA::MethodTMlpANN::~MethodTMlpANN( void )
{
   // destructor
}
 
//_______________________________________________________________________
void TMVA::MethodTMlpANN::CreateMLPOptions( TString layerSpec )
{
   // translates options from option string into TMlpANN language

   fHiddenLayer = ":";

   while (layerSpec.Length()>0) {
      TString sToAdd="";
      if (layerSpec.First(',')<0) {
         sToAdd = layerSpec;
         layerSpec = "";
      } 
      else {
         sToAdd = layerSpec(0,layerSpec.First(','));
         layerSpec = layerSpec(layerSpec.First(',')+1,layerSpec.Length());
      }
      int nNodes = 0;
      if (sToAdd.BeginsWith("N")) { sToAdd.Remove(0,1); nNodes = GetNvar(); }
      nNodes += atoi(sToAdd);
      fHiddenLayer = Form( "%s%i:", (const char*)fHiddenLayer, nNodes );
   }

   // set input vars
   std::vector<TString>::iterator itrVar    = (*fInputVars).begin();
   std::vector<TString>::iterator itrVarEnd = (*fInputVars).end();
   fMLPBuildOptions = "";
   for (; itrVar != itrVarEnd; itrVar++) {
      if (EnforceNormalization__) fMLPBuildOptions += "@";
      TString myVar = *itrVar; ;
      fMLPBuildOptions += myVar;
      fMLPBuildOptions += ",";
   }
   fMLPBuildOptions.Chop(); // remove last ","

   // prepare final options for MLP kernel
   fMLPBuildOptions += fHiddenLayer;
   fMLPBuildOptions += "type";

   Log() << kINFO << "Use " << fNcycles << " training cycles" << Endl;
   Log() << kINFO << "Use configuration (nodes per hidden layer): " << fHiddenLayer << Endl;  
}

//_______________________________________________________________________
void TMVA::MethodTMlpANN::DeclareOptions() 
{
   // define the options (their key words) that can be set in the option string 
   // know options:
   // NCycles       <integer>    Number of training cycles (too many cycles could overtrain the network) 
   // HiddenLayers  <string>     Layout of the hidden layers (nodes per layer)
   //   * specifiactions for each hidden layer are separated by commata
   //   * for each layer the number of nodes can be either absolut (simply a number)
   //        or relative to the number of input nodes to the neural net (N)
   //   * there is always a single node in the output layer 
   //   example: a net with 6 input nodes and "Hiddenlayers=N-1,N-2" has 6,5,4,1 nodes in the 
   //   layers 1,2,3,4, repectively 
   DeclareOptionRef( fNcycles    = 200,       "NCycles",      "Number of training cycles" );
   DeclareOptionRef( fLayerSpec  = "N,N-1",   "HiddenLayers", "Specification of hidden layer architecture (N stands for number of variables; any integers may also be used)" );
   
   DeclareOptionRef( fValidationFraction = 0.5, "ValidationFraction", 
                     "Fraction of events in training tree used for cross validation" );

   DeclareOptionRef( fLearningMethod = "Stochastic", "LearningMethod", "Learning method" );
   AddPreDefVal( TString("Stochastic") );
   AddPreDefVal( TString("Batch") );
   AddPreDefVal( TString("SteepestDescent") );
   AddPreDefVal( TString("RibierePolak") );
   AddPreDefVal( TString("FletcherReeves") );
   AddPreDefVal( TString("BFGS") );
}

//_______________________________________________________________________
void TMVA::MethodTMlpANN::ProcessOptions() 
{
   // builds the neural network as specified by the user
   CreateMLPOptions(fLayerSpec);

   if (IgnoreEventsWithNegWeightsInTraining()) {
      Log() << kFATAL << "Mechanism to ignore events with negative weights in training not available for method"
            << GetMethodTypeName() 
            << " --> please remove \"IgnoreNegWeightsInTraining\" option from booking string."
            << Endl;
   }
}

//_______________________________________________________________________
Double_t TMVA::MethodTMlpANN::GetMvaValue( Double_t* err )
{
   // calculate the value of the neural net for the current event 
   const Event* ev = GetEvent();
   static Double_t* d = new Double_t[Data()->GetNVariables()];
   for (UInt_t ivar = 0; ivar<Data()->GetNVariables(); ivar++) {
      d[ivar] = (Double_t)ev->GetValue(ivar);
   }
   Double_t mvaVal = fMLP->Evaluate(0,d);

   // cannot determine error
   if (err != 0) *err = -1;

   return mvaVal;
}

//_______________________________________________________________________
void TMVA::MethodTMlpANN::Train( void )
{
   // performs TMlpANN training
   // available learning methods:
   //
   //       TMultiLayerPerceptron::kStochastic      
   //       TMultiLayerPerceptron::kBatch           
   //       TMultiLayerPerceptron::kSteepestDescent 
   //       TMultiLayerPerceptron::kRibierePolak    
   //       TMultiLayerPerceptron::kFletcherReeves  
   //       TMultiLayerPerceptron::kBFGS            
   //
   // TMultiLayerPerceptron wants test and training tree at once
   // so merge the training and testing trees from the MVA factory first:

   Int_t type;
   Float_t weight;
   const Long_t basketsize = 128000;
   Float_t* vArr = new Float_t[GetNvar()];

   TTree *localTrainingTree = new TTree( "TMLPtrain", "Local training tree for TMlpANN" );
   localTrainingTree->Branch( "type",       &type,        "type/I",        basketsize );
   localTrainingTree->Branch( "weight",     &weight,      "weight/F",      basketsize );
   
   for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
      const char* myVar = GetInternalVarName(ivar).Data();
      localTrainingTree->Branch( myVar, &vArr[ivar], Form("Var%02i/F", ivar), basketsize );
   }
   
   for (UInt_t ievt=0; ievt<Data()->GetNEvents(); ievt++) {
      const Event *ev = GetEvent(ievt);
      for (UInt_t i=0; i<GetNvar(); i++) {
         vArr[i] = ev->GetValue( i );
      }
      type   = DataInfo().IsSignal( ev ) ? 1 : 0;
      weight = ev->GetWeight();
      localTrainingTree->Fill();
   }

   // These are the event lists for the mlp train method
   // first events in the tree are for training
   // the rest for internal testing (cross validation)...
   // NOTE: the training events are ordered: first part is signal, second part background
   TString trainList = "Entry$<";
   trainList += 1.0-fValidationFraction;
   trainList += "*";
   trainList += (Int_t)Data()->GetNEvtSigTrain();
   trainList += " || (Entry$>";
   trainList += (Int_t)Data()->GetNEvtSigTrain();
   trainList += " && Entry$<";
   trainList += (Int_t)(Data()->GetNEvtSigTrain() + (1.0 - fValidationFraction)*Data()->GetNEvtBkgdTrain());
   trainList += ")";
   TString testList  = TString("!(") + trainList + ")";

   // print the requirements
   Log() << kINFO << "Requirement for training   events: \"" << trainList << "\"" << Endl;
   Log() << kINFO << "Requirement for validation events: \"" << testList << "\"" << Endl;

   // localTrainingTree->Print();

   // create NN 
   if (fMLP != 0) { delete fMLP; fMLP = 0; }
   fMLP = new TMultiLayerPerceptron( fMLPBuildOptions.Data(), 
                                     localTrainingTree,
                                     trainList,
                                     testList );
   fMLP->SetEventWeight( "weight" );

   // set learning method
#if ROOT_VERSION_CODE > ROOT_VERSION(5,13,06)
   TMultiLayerPerceptron::ELearningMethod learningMethod = TMultiLayerPerceptron::kStochastic; 
#else
   TMultiLayerPerceptron::LearningMethod  learningMethod = TMultiLayerPerceptron::kStochastic; 
#endif

   fLearningMethod.ToLower();
   if      (fLearningMethod == "stochastic"      ) learningMethod = TMultiLayerPerceptron::kStochastic;
   else if (fLearningMethod == "batch"           ) learningMethod = TMultiLayerPerceptron::kBatch;
   else if (fLearningMethod == "steepestdescent" ) learningMethod = TMultiLayerPerceptron::kSteepestDescent;
   else if (fLearningMethod == "ribierepolak"    ) learningMethod = TMultiLayerPerceptron::kRibierePolak;
   else if (fLearningMethod == "fletcherreeves"  ) learningMethod = TMultiLayerPerceptron::kFletcherReeves;
   else if (fLearningMethod == "bfgs"            ) learningMethod = TMultiLayerPerceptron::kBFGS;
   else {
      Log() << kFATAL << "Unknown Learning Method: \"" << fLearningMethod << "\"" << Endl;
   }
   fMLP->SetLearningMethod( learningMethod );

   // train NN
   fMLP->Train(fNcycles, "text,update=50" );

   // write weights to File;
   // this is not nice, but fMLP gets deleted at the end of Train()
   delete localTrainingTree;

}

 
//_______________________________________________________________________
void TMVA::MethodTMlpANN::AddWeightsXMLTo( void* parent ) const 
{
   // write weights to xml file
   
   // first the architecture
   void *wght = gTools().xmlengine().NewChild(parent, 0, "Weights");
   void* arch = gTools().xmlengine().NewChild( wght, 0, "Architecture" );
   gTools().AddAttr( arch, "BuildOptions", fMLPBuildOptions.Data() );

   // dump weights first in temporary txt file, read from there into xml
   fMLP->DumpWeights( "weights/TMlp.nn.weights.temp" );
   std::ifstream inf( "weights/TMlp.nn.weights.temp" );
   char temp[256];
   TString data("");
   void *ch=NULL;
   while (inf.getline(temp,256)) {
      TString dummy(temp);
      if (dummy.BeginsWith('#')) {
         if (ch!=0) gTools().xmlengine().AddRawLine( ch, data.Data() );
         dummy = dummy.Strip(TString::kLeading, '#');
         dummy = dummy(0,dummy.First(' '));
         ch = gTools().xmlengine().NewChild(wght, 0, dummy);
         data.Resize(0);
         continue;
      }
      data += (dummy + " ");
   }
   if (ch != 0) gTools().xmlengine().AddRawLine( ch, data.Data() );
   inf.close();
}

//_______________________________________________________________________
void  TMVA::MethodTMlpANN::ReadWeightsFromXML( void* wghtnode )
{
   // rebuild temporary textfile from xml weightfile and load this
   // file into MLP
   void* ch = gTools().xmlengine().GetChild(wghtnode);
   gTools().ReadAttr( ch, "BuildOptions", fMLPBuildOptions );

   ch = gTools().xmlengine().GetNext(ch);
   const char* fname = "weights/TMlp.nn.weights.temp";
   std::ofstream fout( fname );
   double temp1=0,temp2=0;
   while (ch) {
      const char* nodecontent = gTools().xmlengine().GetNodeContent(ch);
      std::stringstream content(nodecontent);
      if (strcmp(gTools().xmlengine().GetNodeName(ch),"input")==0) {
         fout << "#input normalization" << std::endl;         
         while ((content >> temp1) &&(content >> temp2)) {
            fout << temp1 << " " << temp2 << std::endl;
         }
      }
      if (strcmp(gTools().xmlengine().GetNodeName(ch),"output")==0) {
         fout << "#output normalization" << std::endl;         
         while ((content >> temp1) &&(content >> temp2)) {
            fout << temp1 << " " << temp2 << std::endl;
         }
      }
      if (strcmp(gTools().xmlengine().GetNodeName(ch),"neurons")==0) {
         fout << "#neurons weights" << std::endl;         
         while (content >> temp1) {
            fout << temp1 << std::endl;
         }
      }
      if (strcmp(gTools().xmlengine().GetNodeName(ch),"synapses")==0) {
         fout << "#synapses weights" ;         
         while (content >> temp1) {
            fout << std::endl << temp1 ;                
         }
      }
      ch = gTools().xmlengine().GetNext(ch);
   }
   fout.close();;

   // Here we create a dummy tree necessary to create a minimal NN
   // to be used for testing, evaluation and application
   static Double_t* d = new Double_t[Data()->GetNVariables()] ;
   static Int_t type;

   gROOT->cd();
   TTree * dummyTree = new TTree("dummy","Empty dummy tree", 1);
   for (UInt_t ivar = 0; ivar<Data()->GetNVariables(); ivar++) {
      TString vn = DataInfo().GetVariableInfo(ivar).GetInternalName();
      dummyTree->Branch(Form("%s",vn.Data()), d+ivar, Form("%s/D",vn.Data()));
   }
   dummyTree->Branch("type", &type, "type/I");

   if (fMLP != 0) { delete fMLP; fMLP = 0; }
   fMLP = new TMultiLayerPerceptron( fMLPBuildOptions.Data(), dummyTree );
   fMLP->LoadWeights( fname );
}
 
//_______________________________________________________________________
void  TMVA::MethodTMlpANN::ReadWeightsFromStream( istream& istr )
{
   // read weights from stream
   // since the MLP can not read from the stream, we
   // 1st: write the weights to temporary file
   std::ofstream fout( "./TMlp.nn.weights.temp" );
   fout << istr.rdbuf();
   fout.close();
   // 2nd: load the weights from the temporary file into the MLP
   // the MLP is already build
   Log() << kINFO << "Load TMLP weights into " << fMLP << Endl;

   Double_t* d = new Double_t[Data()->GetNVariables()] ;
   static Int_t type;
   gROOT->cd();
   TTree * dummyTree = new TTree("dummy","Empty dummy tree", 1);
   for (UInt_t ivar = 0; ivar<Data()->GetNVariables(); ivar++) {
      TString vn = DataInfo().GetVariableInfo(ivar).GetLabel();
      dummyTree->Branch(Form("%s",vn.Data()), d+ivar, Form("%s/D",vn.Data()));
   }
   dummyTree->Branch("type", &type, "type/I");

   if (fMLP != 0) { delete fMLP; fMLP = 0; }
   fMLP = new TMultiLayerPerceptron( fMLPBuildOptions.Data(), dummyTree );

   fMLP->LoadWeights( "./TMlp.nn.weights.temp" );
   // here we can delete the temporary file
   // how?
}

//_______________________________________________________________________
void TMVA::MethodTMlpANN::MakeClass( const TString& theClassFileName ) const
{
   // create reader class for classifier -> overwrites base class function
   // create specific class for TMultiLayerPerceptron

   // the default consists of
   TString classFileName = "";
   if (theClassFileName == "")
      classFileName = GetWeightFileDir() + "/" + GetJobName() + "_" + GetMethodName() + ".class";
   else
      classFileName = theClassFileName;

   Log() << kINFO << "Creating specific (TMultiLayerPerceptron) standalone response class: " << Endl;
   fMLP->Export( classFileName.Data() );
}

//_______________________________________________________________________
void TMVA::MethodTMlpANN::MakeClassSpecific( std::ostream& /*fout*/, const TString& /*className*/ ) const
{
   // write specific classifier response
   // nothing to do here - all taken care of by TMultiLayerPerceptron
}

//_______________________________________________________________________
void TMVA::MethodTMlpANN::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() << "This feed-forward multilayer perceptron neural network is the " << Endl;
   Log() << "standard implementation distributed with ROOT (class TMultiLayerPerceptron)." << Endl;
   Log() << Endl;
   Log() << "Detailed information is available here:" << Endl;
   if (gConfig().WriteOptionsReference()) {
      Log() << "<a href=\"http://root.cern.ch/root/html/TMultiLayerPerceptron.html\">";
      Log() << "http://root.cern.ch/root/html/TMultiLayerPerceptron.html</a>" << Endl;
   }
   else Log() << "http://root.cern.ch/root/html/TMultiLayerPerceptron.html" << Endl;
   Log() << Endl;
}
 MethodTMlpANN.cxx:1
 MethodTMlpANN.cxx:2
 MethodTMlpANN.cxx:3
 MethodTMlpANN.cxx:4
 MethodTMlpANN.cxx:5
 MethodTMlpANN.cxx:6
 MethodTMlpANN.cxx:7
 MethodTMlpANN.cxx:8
 MethodTMlpANN.cxx:9
 MethodTMlpANN.cxx:10
 MethodTMlpANN.cxx:11
 MethodTMlpANN.cxx:12
 MethodTMlpANN.cxx:13
 MethodTMlpANN.cxx:14
 MethodTMlpANN.cxx:15
 MethodTMlpANN.cxx:16
 MethodTMlpANN.cxx:17
 MethodTMlpANN.cxx:18
 MethodTMlpANN.cxx:19
 MethodTMlpANN.cxx:20
 MethodTMlpANN.cxx:21
 MethodTMlpANN.cxx:22
 MethodTMlpANN.cxx:23
 MethodTMlpANN.cxx:24
 MethodTMlpANN.cxx:25
 MethodTMlpANN.cxx:26
 MethodTMlpANN.cxx:27
 MethodTMlpANN.cxx:28
 MethodTMlpANN.cxx:29
 MethodTMlpANN.cxx:30
 MethodTMlpANN.cxx:31
 MethodTMlpANN.cxx:32
 MethodTMlpANN.cxx:33
 MethodTMlpANN.cxx:34
 MethodTMlpANN.cxx:35
 MethodTMlpANN.cxx:36
 MethodTMlpANN.cxx:37
 MethodTMlpANN.cxx:38
 MethodTMlpANN.cxx:39
 MethodTMlpANN.cxx:40
 MethodTMlpANN.cxx:41
 MethodTMlpANN.cxx:42
 MethodTMlpANN.cxx:43
 MethodTMlpANN.cxx:44
 MethodTMlpANN.cxx:45
 MethodTMlpANN.cxx:46
 MethodTMlpANN.cxx:47
 MethodTMlpANN.cxx:48
 MethodTMlpANN.cxx:49
 MethodTMlpANN.cxx:50
 MethodTMlpANN.cxx:51
 MethodTMlpANN.cxx:52
 MethodTMlpANN.cxx:53
 MethodTMlpANN.cxx:54
 MethodTMlpANN.cxx:55
 MethodTMlpANN.cxx:56
 MethodTMlpANN.cxx:57
 MethodTMlpANN.cxx:58
 MethodTMlpANN.cxx:59
 MethodTMlpANN.cxx:60
 MethodTMlpANN.cxx:61
 MethodTMlpANN.cxx:62
 MethodTMlpANN.cxx:63
 MethodTMlpANN.cxx:64
 MethodTMlpANN.cxx:65
 MethodTMlpANN.cxx:66
 MethodTMlpANN.cxx:67
 MethodTMlpANN.cxx:68
 MethodTMlpANN.cxx:69
 MethodTMlpANN.cxx:70
 MethodTMlpANN.cxx:71
 MethodTMlpANN.cxx:72
 MethodTMlpANN.cxx:73
 MethodTMlpANN.cxx:74
 MethodTMlpANN.cxx:75
 MethodTMlpANN.cxx:76
 MethodTMlpANN.cxx:77
 MethodTMlpANN.cxx:78
 MethodTMlpANN.cxx:79
 MethodTMlpANN.cxx:80
 MethodTMlpANN.cxx:81
 MethodTMlpANN.cxx:82
 MethodTMlpANN.cxx:83
 MethodTMlpANN.cxx:84
 MethodTMlpANN.cxx:85
 MethodTMlpANN.cxx:86
 MethodTMlpANN.cxx:87
 MethodTMlpANN.cxx:88
 MethodTMlpANN.cxx:89
 MethodTMlpANN.cxx:90
 MethodTMlpANN.cxx:91
 MethodTMlpANN.cxx:92
 MethodTMlpANN.cxx:93
 MethodTMlpANN.cxx:94
 MethodTMlpANN.cxx:95
 MethodTMlpANN.cxx:96
 MethodTMlpANN.cxx:97
 MethodTMlpANN.cxx:98
 MethodTMlpANN.cxx:99
 MethodTMlpANN.cxx:100
 MethodTMlpANN.cxx:101
 MethodTMlpANN.cxx:102
 MethodTMlpANN.cxx:103
 MethodTMlpANN.cxx:104
 MethodTMlpANN.cxx:105
 MethodTMlpANN.cxx:106
 MethodTMlpANN.cxx:107
 MethodTMlpANN.cxx:108
 MethodTMlpANN.cxx:109
 MethodTMlpANN.cxx:110
 MethodTMlpANN.cxx:111
 MethodTMlpANN.cxx:112
 MethodTMlpANN.cxx:113
 MethodTMlpANN.cxx:114
 MethodTMlpANN.cxx:115
 MethodTMlpANN.cxx:116
 MethodTMlpANN.cxx:117
 MethodTMlpANN.cxx:118
 MethodTMlpANN.cxx:119
 MethodTMlpANN.cxx:120
 MethodTMlpANN.cxx:121
 MethodTMlpANN.cxx:122
 MethodTMlpANN.cxx:123
 MethodTMlpANN.cxx:124
 MethodTMlpANN.cxx:125
 MethodTMlpANN.cxx:126
 MethodTMlpANN.cxx:127
 MethodTMlpANN.cxx:128
 MethodTMlpANN.cxx:129
 MethodTMlpANN.cxx:130
 MethodTMlpANN.cxx:131
 MethodTMlpANN.cxx:132
 MethodTMlpANN.cxx:133
 MethodTMlpANN.cxx:134
 MethodTMlpANN.cxx:135
 MethodTMlpANN.cxx:136
 MethodTMlpANN.cxx:137
 MethodTMlpANN.cxx:138
 MethodTMlpANN.cxx:139
 MethodTMlpANN.cxx:140
 MethodTMlpANN.cxx:141
 MethodTMlpANN.cxx:142
 MethodTMlpANN.cxx:143
 MethodTMlpANN.cxx:144
 MethodTMlpANN.cxx:145
 MethodTMlpANN.cxx:146
 MethodTMlpANN.cxx:147
 MethodTMlpANN.cxx:148
 MethodTMlpANN.cxx:149
 MethodTMlpANN.cxx:150
 MethodTMlpANN.cxx:151
 MethodTMlpANN.cxx:152
 MethodTMlpANN.cxx:153
 MethodTMlpANN.cxx:154
 MethodTMlpANN.cxx:155
 MethodTMlpANN.cxx:156
 MethodTMlpANN.cxx:157
 MethodTMlpANN.cxx:158
 MethodTMlpANN.cxx:159
 MethodTMlpANN.cxx:160
 MethodTMlpANN.cxx:161
 MethodTMlpANN.cxx:162
 MethodTMlpANN.cxx:163
 MethodTMlpANN.cxx:164
 MethodTMlpANN.cxx:165
 MethodTMlpANN.cxx:166
 MethodTMlpANN.cxx:167
 MethodTMlpANN.cxx:168
 MethodTMlpANN.cxx:169
 MethodTMlpANN.cxx:170
 MethodTMlpANN.cxx:171
 MethodTMlpANN.cxx:172
 MethodTMlpANN.cxx:173
 MethodTMlpANN.cxx:174
 MethodTMlpANN.cxx:175
 MethodTMlpANN.cxx:176
 MethodTMlpANN.cxx:177
 MethodTMlpANN.cxx:178
 MethodTMlpANN.cxx:179
 MethodTMlpANN.cxx:180
 MethodTMlpANN.cxx:181
 MethodTMlpANN.cxx:182
 MethodTMlpANN.cxx:183
 MethodTMlpANN.cxx:184
 MethodTMlpANN.cxx:185
 MethodTMlpANN.cxx:186
 MethodTMlpANN.cxx:187
 MethodTMlpANN.cxx:188
 MethodTMlpANN.cxx:189
 MethodTMlpANN.cxx:190
 MethodTMlpANN.cxx:191
 MethodTMlpANN.cxx:192
 MethodTMlpANN.cxx:193
 MethodTMlpANN.cxx:194
 MethodTMlpANN.cxx:195
 MethodTMlpANN.cxx:196
 MethodTMlpANN.cxx:197
 MethodTMlpANN.cxx:198
 MethodTMlpANN.cxx:199
 MethodTMlpANN.cxx:200
 MethodTMlpANN.cxx:201
 MethodTMlpANN.cxx:202
 MethodTMlpANN.cxx:203
 MethodTMlpANN.cxx:204
 MethodTMlpANN.cxx:205
 MethodTMlpANN.cxx:206
 MethodTMlpANN.cxx:207
 MethodTMlpANN.cxx:208
 MethodTMlpANN.cxx:209
 MethodTMlpANN.cxx:210
 MethodTMlpANN.cxx:211
 MethodTMlpANN.cxx:212
 MethodTMlpANN.cxx:213
 MethodTMlpANN.cxx:214
 MethodTMlpANN.cxx:215
 MethodTMlpANN.cxx:216
 MethodTMlpANN.cxx:217
 MethodTMlpANN.cxx:218
 MethodTMlpANN.cxx:219
 MethodTMlpANN.cxx:220
 MethodTMlpANN.cxx:221
 MethodTMlpANN.cxx:222
 MethodTMlpANN.cxx:223
 MethodTMlpANN.cxx:224
 MethodTMlpANN.cxx:225
 MethodTMlpANN.cxx:226
 MethodTMlpANN.cxx:227
 MethodTMlpANN.cxx:228
 MethodTMlpANN.cxx:229
 MethodTMlpANN.cxx:230
 MethodTMlpANN.cxx:231
 MethodTMlpANN.cxx:232
 MethodTMlpANN.cxx:233
 MethodTMlpANN.cxx:234
 MethodTMlpANN.cxx:235
 MethodTMlpANN.cxx:236
 MethodTMlpANN.cxx:237
 MethodTMlpANN.cxx:238
 MethodTMlpANN.cxx:239
 MethodTMlpANN.cxx:240
 MethodTMlpANN.cxx:241
 MethodTMlpANN.cxx:242
 MethodTMlpANN.cxx:243
 MethodTMlpANN.cxx:244
 MethodTMlpANN.cxx:245
 MethodTMlpANN.cxx:246
 MethodTMlpANN.cxx:247
 MethodTMlpANN.cxx:248
 MethodTMlpANN.cxx:249
 MethodTMlpANN.cxx:250
 MethodTMlpANN.cxx:251
 MethodTMlpANN.cxx:252
 MethodTMlpANN.cxx:253
 MethodTMlpANN.cxx:254
 MethodTMlpANN.cxx:255
 MethodTMlpANN.cxx:256
 MethodTMlpANN.cxx:257
 MethodTMlpANN.cxx:258
 MethodTMlpANN.cxx:259
 MethodTMlpANN.cxx:260
 MethodTMlpANN.cxx:261
 MethodTMlpANN.cxx:262
 MethodTMlpANN.cxx:263
 MethodTMlpANN.cxx:264
 MethodTMlpANN.cxx:265
 MethodTMlpANN.cxx:266
 MethodTMlpANN.cxx:267
 MethodTMlpANN.cxx:268
 MethodTMlpANN.cxx:269
 MethodTMlpANN.cxx:270
 MethodTMlpANN.cxx:271
 MethodTMlpANN.cxx:272
 MethodTMlpANN.cxx:273
 MethodTMlpANN.cxx:274
 MethodTMlpANN.cxx:275
 MethodTMlpANN.cxx:276
 MethodTMlpANN.cxx:277
 MethodTMlpANN.cxx:278
 MethodTMlpANN.cxx:279
 MethodTMlpANN.cxx:280
 MethodTMlpANN.cxx:281
 MethodTMlpANN.cxx:282
 MethodTMlpANN.cxx:283
 MethodTMlpANN.cxx:284
 MethodTMlpANN.cxx:285
 MethodTMlpANN.cxx:286
 MethodTMlpANN.cxx:287
 MethodTMlpANN.cxx:288
 MethodTMlpANN.cxx:289
 MethodTMlpANN.cxx:290
 MethodTMlpANN.cxx:291
 MethodTMlpANN.cxx:292
 MethodTMlpANN.cxx:293
 MethodTMlpANN.cxx:294
 MethodTMlpANN.cxx:295
 MethodTMlpANN.cxx:296
 MethodTMlpANN.cxx:297
 MethodTMlpANN.cxx:298
 MethodTMlpANN.cxx:299
 MethodTMlpANN.cxx:300
 MethodTMlpANN.cxx:301
 MethodTMlpANN.cxx:302
 MethodTMlpANN.cxx:303
 MethodTMlpANN.cxx:304
 MethodTMlpANN.cxx:305
 MethodTMlpANN.cxx:306
 MethodTMlpANN.cxx:307
 MethodTMlpANN.cxx:308
 MethodTMlpANN.cxx:309
 MethodTMlpANN.cxx:310
 MethodTMlpANN.cxx:311
 MethodTMlpANN.cxx:312
 MethodTMlpANN.cxx:313
 MethodTMlpANN.cxx:314
 MethodTMlpANN.cxx:315
 MethodTMlpANN.cxx:316
 MethodTMlpANN.cxx:317
 MethodTMlpANN.cxx:318
 MethodTMlpANN.cxx:319
 MethodTMlpANN.cxx:320
 MethodTMlpANN.cxx:321
 MethodTMlpANN.cxx:322
 MethodTMlpANN.cxx:323
 MethodTMlpANN.cxx:324
 MethodTMlpANN.cxx:325
 MethodTMlpANN.cxx:326
 MethodTMlpANN.cxx:327
 MethodTMlpANN.cxx:328
 MethodTMlpANN.cxx:329
 MethodTMlpANN.cxx:330
 MethodTMlpANN.cxx:331
 MethodTMlpANN.cxx:332
 MethodTMlpANN.cxx:333
 MethodTMlpANN.cxx:334
 MethodTMlpANN.cxx:335
 MethodTMlpANN.cxx:336
 MethodTMlpANN.cxx:337
 MethodTMlpANN.cxx:338
 MethodTMlpANN.cxx:339
 MethodTMlpANN.cxx:340
 MethodTMlpANN.cxx:341
 MethodTMlpANN.cxx:342
 MethodTMlpANN.cxx:343
 MethodTMlpANN.cxx:344
 MethodTMlpANN.cxx:345
 MethodTMlpANN.cxx:346
 MethodTMlpANN.cxx:347
 MethodTMlpANN.cxx:348
 MethodTMlpANN.cxx:349
 MethodTMlpANN.cxx:350
 MethodTMlpANN.cxx:351
 MethodTMlpANN.cxx:352
 MethodTMlpANN.cxx:353
 MethodTMlpANN.cxx:354
 MethodTMlpANN.cxx:355
 MethodTMlpANN.cxx:356
 MethodTMlpANN.cxx:357
 MethodTMlpANN.cxx:358
 MethodTMlpANN.cxx:359
 MethodTMlpANN.cxx:360
 MethodTMlpANN.cxx:361
 MethodTMlpANN.cxx:362
 MethodTMlpANN.cxx:363
 MethodTMlpANN.cxx:364
 MethodTMlpANN.cxx:365
 MethodTMlpANN.cxx:366
 MethodTMlpANN.cxx:367
 MethodTMlpANN.cxx:368
 MethodTMlpANN.cxx:369
 MethodTMlpANN.cxx:370
 MethodTMlpANN.cxx:371
 MethodTMlpANN.cxx:372
 MethodTMlpANN.cxx:373
 MethodTMlpANN.cxx:374
 MethodTMlpANN.cxx:375
 MethodTMlpANN.cxx:376
 MethodTMlpANN.cxx:377
 MethodTMlpANN.cxx:378
 MethodTMlpANN.cxx:379
 MethodTMlpANN.cxx:380
 MethodTMlpANN.cxx:381
 MethodTMlpANN.cxx:382
 MethodTMlpANN.cxx:383
 MethodTMlpANN.cxx:384
 MethodTMlpANN.cxx:385
 MethodTMlpANN.cxx:386
 MethodTMlpANN.cxx:387
 MethodTMlpANN.cxx:388
 MethodTMlpANN.cxx:389
 MethodTMlpANN.cxx:390
 MethodTMlpANN.cxx:391
 MethodTMlpANN.cxx:392
 MethodTMlpANN.cxx:393
 MethodTMlpANN.cxx:394
 MethodTMlpANN.cxx:395
 MethodTMlpANN.cxx:396
 MethodTMlpANN.cxx:397
 MethodTMlpANN.cxx:398
 MethodTMlpANN.cxx:399
 MethodTMlpANN.cxx:400
 MethodTMlpANN.cxx:401
 MethodTMlpANN.cxx:402
 MethodTMlpANN.cxx:403
 MethodTMlpANN.cxx:404
 MethodTMlpANN.cxx:405
 MethodTMlpANN.cxx:406
 MethodTMlpANN.cxx:407
 MethodTMlpANN.cxx:408
 MethodTMlpANN.cxx:409
 MethodTMlpANN.cxx:410
 MethodTMlpANN.cxx:411
 MethodTMlpANN.cxx:412
 MethodTMlpANN.cxx:413
 MethodTMlpANN.cxx:414
 MethodTMlpANN.cxx:415
 MethodTMlpANN.cxx:416
 MethodTMlpANN.cxx:417
 MethodTMlpANN.cxx:418
 MethodTMlpANN.cxx:419
 MethodTMlpANN.cxx:420
 MethodTMlpANN.cxx:421
 MethodTMlpANN.cxx:422
 MethodTMlpANN.cxx:423
 MethodTMlpANN.cxx:424
 MethodTMlpANN.cxx:425
 MethodTMlpANN.cxx:426
 MethodTMlpANN.cxx:427
 MethodTMlpANN.cxx:428
 MethodTMlpANN.cxx:429
 MethodTMlpANN.cxx:430
 MethodTMlpANN.cxx:431
 MethodTMlpANN.cxx:432
 MethodTMlpANN.cxx:433
 MethodTMlpANN.cxx:434
 MethodTMlpANN.cxx:435
 MethodTMlpANN.cxx:436
 MethodTMlpANN.cxx:437
 MethodTMlpANN.cxx:438
 MethodTMlpANN.cxx:439
 MethodTMlpANN.cxx:440
 MethodTMlpANN.cxx:441
 MethodTMlpANN.cxx:442
 MethodTMlpANN.cxx:443
 MethodTMlpANN.cxx:444
 MethodTMlpANN.cxx:445
 MethodTMlpANN.cxx:446
 MethodTMlpANN.cxx:447
 MethodTMlpANN.cxx:448
 MethodTMlpANN.cxx:449
 MethodTMlpANN.cxx:450
 MethodTMlpANN.cxx:451
 MethodTMlpANN.cxx:452
 MethodTMlpANN.cxx:453
 MethodTMlpANN.cxx:454
 MethodTMlpANN.cxx:455
 MethodTMlpANN.cxx:456
 MethodTMlpANN.cxx:457
 MethodTMlpANN.cxx:458
 MethodTMlpANN.cxx:459
 MethodTMlpANN.cxx:460
 MethodTMlpANN.cxx:461
 MethodTMlpANN.cxx:462
 MethodTMlpANN.cxx:463
 MethodTMlpANN.cxx:464
 MethodTMlpANN.cxx:465
 MethodTMlpANN.cxx:466
 MethodTMlpANN.cxx:467
 MethodTMlpANN.cxx:468
 MethodTMlpANN.cxx:469
 MethodTMlpANN.cxx:470
 MethodTMlpANN.cxx:471
 MethodTMlpANN.cxx:472
 MethodTMlpANN.cxx:473
 MethodTMlpANN.cxx:474
 MethodTMlpANN.cxx:475
 MethodTMlpANN.cxx:476
 MethodTMlpANN.cxx:477
 MethodTMlpANN.cxx:478
 MethodTMlpANN.cxx:479
 MethodTMlpANN.cxx:480
 MethodTMlpANN.cxx:481
 MethodTMlpANN.cxx:482
 MethodTMlpANN.cxx:483
 MethodTMlpANN.cxx:484
 MethodTMlpANN.cxx:485
 MethodTMlpANN.cxx:486
 MethodTMlpANN.cxx:487
 MethodTMlpANN.cxx:488
 MethodTMlpANN.cxx:489
 MethodTMlpANN.cxx:490
 MethodTMlpANN.cxx:491
 MethodTMlpANN.cxx:492
 MethodTMlpANN.cxx:493
 MethodTMlpANN.cxx:494
 MethodTMlpANN.cxx:495