BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
MinimizerAdapter.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Fit/Adapter/MinimizerAdapter.cpp
6 //! @brief Implements class MinimizerAdapter.
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
17 #include "Fit/Adapter/Report.h"
20 #include "Fit/Tools/StringUtils.h"
21 #include <Math/Minimizer.h>
22 
23 using namespace mumufit;
24 
26  : m_minimizerInfo(minimizerInfo)
27  , m_adapter(new mumufit::ObjectiveFunctionAdapter)
28  , m_status(false)
29 {
30 }
31 
33 
35 {
36  // Genetic minimizer requires SetFunction before setParameters, others don't care
37  rootMinimizer()->SetFunction(*m_adapter->rootObjectiveFunction(fcn, parameters));
38  return minimize(parameters);
39 }
40 
42 {
43  // Genetic minimizer requires SetFunction before setParameters, others don't care
44  rootMinimizer()->SetFunction(*m_adapter->rootResidualFunction(fcn, parameters));
45  return minimize(parameters);
46 }
47 
49 {
50  setParameters(parameters);
52 
53  m_status = rootMinimizer()->Minimize();
54  propagateResults(parameters);
55 
56  MinimizerResult result;
57  result.setParameters(parameters);
58  result.setMinValue(minValue());
59  result.setReport(internal::reportToString(*this));
60  result.setNumberOfCalls(m_adapter->numberOfCalls());
61  result.setNumberOfGradientCalls(m_adapter->numberOfGradientCalls());
62 
63  return result;
64 }
65 
67 {
68  return m_minimizerInfo.name();
69 }
70 
72 {
74 }
75 
77 {
78  unsigned int index(0);
79  for (const auto& par : parameters)
80  setParameter(index++, par);
81 }
82 
84 {
85  return rootMinimizer()->MinValue();
86 }
87 
89 {
90  return m_status ? "Minimum found" : "Error in solving";
91 }
92 
94 {
95  return rootMinimizer()->ProvidesError();
96 }
97 
98 std::map<std::string, std::string> MinimizerAdapter::statusMap() const
99 {
100  std::map<std::string, std::string> result;
101  result["Status"] = statusToString();
102 
103  if (providesError())
104  result["ProvidesError"] = "Provides parameters error and error matrix";
105  else
106  result["ProvidesError"] = "Doesn't provide error calculation";
107 
108  result["MinValue"] = mumufit::stringUtils::scientific(minValue());
109 
110  return result;
111 }
112 
113 void MinimizerAdapter::setOptions(const std::string& optionString)
114 {
115  options().setOptionString(optionString);
116 }
117 
118 //! Propagates results of minimization to fit parameter set
119 
121 {
122  parameters.setValues(parValuesAtMinimum());
123  parameters.setErrors(parErrorsAtMinimum());
124  // sets correlation matrix
125  if (providesError()) {
127  matrix.resize(fitDimension());
128 
129  for (size_t i = 0; i < fitDimension(); ++i) {
130  matrix[i].resize(fitDimension(), 0.0);
131  for (size_t j = 0; j < fitDimension(); ++j)
132  matrix[i][j] = rootMinimizer()->Correlation(static_cast<unsigned int>(i),
133  static_cast<unsigned int>(j));
134  }
135  parameters.setCorrelationMatrix(matrix);
136  }
137 }
138 
139 void MinimizerAdapter::setParameter(unsigned int index, const mumufit::Parameter& par)
140 {
141  bool success;
142  if (par.limits().isFixed()) {
143  success = rootMinimizer()->SetFixedVariable(index, par.name().c_str(), par.value());
144 
145  }
146 
147  else if (par.limits().isLimited()) {
148  success = rootMinimizer()->SetLimitedVariable(index, par.name().c_str(), par.value(),
149  par.step(), par.limits().lowerLimit(),
150  par.limits().upperLimit());
151  }
152 
153  else if (par.limits().isLowerLimited()) {
154  success = rootMinimizer()->SetLowerLimitedVariable(index, par.name().c_str(), par.value(),
155  par.step(), par.limits().lowerLimit());
156  }
157 
158  else if (par.limits().isUpperLimited()) {
159  success = rootMinimizer()->SetUpperLimitedVariable(index, par.name().c_str(), par.value(),
160  par.step(), par.limits().upperLimit());
161  }
162 
163  else if (par.limits().isLimitless()) {
164  success = rootMinimizer()->SetVariable(index, par.name().c_str(), par.value(), par.step());
165  }
166 
167  else {
168  throw std::runtime_error("BasicMinimizer::setParameter() -> Error! Unexpected parameter.");
169  }
170 
171  if (!success) {
172  std::ostringstream ostr;
173  ostr << "BasicMinimizer::setParameter() -> Error! Can't set minimizer's fit parameter";
174  ostr << "Index:" << index << " name '" << par.name() << "'";
175  throw std::runtime_error(ostr.str());
176  }
177 }
178 
179 //! Returns number of fit parameters defined (i.e. dimension of the function to be minimized).
180 
182 {
183  return rootMinimizer()->NDim();
184 }
185 
186 //! Returns value of the variables at minimum.
187 
188 std::vector<double> MinimizerAdapter::parValuesAtMinimum() const
189 {
190  std::vector<double> result;
191  result.resize(fitDimension(), 0.0);
192  std::copy(rootMinimizer()->X(), rootMinimizer()->X() + fitDimension(), result.begin());
193  return result;
194 }
195 
196 //! Returns errors of the variables at minimum.
197 
198 std::vector<double> MinimizerAdapter::parErrorsAtMinimum() const
199 {
200  std::vector<double> result;
201  result.resize(fitDimension(), 0.0);
202  if (rootMinimizer()->Errors() != 0) {
203  std::copy(rootMinimizer()->Errors(), rootMinimizer()->Errors() + fitDimension(),
204  result.begin());
205  }
206  return result;
207 }
208 
210 {
211  return const_cast<root_minimizer_t*>(
212  static_cast<const MinimizerAdapter*>(this)->rootMinimizer());
213 }
Defines a few helper functions.
Declares class MinimizerAdapter.
Declares class ObjectiveFunctionAdapter.
Declares report namespace.
Declares class RootResidualFunction.
Defines classes RootScalarFunction.
std::function< double(const mumufit::Parameters &)> fcn_scalar_t
Definition: Types.h:39
std::function< std::vector< double >(const mumufit::Parameters &)> fcn_residual_t
Definition: Types.h:40
double lowerLimit() const
Definition: AttLimits.cpp:86
double upperLimit() const
Definition: AttLimits.cpp:91
bool isUpperLimited() const
Definition: AttLimits.cpp:71
bool isFixed() const
Definition: AttLimits.cpp:61
bool isLimitless() const
Definition: AttLimits.cpp:81
bool isLimited() const
Definition: AttLimits.cpp:66
bool isLowerLimited() const
Definition: AttLimits.cpp:76
Abstract base class that adapts the CERN ROOT minimizer to our IMinimizer.
mumufit::MinimizerResult minimize(mumufit::Parameters parameters)
virtual const root_minimizer_t * rootMinimizer() const =0
virtual std::map< std::string, std::string > statusMap() const
Returns map of string representing different minimizer statuses.
std::string minimizerName() const final
Returns name of the minimizer.
double minValue() const final
Returns minimum function value.
virtual void setParameter(unsigned int index, const mumufit::Parameter &par)
void propagateResults(mumufit::Parameters &parameters)
Propagates results of minimization to fit parameter set.
ROOT::Math::Minimizer root_minimizer_t
void setParameters(const mumufit::Parameters &parameters)
void setOptions(const std::string &optionString) final
Sets option string to the minimizer.
virtual std::string statusToString() const
Returns string representation of current minimizer status.
virtual ~MinimizerAdapter() override
MinimizerInfo m_minimizerInfo
virtual void propagateOptions()=0
std::vector< double > parValuesAtMinimum() const
Returns value of the variables at minimum.
mumufit::MinimizerResult minimize_scalar(fcn_scalar_t fcn, mumufit::Parameters parameters) override
run minimization
std::string algorithmName() const final
Returns name of the minimization algorithm.
std::unique_ptr< mumufit::ObjectiveFunctionAdapter > m_adapter
MinimizerOptions & options()
mumufit::MinimizerResult minimize_residual(fcn_residual_t fcn, mumufit::Parameters parameters) override
bool providesError() const
Returns true if minimizer provides error and error matrix.
MinimizerAdapter(const MinimizerInfo &minimizerInfo)
size_t fitDimension() const
Returns number of fit parameters defined (i.e. dimension of the function to be minimized).
std::vector< double > parErrorsAtMinimum() const
Returns errors of the variables at minimum.
Info about a minimizer, including list of defined minimization algorithms.
Definition: MinimizerInfo.h:48
std::string algorithmName() const
Definition: MinimizerInfo.h:62
std::string name() const
Definition: MinimizerInfo.h:59
void setOptionString(const std::string &options)
Set options from their string representation.
Result of minimization round.
void setReport(const std::string &value)
void setMinValue(double value)
void setNumberOfGradientCalls(int value)
void setNumberOfCalls(int value)
void setParameters(const Parameters &parameters)
Converts user objective function to function ROOT expects.
A fittable parameter with value, error, step, and limits.
Definition: Parameter.h:26
double step() const
Definition: Parameter.cpp:69
std::string name() const
Definition: Parameter.cpp:44
AttLimits limits() const
Definition: Parameter.cpp:54
double value() const
Definition: Parameter.cpp:59
A collection of fit parameters.
Definition: Parameters.h:26
void setValues(const std::vector< double > &values)
Definition: Parameters.cpp:64
void setCorrelationMatrix(const corr_matrix_t &matrix)
Definition: Parameters.cpp:122
void setErrors(const std::vector< double > &errors)
Definition: Parameters.cpp:90
std::vector< std::vector< double > > corr_matrix_t
Definition: Parameters.h:31
std::string reportToString(const MinimizerAdapter &minimizer)
Reports results of minimization in the form of multi-line string.
Definition: Report.cpp:76
std::string scientific(const T value, int n=10)
Returns scientific string representing given value of any numeric type.
Definition: StringUtils.h:41
The multi-library, multi-algorithm fit wrapper library.