Minou.h
Go to the documentation of this file.
1 #ifndef _utl_Minou_h_
2 #define _utl_Minou_h_
3 
4 #include <utl/Math.h>
5 #include <TMinuit.h>
6 #include <TMatrixD.h>
7 //#include <TGraph.h>
8 #include <vector>
9 #include <exception>
10 #include <iostream>
11 
12 
13 namespace utl {
14 
15  namespace Minou {
16 
23  struct ParameterDef {
24 
25  ParameterDef() = default;
26 
27  ParameterDef(const std::string name,
28  const double value = 0, const double step = 1,
29  const double low = 0, const double high = 0,
30  const bool fixed = false) :
31  fName(name),
32  fValue(value),
33  fStep(step),
34  fLow(low),
35  fHigh(high),
36  fFixed(fixed)
37  { }
38 
39  bool IsFree() const { return !fFixed && fStep; }
40  bool IsFixed() const { return !IsFree(); }
41 
42  std::string fName;
43  double fValue = 0;
44  double fStep = 1;
45  double fLow = 0;
46  double fHigh = 0;
47  bool fFixed = false;
48 
49  };
50 
51 
53  int fParNumber = 0;
54  double fValue = 0;
55  double fParabolicError = 0;
56  double fLowerError = 0;
57  double fUpperError = 0;
58  double fGlobalCorrelation = 0;
59  };
60 
61 
62  /*
63  Your functor should inherit from Base.
64 
65  The minimizer will take number of parameters, initial values, step size
66  and free/fixed information from the Base::GetParameterDefs() so you should
67  either initialize your class and its Base with an appropriate vector or set it
68  (after creation through your ctor) with Base::SetParameterDefs(vector).
69 
70  Minimizer will call operator()(const vector<double>& p) in your
71  Base-derived class where "p" are the current values of parameters, which are
72  also available (to other methods) with Base::GetCurrentParameters().
73  */
74 
75  class Base {
76  public:
77  Base(const unsigned int nPar = 0, const double up = 1)
79 
80  Base(const std::vector<ParameterDef>& pars, const double up = 1)
81  : fParameterDefs(pars), fCurrentParameters(pars.size()), fErrorDefinition(up) { }
82 
83  unsigned int GetNParameters() const { return fParameterDefs.size(); }
84 
85  unsigned int
86  GetNFreeParameters()
87  const
88  {
89  unsigned int n = 0;
90  for (const auto& p : fParameterDefs)
91  if (p.IsFree())
92  ++n;
93  return n;
94  }
95 
96  // parameter definitions including initial values
97  std::vector<ParameterDef>& GetParameterDefs() { return fParameterDefs; }
98  const std::vector<ParameterDef>& GetParameterDefs() const { return fParameterDefs; }
99  void SetParameterDefs(const std::vector<ParameterDef>& defs) { fParameterDefs = defs; }
100 
101  std::vector<double>
102  GetParameterDefValues()
103  const
104  {
105  std::vector<double> r;
106  r.reserve(GetNParameters());
107  for (const auto& p : fParameterDefs)
108  r.push_back(p.fValue);
109  return r;
110  }
111 
112  void
113  SetParameterDefValues(const std::vector<double>& vals)
114  {
115  const unsigned int n = GetNParameters();
116  if (vals.size() != n)
117  throw std::runtime_error("SetParameterDefValues: requires the same length");
118  for (unsigned int i = 0; i < n; ++i)
119  fParameterDefs[i].fValue = vals[i];
120  }
121 
122  std::vector<int>
123  GetParameterDefFixed()
124  const
125  {
126  std::vector<int> r;
127  r.reserve(GetNParameters());
128  for (const auto& p : fParameterDefs)
129  r.push_back(p.fFixed);
130  return r;
131  }
132 
133  void
134  SetParameterDefFixed(const std::vector<int>& fixed)
135  {
136  const unsigned int n = GetNParameters();
137  if (fixed.size() != n)
138  throw std::runtime_error("SetParameterDefFixed: requires the same length");
139  for (unsigned int i = 0; i < n; ++i)
140  fParameterDefs[i].fFixed = fixed[i];
141  }
142 
143  // current values of parameters during the minimization
144  std::vector<double>& GetCurrentParameters() { return fCurrentParameters; }
145  const std::vector<double>& GetCurrentParameters() const { return fCurrentParameters; }
146 
147  void
148  SetCurrentParameters(const std::vector<double>& p)
149  {
150  if (p.size() != GetNParameters())
151  throw std::runtime_error("SetCurrentParameters: requires the same number");
153  }
154 
155  void SetErrorDefinition(const double up) { fErrorDefinition = up; }
156 
157  double GetErrorDefinition() const { return fErrorDefinition; }
158 
159  std::string GetName(const int i) const
160  { return fParameterDefs.at(i).fName; }
161 
162  std::vector<std::string>
163  GetNames()
164  const
165  {
166  const int n = GetNParameters();
167  std::vector<std::string> r;
168  r.reserve(n);
169  for (int i = 0; i < n; ++i)
170  r.push_back(GetName(i));
171  return r;
172  }
173 
174  unsigned int
175  GetIndex(const std::string& parameterName)
176  const
177  {
178  for (unsigned int i = 0, n = fParameterDefs.size(); i < n; ++i) {
179  if (parameterName == fParameterDefs[i].fName)
180  return i;
181  }
182  throw std::out_of_range("GetIndex: parameter " + parameterName + " not found!");
183  }
184 
185  private:
186  std::vector<ParameterDef> fParameterDefs;
187  std::vector<double> fCurrentParameters;
188  double fErrorDefinition = 0;
189  };
190 
191 
192  /*
193  F = functor derived from Base and implements the operator()(const vector<double>& par)
194  to reduce copying
195  */
196  template<class F>
197  class Minimizer {
198  public:
199  Minimizer(F& func) :
200  fFunction(&func),
201  fMinuit(func.GetNParameters())
202  {
203  if (fgMinimizer)
204  throw std::runtime_error("only one instance at the time allowed");
205  fgMinimizer = this;
206  SetVerbose(false);
207  fMinuit.SetFCN(Function);
208  SetErrorDefinition(func.GetErrorDefinition());
210  }
211 
212  ~Minimizer() { fgMinimizer = nullptr; }
213 
214  void
216  {
217  const auto& ps = fFunction->GetParameterDefs();
218  for (unsigned int i = 0, n = ps.size(); i < n; ++i) {
219  const auto& p = ps[i];
220  if (p.fStep <= 0 && !p.fFixed) {
221  const std::string err = "In Minou::Minimizer::DefineParameters(): "
222  "Parameter " + p.fName + ": "
223  "step should be > 0! (or fix the parameter)";
224  std::cerr << err << std::endl;
225  throw std::runtime_error(err);
226  }
227  fMinuit.DefineParameter(i, p.fName.c_str(), p.fValue, p.fStep, p.fLow, p.fHigh);
228  if (p.fFixed)
229  fMinuit.FixParameter(i);
230  }
231  }
232 
233  void
234  SetVerbose(const bool verbose)
235  {
236  fArgumentList[0] = (verbose ? 1 : -1);
237  fMinuit.mnexcm("SET PRINTOUT", fArgumentList, 1, fErrorFlag);
238  if (verbose)
239  fMinuit.mnexcm("SET WARNINGS", fArgumentList, 0, fErrorFlag);
240  else
241  fMinuit.mnexcm("SET NOWARNINGS", fArgumentList, 0, fErrorFlag);
242  fMinuit.SetPrintLevel(fArgumentList[0]);
243  }
244 
245  F& GetFunction() { return *fFunction; }
246 
247  TMinuit& GetMinuit() { return fMinuit; }
248 
249  int
250  Minimize(const int n = 500)
251  {
252  fArgumentList[0] = n;
253  fMinuit.mnexcm("MINIMIZE", fArgumentList, 1, fErrorFlag);
254  return fErrorFlag;
255  }
256 
257  int
258  Minos(const int n = 500)
259  {
260  fArgumentList[0] = n;
261  fMinuit.mnexcm("MINOS", fArgumentList, 1, fErrorFlag);
262  return fErrorFlag;
263  }
264 
265  int
266  Migrad(const int n = 500)
267  {
268  fArgumentList[0] = n;
269  fErrorFlag = 0;
270  fMinuit.mnexcm("MIGRAD", fArgumentList, 1, fErrorFlag);
271  return fErrorFlag;
272  }
273 
275  GetMinosError(const int parIndex)
276  const
277  {
279  eRes.fParNumber = parIndex;
280  fMinuit.GetParameter(parIndex, eRes.fValue, eRes.fParabolicError);
281  fMinuit.mnerrs(parIndex, eRes.fUpperError, eRes.fLowerError,
283  return eRes;
284  }
285 
286  std::vector<MinosParameterResult>
287  GetMinosErrors()
288  const
289  {
290  const int n = fFunction->GetNParameters();
291  std::vector<MinosParameterResult> r;
292  r.reserve(n);
293  for (int i = 0; i < n; ++i) {
294  const auto mRes = GetMinosError(i);
295  r.push_back(mRes);
296  }
297  return r;
298  }
299 
300  std::pair<double, double>
301  GetParameterAndError(const int i)
302  const
303  {
304  std::pair<double, double> ve;
305  fMinuit.GetParameter(i, ve.first, ve.second);
306  return ve;
307  }
308 
309  std::vector<std::pair<double, double>>
310  GetParametersAndErrors()
311  const
312  {
313  const int n = fFunction->GetNParameters();
314  std::vector<std::pair<double, double>> r;
315  r.reserve(n);
316  for (int i = 0; i < n; ++i) {
317  const auto p = GetParameterAndError(i);
318  r.push_back(p);
319  }
320  return r;
321  }
322 
323  double GetParameter(const int i) const
324  { return GetParameterAndError(i).first; }
325 
326  std::vector<double>
327  GetParameters()
328  const
329  {
330  const int n = fFunction->GetNParameters();
331  std::vector<double> r;
332  r.reserve(n);
333  for (int i = 0; i < n; ++i)
334  r.push_back(GetParameter(i));
335  return r;
336  }
337 
338  void WriteBack() const { WriteBack(*fFunction); }
339 
340  void WriteBack(Base& base) const
341  { base.GetCurrentParameters() = GetParameters(); }
342 
343  double GetMinimum() const { return fMinuit.fAmin; }
344 
345  double EvaluateFunction(const std::vector<double>& p) const
346  { return (*fFunction)(p); }
347 
348  TMatrixD
349  GetCovarianceMatrix()
350  const
351  {
352  const int n = fMinuit.GetNumFreePars();
353  double matrix[n][n];
354  for (int i = 0; i < n; i++)
355  for (int j = 0; j < n; j++)
356  matrix[i][j] = 0;
357  fMinuit.mnemat(&matrix[0][0], n);
358 
359  const int nTotal = fFunction->GetNParameters();
361  const auto& ps = fFunction->GetParameterDefs();
362 
363  {
364  int iFree = -1;
365  for (int i = 0; i < nTotal; ++i)
366  if (ps[i].IsFree())
367  inverseIndex[i] = ++iFree;
368  else
369  inverseIndex[i] = 0;
370  }
371 
372  TMatrixD fullMatrix(nTotal, nTotal);
373 
374  for (int i = 0; i < nTotal; ++i) {
375  const bool iIsFree = ps[i].IsFree();
376  const auto& mii = matrix[inverseIndex[i]];
377  auto fmi = fullMatrix[i];
378  for (int j = i; j < nTotal; ++j) {
379  const double covariance = (iIsFree && ps[j].IsFree()) ? mii[inverseIndex[j]] : 0;
380  const auto el = fmi[j] = covariance;
381  if (i != j)
382  fullMatrix[j][i] = el;
383  }
384  }
385 
386  return fullMatrix;
387  }
388 
389  /*TGraph
390  ParameterScan(const int parNumber, const double minValue,
391  const double maxValue, const int nPoints = 100)
392  {
393  fArgumentList[0] = parNumber;
394  fArgumentList[1] = nPoints;
395  fArgumentList[2] = minValue;
396  fArgumentList[3] = maxValue;
397  fMinuit.mnexcm("SCAN", fArgumentList, 4, fErrorFlag);
398  return *(TGraph*)(fMinuit.GetPlot());
399  }*/
400 
401  private:
402  void
403  SetErrorDefinition(const double up)
404  {
405  fArgumentList[0] = up;
406  fMinuit.mnexcm("SET ERRORDEF", fArgumentList, 1, fErrorFlag);
407  }
408 
409  static
410  void
411  Function(int& /*npar*/, double* /*gin*/, double& f, double* par, int /*iflag*/)
412  {
413  auto& func = *fgMinimizer->fFunction;
414  auto& fpars = func.GetCurrentParameters();
415  fpars.assign(par, par + func.GetNParameters());
416  f = func(fpars);
417  }
418 
420  F* fFunction = nullptr;
421  mutable TMinuit fMinuit;
422  int fErrorFlag = 0;
423  double fArgumentList[10] = { 0 };
424  };
425 
426  template<class Functor> Minimizer<Functor>* Minimizer<Functor>::fgMinimizer = nullptr;
427 
428  }
429 
430 }
431 
432 
433 #endif
void SetVerbose(const bool verbose)
Definition: Minou.h:234
const std::vector< double > & GetCurrentParameters() const
Definition: Minou.h:145
return r
Definition: Minou.h:109
void SetErrorDefinition(const double up)
Definition: Minou.h:155
double GetParameter(const int i) const
Definition: Minou.h:323
fMinuit GetParameter(parIndex, eRes.fValue, eRes.fParabolicError)
bool IsFree() const
Definition: Minou.h:39
double GetErrorDefinition() const
Definition: Minou.h:157
return n
Definition: Minou.h:93
int Minos(const int n=500)
Definition: Minou.h:258
void DefineParameters()
Definition: Minou.h:215
void SetParameterDefFixed(const std::vector< int > &fixed)
Definition: Minou.h:134
static Minimizer * fgMinimizer
Definition: Minou.h:419
std::vector< double > & GetCurrentParameters()
Definition: Minou.h:144
int Migrad(const int n=500)
Definition: Minou.h:266
std::vector< ParameterDef > fParameterDefs
Definition: Minou.h:186
const double high[npar]
Definition: UnivRec.h:78
Base(const unsigned int nPar=0, const double up=1)
Definition: Minou.h:77
static void Function(int &, double *, double &f, double *par, int)
Definition: Minou.h:411
ParameterDef(const std::string name, const double value=0, const double step=1, const double low=0, const double high=0, const bool fixed=false)
Definition: Minou.h:27
std::vector< double > r
Definition: Minou.h:331
std::vector< double > fCurrentParameters
Definition: Minou.h:187
std::vector< ParameterDef > & GetParameterDefs()
Definition: Minou.h:97
Evaluate functions given in a string. The real work is done by the ExpressionParser class...
Definition: Function.h:27
void WriteBack(Base &base) const
Definition: Minou.h:340
const auto & ps
Definition: Minou.h:361
Minimizer(F &func)
Definition: Minou.h:199
const double low[npar]
Definition: UnivRec.h:77
int Minimize(const int n=500)
Definition: Minou.h:250
std::vector< std::pair< double, double > > r
Definition: Minou.h:314
TMinuit & GetMinuit()
Definition: Minou.h:247
void SetParameterDefValues(const std::vector< double > &vals)
Definition: Minou.h:113
bool IsFixed() const
Definition: Minou.h:40
int inverseIndex[nTotal]
Definition: Minou.h:360
std::vector< std::string > r
Definition: Minou.h:167
unsigned int GetNParameters() const
Definition: Minou.h:83
const int nTotal
Definition: Minou.h:359
std::string fName
Definition: Minou.h:42
double fArgumentList[10]
Definition: Minou.h:423
void SetCurrentParameters(const std::vector< double > &p)
Definition: Minou.h:148
const int nPar
Definition: GeomAsym.h:37
Base(const std::vector< ParameterDef > &pars, const double up=1)
Definition: Minou.h:80
double matrix[n][n]
Definition: Minou.h:353
void SetParameterDefs(const std::vector< ParameterDef > &defs)
Definition: Minou.h:99
const std::vector< ParameterDef > & GetParameterDefs() const
Definition: Minou.h:98
std::string GetName(const int i) const
Definition: Minou.h:159
double EvaluateFunction(const std::vector< double > &p) const
Definition: Minou.h:345
double fErrorDefinition
Definition: Minou.h:188
double GetMinimum() const
Definition: Minou.h:343
void SetErrorDefinition(const double up)
Definition: Minou.h:403
std::vector< MinosParameterResult > r
Definition: Minou.h:291
void WriteBack() const
Definition: Minou.h:338

, generated on Tue Sep 26 2023.