BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
ObjectiveMetricUtils.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Core/Fitting/ObjectiveMetricUtils.cpp
6 //! @brief Implements ObjectiveMetric utilities.
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 <algorithm>
18 #include <cmath>
19 #include <map>
20 #include <sstream>
21 
22 namespace {
23 const std::function<double(double)> l1_norm = [](double term) { return std::abs(term); };
24 const std::function<double(double)> l2_norm = [](double term) { return term * term; };
25 
26 const std::map<std::string, std::function<std::unique_ptr<ObjectiveMetric>()>> metric_factory = {
27  {"chi2", []() { return std::make_unique<Chi2Metric>(); }},
28  {"poisson-like", []() { return std::make_unique<PoissonLikeMetric>(); }},
29  {"log", []() { return std::make_unique<LogMetric>(); }},
30  {"reldiff", []() { return std::make_unique<RelativeDifferenceMetric>(); }},
31  {"rq4", []() { return std::make_unique<RQ4Metric>(); }}};
32 const std::string default_metric_name = "poisson-like";
33 
34 const std::map<std::string, std::function<double(double)>> norm_factory = {{"l1", l1_norm},
35  {"l2", l2_norm}};
36 const std::string default_norm_name = "l2";
37 
38 template <class U> std::vector<std::string> keys(const std::map<std::string, U>& map)
39 {
40  std::vector<std::string> result;
41  result.reserve(map.size());
42  for (auto& item : map)
43  result.push_back(item.first);
44  return result;
45 }
46 } // namespace
47 
48 const std::function<double(double)> ObjectiveMetricUtils::l1Norm()
49 {
50  return l1_norm;
51 }
52 
53 const std::function<double(double)> ObjectiveMetricUtils::l2Norm()
54 {
55  return l2_norm;
56 }
57 
58 std::unique_ptr<ObjectiveMetric> ObjectiveMetricUtils::createMetric(const std::string& metric)
59 {
60  return createMetric(metric, defaultNormName());
61 }
62 
63 std::unique_ptr<ObjectiveMetric> ObjectiveMetricUtils::createMetric(std::string metric,
64  std::string norm)
65 {
66  std::transform(metric.begin(), metric.end(), metric.begin(), ::tolower);
67  std::transform(norm.begin(), norm.end(), norm.begin(), ::tolower);
68  const auto metric_iter = metric_factory.find(metric);
69  const auto norm_iter = norm_factory.find(norm);
70  if (metric_iter == metric_factory.end() || norm_iter == norm_factory.end()) {
71  std::stringstream ss;
72  ss << "Error in ObjectiveMetricUtils::createMetric: either metric (" << metric
73  << ") or norm (" << norm << ") name is unknown.\n";
74  ss << availableMetricOptions();
75  throw std::runtime_error(ss.str());
76  }
77 
78  auto result = metric_iter->second();
79  result->setNorm(norm_iter->second);
80  return result;
81 }
82 
84 {
85  std::stringstream ss;
86  ss << "Available metrics:\n";
87  for (auto& item : metricNames())
88  ss << "\t" << item << "\n";
89  ss << "default metric: " << defaultMetricName() << "\n";
90  ss << "Available norms:\n";
91  for (auto& item : normNames())
92  ss << "\t" << item << "\n";
93  ss << "default norm: " << defaultNormName() << "\n";
94  return ss.str();
95 }
96 
97 std::vector<std::string> ObjectiveMetricUtils::normNames()
98 {
99  return keys(norm_factory);
100 }
101 
102 std::vector<std::string> ObjectiveMetricUtils::metricNames()
103 {
104  return keys(metric_factory);
105 }
106 
108 {
109  return default_norm_name;
110 }
111 
113 {
114  return default_metric_name;
115 }
Defines ObjectiveMetric utilities and corresponding namespace.
Defines ObjectiveMetric classes.
const std::function< double(double)> l2Norm()
Returns L2 normalization function.
std::string defaultMetricName()
Returns default metric name.
std::string defaultNormName()
Returns default norm name.
std::string availableMetricOptions()
Prints available metric options.
std::unique_ptr< ObjectiveMetric > createMetric(const std::string &metric)
Creates the specified metric with the default norm.
std::vector< std::string > metricNames()
Returns the names of the objective metrics used.
const std::function< double(double)> l1Norm()
Returns L1 normalization function.
std::vector< std::string > normNames()
Returns the names of the norms used by ObjectiveMetric.