15#include <Math/IFunctionfwd.h>
16#include <RtypesCore.h>
24 Minimizer* Minimizer::fgInstance = NULL;
25 Minimizer::Minimizer() :
33 fQuantumFits(nullptr),
36 fTempParams(nullptr) {}
40 bool Minimizer::SetFixedVariable(
unsigned int ivar,
const std::string& name,
double val) {
41 if (fParameters.size() <= ivar) { fParameters.resize(ivar + 1); }
42 fParameters[ivar].SetParName(name);
43 fParameters[ivar].SetRange(val, val);
44 fParameters[ivar].SetIsFixed(kTRUE);
48 bool Minimizer::SetVariableLimits(
unsigned int ivar,
double lower,
double upper) {
54 if (fParameters.size() <= ivar) { fParameters.resize(ivar + 1); }
55 fParameters[ivar].SetRange(lower, upper);
56 fParameters[ivar].SetIsFixed(kFALSE);
61 Minimizer::SetLimitedVariable(
unsigned int ivar,
const std::string& name,
double val,
double step,
double lower,
double upper) {
62 if (fParameters.size() <= ivar) { fParameters.resize(ivar + 1); }
63 fParameters[ivar].SetParName(name);
64 fParameters[ivar].SetRange(lower, upper);
65 fParameters[ivar].SetStartVal(val);
66 fParameters[ivar].SetMapRange(lower, upper, TMath::Nint((upper - lower) / step + 1));
67 fParameters[ivar].SetIsFixed(kFALSE);
73 void Minimizer::InitFit() {
75 fAllowedValues.clear();
76 fStateVector.resize(GetNParams());
77 fStateVectorMin.resize(GetNParams());
78 for (
auto& x : fStateVector)
80 for (
auto& x : fStateVectorMin)
84 for (
unsigned int i = 0; i < fParameters.size(); i++) {
85 if (!fParameters[i].IsFixed()) {
86 fNonConstMap.push_back(i);
91 auto lambda = [](Int_t a, Int_t b) ->
bool {
return a < b; };
92 std::sort(fNonConstMap.begin(), fNonConstMap.end(), lambda);
93 Cout::PrintInfo(
"BEFORE INIT ", EInfo::kLowWarning);
94 std::cout << Cout::GetColor(kBlue);
95 Cout::Database({
"ParName",
"MinMap",
"MaxMap",
"Points",
"Step",
"Min",
"Max"});
96 std::cout << Cout::GetDisableColor();
97 for (
unsigned int i = 0; i < fParameters.size(); i++) {
98 if (fParameters[i].IsFixed()) { std::cout << Cout::GetColor(kOrange); }
99 Cout::Database({fParameters[i].GetParName().Data(),
100 Form(
"%4.4f", fParameters[i].GetMapMin()),
101 Form(
"%4.4f", fParameters[i].GetMapMax()),
102 Form(
"%d", fParameters[i].GetNPoints()),
103 Form(
"%4.4f", fParameters[i].GetDParam()),
104 Form(
"%4.4f", fParameters[i].GetMin()),
105 Form(
"%4.4f", fParameters[i].GetMax())});
106 if (fParameters[i].IsFixed()) std::cout << Cout::GetDisableColor();
110 for (
unsigned int i = 0; i < fParameters.size(); i++) {
111 fParameters[i].SetIsDiscrete(kTRUE);
112 fParameters[i].Init();
115 Cout::PrintInfo(
"AFTER INIT ", EInfo::kLowWarning);
116 std::cout << Cout::GetColor(kBlue);
117 Cout::Database({
"ParName",
"MinMap",
"MaxMap",
"Points",
"Step",
"Min",
"Max"});
118 std::cout << Cout::GetDisableColor();
119 for (
unsigned int i = 0; i < fParameters.size(); i++) {
120 if (fParameters[i].IsFixed()) { std::cout << Cout::GetColor(kOrange); }
121 Cout::Database({fParameters[i].GetParName().Data(),
122 Form(
"%4.4f", fParameters[i].GetMapMin()),
123 Form(
"%4.4f", fParameters[i].GetMapMax()),
124 Form(
"%d", fParameters[i].GetNPoints()),
125 Form(
"%4.4f", fParameters[i].GetDParam()),
126 Form(
"%4.4f", fParameters[i].GetMin()),
127 Form(
"%4.4f", fParameters[i].GetMax())});
128 if (fParameters[i].IsFixed()) std::cout << Cout::GetDisableColor();
131 delete[] fQuantumFits;
132 delete[] fSmoothFits;
134 delete[] fTempParams;
136 fQuantumFits =
new double[GetNParams()];
137 fSmoothFits =
new double[GetNParams()];
138 fErrors =
new double[GetNParams()];
139 fParamsMin.resize(GetNParams());
140 fTempParams =
new double[GetNParams()];
141 for (
int i = 0; i < GetNParams(); i++) {
142 if (fParameters[i].IsFixed()) { fTempParams[i] = fParameters[i].GetStartVal(); }
145 for (
int i = 0; i < GetNParams(); i++) {
146 fAllowedValues.push_back(fParameters[i].GetValuesArray());
150 void Minimizer::Reset() { fParameters.clear(); }
156 bool Minimizer::Minimize() {
157 if (GetNParams() == 0)
return false;
159 switch (fMinimizeType) {
160 case eMinimizeType::kAnt: {
169 std::cout <<
"Ant Minimiser" << std::endl;
172 case eMinimizeType::kScan: {
174 std::cout <<
"Scan minimizer" << std::endl;
182 const double* Minimizer::X()
const {
183 if (!fDiscreteFit)
return fSmoothFits;
187 void Minimizer::SetFunction(
const ROOT::Math::IMultiGenFunction& func) {
188 fFunc =
const_cast<ROOT::Math::IMultiGenFunction*
>(&func);
191 void Minimizer::SetParamConf(
const MinimizerStepConf& conf, Bool_t overwrite) { conf.SetParameters(fParameters, overwrite); }
193 Minimizer::~Minimizer() {
195 delete[] fQuantumFits;
196 delete[] fSmoothFits;
198 delete[] fTempParams;
202 Bool_t Minimizer::LoopOverParameter(Int_t param) {
204 if ((UInt_t) param == fNonConstMap.size()) {
205 Double_t chi = GetChi2();
206 if (chi < fGlobMin) {
208 fStateVectorMin = fStateVector;
213 Int_t pairID = fNonConstMap[param];
214 for (
unsigned int i = 0; i < fAllowedValues[pairID].size(); i++) {
215 fStateVector[pairID] = i;
216 Bool_t val = LoopOverParameter(param + 1);
217 if (val == kFALSE)
return kFALSE;
222 void Minimizer::EstimateErrors() {
223 for (
int i = 0; i < GetNParams(); i++) {
225 fQuantumFits[i] = fParamsMin[i];
226 fSmoothFits[i] = fParamsMin[i];
229 Double_t par, err, parQ;
230 EstimateError(i, par, parQ, err);
232 if (fParameters[i].IsDiscrete()) {
233 fQuantumFits[i] = fParamsMin[i];
234 fSmoothFits[i] = fParamsMin[i];
236 fQuantumFits[i] = parQ;
237 fSmoothFits[i] = par;
245 void Minimizer::EstimateError(Int_t par, Double_t& min, Double_t& quantumMin, Double_t& error) {
247 Double_t x2 = fParamsMin[par];
248 Double_t step = fParameters[par].GetDParam();
249 Double_t x1 = x2 - step;
250 Double_t x3 = x2 + step;
251 Double_t y2 = fGlobMin / fNDF;
253 if (fParameters[par].IsFixed()) {
260 for (
int i = 0; i < GetNParams(); i++)
261 fTempParams[i] = fParamsMin[i];
262 if (x1 >= fParameters[par].GetMapMin()) {
263 fTempParams[par] = x1;
264 y1 = (*fFunc)(fTempParams) / fNDF;
266 if (x3 > fParameters[par].GetMapMax()) {
269 fTempParams[par] = x3;
270 y3 = (*fFunc)(fTempParams) / fNDF;
272 if (x1 < fParameters[par].GetMapMin()) { y1 = y3; }
273 fTempParams[par] = fParamsMin[par];
275 Hal::Std::FitParabola(x1, x2, x3, y1, y2, y3, a, b, c);
277 Hal::Std::SolveParabola(a, b, c - 0.9 * fGlobMin / fNDF, X1, X2);
278 Double_t min_Fit = -b / (2.0 * a);
283 quantumMin = fParamsMin[par];
285 error = TMath::Max(TMath::Abs(min_Fit - X1), TMath::Abs(min_Fit - X2));
287 error = TMath::Sqrt(1.0 / a) * y2;
312 Bool_t Minimizer::IsFixed(Int_t i)
const {
return fParameters[i].IsFixed(); }
315 if (fgInstance == NULL) fgInstance =
new Minimizer();
320 void Minimizer::FinishFit() {
321 for (
int i = 0; i < GetNParams(); i++) {
322 fParamsMin[i] = fAllowedValues[i][fStateVectorMin[i]];
325 delete[] fTempParams;
326 fTempParams =
nullptr;
329 void Minimizer::SetMinimizerType(TString opt) {
332 fMinimizeType = kScan;
333 }
else if (opt ==
"ant") {
334 fMinimizeType = kAnt;
338 void Minimizer::MinimizeAnt() {
339 std::vector<std::vector<int>> directionIndex;
340 for (
int i = 0; i < GetNFree(); i++) {
341 std::vector<int> poz;
342 for (
int j = 0; j < GetNFree(); j++) {
346 directionIndex.push_back(poz);
348 for (
int i = 0; i < GetNFree(); i++) {
349 std::vector<int> poz;
350 for (
int j = 0; j < GetNFree(); j++) {
354 directionIndex.push_back(poz);
357 int freePars = GetNFree();
358 std::vector<int> tmpVec(freePars, 0);
361 auto applyVector = [&]() {
362 for (
int p = 0; p < freePars; p++) {
363 int constToPar = fNonConstMap[p];
364 tmpVec[constToPar] += directionIndex[direction][p];
365 if (tmpVec[constToPar] < 0 || tmpVec[constToPar] > fParameters[constToPar].GetNPoints()) {
return kFALSE; }
378 for (
int p = 0; p < freePars; p++) {
379 fStateVector[fNonConstMap[p]] = tmpVec[p];
384 double old_chi = 1E+9;
387 cont = applyVector();
389 double chi = GetChi2();
391 direction = (direction + 1) % freePars;
394 if (chi < fGlobMin) {
396 fStateVectorMin = fStateVector;
401 direction = (direction + 1) % freePars;
405 if (bad == freePars) {
409 if (fNCalls > 1E+6)
break;
413 void Minimizer::MinimizeScan() {
415 for (
auto& x : fStateVector) {
419 for (
unsigned int i = 0; i < fParameters.size(); i++) {
420 fTempParams[i] = fParameters[i].GetMin();
422 LoopOverParameter(0);
423 for (
int i = 0; i < GetNParams(); i++) {
424 fTempParams[i] = fParamsMin[i];
425 fSmoothFits[i] = fParamsMin[i];
426 fQuantumFits[i] = fParamsMin[i];
430 void Minimizer::MinimizeNelderMead() {
434 vertices.
MakeBigger(fFreePars + 1, fFreePars);
441 for (
int i = 0; i < fFreePars; i++) {
442 for (
int j = 0; j < fFreePars; j++) {
443 vertices[i][j] = fParameters[fNonConstMap[i]].GetMin();
446 for (
int j = 0; j < fFreePars; j++) {
447 vertices[fFreePars][j] = fParameters[fNonConstMap[0]].GetMax();
451 for (
int i = 0; i < fFreePars; i++) {
457 for (
int i = 0; i < fFreePars + 1; i++) {
458 for (
int j = 0; j < fFreePars; j++) {
459 copyPars(vertices[i]);
461 chiMap[i] = (*fFunc)(fTempParams);
464 Bool_t found = kTRUE;
466 int largest_chi, lowest_chi;
467 double max_chi = chiMap.FindMax(largest_chi);
468 double min_chi = chiMap.FindMin(lowest_chi);
470 double almost_max_chi = 0;
471 for (
int i = 0; i < fFreePars + 1; i++) {
472 if (chiMap[i] > almost_max_chi && chiMap[i] != max_chi) { almost_max_chi = chiMap[i]; }
474 worstPar = vertices[largest_chi];
478 for (
int i = 0; i < fFreePars; i++) {
480 for (
int j = 0; j < fFreePars + 1; j++) {
481 if (j == largest_chi)
continue;
482 centroid += vertices[i];
484 centroid = centroid / double(fFreePars);
487 futurePar = centroid + (centroid - worstPar);
489 double chi_r = (*fFunc)(fTempParams);
491 if (chi_r < almost_max_chi && chi_r > min_chi) {
492 vertices[largest_chi] = futurePar;
495 if (chi_r <= min_chi) {
499 for (
int i = 0; i < fFreePars; i++) {
501 for (
int j = 0; j < fFreePars + 1; j++) {
502 if (j == largest_chi)
continue;
503 centroid += vertices[i];
504 centroid += vertices[i];
506 centroid = centroid / double(fFreePars);
510 futurePar = centroid + (centroid - worstPar);
519 void Minimizer::ChangeStateVector(std::vector<Int_t>& vec) {
520 std::vector<Int_t> temp = vec;
521 for (
unsigned int i = 0; i < vec.size(); i++) {
522 vec[i + 1] = temp[i];
524 vec[0] = temp[temp.size() - 1];
527 bool Minimizer::SetParLimits(
unsigned int ivar,
double min,
double max) {
533 fParameters[ivar].SetMin(min);
534 fParameters[ivar].SetMax(max);
538 void Minimizer::SetTempParams() {
539 for (
int i = 0; i < GetNParams(); i++) {
540 fTempParams[i] = fAllowedValues[i][fStateVector[i]];
544 Double_t Minimizer::GetChi2() {
546 return (*fFunc)(fTempParams);
void MakeBigger(Int_t new_dim)
void MakeBigger(Int_t sizeA, Int_t sizeB)