ROOT logo
/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : TMVA::DecisionTree                                                    *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Implementation of a Decision Tree                                         *
 *                                                                                *
 * 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         *
 *      Doug Schouten   <dschoute@sfu.ca>        - Simon Fraser U., 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://mva.sourceforge.net/license.txt)                                       *
 *                                                                                *
 **********************************************************************************/

#include "TMVA/CostComplexityPruneTool.h"

#include "TMVA/MsgLogger.h"

#include <fstream>
#include <limits>
#include <math.h>

using namespace TMVA;


//_______________________________________________________________________
CostComplexityPruneTool::CostComplexityPruneTool( SeparationBase* qualityIndex ) : 
   IPruneTool(),
   fLogger(new MsgLogger("CostComplexityPruneTool") )
{
   // the constructor for the cost complexity prunig

   fOptimalK = -1;

   // !! changed from Dougs code. Now use the QualityIndex stored already
   // in the nodes when no "new" QualityIndex calculator is given. Like this
   // I can easily implement the Regression. For Regression, the pruning uses the
   // same sepearation index as in the tree building, hence doesn't need to re-calculate
   // (which would need more info than simply "s" and "b")
   
   fQualityIndexTool = qualityIndex;

   //fLogger->SetMinType( kDEBUG );
   fLogger->SetMinType( kWARNING );
}

//_______________________________________________________________________
CostComplexityPruneTool::~CostComplexityPruneTool( ) {
   // the destructor for the cost complexity prunig
   if(fQualityIndexTool != NULL) delete fQualityIndexTool;
}

//_______________________________________________________________________
PruningInfo*
CostComplexityPruneTool::CalculatePruningInfo( DecisionTree* dt,
                                               const IPruneTool::EventSample* validationSample,
                                               Bool_t isAutomatic )
{

   // the routine that basically "steers" the pruning process. Call the calculation of
   // the pruning sequence, the tree quality and alike..
   
   if( isAutomatic ) SetAutomatic();

   if( dt == NULL || (IsAutomatic() && validationSample == NULL) ) {
      // must have a valid decision tree to prune, and if the prune strength
      // is to be chosen automatically, must have a test sample from
      // which to calculate the quality of the pruned tree(s)
      return NULL;
   }

   Double_t Q = -1.0;
   Double_t W = 1.0;

   if(IsAutomatic()) {
      // run the pruning validation sample through the unpruned tree
      dt->ApplyValidationSample(validationSample);
      W = dt->GetSumWeights(validationSample); // get the sum of weights in the pruning validation sample
      // calculate the quality of the tree in the unpruned case
      Q = dt->TestPrunedTreeQuality();

      Log() << kDEBUG << "Node purity limit is: " << dt->GetNodePurityLimit() << Endl;
      Log() << kDEBUG << "Sum of weights in pruning validation sample: " << W << Endl;
      Log() << kDEBUG << "Quality of tree prior to any pruning is " << Q/W << Endl;
   }

   // store the cost complexity metadata for the decision tree at each node
   try {
      InitTreePruningMetaData((DecisionTreeNode*)dt->GetRoot());
   }
   catch(std::string error) {
      Log() << kERROR << "Couldn't initialize the tree meta data because of error ("
              << error << ")" << Endl;
      return NULL;
   }

   Log() << kDEBUG << "Automatic cost complexity pruning is " << (IsAutomatic()?"on":"off") << "." << Endl;

   try {
      Optimize( dt, W );  // run the cost complexity pruning algorithm
   }
   catch(std::string error) {
      Log() << kERROR << "Error optimzing pruning sequence ("
              << error << ")" << Endl;
      return NULL;
   }

   Log() << kDEBUG << "Index of pruning sequence to stop at: " << fOptimalK << Endl;

   PruningInfo* info = new PruningInfo();


   if(fOptimalK < 0) {
      // no pruning necessary, or wasn't able to compute a sequence
      info->PruneStrength = 0;
      info->QualityIndex = Q/W;
      info->PruneSequence.clear();
      Log() << kINFO << "no proper pruning could be calulated. Tree "   
            <<  dt->GetTreeID() << " will not be pruned. Do not worry if this " 
            << " happens for a few trees " << Endl;
      return info;
   }
   info->QualityIndex = fQualityIndexList[fOptimalK]/W;
   Log() << kDEBUG << " prune until k=" << fOptimalK << " with alpha="<<fPruneStrengthList[fOptimalK]<< Endl;
   for( Int_t i = 0; i < fOptimalK; i++ ){
      info->PruneSequence.push_back(fPruneSequence[i]);
   }
   if( IsAutomatic() ){
      info->PruneStrength = fPruneStrengthList[fOptimalK];
   }
   else {
      info->PruneStrength = fPruneStrength;
   }

   return info;
}

//_______________________________________________________________________
void CostComplexityPruneTool::InitTreePruningMetaData( DecisionTreeNode* n ) {
   // initialise "meta data" for the pruning, like the "costcomplexity", the
   // critical alpha, the minimal alpha down the tree, etc...  for each node!!

   if( n == NULL ) return;

   Double_t s = n->GetNSigEvents();
   Double_t b = n->GetNBkgEvents();
   // set R(t) = N_events*Gini(t) or MisclassificationError(t), etc.
   if (fQualityIndexTool) n->SetNodeR( (s+b)*fQualityIndexTool->GetSeparationIndex(s,b));
   else n->SetNodeR( (s+b)*n->GetSeparationIndex() );

   if(n->GetLeft() != NULL && n->GetRight() != NULL) { // n is an interior (non-leaf) node
      n->SetTerminal(kFALSE);
      // traverse the tree
      InitTreePruningMetaData(n->GetLeftDaughter());
      InitTreePruningMetaData(n->GetRightDaughter());
      // set |~T_t|
      n->SetNTerminal( n->GetLeftDaughter()->GetNTerminal() +
                       n->GetRightDaughter()->GetNTerminal());
      // set R(T) = sum[n' in ~T]{ R(n') }
      n->SetSubTreeR( (n->GetLeftDaughter()->GetSubTreeR() +
                       n->GetRightDaughter()->GetSubTreeR()));
      // set alpha_c, the alpha value at which it becomes advantageaus to prune at node n
      n->SetAlpha( ((n->GetNodeR() - n->GetSubTreeR()) /
                    (n->GetNTerminal() - 1)));

      // G(t) = min( alpha_c, G(l(n)), G(r(n)) )
      // the minimum alpha in subtree rooted at this node
      n->SetAlphaMinSubtree( std::min(n->GetAlpha(), std::min(n->GetLeftDaughter()->GetAlphaMinSubtree(),
                                                              n->GetRightDaughter()->GetAlphaMinSubtree())));
      n->SetCC(n->GetAlpha());

   } else { // n is a terminal node
      n->SetNTerminal( 1 ); n->SetTerminal( );
      if (fQualityIndexTool) n->SetSubTreeR(((s+b)*fQualityIndexTool->GetSeparationIndex(s,b)));
      else n->SetSubTreeR( (s+b)*n->GetSeparationIndex() );
      n->SetAlpha(std::numeric_limits<double>::infinity( ));
      n->SetAlphaMinSubtree(std::numeric_limits<double>::infinity( ));
      n->SetCC(n->GetAlpha());
   }

//    DecisionTreeNode* R = (DecisionTreeNode*)mdt->GetRoot();
//    Double_t x = R->GetAlphaMinSubtree();
//    Log() << "alphaMin(Root) = " << x << Endl;
}


//_______________________________________________________________________
void CostComplexityPruneTool::Optimize( DecisionTree* dt, Double_t weights ) {
   // after the critical alpha values (at which the corresponding nodes would
   // be pruned away) had been established in the "InitMetaData" we need now:
   // automatic pruning:
   //   find the value of "alpha" for which the test sample gives minimal error,
   //   on the tree with all nodes pruned that have alpha_critital < alpha,
   // fixed parameter pruning
   //

   Int_t k = 1;
   Double_t alpha   = -1.0e10;
   Double_t epsilon = std::numeric_limits<double>::epsilon();

   fQualityIndexList.clear();
   fPruneSequence.clear();
   fPruneStrengthList.clear();

   DecisionTreeNode* R = (DecisionTreeNode*)dt->GetRoot();

   Double_t qmin = 0.0;
   if(IsAutomatic()){
      // initialize the tree quality (actually at this stage, it is the quality of the yet unpruned tree
      qmin = dt->TestPrunedTreeQuality()/weights;
   }

   // now prune the tree in steps until it is gone. At each pruning step, the pruning 
   // takes place at the node that is regarded as the "weakest link".
   // for automatic pruning, at each step, we calculate the current quality of the 
   //     tree and in the end we will prune at the minimum of the tree quality   
   // for the fixed parameter pruing, the cut is simply set at a relative position
   //     in the sequence according to the "lenght" of the sequence of pruned trees.
   //     100: at the end (pruned until the root node would be the next pruning candidate
   //     50: in the middle of the sequence
   //     etc...
   while(R->GetNTerminal() > 1) { // prune upwards to the root node

      // initialize alpha
      alpha = TMath::Max(R->GetAlphaMinSubtree(), alpha);

      if( R->GetAlphaMinSubtree() >= R->GetAlpha() ) {
         Log() << kDEBUG << "\nCaught trying to prune the root node!" << Endl;
         break;
      }


      DecisionTreeNode* t = R;

      // descend to the weakest link
      while(t->GetAlphaMinSubtree() < t->GetAlpha()) {
//          std::cout << t->GetAlphaMinSubtree() << "  " << t->GetAlpha()<< "  "
//                    << t->GetAlphaMinSubtree()- t->GetAlpha()<<  " t==R?" << int(t == R) << std::endl;
         //      while(  (t->GetAlphaMinSubtree() - t->GetAlpha()) < epsilon)  {
         //         if(TMath::Abs(t->GetAlphaMinSubtree() - t->GetLeftDaughter()->GetAlphaMinSubtree())/TMath::Abs(t->GetAlphaMinSubtree()) < epsilon) {
         if(TMath::Abs(t->GetAlphaMinSubtree() - t->GetLeftDaughter()->GetAlphaMinSubtree()) < epsilon) {
            t = t->GetLeftDaughter();
         } else {
            t = t->GetRightDaughter();
         }
      }

      if( t == R ) {
         Log() << kDEBUG << "\nCaught trying to prune the root node!" << Endl;
         break;
      }

      DecisionTreeNode* n = t;

//       Log() << kDEBUG  << "alpha[" << k << "]: " << alpha << Endl;
//       Log() << kDEBUG  << "===========================" << Endl
//               << "Pruning branch listed below the node" << Endl;
//       t->Print( Log() );
//       Log() << kDEBUG << "===========================" << Endl;
//       t->PrintRecPrune( Log() );

      dt->PruneNodeInPlace(t); // prune the branch rooted at node t

      while(t != R) { // go back up the (pruned) tree and recalculate R(T), alpha_c
         t = t->GetMother();
         t->SetNTerminal(t->GetLeftDaughter()->GetNTerminal() + t->GetRightDaughter()->GetNTerminal());
         t->SetSubTreeR(t->GetLeftDaughter()->GetSubTreeR() + t->GetRightDaughter()->GetSubTreeR());
         t->SetAlpha((t->GetNodeR() - t->GetSubTreeR())/(t->GetNTerminal() - 1));
         t->SetAlphaMinSubtree(std::min(t->GetAlpha(), std::min(t->GetLeftDaughter()->GetAlphaMinSubtree(),
                                                                t->GetRightDaughter()->GetAlphaMinSubtree())));
         t->SetCC(t->GetAlpha());
      }
      k += 1;
   
      Log() << kDEBUG << "after this pruning step I would have " << R->GetNTerminal() << " remaining terminal nodes " << Endl;

      if(IsAutomatic()) {
         Double_t q = dt->TestPrunedTreeQuality()/weights;
         fQualityIndexList.push_back(q);
      }
      else {
         fQualityIndexList.push_back(1.0);
      }
      fPruneSequence.push_back(n);
      fPruneStrengthList.push_back(alpha);
   }

   if(fPruneSequence.size() == 0) {
      fOptimalK = -1;
      return;
   }

   if(IsAutomatic()) {
      k = -1;
      for(UInt_t i = 0; i < fQualityIndexList.size(); i++) {
         if(fQualityIndexList[i] < qmin) {
            qmin = fQualityIndexList[i];
            k = i;
         }
      }
      fOptimalK = k;
   }
   else {
      // regularize the prune strength relative to this tree
      fOptimalK = int(fPruneStrength/100.0 * fPruneSequence.size() );
      Log() << kDEBUG << "SequenzeSize="<<fPruneSequence.size()
            << "  fOptimalK " << fOptimalK << Endl;

   }

   Log() << kDEBUG  << "\n************ Summary for Tree " << dt->GetTreeID() << " *******"  << Endl
         << "Number of trees in the sequence: " << fPruneSequence.size() << Endl;

   Log() << kDEBUG  << "Pruning strength parameters: [";
   for(UInt_t i = 0; i < fPruneStrengthList.size()-1; i++)
      Log() << kDEBUG << fPruneStrengthList[i] << ", ";
   Log() << kDEBUG << fPruneStrengthList[fPruneStrengthList.size()-1] << "]" << Endl;

   Log() << kDEBUG  << "Misclassification rates: [";
   for(UInt_t i = 0; i < fQualityIndexList.size()-1; i++)
      Log() << kDEBUG  << fQualityIndexList[i] << ", ";
   Log() << kDEBUG  << fQualityIndexList[fQualityIndexList.size()-1] << "]"  << Endl;

   Log() << kDEBUG  << "Prune index: " << fOptimalK+1 << Endl;

}

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