TLinearMinimizer.cxx

Go to the documentation of this file.
00001 // @(#)root/minuit:$Id: TLinearMinimizer.cxx 36058 2010-10-04 14:38:48Z moneta $
00002 // Author: L. Moneta Wed Oct 25 16:28:55 2006
00003 
00004 /**********************************************************************
00005  *                                                                    *
00006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
00007  *                                                                    *
00008  *                                                                    *
00009  **********************************************************************/
00010 
00011 // Implementation file for class TLinearMinimizer
00012 
00013 #include "TLinearMinimizer.h"
00014 #include "Math/IParamFunction.h"
00015 #include "TF1.h"
00016 #include "TUUID.h"
00017 #include "TROOT.h"
00018 #include "Fit/Chi2FCN.h"
00019 
00020 #include "TLinearFitter.h"
00021 
00022 #include <iostream>
00023 #include <cassert>
00024 #include <algorithm>
00025 #include <functional>
00026 
00027 
00028 
00029 // namespace ROOT { 
00030 
00031 //    namespace Fit { 
00032 
00033 
00034 // structure used for creating the TF1 representing the basis functions
00035 // they are the derivatives w.r.t the parameters of the model function 
00036 template<class Func> 
00037 struct BasisFunction { 
00038    BasisFunction(Func & f, int k) : 
00039       fKPar(k), 
00040       fFunc(&f) 
00041    {}
00042 
00043    double operator() ( double * x, double *)  { 
00044       return fFunc->ParameterDerivative(x,fKPar); 
00045    }
00046 
00047    unsigned int fKPar; // param component
00048    Func * fFunc; 
00049 };
00050 
00051 
00052 //______________________________________________________________________________
00053 //
00054 //  TLinearMinimizer, simple class implementing the ROOT::Math::Minimizer interface using 
00055 //  TLinearFitter. 
00056 //  This class uses TLinearFitter to find directly (by solving a system of linear equations) 
00057 //  the minimum of a 
00058 //  least-square function which has a linear dependence in the fit parameters. 
00059 //  This class is not used directly, but via the ROOT::Fitter class, when calling the 
00060 //  LinearFit method. It is instantiates using the plug-in manager (plug-in name is "Linear")
00061 //  
00062 //__________________________________________________________________________________________
00063 
00064 
00065 ClassImp(TLinearMinimizer)
00066 
00067 
00068 TLinearMinimizer::TLinearMinimizer(int ) : 
00069    fRobust(false), 
00070    fDim(0),
00071    fNFree(0),
00072    fMinVal(0),
00073    fObjFunc(0),
00074    fFitter(0)
00075 {
00076    // Default constructor implementation.
00077    // type is not used - needed for consistency with other minimizer plug-ins
00078 }
00079 
00080 TLinearMinimizer::TLinearMinimizer ( const char * type ) : 
00081    fRobust(false),
00082    fDim(0),
00083    fNFree(0),
00084    fMinVal(0),
00085    fObjFunc(0),
00086    fFitter(0)
00087 {
00088    // constructor passing a type of algorithm, (supported now robust via LTS regression)
00089 
00090    // select type from the string
00091    std::string algoname(type);
00092    std::transform(algoname.begin(), algoname.end(), algoname.begin(), (int(*)(int)) tolower ); 
00093 
00094    if (algoname.find("robust") != std::string::npos) fRobust = true;
00095 
00096 }
00097 
00098 TLinearMinimizer::~TLinearMinimizer() 
00099 {
00100    // Destructor implementation.
00101    if (fFitter) delete fFitter; 
00102 }
00103 
00104 TLinearMinimizer::TLinearMinimizer(const TLinearMinimizer &) : 
00105    Minimizer()
00106 {
00107    // Implementation of copy constructor.
00108 }
00109 
00110 TLinearMinimizer & TLinearMinimizer::operator = (const TLinearMinimizer &rhs) 
00111 {
00112    // Implementation of assignment operator.
00113    if (this == &rhs) return *this;  // time saving self-test
00114    return *this;
00115 }
00116 
00117 
00118 void TLinearMinimizer::SetFunction(const  ROOT::Math::IMultiGenFunction & ) { 
00119    // Set function to be minimized. Flag an error since only support Gradient objective functions
00120 
00121    Error("TLinearMinimizer::SetFunction(IMultiGenFunction)","Wrong type of function used for Linear fitter");
00122 }
00123 
00124 
00125 void TLinearMinimizer::SetFunction(const  ROOT::Math::IMultiGradFunction & objfunc) { 
00126    // Set the function to be minimized. The function must be a Chi2 gradient function 
00127    // When performing a linear fit we need the basis functions, which are the partial derivatives with respect to the parameters of the model function.
00128 
00129    typedef ROOT::Fit::Chi2FCN<ROOT::Math::IMultiGradFunction> Chi2Func; 
00130    const Chi2Func * chi2func = dynamic_cast<const Chi2Func *>(&objfunc); 
00131    if (chi2func ==0) { 
00132       Error("TLinearMinimizer::SetFunction(IMultiGradFunction)","Wrong type of function used for Linear fitter");
00133       return; 
00134    }
00135    fObjFunc = chi2func;
00136 
00137    // get model function
00138    typedef  Chi2Func::IModelFunction ModelFunc; 
00139    const ModelFunc & modfunc =  chi2func->ModelFunction(); 
00140    fDim = chi2func->NDim(); // number of parameters
00141    fNFree = fDim;
00142 
00143    // get the basis functions (derivatives of the modelfunc)
00144    TObjArray flist; 
00145    for (unsigned int i = 0; i < fDim; ++i) { 
00146       // t.b.f: should not create TF1 classes
00147       // when creating TF1 (if onother function with same name exists it is 
00148       // deleted since it is added in function list in gROOT 
00149       // fix the problem using meaniful names (difficult to re-produce)
00150       BasisFunction<const ModelFunc> bf(modfunc,i); 
00151       TUUID u; 
00152       std::string fname = "_LinearMinimimizer_BasisFunction_" + 
00153          std::string(u.AsString() );
00154       TF1 * f = new TF1(fname.c_str(),ROOT::Math::ParamFunctor(bf));
00155       flist.Add(f);
00156       // remove this functions from gROOT
00157       gROOT->GetListOfFunctions()->Remove(f); 
00158       
00159    }
00160 
00161    // create TLinearFitter (do it now because olny now now the coordinate dimensions)
00162    if (fFitter) delete fFitter; // reset by deleting previous copy
00163    fFitter = new TLinearFitter( static_cast<const ModelFunc::BaseFunc&>(modfunc).NDim() ); 
00164 
00165    fFitter->StoreData(fRobust); //  need a copy of data in case of robust fitting 
00166 
00167    fFitter->SetBasisFunctions(&flist); 
00168 
00169    // get the fitter data
00170    const ROOT::Fit::BinData & data = chi2func->Data(); 
00171    // add the data but not store them 
00172    for (unsigned int i = 0; i < data.Size(); ++i) { 
00173       double y = 0; 
00174       const double * x = data.GetPoint(i,y); 
00175       double ey = 1;
00176       if (! data.Opt().fErrors1) { 
00177          ey = data.Error(i); 
00178       } 
00179       // interface should take a double *
00180       fFitter->AddPoint( const_cast<double *>(x) , y, ey); 
00181    }
00182 
00183 }
00184 
00185 bool TLinearMinimizer::SetFixedVariable(unsigned int ivar, const std::string & /* name */ , double val) { 
00186    // set a fixed variable.
00187    if (!fFitter) return false; 
00188    fFitter->FixParameter(ivar, val);
00189    return true; 
00190 }
00191 
00192 bool TLinearMinimizer::Minimize() { 
00193    // find directly the minimum of the chi2 function 
00194    // solving the linear equation. Use  TVirtualFitter::Eval. 
00195 
00196    if (fFitter == 0 || fObjFunc == 0) return false;
00197 
00198    int iret = 0; 
00199    if (!fRobust) 
00200       iret = fFitter->Eval(); 
00201    else { 
00202       // robust fitting - get h parameter using tolerance (t.b. improved)
00203       double h = Tolerance(); 
00204       if (PrintLevel() >  0)
00205          std::cout << "TLinearMinimizer: Robust fitting with h = " << h << std::endl; 
00206       iret = fFitter->EvalRobust(h); 
00207    }
00208    fStatus = iret; 
00209  
00210    if (iret != 0) { 
00211       Warning("Minimize","TLinearFitter failed in finding the solution");  
00212       return false; 
00213    }
00214    
00215 
00216    // get parameter values 
00217    fParams.resize( fDim); 
00218    // no error available for robust fitting
00219    if (!fRobust) fErrors.resize( fDim); 
00220    for (unsigned int i = 0; i < fDim; ++i) { 
00221       fParams[i] = fFitter->GetParameter( i);
00222       if (!fRobust) fErrors[i] = fFitter->GetParError( i ); 
00223    }
00224    fCovar.resize(fDim*fDim); 
00225    double * cov = fFitter->GetCovarianceMatrix();
00226 
00227    if (!fRobust && cov) std::copy(cov,cov+fDim*fDim,fCovar.begin() );
00228 
00229    // calculate chi2 value
00230    
00231    fMinVal = (*fObjFunc)(&fParams.front());
00232 
00233    return true;
00234 
00235 }
00236 
00237 
00238 //    } // end namespace Fit
00239 
00240 // } // end namespace ROOT
00241 

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