00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00030
00031
00032
00033
00034
00035
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;
00048 Func * fFunc;
00049 };
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
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
00077
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
00089
00090
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
00101 if (fFitter) delete fFitter;
00102 }
00103
00104 TLinearMinimizer::TLinearMinimizer(const TLinearMinimizer &) :
00105 Minimizer()
00106 {
00107
00108 }
00109
00110 TLinearMinimizer & TLinearMinimizer::operator = (const TLinearMinimizer &rhs)
00111 {
00112
00113 if (this == &rhs) return *this;
00114 return *this;
00115 }
00116
00117
00118 void TLinearMinimizer::SetFunction(const ROOT::Math::IMultiGenFunction & ) {
00119
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
00127
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
00138 typedef Chi2Func::IModelFunction ModelFunc;
00139 const ModelFunc & modfunc = chi2func->ModelFunction();
00140 fDim = chi2func->NDim();
00141 fNFree = fDim;
00142
00143
00144 TObjArray flist;
00145 for (unsigned int i = 0; i < fDim; ++i) {
00146
00147
00148
00149
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
00157 gROOT->GetListOfFunctions()->Remove(f);
00158
00159 }
00160
00161
00162 if (fFitter) delete fFitter;
00163 fFitter = new TLinearFitter( static_cast<const ModelFunc::BaseFunc&>(modfunc).NDim() );
00164
00165 fFitter->StoreData(fRobust);
00166
00167 fFitter->SetBasisFunctions(&flist);
00168
00169
00170 const ROOT::Fit::BinData & data = chi2func->Data();
00171
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
00180 fFitter->AddPoint( const_cast<double *>(x) , y, ey);
00181 }
00182
00183 }
00184
00185 bool TLinearMinimizer::SetFixedVariable(unsigned int ivar, const std::string & , double val) {
00186
00187 if (!fFitter) return false;
00188 fFitter->FixParameter(ivar, val);
00189 return true;
00190 }
00191
00192 bool TLinearMinimizer::Minimize() {
00193
00194
00195
00196 if (fFitter == 0 || fObjFunc == 0) return false;
00197
00198 int iret = 0;
00199 if (!fRobust)
00200 iret = fFitter->Eval();
00201 else {
00202
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
00217 fParams.resize( fDim);
00218
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
00230
00231 fMinVal = (*fObjFunc)(&fParams.front());
00232
00233 return true;
00234
00235 }
00236
00237
00238
00239
00240
00241