BornAgain  1.18.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 scattering at grazing incidence
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 {
24 const std::function<double(double)> l1_norm = [](double term) { return std::abs(term); };
25 const std::function<double(double)> l2_norm = [](double term) { return term * term; };
26 
27 const std::map<std::string, std::function<std::unique_ptr<ObjectiveMetric>()>> metric_factory = {
28  {"chi2", []() { return std::make_unique<Chi2Metric>(); }},
29  {"poisson-like", []() { return std::make_unique<PoissonLikeMetric>(); }},
30  {"log", []() { return std::make_unique<LogMetric>(); }},
31  {"reldiff", []() { return std::make_unique<RelativeDifferenceMetric>(); }},
32  {"rq4", []() { return std::make_unique<RQ4Metric>(); }}};
33 const std::string default_metric_name = "poisson-like";
34 
35 const std::map<std::string, std::function<double(double)>> norm_factory = {{"l1", l1_norm},
36  {"l2", l2_norm}};
37 const std::string default_norm_name = "l2";
38 
39 template <class U> std::vector<std::string> keys(const std::map<std::string, U>& map)
40 {
41  std::vector<std::string> result;
42  result.reserve(map.size());
43  for (auto& item : map)
44  result.push_back(item.first);
45  return result;
46 }
47 } // namespace
48 
49 const std::function<double(double)> ObjectiveMetricUtils::l1Norm()
50 {
51  return l1_norm;
52 }
53 
54 const std::function<double(double)> ObjectiveMetricUtils::l2Norm()
55 {
56  return l2_norm;
57 }
58 
59 std::unique_ptr<ObjectiveMetric> ObjectiveMetricUtils::createMetric(const std::string& metric)
60 {
61  return createMetric(metric, defaultNormName());
62 }
63 
64 std::unique_ptr<ObjectiveMetric> ObjectiveMetricUtils::createMetric(std::string metric,
65  std::string norm)
66 {
67  std::transform(metric.begin(), metric.end(), metric.begin(), ::tolower);
68  std::transform(norm.begin(), norm.end(), norm.begin(), ::tolower);
69  const auto metric_iter = metric_factory.find(metric);
70  const auto norm_iter = norm_factory.find(norm);
71  if (metric_iter == metric_factory.end() || norm_iter == norm_factory.end()) {
72  std::stringstream ss;
73  ss << "Error in ObjectiveMetricUtils::createMetric: either metric (" << metric
74  << ") or norm (" << norm << ") name is unknown.\n";
75  ss << availableMetricOptions();
76  throw std::runtime_error(ss.str());
77  }
78 
79  auto result = metric_iter->second();
80  result->setNorm(norm_iter->second);
81  return result;
82 }
83 
85 {
86  std::stringstream ss;
87  ss << "Available metrics:\n";
88  for (auto& item : metricNames())
89  ss << "\t" << item << "\n";
90  ss << "default metric: " << defaultMetricName() << "\n";
91  ss << "Available norms:\n";
92  for (auto& item : normNames())
93  ss << "\t" << item << "\n";
94  ss << "default norm: " << defaultNormName() << "\n";
95  return ss.str();
96 }
97 
98 std::vector<std::string> ObjectiveMetricUtils::normNames()
99 {
100  return keys(norm_factory);
101 }
102 
103 std::vector<std::string> ObjectiveMetricUtils::metricNames()
104 {
105  return keys(metric_factory);
106 }
107 
109 {
110  return default_norm_name;
111 }
112 
114 {
115  return default_metric_name;
116 }
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.
const std::function< double(double)> l1_norm
const std::map< std::string, std::function< std::unique_ptr< ObjectiveMetric >)> > metric_factory
const std::map< std::string, std::function< double(double)> > norm_factory
const std::function< double(double)> l2_norm
std::vector< std::string > keys(const std::map< std::string, U > &map)