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