2014-02-20 20:21:45 +00:00
|
|
|
/*
|
|
|
|
* MinuitMinimizer.cpp, part of LatAnalyze 3
|
|
|
|
*
|
2020-01-13 09:57:06 +00:00
|
|
|
* Copyright (C) 2013 - 2020 Antonin Portelli
|
2014-02-20 20:21:45 +00:00
|
|
|
*
|
|
|
|
* LatAnalyze 3 is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* LatAnalyze 3 is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2019-02-10 00:23:36 +00:00
|
|
|
#include <LatAnalyze/Numerical/MinuitMinimizer.hpp>
|
2014-03-13 18:51:01 +00:00
|
|
|
#include <LatAnalyze/includes.hpp>
|
2021-11-16 21:34:25 +00:00
|
|
|
|
|
|
|
// forward declaration necessary in the ROOT-based version of Minuit2
|
|
|
|
namespace ROOT
|
|
|
|
{
|
|
|
|
namespace Fit
|
|
|
|
{
|
|
|
|
class ParameterSettings;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// macros necessary in the ROOT-based version of Minuit2
|
|
|
|
#define ROOT_Math_VecTypes
|
|
|
|
#define MATHCORE_STANDALONE
|
|
|
|
|
2016-03-23 17:08:25 +00:00
|
|
|
#include <Minuit2/Minuit2Minimizer.h>
|
|
|
|
#include <Math/Functor.h>
|
2014-02-20 20:21:45 +00:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace Latan;
|
|
|
|
|
2016-04-01 21:39:49 +01:00
|
|
|
static constexpr double initErr = 0.1;
|
2014-09-18 17:18:51 +01:00
|
|
|
|
2014-02-20 20:21:45 +00:00
|
|
|
/******************************************************************************
|
2016-03-23 17:16:50 +00:00
|
|
|
* MinuitMinimizer implementation *
|
2014-02-20 20:21:45 +00:00
|
|
|
******************************************************************************/
|
2015-11-13 14:30:10 +00:00
|
|
|
// constructors ////////////////////////////////////////////////////////////////
|
|
|
|
MinuitMinimizer::MinuitMinimizer(const Algorithm algorithm)
|
|
|
|
{
|
|
|
|
setAlgorithm(algorithm);
|
|
|
|
}
|
|
|
|
|
2014-09-22 15:19:30 +01:00
|
|
|
// access //////////////////////////////////////////////////////////////////////
|
2015-08-07 15:10:03 +01:00
|
|
|
MinuitMinimizer::Algorithm MinuitMinimizer::getAlgorithm(void) const
|
|
|
|
{
|
|
|
|
return algorithm_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MinuitMinimizer::setAlgorithm(const Algorithm algorithm)
|
|
|
|
{
|
|
|
|
algorithm_ = algorithm;
|
|
|
|
}
|
|
|
|
|
2016-04-12 20:10:37 +01:00
|
|
|
bool MinuitMinimizer::supportLimits(void) const
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-02-20 20:21:45 +00:00
|
|
|
// minimization ////////////////////////////////////////////////////////////////
|
|
|
|
const DVec & MinuitMinimizer::operator()(const DoubleFunction &f)
|
|
|
|
{
|
2016-03-23 17:08:25 +00:00
|
|
|
using namespace ROOT;
|
|
|
|
using namespace Minuit2;
|
|
|
|
|
2016-04-15 18:23:45 +01:00
|
|
|
DVec &x = getState();
|
|
|
|
int printLevel = 0;
|
|
|
|
EMinimizerType minuitAlg = kCombined;
|
|
|
|
double prec = getPrecision();
|
2016-03-23 17:08:25 +00:00
|
|
|
|
|
|
|
// convert Latan parameters to Minuit parameters
|
|
|
|
switch (getVerbosity())
|
|
|
|
{
|
|
|
|
case Verbosity::Silent:
|
|
|
|
printLevel = 0;
|
|
|
|
break;
|
|
|
|
case Verbosity::Normal:
|
|
|
|
printLevel = 2;
|
|
|
|
break;
|
|
|
|
case Verbosity::Debug:
|
|
|
|
printLevel = 3;
|
|
|
|
break;
|
|
|
|
}
|
2016-04-15 18:23:45 +01:00
|
|
|
// The factor of 0.002 here is to compensate the dirty hack in Minuit
|
|
|
|
// source used to match the C++ and F77 versions
|
|
|
|
// (cf. VariableMetricBuilder.cxx)
|
2016-03-23 17:08:25 +00:00
|
|
|
switch (getAlgorithm())
|
|
|
|
{
|
2016-04-12 20:10:37 +01:00
|
|
|
case Algorithm::migrad:
|
2016-04-15 18:23:45 +01:00
|
|
|
minuitAlg = kMigrad;
|
|
|
|
prec /= 0.002;
|
2016-03-23 17:08:25 +00:00
|
|
|
break;
|
2016-04-12 20:10:37 +01:00
|
|
|
case Algorithm::simplex:
|
2016-03-23 17:08:25 +00:00
|
|
|
minuitAlg = kSimplex;
|
|
|
|
break;
|
2016-04-12 20:10:37 +01:00
|
|
|
case Algorithm::combined:
|
2016-04-15 18:23:45 +01:00
|
|
|
minuitAlg = kCombined;
|
|
|
|
prec /= 0.002;
|
2016-03-23 17:08:25 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-02-20 20:21:45 +00:00
|
|
|
|
2016-03-23 17:08:25 +00:00
|
|
|
// resize minimizer state to match function number of arguments
|
2014-02-20 20:21:45 +00:00
|
|
|
if (f.getNArg() != x.size())
|
|
|
|
{
|
2015-11-13 14:30:10 +00:00
|
|
|
resize(f.getNArg());
|
2014-02-20 20:21:45 +00:00
|
|
|
}
|
|
|
|
|
2016-03-23 17:08:25 +00:00
|
|
|
// create and set minimizer
|
2016-04-07 20:10:47 +01:00
|
|
|
Minuit2Minimizer min(minuitAlg);
|
|
|
|
|
|
|
|
min.SetStrategy(2);
|
|
|
|
min.SetMaxFunctionCalls(getMaxIteration());
|
2016-04-15 18:23:45 +01:00
|
|
|
min.SetTolerance(prec);
|
2016-04-07 20:10:47 +01:00
|
|
|
min.SetPrintLevel(printLevel);
|
2016-03-23 17:08:25 +00:00
|
|
|
|
|
|
|
// set function and variables
|
|
|
|
Math::Functor minuitF(f, x.size());
|
|
|
|
string name;
|
|
|
|
double val, step;
|
2014-02-20 20:21:45 +00:00
|
|
|
|
2016-04-07 20:10:47 +01:00
|
|
|
min.SetFunction(minuitF);
|
2014-02-26 18:36:29 +00:00
|
|
|
for (Index i = 0; i < x.size(); ++i)
|
2014-02-20 20:21:45 +00:00
|
|
|
{
|
2016-03-31 12:12:30 +01:00
|
|
|
name = f.varName().getName(i);
|
2016-03-23 17:08:25 +00:00
|
|
|
val = x(i);
|
|
|
|
step = (fabs(x(i)) != 0.) ? initErr*fabs(x(i)) : 1.;
|
|
|
|
if (hasHighLimit(i) and !hasLowLimit(i))
|
|
|
|
{
|
2016-04-07 20:10:47 +01:00
|
|
|
min.SetUpperLimitedVariable(i, name, val, step, getHighLimit(i));
|
2016-03-23 17:08:25 +00:00
|
|
|
}
|
|
|
|
else if (!hasHighLimit(i) and hasLowLimit(i))
|
2015-01-28 17:22:12 +00:00
|
|
|
{
|
2016-04-07 20:10:47 +01:00
|
|
|
min.SetLowerLimitedVariable(i, name, val, step, getLowLimit(i));
|
2015-01-28 17:22:12 +00:00
|
|
|
}
|
2016-03-23 17:08:25 +00:00
|
|
|
else if (hasHighLimit(i) and hasLowLimit(i))
|
2014-10-14 16:34:27 +01:00
|
|
|
{
|
2016-04-07 20:10:47 +01:00
|
|
|
min.SetLimitedVariable(i, name, val, step, getLowLimit(i),
|
|
|
|
getHighLimit(i));
|
2014-10-14 16:34:27 +01:00
|
|
|
}
|
2016-03-23 17:08:25 +00:00
|
|
|
else
|
2014-10-14 16:34:27 +01:00
|
|
|
{
|
2016-04-07 20:10:47 +01:00
|
|
|
min.SetVariable(i, name, val, step);
|
2014-10-14 16:34:27 +01:00
|
|
|
}
|
2014-02-20 20:21:45 +00:00
|
|
|
}
|
|
|
|
|
2016-03-23 17:08:25 +00:00
|
|
|
// minimize
|
|
|
|
int status;
|
|
|
|
unsigned int n = 0;
|
2014-02-20 20:21:45 +00:00
|
|
|
|
2016-03-23 17:08:25 +00:00
|
|
|
do
|
2015-01-28 17:22:12 +00:00
|
|
|
{
|
2016-03-23 17:08:25 +00:00
|
|
|
if (getVerbosity() >= Verbosity::Normal)
|
|
|
|
{
|
2016-03-31 12:12:30 +01:00
|
|
|
cout << "========== Minuit minimization, pass #" << n + 1;
|
2016-04-01 21:39:49 +01:00
|
|
|
cout << " =========" << endl;
|
2016-03-23 17:08:25 +00:00
|
|
|
}
|
2016-04-07 20:10:47 +01:00
|
|
|
min.Minimize();
|
|
|
|
status = min.Status();
|
2016-04-01 21:39:49 +01:00
|
|
|
n++;
|
2016-04-15 18:23:45 +01:00
|
|
|
} while ((status >= 2) and (n < getMaxPass()));
|
2016-03-23 17:08:25 +00:00
|
|
|
if (getVerbosity() >= Verbosity::Normal)
|
2014-02-20 20:21:45 +00:00
|
|
|
{
|
2016-04-01 21:39:49 +01:00
|
|
|
cout << "=================================================" << endl;
|
2014-02-20 20:21:45 +00:00
|
|
|
}
|
2016-03-23 17:08:25 +00:00
|
|
|
switch (status)
|
2014-02-20 20:21:45 +00:00
|
|
|
{
|
2016-03-23 17:08:25 +00:00
|
|
|
case 1:
|
2016-04-15 18:23:45 +01:00
|
|
|
// covariance matrix was made positive, the minimum is still good
|
|
|
|
// it just means that Minuit error analysis is inaccurate
|
2016-03-23 17:08:25 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
LATAN_WARNING("invalid minimum: Hesse analysis is not valid");
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
LATAN_WARNING("invalid minimum: requested precision not reached");
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
LATAN_WARNING("invalid minimum: iteration limit reached");
|
|
|
|
break;
|
2014-02-20 20:21:45 +00:00
|
|
|
}
|
2016-03-23 17:08:25 +00:00
|
|
|
|
|
|
|
// save and return result
|
|
|
|
for (Index i = 0; i < x.size(); ++i)
|
2014-02-20 20:21:45 +00:00
|
|
|
{
|
2016-04-07 20:10:47 +01:00
|
|
|
x(i) = min.X()[i];
|
2014-02-20 20:21:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return x;
|
|
|
|
}
|