// @(#)root/tmva $Id$
// Author: Marcin Wolter, Andrzej Zemla

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : MethodSVM                                                             *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Implementation                                                            *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Marcin Wolter  <Marcin.Wolter@cern.ch> - IFJ PAN, Krakow, Poland          *
 *      Andrzej Zemla  <azemla@cern.ch>          - IFJ PAN, Krakow, Poland        *
 *      (IFJ PAN: Henryk Niewodniczanski Inst. Nucl. Physics, Krakow, Poland)     *
 *                                                                                *
 * Introduction of regression by:                                                 *
 *      Krzysztof Danielowski <danielow@cern.ch> - IFJ PAN & AGH, Krakow, Poland  *
 *      Kamil Kraszewski      <kalq@cern.ch>     - IFJ PAN & UJ, Krakow, Poland   *
 *      Maciej Kruk           <mkruk@cern.ch>    - IFJ PAN & AGH, Krakow, Poland  *
 *                                                                                *
 *                                                                                *
 * Copyright (c) 2005:                                                            *
 *      CERN, Switzerland                                                         *
 *      MPI-K Heidelberg, Germany                                                 *
 *      PAN, Krakow, Poland                                                       *
 *                                                                                *
 * 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)                                          *
 **********************************************************************************/

//_______________________________________________________________________
//
// SMO Platt's SVM classifier with Keerthi & Shavade improvements
//_______________________________________________________________________

#include "Riostream.h"
#include "TMath.h"
#include "TFile.h"

#include "TMVA/ClassifierFactory.h"
#ifndef ROOT_TMVA_MethodSVM
#include "TMVA/MethodSVM.h"
#endif
#ifndef ROOT_TMVA_Tools
#include "TMVA/Tools.h"
#endif
#ifndef ROOT_TMVA_Timer
#include "TMVA/Timer.h"
#endif

#ifndef ROOT_TMVA_SVWorkingSet
#include "TMVA/SVWorkingSet.h"
#endif

#ifndef ROOT_TMVA_SVEvent
#include "TMVA/SVEvent.h"
#endif

#ifndef ROOT_TMVA_SVKernelFunction
#include "TMVA/SVKernelFunction.h"
#endif

#include <string>

using std::vector;

//const Int_t basketsize__ = 1280000;
REGISTER_METHOD(SVM)

ClassImp(TMVA::MethodSVM)

//_______________________________________________________________________
TMVA::MethodSVM::MethodSVM( const TString& jobName, const TString& methodTitle, DataSetInfo& theData,
                            const TString& theOption, TDirectory* theTargetDir )
   : MethodBase( jobName, Types::kSVM, methodTitle, theData, theOption, theTargetDir )
   , fCost(0)
   , fTolerance(0)
   , fMaxIter(0)
   , fNSubSets(0)
   , fBparm(0)
   , fGamma(0)
   , fWgSet(0)
   , fInputData(0)
   , fSupportVectors(0)
   , fSVKernelFunction(0)
   , fMinVars(0)
   , fMaxVars(0)
   , fDoubleSigmaSquared(0)
   , fOrder(0)
   , fTheta(0)
   , fKappa(0)
{
   // standard constructor
}

//_______________________________________________________________________
TMVA::MethodSVM::MethodSVM( DataSetInfo& theData, const TString& theWeightFile, TDirectory*  theTargetDir )
   : MethodBase( Types::kSVM, theData, theWeightFile, theTargetDir )
   , fCost(0)
   , fTolerance(0)
   , fMaxIter(0)
   , fNSubSets(0)
   , fBparm(0)
   , fGamma(0)
   , fWgSet(0)
   , fInputData(0)
   , fSupportVectors(0)
   , fSVKernelFunction(0)
   , fMinVars(0)
   , fMaxVars(0)
   , fDoubleSigmaSquared(0)
   , fOrder(0)
   , fTheta(0)
   , fKappa(0)
{
   // constructor from weight file
}

//_______________________________________________________________________
TMVA::MethodSVM::~MethodSVM()
{
   // destructor
   if (fInputData !=0)       { delete fInputData; fInputData=0; }
   if (fSupportVectors !=0 ) { delete fSupportVectors; fSupportVectors = 0; }
   if (fWgSet !=0)           { delete fWgSet; fWgSet=0; }
   if (fSVKernelFunction !=0 ) { delete fSVKernelFunction; fSVKernelFunction = 0; }
}

//_______________________________________________________________________
Bool_t TMVA::MethodSVM::HasAnalysisType( Types::EAnalysisType type, UInt_t numberClasses, UInt_t numberTargets )
{
   // SVM 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::MethodSVM::Init()
{
   // default initialisation

   // SVM always uses normalised input variables
   SetNormalised( kTRUE );

   // Helge: do not book a event vector of given size but rather fill the vector
   //        later with pus_back. Anyway, this is NOT what is time consuming in
   //        SVM and it allows to skip totally events with weights == 0 ;)
   fInputData = new std::vector<TMVA::SVEvent*>(0);
   fSupportVectors = new std::vector<TMVA::SVEvent*>(0);
}

//_______________________________________________________________________
void TMVA::MethodSVM::DeclareOptions()
{
   // declare options available for this method

   // for gaussian kernel parameter(s)
   DeclareOptionRef( fGamma = 1., "Gamma", "RBF kernel parameter: Gamma (size of the Kernel)");

   DeclareOptionRef( fCost,   "C",        "Cost parameter" );
   if (DoRegression()) {
      fCost = 0.002;
   }else{
      fCost = 1.;
   }
   DeclareOptionRef( fTolerance = 0.01, "Tol",      "Tolerance parameter" );  //should be fixed
   DeclareOptionRef( fMaxIter   = 1000, "MaxIter",  "Maximum number of training loops" );

}

//_______________________________________________________________________
void TMVA::MethodSVM::DeclareCompatibilityOptions()
{
   // options that are used ONLY for the READER to ensure backward compatibility
   MethodBase::DeclareCompatibilityOptions();
   DeclareOptionRef( fNSubSets  = 1,    "NSubSets", "Number of training subsets" );
   DeclareOptionRef( fTheKernel = "Gauss", "Kernel", "Uses kernel function");
   // for gaussian kernel parameter(s)
   DeclareOptionRef( fDoubleSigmaSquared = 2., "Sigma", "Kernel parameter: sigma");
   // for polynomiarl kernel parameter(s)
   DeclareOptionRef( fOrder = 3, "Order", "Polynomial Kernel parameter: polynomial order");
   // for sigmoid kernel parameters
   DeclareOptionRef( fTheta = 1., "Theta", "Sigmoid Kernel parameter: theta");
   DeclareOptionRef( fKappa = 1., "Kappa", "Sigmoid Kernel parameter: kappa");
}

//_______________________________________________________________________
void TMVA::MethodSVM::ProcessOptions()
{
   // option post processing (if necessary)
   if (IgnoreEventsWithNegWeightsInTraining()) {
      Log() << kFATAL << "Mechanism to ignore events with negative weights in training not yet available for method: "
            << GetMethodTypeName()
            << " --> please remove \"IgnoreNegWeightsInTraining\" option from booking string."
            << Endl;
   }
}

//_______________________________________________________________________
void TMVA::MethodSVM::Train()
{
   // Train SVM
   Data()->SetCurrentType(Types::kTraining);

   Log() << kDEBUG << "Create event vector"<< Endl;
   for (Int_t ievt=0; ievt<Data()->GetNEvents(); ievt++){
      if (GetEvent(ievt)->GetWeight() != 0) 
         fInputData->push_back(new SVEvent(GetEvent(ievt), fCost, DataInfo().IsSignal(GetEvent(ievt)))); 
   }

   fSVKernelFunction = new SVKernelFunction(fGamma);

   Log()<< kINFO << "Building SVM Working Set...with "<<fInputData->size()<<" event instances"<< Endl;
   Timer bldwstime( GetName());
   fWgSet = new SVWorkingSet( fInputData, fSVKernelFunction,fTolerance, DoRegression() );
   Log() << kINFO <<"Elapsed time for Working Set build: "<< bldwstime.GetElapsedTime()<<Endl;

   // timing
   Timer timer( GetName() );
   Log() << kINFO << "Sorry, no computing time forecast available for SVM, please wait ..." << Endl;

   fWgSet->Train(fMaxIter);

   Log() << kINFO << "Elapsed time: " << timer.GetElapsedTime()
         << "                                          " << Endl;

   fBparm          = fWgSet->GetBpar();
   fSupportVectors = fWgSet->GetSupportVectors();


   delete fWgSet;
   fWgSet=0;

   //   for (UInt_t i=0; i<fInputData->size();i++) delete fInputData->at(i);
   delete fInputData; 
   fInputData=0;
}

//_______________________________________________________________________
void TMVA::MethodSVM::AddWeightsXMLTo( void* parent ) const
{
   // write configuration to xml file
   void* wght = gTools().AddChild(parent, "Weights");
   gTools().AddAttr(wght,"fBparm",fBparm);
   gTools().AddAttr(wght,"fGamma",fGamma);
   gTools().AddAttr(wght,"NSupVec",fSupportVectors->size());

   for (std::vector<TMVA::SVEvent*>::iterator veciter=fSupportVectors->begin();
        veciter!=fSupportVectors->end() ; ++veciter ) {
      TVectorD temp(GetNvar()+4);
      temp[0] = (*veciter)->GetNs();
      temp[1] = (*veciter)->GetTypeFlag();
      temp[2] = (*veciter)->GetAlpha();
      temp[3] = (*veciter)->GetAlpha_p();
      for (UInt_t ivar = 0; ivar < GetNvar(); ivar++)
         temp[ivar+4] = (*(*veciter)->GetDataVector())[ivar];
      gTools().WriteTVectorDToXML(wght,"SupportVector",&temp);
   }
   // write max/min data values
   void* maxnode = gTools().AddChild(wght, "Maxima");
   for (UInt_t ivar = 0; ivar < GetNvar(); ivar++)
      gTools().AddAttr(maxnode, "Var"+gTools().StringFromInt(ivar), GetXmax(ivar));
   void* minnode = gTools().AddChild(wght, "Minima");
   for (UInt_t ivar = 0; ivar < GetNvar(); ivar++)
      gTools().AddAttr(minnode, "Var"+gTools().StringFromInt(ivar), GetXmin(ivar));
}

//_______________________________________________________________________
void TMVA::MethodSVM::ReadWeightsFromXML( void* wghtnode )
{
   gTools().ReadAttr( wghtnode, "fBparm",fBparm   );
   gTools().ReadAttr( wghtnode, "fGamma",fGamma);
   UInt_t fNsupv=0;
   gTools().ReadAttr( wghtnode, "NSupVec",fNsupv   );

   Float_t alpha=0.;
   Float_t alpha_p = 0.;

   Int_t typeFlag=-1;
   // UInt_t ns = 0;
   std::vector<Float_t>* svector = new std::vector<Float_t>(GetNvar());

   if (fMaxVars!=0) delete fMaxVars;
   fMaxVars = new TVectorD( GetNvar() );
   if (fMinVars!=0) delete fMinVars;
   fMinVars = new TVectorD( GetNvar() );
   if (fSupportVectors!=0) {
      for (vector< SVEvent* >::iterator it = fSupportVectors->begin(); it!=fSupportVectors->end(); ++it)
         delete *it;
      delete fSupportVectors;
   }
   fSupportVectors = new std::vector<TMVA::SVEvent*>(0);
   void* supportvectornode = gTools().GetChild(wghtnode);
   for (UInt_t ievt = 0; ievt < fNsupv; ievt++) {
      TVectorD temp(GetNvar()+4);
      gTools().ReadTVectorDFromXML(supportvectornode,"SupportVector",&temp);
      // ns=(UInt_t)temp[0];
      typeFlag=(int)temp[1];
      alpha=temp[2];
      alpha_p=temp[3];
      for (UInt_t ivar = 0; ivar < GetNvar(); ivar++) (*svector)[ivar]=temp[ivar+4];

      fSupportVectors->push_back(new SVEvent(svector,alpha,alpha_p,typeFlag));
      supportvectornode = gTools().GetNextChild(supportvectornode);
   }

   void* maxminnode = supportvectornode;
   for (UInt_t ivar = 0; ivar < GetNvar(); ivar++)
      gTools().ReadAttr( maxminnode,"Var"+gTools().StringFromInt(ivar),(*fMaxVars)[ivar]);
   maxminnode = gTools().GetNextChild(maxminnode);
   for (UInt_t ivar = 0; ivar < GetNvar(); ivar++)
      gTools().ReadAttr( maxminnode,"Var"+gTools().StringFromInt(ivar),(*fMinVars)[ivar]);
   if (fSVKernelFunction!=0) delete fSVKernelFunction;
   fSVKernelFunction = new SVKernelFunction(fGamma);
   delete svector;
}

//_______________________________________________________________________
void TMVA::MethodSVM::WriteWeightsToStream( TFile& ) const
{
   //TODO write IT
   // write training sample (TTree) to file
}

//_______________________________________________________________________
void  TMVA::MethodSVM::ReadWeightsFromStream( std::istream& istr )
{
   if (fSupportVectors !=0) { delete fSupportVectors; fSupportVectors = 0;}
   fSupportVectors = new std::vector<TMVA::SVEvent*>(0);

   // read configuration from input stream
   istr >> fBparm;

   UInt_t fNsupv;
   // coverity[tainted_data_argument]
   istr >> fNsupv;
   fSupportVectors->reserve(fNsupv);

   Float_t typeTalpha=0.;
   Float_t alpha=0.;
   Int_t typeFlag=-1;
   UInt_t ns = 0;
   std::vector<Float_t>* svector = new std::vector<Float_t>(GetNvar());

   fMaxVars = new TVectorD( GetNvar() );
   fMinVars = new TVectorD( GetNvar() );

   for (UInt_t ievt = 0; ievt < fNsupv; ievt++) {
      istr>>ns;
      istr>>typeTalpha;
      typeFlag = typeTalpha<0?-1:1;
      alpha = typeTalpha<0?-typeTalpha:typeTalpha;
      for (UInt_t ivar = 0; ivar < GetNvar(); ivar++) istr >> svector->at(ivar);

      fSupportVectors->push_back(new SVEvent(svector,alpha,typeFlag,ns));
   }

   for (UInt_t ivar = 0; ivar < GetNvar(); ivar++) istr >> (*fMaxVars)[ivar];

   for (UInt_t ivar = 0; ivar < GetNvar(); ivar++) istr >> (*fMinVars)[ivar];

   delete fSVKernelFunction;
   if (fTheKernel == "Gauss" ) {
      fSVKernelFunction = new SVKernelFunction(1/fDoubleSigmaSquared);
   } 
   else {
      SVKernelFunction::EKernelType k = SVKernelFunction::kLinear;
      if(fTheKernel == "Linear")           k = SVKernelFunction::kLinear;
      else if (fTheKernel == "Polynomial") k = SVKernelFunction::kPolynomial;
      else if (fTheKernel == "Sigmoid"   ) k = SVKernelFunction::kSigmoidal;
      else {
         Log() << kFATAL <<"Unknown kernel function found in weight file!" << Endl;
      }
      fSVKernelFunction = new SVKernelFunction();
      fSVKernelFunction->setCompatibilityParams(k, fOrder, fTheta, fKappa);
   }
   delete svector;
}

//_______________________________________________________________________
void TMVA::MethodSVM::ReadWeightsFromStream( TFile& /* fFin */ )
{
   // TODO write IT
}

//_______________________________________________________________________
Double_t TMVA::MethodSVM::GetMvaValue( Double_t* err, Double_t* errUpper )
{
   // returns MVA value for given event
   Double_t myMVA = 0;

   // TODO: avoid creation of a new SVEvent every time (Joerg)
   SVEvent* ev = new SVEvent( GetEvent(), 0. ); // check for specificators

   for (UInt_t ievt = 0; ievt < fSupportVectors->size() ; ievt++) {
      myMVA += ( fSupportVectors->at(ievt)->GetAlpha()
                 * fSupportVectors->at(ievt)->GetTypeFlag()
                 * fSVKernelFunction->Evaluate( fSupportVectors->at(ievt), ev ) );
   }

   delete ev;

   myMVA -= fBparm;

   // cannot determine error
   NoErrorCalc(err, errUpper);

   // 08/12/09: changed sign here to make results agree with convention signal=1
   return 1.0/(1.0 + TMath::Exp(myMVA));
}
//_______________________________________________________________________
const std::vector<Float_t>& TMVA::MethodSVM::GetRegressionValues()
{

   if( fRegressionReturnVal == NULL )
      fRegressionReturnVal = new std::vector<Float_t>();
   fRegressionReturnVal->clear();

   Double_t myMVA = 0;

   const Event *baseev = GetEvent();
   SVEvent* ev = new SVEvent( baseev,0. ); //check for specificators

   for (UInt_t ievt = 0; ievt < fSupportVectors->size() ; ievt++) {
      myMVA += ( fSupportVectors->at(ievt)->GetDeltaAlpha()
                 *fSVKernelFunction->Evaluate( fSupportVectors->at(ievt), ev ) );
   }
   myMVA += fBparm;
   Event * evT = new Event(*baseev);
   evT->SetTarget(0,myMVA);

   const Event* evT2 = GetTransformationHandler().InverseTransform( evT );

   fRegressionReturnVal->push_back(evT2->GetTarget(0));

   delete evT;

   delete ev;

   return *fRegressionReturnVal;
}

//_______________________________________________________________________
void TMVA::MethodSVM::MakeClassSpecific( std::ostream& fout, const TString& className ) const
{
   // write specific classifier response
   const int fNsupv = fSupportVectors->size();
   fout << "   // not implemented for class: \"" << className << "\"" << std::endl;
   fout << "   float        fBparameter;" << std::endl;
   fout << "   int          fNOfSuppVec;" << std::endl;
   fout << "   static float fAllSuppVectors[][" << fNsupv << "];" << std::endl;
   fout << "   static float fAlphaTypeCoef[" << fNsupv << "];" << std::endl;
   fout << std::endl;
   fout << "   // Kernel parameter(s) " << std::endl;
   fout << "   float fGamma;"  << std::endl;
   fout << "};" << std::endl;
   fout << "" << std::endl;

   //Initialize function definition
   fout << "inline void " << className << "::Initialize() " << std::endl;
   fout << "{" << std::endl;
   fout << "   fBparameter = " << fBparm << ";" << std::endl;
   fout << "   fNOfSuppVec = " << fNsupv << ";" << std::endl;
   fout << "   fGamma = " << fGamma << ";" <<std::endl;
   fout << "}" << std::endl;
   fout << std::endl;

   // GetMvaValue__ function defninition
   fout << "inline double " << className << "::GetMvaValue__(const std::vector<double>& inputValues ) const" << std::endl;
   fout << "{" << std::endl;
   fout << "   double mvaval = 0; " << std::endl;
   fout << "   double temp = 0; " << std::endl;
   fout << std::endl;
   fout << "   for (int ievt = 0; ievt < fNOfSuppVec; ievt++ ){" << std::endl;
   fout << "      temp = 0;" << std::endl;
   fout << "      for ( unsigned int ivar = 0; ivar < GetNvar(); ivar++ ) {" << std::endl;

   fout << "         temp += (fAllSuppVectors[ivar][ievt] - inputValues[ivar])  " << std::endl;
   fout << "               * (fAllSuppVectors[ivar][ievt] - inputValues[ivar]); " << std::endl;
   fout << "      }" << std::endl;
   fout << "      mvaval += fAlphaTypeCoef[ievt] * exp( -fGamma * temp ); " << std::endl;

   fout << "   }" << std::endl;
   fout << "   mvaval -= fBparameter;" << std::endl;
   fout << "   return 1./(1. + exp(mvaval));" << std::endl;
   fout << "}" << std::endl;
   fout << "// Clean up" << std::endl;
   fout << "inline void " << className << "::Clear() " << std::endl;
   fout << "{" << std::endl;
   fout << "   // nothing to clear " << std::endl;
   fout << "}" << std::endl;
   fout << "" << std::endl;

   // define support vectors
   fout << "float " << className << "::fAlphaTypeCoef[] =" << std::endl;
   fout << "{ ";
   for (Int_t isv = 0; isv < fNsupv; isv++) {
      fout << fSupportVectors->at(isv)->GetDeltaAlpha() * fSupportVectors->at(isv)->GetTypeFlag();
      if (isv < fNsupv-1) fout << ", ";
   }
   fout << " };" << std::endl << std::endl;

   fout << "float " << className << "::fAllSuppVectors[][" << fNsupv << "] =" << std::endl;
   fout << "{";
   for (UInt_t ivar = 0; ivar < GetNvar(); ivar++) {
      fout << std::endl;
      fout << "   { ";
      for (Int_t isv = 0; isv < fNsupv; isv++){
         fout << fSupportVectors->at(isv)->GetDataVector()->at(ivar);
         if (isv < fNsupv-1) fout << ", ";
      }
      fout << " }";
      if (ivar < GetNvar()-1) fout << ", " << std::endl;
      else                    fout << std::endl;
   }
   fout << "};" << std::endl<< std::endl;
}

//_______________________________________________________________________
void TMVA::MethodSVM::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 Support Vector Machine (SVM) builds a hyperplance separating" << Endl;
   Log() << "signal and background events (vectors) using the minimal subset of " << Endl;
   Log() << "all vectors used for training (support vectors). The extension to" << Endl;
   Log() << "the non-linear case is performed by mapping input vectors into a " << Endl;
   Log() << "higher-dimensional feature space in which linear separation is " << Endl;
   Log() << "possible. The use of the kernel functions thereby eliminates the " << Endl;
   Log() << "explicit transformation to the feature space. The implemented SVM " << Endl;
   Log() << "algorithm performs the classification tasks using linear, polynomial, " << Endl;
   Log() << "Gaussian and sigmoidal kernel functions. The Gaussian kernel allows " << Endl;
   Log() << "to apply any discriminant shape in the input space." << Endl;
   Log() << Endl;
   Log() << gTools().Color("bold") << "--- Performance optimisation:" << gTools().Color("reset") << Endl;
   Log() << Endl;
   Log() << "SVM is a general purpose non-linear classification method, which " << Endl;
   Log() << "does not require data preprocessing like decorrelation or Principal " << Endl;
   Log() << "Component Analysis. It generalises quite well and can handle analyses " << Endl;
   Log() << "with large numbers of input variables." << Endl;
   Log() << Endl;
   Log() << gTools().Color("bold") << "--- Performance tuning via configuration options:" << gTools().Color("reset") << Endl;
   Log() << Endl;
   Log() << "Optimal performance requires primarily a proper choice of the kernel " << Endl;
   Log() << "parameters (the width \"Sigma\" in case of Gaussian kernel) and the" << Endl;
   Log() << "cost parameter \"C\". The user must optimise them empirically by running" << Endl;
   Log() << "SVM several times with different parameter sets. The time needed for " << Endl;
   Log() << "each evaluation scales like the square of the number of training " << Endl;
   Log() << "events so that a coarse preliminary tuning should be performed on " << Endl;
   Log() << "reduced data sets." << Endl;
}
 MethodSVM.cxx:1
 MethodSVM.cxx:2
 MethodSVM.cxx:3
 MethodSVM.cxx:4
 MethodSVM.cxx:5
 MethodSVM.cxx:6
 MethodSVM.cxx:7
 MethodSVM.cxx:8
 MethodSVM.cxx:9
 MethodSVM.cxx:10
 MethodSVM.cxx:11
 MethodSVM.cxx:12
 MethodSVM.cxx:13
 MethodSVM.cxx:14
 MethodSVM.cxx:15
 MethodSVM.cxx:16
 MethodSVM.cxx:17
 MethodSVM.cxx:18
 MethodSVM.cxx:19
 MethodSVM.cxx:20
 MethodSVM.cxx:21
 MethodSVM.cxx:22
 MethodSVM.cxx:23
 MethodSVM.cxx:24
 MethodSVM.cxx:25
 MethodSVM.cxx:26
 MethodSVM.cxx:27
 MethodSVM.cxx:28
 MethodSVM.cxx:29
 MethodSVM.cxx:30
 MethodSVM.cxx:31
 MethodSVM.cxx:32
 MethodSVM.cxx:33
 MethodSVM.cxx:34
 MethodSVM.cxx:35
 MethodSVM.cxx:36
 MethodSVM.cxx:37
 MethodSVM.cxx:38
 MethodSVM.cxx:39
 MethodSVM.cxx:40
 MethodSVM.cxx:41
 MethodSVM.cxx:42
 MethodSVM.cxx:43
 MethodSVM.cxx:44
 MethodSVM.cxx:45
 MethodSVM.cxx:46
 MethodSVM.cxx:47
 MethodSVM.cxx:48
 MethodSVM.cxx:49
 MethodSVM.cxx:50
 MethodSVM.cxx:51
 MethodSVM.cxx:52
 MethodSVM.cxx:53
 MethodSVM.cxx:54
 MethodSVM.cxx:55
 MethodSVM.cxx:56
 MethodSVM.cxx:57
 MethodSVM.cxx:58
 MethodSVM.cxx:59
 MethodSVM.cxx:60
 MethodSVM.cxx:61
 MethodSVM.cxx:62
 MethodSVM.cxx:63
 MethodSVM.cxx:64
 MethodSVM.cxx:65
 MethodSVM.cxx:66
 MethodSVM.cxx:67
 MethodSVM.cxx:68
 MethodSVM.cxx:69
 MethodSVM.cxx:70
 MethodSVM.cxx:71
 MethodSVM.cxx:72
 MethodSVM.cxx:73
 MethodSVM.cxx:74
 MethodSVM.cxx:75
 MethodSVM.cxx:76
 MethodSVM.cxx:77
 MethodSVM.cxx:78
 MethodSVM.cxx:79
 MethodSVM.cxx:80
 MethodSVM.cxx:81
 MethodSVM.cxx:82
 MethodSVM.cxx:83
 MethodSVM.cxx:84
 MethodSVM.cxx:85
 MethodSVM.cxx:86
 MethodSVM.cxx:87
 MethodSVM.cxx:88
 MethodSVM.cxx:89
 MethodSVM.cxx:90
 MethodSVM.cxx:91
 MethodSVM.cxx:92
 MethodSVM.cxx:93
 MethodSVM.cxx:94
 MethodSVM.cxx:95
 MethodSVM.cxx:96
 MethodSVM.cxx:97
 MethodSVM.cxx:98
 MethodSVM.cxx:99
 MethodSVM.cxx:100
 MethodSVM.cxx:101
 MethodSVM.cxx:102
 MethodSVM.cxx:103
 MethodSVM.cxx:104
 MethodSVM.cxx:105
 MethodSVM.cxx:106
 MethodSVM.cxx:107
 MethodSVM.cxx:108
 MethodSVM.cxx:109
 MethodSVM.cxx:110
 MethodSVM.cxx:111
 MethodSVM.cxx:112
 MethodSVM.cxx:113
 MethodSVM.cxx:114
 MethodSVM.cxx:115
 MethodSVM.cxx:116
 MethodSVM.cxx:117
 MethodSVM.cxx:118
 MethodSVM.cxx:119
 MethodSVM.cxx:120
 MethodSVM.cxx:121
 MethodSVM.cxx:122
 MethodSVM.cxx:123
 MethodSVM.cxx:124
 MethodSVM.cxx:125
 MethodSVM.cxx:126
 MethodSVM.cxx:127
 MethodSVM.cxx:128
 MethodSVM.cxx:129
 MethodSVM.cxx:130
 MethodSVM.cxx:131
 MethodSVM.cxx:132
 MethodSVM.cxx:133
 MethodSVM.cxx:134
 MethodSVM.cxx:135
 MethodSVM.cxx:136
 MethodSVM.cxx:137
 MethodSVM.cxx:138
 MethodSVM.cxx:139
 MethodSVM.cxx:140
 MethodSVM.cxx:141
 MethodSVM.cxx:142
 MethodSVM.cxx:143
 MethodSVM.cxx:144
 MethodSVM.cxx:145
 MethodSVM.cxx:146
 MethodSVM.cxx:147
 MethodSVM.cxx:148
 MethodSVM.cxx:149
 MethodSVM.cxx:150
 MethodSVM.cxx:151
 MethodSVM.cxx:152
 MethodSVM.cxx:153
 MethodSVM.cxx:154
 MethodSVM.cxx:155
 MethodSVM.cxx:156
 MethodSVM.cxx:157
 MethodSVM.cxx:158
 MethodSVM.cxx:159
 MethodSVM.cxx:160
 MethodSVM.cxx:161
 MethodSVM.cxx:162
 MethodSVM.cxx:163
 MethodSVM.cxx:164
 MethodSVM.cxx:165
 MethodSVM.cxx:166
 MethodSVM.cxx:167
 MethodSVM.cxx:168
 MethodSVM.cxx:169
 MethodSVM.cxx:170
 MethodSVM.cxx:171
 MethodSVM.cxx:172
 MethodSVM.cxx:173
 MethodSVM.cxx:174
 MethodSVM.cxx:175
 MethodSVM.cxx:176
 MethodSVM.cxx:177
 MethodSVM.cxx:178
 MethodSVM.cxx:179
 MethodSVM.cxx:180
 MethodSVM.cxx:181
 MethodSVM.cxx:182
 MethodSVM.cxx:183
 MethodSVM.cxx:184
 MethodSVM.cxx:185
 MethodSVM.cxx:186
 MethodSVM.cxx:187
 MethodSVM.cxx:188
 MethodSVM.cxx:189
 MethodSVM.cxx:190
 MethodSVM.cxx:191
 MethodSVM.cxx:192
 MethodSVM.cxx:193
 MethodSVM.cxx:194
 MethodSVM.cxx:195
 MethodSVM.cxx:196
 MethodSVM.cxx:197
 MethodSVM.cxx:198
 MethodSVM.cxx:199
 MethodSVM.cxx:200
 MethodSVM.cxx:201
 MethodSVM.cxx:202
 MethodSVM.cxx:203
 MethodSVM.cxx:204
 MethodSVM.cxx:205
 MethodSVM.cxx:206
 MethodSVM.cxx:207
 MethodSVM.cxx:208
 MethodSVM.cxx:209
 MethodSVM.cxx:210
 MethodSVM.cxx:211
 MethodSVM.cxx:212
 MethodSVM.cxx:213
 MethodSVM.cxx:214
 MethodSVM.cxx:215
 MethodSVM.cxx:216
 MethodSVM.cxx:217
 MethodSVM.cxx:218
 MethodSVM.cxx:219
 MethodSVM.cxx:220
 MethodSVM.cxx:221
 MethodSVM.cxx:222
 MethodSVM.cxx:223
 MethodSVM.cxx:224
 MethodSVM.cxx:225
 MethodSVM.cxx:226
 MethodSVM.cxx:227
 MethodSVM.cxx:228
 MethodSVM.cxx:229
 MethodSVM.cxx:230
 MethodSVM.cxx:231
 MethodSVM.cxx:232
 MethodSVM.cxx:233
 MethodSVM.cxx:234
 MethodSVM.cxx:235
 MethodSVM.cxx:236
 MethodSVM.cxx:237
 MethodSVM.cxx:238
 MethodSVM.cxx:239
 MethodSVM.cxx:240
 MethodSVM.cxx:241
 MethodSVM.cxx:242
 MethodSVM.cxx:243
 MethodSVM.cxx:244
 MethodSVM.cxx:245
 MethodSVM.cxx:246
 MethodSVM.cxx:247
 MethodSVM.cxx:248
 MethodSVM.cxx:249
 MethodSVM.cxx:250
 MethodSVM.cxx:251
 MethodSVM.cxx:252
 MethodSVM.cxx:253
 MethodSVM.cxx:254
 MethodSVM.cxx:255
 MethodSVM.cxx:256
 MethodSVM.cxx:257
 MethodSVM.cxx:258
 MethodSVM.cxx:259
 MethodSVM.cxx:260
 MethodSVM.cxx:261
 MethodSVM.cxx:262
 MethodSVM.cxx:263
 MethodSVM.cxx:264
 MethodSVM.cxx:265
 MethodSVM.cxx:266
 MethodSVM.cxx:267
 MethodSVM.cxx:268
 MethodSVM.cxx:269
 MethodSVM.cxx:270
 MethodSVM.cxx:271
 MethodSVM.cxx:272
 MethodSVM.cxx:273
 MethodSVM.cxx:274
 MethodSVM.cxx:275
 MethodSVM.cxx:276
 MethodSVM.cxx:277
 MethodSVM.cxx:278
 MethodSVM.cxx:279
 MethodSVM.cxx:280
 MethodSVM.cxx:281
 MethodSVM.cxx:282
 MethodSVM.cxx:283
 MethodSVM.cxx:284
 MethodSVM.cxx:285
 MethodSVM.cxx:286
 MethodSVM.cxx:287
 MethodSVM.cxx:288
 MethodSVM.cxx:289
 MethodSVM.cxx:290
 MethodSVM.cxx:291
 MethodSVM.cxx:292
 MethodSVM.cxx:293
 MethodSVM.cxx:294
 MethodSVM.cxx:295
 MethodSVM.cxx:296
 MethodSVM.cxx:297
 MethodSVM.cxx:298
 MethodSVM.cxx:299
 MethodSVM.cxx:300
 MethodSVM.cxx:301
 MethodSVM.cxx:302
 MethodSVM.cxx:303
 MethodSVM.cxx:304
 MethodSVM.cxx:305
 MethodSVM.cxx:306
 MethodSVM.cxx:307
 MethodSVM.cxx:308
 MethodSVM.cxx:309
 MethodSVM.cxx:310
 MethodSVM.cxx:311
 MethodSVM.cxx:312
 MethodSVM.cxx:313
 MethodSVM.cxx:314
 MethodSVM.cxx:315
 MethodSVM.cxx:316
 MethodSVM.cxx:317
 MethodSVM.cxx:318
 MethodSVM.cxx:319
 MethodSVM.cxx:320
 MethodSVM.cxx:321
 MethodSVM.cxx:322
 MethodSVM.cxx:323
 MethodSVM.cxx:324
 MethodSVM.cxx:325
 MethodSVM.cxx:326
 MethodSVM.cxx:327
 MethodSVM.cxx:328
 MethodSVM.cxx:329
 MethodSVM.cxx:330
 MethodSVM.cxx:331
 MethodSVM.cxx:332
 MethodSVM.cxx:333
 MethodSVM.cxx:334
 MethodSVM.cxx:335
 MethodSVM.cxx:336
 MethodSVM.cxx:337
 MethodSVM.cxx:338
 MethodSVM.cxx:339
 MethodSVM.cxx:340
 MethodSVM.cxx:341
 MethodSVM.cxx:342
 MethodSVM.cxx:343
 MethodSVM.cxx:344
 MethodSVM.cxx:345
 MethodSVM.cxx:346
 MethodSVM.cxx:347
 MethodSVM.cxx:348
 MethodSVM.cxx:349
 MethodSVM.cxx:350
 MethodSVM.cxx:351
 MethodSVM.cxx:352
 MethodSVM.cxx:353
 MethodSVM.cxx:354
 MethodSVM.cxx:355
 MethodSVM.cxx:356
 MethodSVM.cxx:357
 MethodSVM.cxx:358
 MethodSVM.cxx:359
 MethodSVM.cxx:360
 MethodSVM.cxx:361
 MethodSVM.cxx:362
 MethodSVM.cxx:363
 MethodSVM.cxx:364
 MethodSVM.cxx:365
 MethodSVM.cxx:366
 MethodSVM.cxx:367
 MethodSVM.cxx:368
 MethodSVM.cxx:369
 MethodSVM.cxx:370
 MethodSVM.cxx:371
 MethodSVM.cxx:372
 MethodSVM.cxx:373
 MethodSVM.cxx:374
 MethodSVM.cxx:375
 MethodSVM.cxx:376
 MethodSVM.cxx:377
 MethodSVM.cxx:378
 MethodSVM.cxx:379
 MethodSVM.cxx:380
 MethodSVM.cxx:381
 MethodSVM.cxx:382
 MethodSVM.cxx:383
 MethodSVM.cxx:384
 MethodSVM.cxx:385
 MethodSVM.cxx:386
 MethodSVM.cxx:387
 MethodSVM.cxx:388
 MethodSVM.cxx:389
 MethodSVM.cxx:390
 MethodSVM.cxx:391
 MethodSVM.cxx:392
 MethodSVM.cxx:393
 MethodSVM.cxx:394
 MethodSVM.cxx:395
 MethodSVM.cxx:396
 MethodSVM.cxx:397
 MethodSVM.cxx:398
 MethodSVM.cxx:399
 MethodSVM.cxx:400
 MethodSVM.cxx:401
 MethodSVM.cxx:402
 MethodSVM.cxx:403
 MethodSVM.cxx:404
 MethodSVM.cxx:405
 MethodSVM.cxx:406
 MethodSVM.cxx:407
 MethodSVM.cxx:408
 MethodSVM.cxx:409
 MethodSVM.cxx:410
 MethodSVM.cxx:411
 MethodSVM.cxx:412
 MethodSVM.cxx:413
 MethodSVM.cxx:414
 MethodSVM.cxx:415
 MethodSVM.cxx:416
 MethodSVM.cxx:417
 MethodSVM.cxx:418
 MethodSVM.cxx:419
 MethodSVM.cxx:420
 MethodSVM.cxx:421
 MethodSVM.cxx:422
 MethodSVM.cxx:423
 MethodSVM.cxx:424
 MethodSVM.cxx:425
 MethodSVM.cxx:426
 MethodSVM.cxx:427
 MethodSVM.cxx:428
 MethodSVM.cxx:429
 MethodSVM.cxx:430
 MethodSVM.cxx:431
 MethodSVM.cxx:432
 MethodSVM.cxx:433
 MethodSVM.cxx:434
 MethodSVM.cxx:435
 MethodSVM.cxx:436
 MethodSVM.cxx:437
 MethodSVM.cxx:438
 MethodSVM.cxx:439
 MethodSVM.cxx:440
 MethodSVM.cxx:441
 MethodSVM.cxx:442
 MethodSVM.cxx:443
 MethodSVM.cxx:444
 MethodSVM.cxx:445
 MethodSVM.cxx:446
 MethodSVM.cxx:447
 MethodSVM.cxx:448
 MethodSVM.cxx:449
 MethodSVM.cxx:450
 MethodSVM.cxx:451
 MethodSVM.cxx:452
 MethodSVM.cxx:453
 MethodSVM.cxx:454
 MethodSVM.cxx:455
 MethodSVM.cxx:456
 MethodSVM.cxx:457
 MethodSVM.cxx:458
 MethodSVM.cxx:459
 MethodSVM.cxx:460
 MethodSVM.cxx:461
 MethodSVM.cxx:462
 MethodSVM.cxx:463
 MethodSVM.cxx:464
 MethodSVM.cxx:465
 MethodSVM.cxx:466
 MethodSVM.cxx:467
 MethodSVM.cxx:468
 MethodSVM.cxx:469
 MethodSVM.cxx:470
 MethodSVM.cxx:471
 MethodSVM.cxx:472
 MethodSVM.cxx:473
 MethodSVM.cxx:474
 MethodSVM.cxx:475
 MethodSVM.cxx:476
 MethodSVM.cxx:477
 MethodSVM.cxx:478
 MethodSVM.cxx:479
 MethodSVM.cxx:480
 MethodSVM.cxx:481
 MethodSVM.cxx:482
 MethodSVM.cxx:483
 MethodSVM.cxx:484
 MethodSVM.cxx:485
 MethodSVM.cxx:486
 MethodSVM.cxx:487
 MethodSVM.cxx:488
 MethodSVM.cxx:489
 MethodSVM.cxx:490
 MethodSVM.cxx:491
 MethodSVM.cxx:492
 MethodSVM.cxx:493
 MethodSVM.cxx:494
 MethodSVM.cxx:495
 MethodSVM.cxx:496
 MethodSVM.cxx:497
 MethodSVM.cxx:498
 MethodSVM.cxx:499
 MethodSVM.cxx:500
 MethodSVM.cxx:501
 MethodSVM.cxx:502
 MethodSVM.cxx:503
 MethodSVM.cxx:504
 MethodSVM.cxx:505
 MethodSVM.cxx:506
 MethodSVM.cxx:507
 MethodSVM.cxx:508
 MethodSVM.cxx:509
 MethodSVM.cxx:510
 MethodSVM.cxx:511
 MethodSVM.cxx:512
 MethodSVM.cxx:513
 MethodSVM.cxx:514
 MethodSVM.cxx:515
 MethodSVM.cxx:516
 MethodSVM.cxx:517
 MethodSVM.cxx:518
 MethodSVM.cxx:519
 MethodSVM.cxx:520
 MethodSVM.cxx:521
 MethodSVM.cxx:522
 MethodSVM.cxx:523
 MethodSVM.cxx:524
 MethodSVM.cxx:525
 MethodSVM.cxx:526
 MethodSVM.cxx:527
 MethodSVM.cxx:528
 MethodSVM.cxx:529
 MethodSVM.cxx:530
 MethodSVM.cxx:531
 MethodSVM.cxx:532
 MethodSVM.cxx:533
 MethodSVM.cxx:534
 MethodSVM.cxx:535
 MethodSVM.cxx:536
 MethodSVM.cxx:537
 MethodSVM.cxx:538
 MethodSVM.cxx:539
 MethodSVM.cxx:540
 MethodSVM.cxx:541
 MethodSVM.cxx:542
 MethodSVM.cxx:543
 MethodSVM.cxx:544
 MethodSVM.cxx:545
 MethodSVM.cxx:546
 MethodSVM.cxx:547
 MethodSVM.cxx:548
 MethodSVM.cxx:549
 MethodSVM.cxx:550
 MethodSVM.cxx:551
 MethodSVM.cxx:552
 MethodSVM.cxx:553
 MethodSVM.cxx:554
 MethodSVM.cxx:555
 MethodSVM.cxx:556
 MethodSVM.cxx:557
 MethodSVM.cxx:558
 MethodSVM.cxx:559
 MethodSVM.cxx:560