20 #include "gsl/gsl_errno.h"
38 class FitTransformFunction :
public FitMethodFunction {
42 FitTransformFunction(
const FitMethodFunction & f,
const std::vector<EMinimVariableType> & types,
const std::vector<double> & values,
43 const std::map<
unsigned int, std::pair<double, double> > & bounds) :
44 FitMethodFunction( f.NDim(), f.NPoints() ),
45 fOwnTransformation(true),
47 fTransform(new MinimTransformFunction( new MultiNumGradFunction(f), types, values, bounds) ),
48 fGrad( std::vector<double>(f.NDim() ) )
55 FitTransformFunction(
const FitMethodFunction & f, MinimTransformFunction *transFunc ) :
56 FitMethodFunction( f.NDim(), f.NPoints() ),
57 fOwnTransformation(false),
59 fTransform(transFunc),
60 fGrad( std::vector<double>(f.NDim() ) )
65 ~FitTransformFunction() {
66 if (fOwnTransformation) {
73 virtual double DataElement(
const double * x,
unsigned i,
double * g = 0)
const {
75 const double * xExt = fTransform->Transformation(x);
76 if ( g == 0)
return fFunc.DataElement( xExt, i );
78 double val = fFunc.DataElement( xExt, i, &fGrad[0]);
80 fTransform->GradientTransformation( x, &fGrad.front(), g);
85 IMultiGenFunction * Clone()
const {
91 unsigned int NDim()
const {
92 return fTransform->NDim();
95 unsigned int NTot()
const {
96 return fTransform->NTot();
100 const double * Transformation(
const double * x)
const {
return fTransform->Transformation(x); }
104 void InvTransformation(
const double * xext,
double * xint)
const { fTransform->InvTransformation(xext,xint); }
107 void InvStepTransformation(
const double * x,
const double * sext,
double * sint)
const { fTransform->InvStepTransformation(x,sext,sint); }
110 void GradientTransformation(
const double * x,
const double *gext,
double * gint)
const { fTransform->GradientTransformation(x,gext,gint); }
112 void MatrixTransformation(
const double * x,
const double *cint,
double * cext)
const { fTransform->MatrixTransformation(x,cint,cext); }
117 FitTransformFunction(
const FitTransformFunction& rhs);
118 FitTransformFunction& operator=(
const FitTransformFunction& rhs);
120 double DoEval(
const double * x)
const {
121 return fFunc( fTransform->Transformation(x) );
124 bool fOwnTransformation;
125 const FitMethodFunction & fFunc;
126 MinimTransformFunction * fTransform;
127 mutable std::vector<double> fGrad;
136 GSLNLSMinimizer::GSLNLSMinimizer(
int type ) :
142 const gsl_multifit_fdfsolver_type * gsl_type = 0;
143 if (type == 1) gsl_type = gsl_multifit_fdfsolver_lmsder;
144 if (type == 2) gsl_type = gsl_multifit_fdfsolver_lmder;
146 fGSLMultiFit =
new GSLMultiFit( gsl_type );
151 int niter = ROOT::Math::MinimizerOptions::DefaultMaxIterations();
152 if (niter <= 0) niter = 100;
153 SetMaxIterations(niter);
155 fLSTolerance = ROOT::Math::MinimizerOptions::DefaultTolerance();
156 if (fLSTolerance <=0) fLSTolerance = 0.0001;
158 SetPrintLevel(ROOT::Math::MinimizerOptions::DefaultPrintLevel());
161 GSLNLSMinimizer::~GSLNLSMinimizer () {
162 assert(fGSLMultiFit != 0);
168 void GSLNLSMinimizer::SetFunction(
const ROOT::Math::IMultiGenFunction & func) {
174 BasicMinimizer::SetFunction(func);
176 const ROOT::Math::FitMethodFunction * chi2Func =
dynamic_cast<const ROOT::Math::FitMethodFunction *
>(ObjFunction());
178 if (PrintLevel() > 0) std::cout <<
"GSLNLSMinimizer: Invalid function set - only Chi2Func supported" << std::endl;
181 fSize = chi2Func->NPoints();
185 fResiduals.reserve(fSize);
186 for (
unsigned int i = 0; i < fSize; ++i) {
187 fResiduals.push_back( LSResidualFunc(*chi2Func, i) );
190 fChi2Func = chi2Func;
193 void GSLNLSMinimizer::SetFunction(
const ROOT::Math::IMultiGradFunction & func ) {
196 return SetFunction(static_cast<const ROOT::Math::IMultiGenFunction &>(func) );
200 bool GSLNLSMinimizer::Minimize() {
202 int debugLevel = PrintLevel();
205 assert (fGSLMultiFit != 0);
206 if (fResiduals.size() != fSize || fChi2Func == 0) {
207 MATH_ERROR_MSG(
"GSLNLSMinimizer::Minimize",
"Function has not been set");
211 unsigned int npar = NPar();
212 unsigned int ndim = NDim();
213 if (npar == 0 || npar < ndim) {
214 MATH_ERROR_MSGVAL(
"GSLNLSMinimizer::Minimize",
"Wrong number of parameters",npar);
219 std::vector<double> startValues;
222 MultiNumGradFunction * gradFunction =
new MultiNumGradFunction(*fChi2Func);
223 MinimTransformFunction * trFuncRaw = CreateTransformation(startValues, gradFunction);
225 std::unique_ptr<FitTransformFunction> trFunc;
227 trFunc.reset(
new FitTransformFunction(*fChi2Func, trFuncRaw) );
229 for (
unsigned int ires = 0; ires < fResiduals.size(); ++ires) {
230 fResiduals[ires] = LSResidualFunc(*trFunc, ires);
233 assert(npar == trFunc->NTot() );
236 if (debugLevel >=1 ) std::cout <<
"Minimize using GSLNLSMinimizer " << std::endl;
244 int iret = fGSLMultiFit->Set( fResiduals, &startValues.front() );
246 MATH_ERROR_MSGVAL(
"GSLNLSMinimizer::Minimize",
"Error setting the residual functions ",iret);
250 if (debugLevel >=1 ) std::cout <<
"GSLNLSMinimizer: " << fGSLMultiFit->Name() <<
" - start iterating......... " << std::endl;
253 unsigned int iter = 0;
255 bool minFound =
false;
257 status = fGSLMultiFit->Iterate();
259 if (debugLevel >=1) {
260 std::cout <<
"----------> Iteration " << iter <<
" / " << MaxIterations() <<
" status " << gsl_strerror(status) << std::endl;
261 const double * x = fGSLMultiFit->X();
262 if (trFunc.get()) x = trFunc->Transformation(x);
263 int pr = std::cout.precision(18);
264 std::cout <<
" FVAL = " << (*fChi2Func)(x) << std::endl;
265 std::cout.precision(pr);
266 std::cout <<
" X Values : ";
267 for (
unsigned int i = 0; i < NDim(); ++i)
268 std::cout <<
" " << VariableName(i) <<
" = " << X()[i];
269 std::cout << std::endl;
275 status = fGSLMultiFit->TestDelta( Tolerance(), Tolerance() );
276 if (status == GSL_SUCCESS) {
281 int status2 = fGSLMultiFit->TestGradient( Tolerance() );
282 if ( minFound && status2 != GSL_SUCCESS) {
284 fEdm = fGSLMultiFit->Edm();
285 if (fEdm > Tolerance() ) {
292 if (debugLevel >=1) {
293 std::cout <<
" after Gradient and Delta tests: " << gsl_strerror(status);
294 if (fEdm > 0) std::cout <<
", edm is: " << fEdm;
295 std::cout << std::endl;
301 while (status == GSL_CONTINUE && iter < MaxIterations() );
304 fEdm = fGSLMultiFit->Edm();
305 if ( fEdm < Tolerance() ) {
310 const double * x = fGSLMultiFit->X();
311 if (x == 0)
return false;
315 SetMinValue( (*fChi2Func)(x) );
318 fErrors.resize(NDim());
321 const double * cov = fGSLMultiFit->CovarMatrix();
324 fCovMatrix.resize(ndim*ndim);
327 trFunc->MatrixTransformation(x, fGSLMultiFit->CovarMatrix(), &fCovMatrix[0] );
330 std::copy(cov, cov + ndim*ndim, fCovMatrix.begin() );
333 for (
unsigned int i = 0; i < ndim; ++i)
334 fErrors[i] = std::sqrt(fCovMatrix[i*ndim + i]);
339 if (debugLevel >=1 ) {
340 std::cout <<
"GSLNLSMinimizer: Minimum Found" << std::endl;
341 int pr = std::cout.precision(18);
342 std::cout <<
"FVAL = " << MinValue() << std::endl;
343 std::cout <<
"Edm = " << fEdm << std::endl;
344 std::cout.precision(pr);
345 std::cout <<
"NIterations = " << iter << std::endl;
346 std::cout <<
"NFuncCalls = " << fChi2Func->NCalls() << std::endl;
347 for (
unsigned int i = 0; i < NDim(); ++i)
348 std::cout << std::setw(12) << VariableName(i) <<
" = " << std::setw(12) << X()[i] <<
" +/- " << std::setw(12) << fErrors[i] << std::endl;
354 if (debugLevel >=1 ) {
355 std::cout <<
"GSLNLSMinimizer: Minimization did not converge" << std::endl;
356 std::cout <<
"FVAL = " << MinValue() << std::endl;
357 std::cout <<
"Edm = " << fGSLMultiFit->Edm() << std::endl;
358 std::cout <<
"Niterations = " << iter << std::endl;
365 const double * GSLNLSMinimizer::MinGradient()
const {
367 return fGSLMultiFit->Gradient();
371 double GSLNLSMinimizer::CovMatrix(
unsigned int i ,
unsigned int j )
const {
373 unsigned int ndim = NDim();
374 if ( fCovMatrix.size() == 0)
return 0;
375 if (i > ndim || j > ndim)
return 0;
376 return fCovMatrix[i*ndim + j];
379 int GSLNLSMinimizer::CovMatrixStatus( )
const {
382 if ( fCovMatrix.size() == 0)
return 0;
384 if (fStatus != GSL_SUCCESS)
return 1;