RootFinder.cxx

Go to the documentation of this file.
00001 // @(#)root/tmva $Id: RootFinder.cxx 29195 2009-06-24 10:39:49Z brun $   
00002 // Author: Andreas Hoecker, Joerg Stelzer, Helge Voss
00003 
00004 /**********************************************************************************
00005  * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
00006  * Package: TMVA                                                                  *
00007  * Class  : RootFinder                                                            *
00008  * Web    : http://tmva.sourceforge.net                                           *
00009  *                                                                                *
00010  * Description:                                                                   *
00011  *      Implementation (see header file for description)                          *
00012  *                                                                                *
00013  * Authors (alphabetical):                                                        *
00014  *      Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland              *
00015  *      Helge Voss      <Helge.Voss@cern.ch>     - MPI-K Heidelberg, Germany      *
00016  *      Kai Voss        <Kai.Voss@cern.ch>       - U. of Victoria, Canada         *
00017  *                                                                                *
00018  * Copyright (c) 2005:                                                            *
00019  *      CERN, Switzerland                                                         * 
00020  *      U. of Victoria, Canada                                                    * 
00021  *      MPI-K Heidelberg, Germany                                                 * 
00022  *                                                                                *
00023  * Redistribution and use in source and binary forms, with or without             *
00024  * modification, are permitted according to the terms listed in LICENSE           *
00025  * (http://tmva.sourceforge.net/LICENSE)                                          *
00026  **********************************************************************************/
00027 
00028 #include "TMath.h"
00029 
00030 #include "TMVA/RootFinder.h"
00031 #include "TMVA/MsgLogger.h"
00032 
00033 ClassImp(TMVA::RootFinder)
00034 
00035 //_______________________________________________________________________
00036 TMVA::RootFinder::RootFinder( Double_t (*rootVal)( Double_t ),
00037                               Double_t rootMin, 
00038                               Double_t rootMax,
00039                               Int_t maxIterations, 
00040                               Double_t absTolerance )
00041    : fRootMin( rootMin ),
00042      fRootMax( rootMax ),
00043      fMaxIter( maxIterations ),
00044      fAbsTol ( absTolerance  ),
00045      fLogger ( new MsgLogger("RootFinder") )
00046 {
00047    // constructor
00048    fGetRootVal = rootVal;
00049 }
00050 
00051 //_______________________________________________________________________
00052 TMVA::RootFinder::~RootFinder( void )
00053 {
00054    // destructor
00055    delete fLogger;
00056 }
00057 
00058 //_______________________________________________________________________
00059 Double_t TMVA::RootFinder::Root( Double_t refValue  )
00060 {
00061    // Root finding using Brents algorithm; taken from CERNLIB function RZERO
00062    Double_t a  = fRootMin, b = fRootMax;
00063    Double_t fa = (*fGetRootVal)( a ) - refValue;
00064    Double_t fb = (*fGetRootVal)( b ) - refValue;
00065    if (fb*fa > 0) {
00066       Log() << kWARNING << "<Root> initial interval w/o root: "
00067               << "(a=" << a << ", b=" << b << "),"
00068               << " (Eff_a=" << (*fGetRootVal)( a ) 
00069               << ", Eff_b=" << (*fGetRootVal)( b ) << "), "
00070               << "(fa=" << fa << ", fb=" << fb << "), "
00071               << "refValue = " << refValue << Endl;
00072       return 1;
00073    }
00074 
00075    Bool_t   ac_equal(kFALSE);
00076    Double_t fc = fb;
00077    Double_t c  = 0, d = 0, e = 0;
00078    for (Int_t iter= 0; iter <= fMaxIter; iter++) {
00079       if ((fb < 0 && fc < 0) || (fb > 0 && fc > 0)) {
00080 
00081          // Rename a,b,c and adjust bounding interval d
00082          ac_equal = kTRUE;
00083          c  = a; fc = fa;
00084          d  = b - a; e  = b - a;
00085       }
00086   
00087       if (TMath::Abs(fc) < TMath::Abs(fb)) {
00088          ac_equal = kTRUE;
00089          a  = b;  b  = c;  c  = a;
00090          fa = fb; fb = fc; fc = fa;
00091       }
00092 
00093       Double_t tol = 0.5 * 2.2204460492503131e-16 * TMath::Abs(b);
00094       Double_t m   = 0.5 * (c - b);
00095       if (fb == 0 || TMath::Abs(m) <= tol || TMath::Abs(fb) < fAbsTol) return b;
00096   
00097       // Bounds decreasing too slowly: use bisection
00098       if (TMath::Abs (e) < tol || TMath::Abs (fa) <= TMath::Abs (fb)) { d = m; e = m; }      
00099       else {
00100          // Attempt inverse cubic interpolation
00101          Double_t p, q, r;
00102          Double_t s = fb / fa;
00103       
00104          if (ac_equal) { p = 2 * m * s; q = 1 - s; }
00105          else {
00106             q = fa / fc; r = fb / fc;
00107             p = s * (2 * m * q * (q - r) - (b - a) * (r - 1));
00108             q = (q - 1) * (r - 1) * (s - 1);
00109          }
00110          // Check whether we are in bounds
00111          if (p > 0) q = -q;
00112          else       p = -p;
00113       
00114          Double_t min1 = 3 * m * q - TMath::Abs (tol * q);
00115          Double_t min2 = TMath::Abs (e * q);
00116          if (2 * p < (min1 < min2 ? min1 : min2)) {
00117             // Accept the interpolation
00118             e = d;        d = p / q;
00119          }
00120          else { d = m; e = m; } // Interpolation failed: use bisection.
00121       }
00122       // Move last best guess to a
00123       a  = b; fa = fb;
00124       // Evaluate new trial root
00125       if (TMath::Abs(d) > tol) b += d;
00126       else                     b += (m > 0 ? +tol : -tol);
00127 
00128       fb = (*fGetRootVal)( b ) - refValue;
00129 
00130    }
00131 
00132    // Return our best guess if we run out of iterations
00133    Log() << kWARNING << "<Root> maximum iterations (" << fMaxIter 
00134            << ") reached before convergence" << Endl;
00135 
00136    return b;
00137 }
00138 

Generated on Tue Jul 5 14:34:25 2011 for ROOT_528-00b_version by  doxygen 1.5.1