Alexandria  2.27.0
SDC-CH common library for the Euclid project
SOM.icpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2022 Euclid Science Ground Segment
3  *
4  * This library is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License as published by the Free
6  * Software Foundation; either version 3.0 of the License, or (at your option)
7  * any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /*
20  * @file SOM.icpp
21  * @author nikoapos
22  */
23 
24 #include "SOM/ImplTools.h"
25 
26 namespace Euclid {
27 namespace SOM {
28 
29 template <typename DistFunc>
30 SOM<DistFunc>::SOM(std::size_t dimensions, std::size_t x, std::size_t y, InitFunc::Signature init_func)
31  : m_dimensions(dimensions)
32  , m_cells(std::make_tuple(ImplTools::indexAxis("X", x), ImplTools::indexAxis("Y", y)), m_dimensions)
33  , m_size(x, y) {
34 
35  // Initialize all the grid cells using the given function
36  for (auto array : m_cells) {
37  for (auto& w : array) {
38  w = init_func();
39  }
40  }
41 
42 } // end of namespace SOM_impl
43 
44 template <typename DistFunc>
45 const std::pair<std::size_t, std::size_t>& SOM<DistFunc>::getSize() const {
46  return m_size;
47 }
48 
49 template <typename DistFunc>
50 std::size_t SOM<DistFunc>::getDimensions() const {
51  return m_dimensions;
52 }
53 
54 template <typename DistFunc>
55 auto SOM<DistFunc>::operator()(std::size_t x, std::size_t y) -> reference_type {
56  return m_cells(x, y);
57 }
58 
59 template <typename DistFunc>
60 auto SOM<DistFunc>::operator()(std::size_t x, std::size_t y) const -> const reference_type {
61  return m_cells(x, y);
62 }
63 
64 template <typename DistFunc>
65 typename SOM<DistFunc>::iterator SOM<DistFunc>::begin() {
66  return m_cells.begin();
67 }
68 
69 template <typename DistFunc>
70 typename SOM<DistFunc>::iterator SOM<DistFunc>::end() {
71  return m_cells.end();
72 }
73 
74 template <typename DistFunc>
75 typename SOM<DistFunc>::const_iterator SOM<DistFunc>::begin() const {
76  return m_cells.begin();
77 }
78 
79 template <typename DistFunc>
80 typename SOM<DistFunc>::const_iterator SOM<DistFunc>::end() const {
81  return m_cells.end();
82 }
83 
84 template <typename DistFunc>
85 typename SOM<DistFunc>::const_iterator SOM<DistFunc>::cbegin() {
86  return m_cells.cbegin();
87 }
88 
89 template <typename DistFunc>
90 typename SOM<DistFunc>::const_iterator SOM<DistFunc>::cend() {
91  return m_cells.cend();
92 }
93 
94 template <typename DistFunc>
95 std::tuple<std::size_t, std::size_t, double> SOM<DistFunc>::findBMU(const std::vector<double>& input) const {
96  assert(input.size() == m_dimensions);
97  DistFunc dist_func{};
98  auto result_iter = begin();
99  double closest_distance = std::numeric_limits<double>::max();
100  auto end_ = end();
101  for (auto iter = begin(); iter != end_; ++iter) {
102  double dist = dist_func.distance(iter->cbegin(), iter->cend(), input.cbegin());
103  if (dist < closest_distance) {
104  result_iter = iter;
105  closest_distance = dist;
106  }
107  }
108  return std::make_tuple(result_iter.template axisValue<0>(), result_iter.template axisValue<1>(), closest_distance);
109 }
110 
111 template <typename DistFunc>
112 std::tuple<std::size_t, std::size_t, double> SOM<DistFunc>::findBMU(const std::vector<double>& input,
113  const std::vector<double>& uncertainties) const {
114  assert(input.size() == m_dimensions);
115  DistFunc dist_func{};
116  auto result_iter = begin();
117  double closest_distance = std::numeric_limits<double>::max();
118  const auto end_ = end();
119  for (auto iter = begin(); iter != end_; ++iter) {
120  double dist = dist_func.distance(iter->cbegin(), iter->cend(), input.cbegin(), uncertainties.cbegin());
121  if (dist < closest_distance) {
122  result_iter = iter;
123  closest_distance = dist;
124  }
125  }
126  return std::make_tuple(result_iter.template axisValue<0>(), result_iter.template axisValue<1>(), closest_distance);
127 }
128 
129 template <typename DistFunc>
130 template <typename InputType, typename WeightFunc>
131 std::tuple<std::size_t, std::size_t, double> SOM<DistFunc>::findBMU(const InputType& input,
132  WeightFunc weight_func) const {
133 
134  static_assert(std::is_same<decltype(std::declval<WeightFunc>()(input)), std::vector<double>>::value,
135  "WeightFunc must be callable with input as parameter, returning an std::vector<double>");
136 
137  return findBMU(weight_func(input));
138 }
139 
140 template <typename DistFunc>
141 template <typename InputType, typename WeightFunc, typename UncertaintyFunc>
142 std::tuple<std::size_t, std::size_t, double> SOM<DistFunc>::findBMU(const InputType& input, WeightFunc weight_func,
143  UncertaintyFunc uncertainty_func) const {
144 
145  static_assert(std::is_same<decltype(std::declval<WeightFunc>()(input)), std::vector<double>>::value,
146  "WeightFunc must be callable with input as parameter, returning an std::vector<double>");
147  static_assert(std::is_same<decltype(std::declval<UncertaintyFunc>()(input)), std::vector<double>>::value,
148  "UncertaintyFunc must be callable with input as parameter, returning an std::vector<double>");
149 
150  return findBMU(weight_func(input), uncertainty_func(input));
151 }
152 
153 } // namespace SOM
154 } // namespace Euclid