Alexandria  2.14.1
Please provide a description of the project.
SOM.icpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2020 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/_impl/ImplTools.h"
25 
26 namespace Euclid {
27 namespace SOM {
28 
29 template <std::size_t ND, typename DistFunc>
30 SOM<ND, DistFunc>::SOM(std::size_t x, std::size_t y, InitFunc::Signature init_func)
31  : m_cells(ImplTools::indexAxis("X", x), ImplTools::indexAxis("Y", y)), m_size(x, y) {
32 
33  // Initialize all the grid cells using the given function
34  for (auto& array : m_cells) {
35  for (auto& w : array) {
36  w = init_func();
37  }
38  }
39 
40 } // end of namespace SOM_impl
41 
42 template <std::size_t ND, typename DistFunc>
43 const std::pair<std::size_t, std::size_t>& SOM<ND, DistFunc>::getSize() const {
44  return m_size;
45 }
46 
47 template <std::size_t ND, typename DistFunc>
48 typename std::array<double, ND>& SOM<ND, DistFunc>::operator()(std::size_t x, std::size_t y) {
49  return m_cells(x, y);
50 }
51 
52 template <std::size_t ND, typename DistFunc>
53 const typename std::array<double, ND>& SOM<ND, DistFunc>::operator()(std::size_t x, std::size_t y) const {
54  return m_cells(x, y);
55 }
56 
57 template <std::size_t ND, typename DistFunc>
58 typename SOM<ND, DistFunc>::iterator SOM<ND, DistFunc>::begin() {
59  return m_cells.begin();
60 }
61 
62 template <std::size_t ND, typename DistFunc>
63 typename SOM<ND, DistFunc>::iterator SOM<ND, DistFunc>::end() {
64  return m_cells.end();
65 }
66 
67 template <std::size_t ND, typename DistFunc>
68 typename SOM<ND, DistFunc>::const_iterator SOM<ND, DistFunc>::begin() const {
69  return m_cells.begin();
70 }
71 
72 template <std::size_t ND, typename DistFunc>
73 typename SOM<ND, DistFunc>::const_iterator SOM<ND, DistFunc>::end() const {
74  return m_cells.end();
75 }
76 
77 template <std::size_t ND, typename DistFunc>
78 typename SOM<ND, DistFunc>::const_iterator SOM<ND, DistFunc>::cbegin() {
79  return m_cells.cbegin();
80 }
81 
82 template <std::size_t ND, typename DistFunc>
83 typename SOM<ND, DistFunc>::const_iterator SOM<ND, DistFunc>::cend() {
84  return m_cells.cend();
85 }
86 
87 namespace SOM_impl {
88 
89 template <std::size_t ND, typename DistFunc>
90 std::tuple<std::size_t, std::size_t, double> findBMU_impl(const SOM<ND, DistFunc>& som,
91  std::function<double(const std::array<double, ND>&)> dist_func) {
92  auto result_iter = som.begin();
93  double closest_distance = std::numeric_limits<double>::max();
94  for (auto iter = som.begin(); iter != som.end(); ++iter) {
95  double dist = dist_func(*iter);
96  if (dist < closest_distance) {
97  result_iter = iter;
98  closest_distance = dist;
99  }
100  }
101  return std::make_tuple(result_iter.template axisValue<0>(), result_iter.template axisValue<1>(), closest_distance);
102 }
103 
104 } // end of namespace SOM_impl
105 
106 template <std::size_t ND, typename DistFunc>
107 std::tuple<std::size_t, std::size_t, double> SOM<ND, DistFunc>::findBMU(const std::array<double, ND>& input) const {
108  DistFunc dist_func {};
109  return SOM_impl::findBMU_impl<ND, DistFunc>(*this, [&dist_func, &input](const std::array<double, ND>& cell) -> double {
110  return dist_func.distance(cell, input);
111  });
112 }
113 
114 template <std::size_t ND, typename DistFunc>
115 std::tuple<std::size_t, std::size_t, double> SOM<ND, DistFunc>::findBMU(const std::array<double, ND>& input,
116  const std::array<double, ND>& uncertainties) const {
117  DistFunc dist_func {};
118  return SOM_impl::findBMU_impl<ND, DistFunc>(*this, [&dist_func, &input, &uncertainties](const std::array<double, ND>& cell) -> double {
119  return dist_func.distance(cell, input, uncertainties);
120  });
121 }
122 
123 template <std::size_t ND, typename DistFunc>
124 template <typename InputType, typename WeightFunc>
125 std::tuple<std::size_t, std::size_t, double> SOM<ND, DistFunc>::findBMU(const InputType& input,
126  WeightFunc weight_func) const {
127 
128  static_assert(std::is_same<decltype(std::declval<WeightFunc>()(input)), std::array<double, ND>>::value,
129  "WeightFunc must be callable with input as parameter, returning an std::array<double, ND>");
130 
131  return findBMU(weight_func(input));
132 }
133 
134 template <std::size_t ND, typename DistFunc>
135 template <typename InputType, typename WeightFunc, typename UncertaintyFunc>
136 std::tuple<std::size_t, std::size_t, double> SOM<ND, DistFunc>::findBMU(const InputType& input,
137  WeightFunc weight_func,
138  UncertaintyFunc uncertainty_func) const {
139 
140  static_assert(std::is_same<decltype(std::declval<WeightFunc>()(input)), std::array<double, ND>>::value,
141  "WeightFunc must be callable with input as parameter, returning an std::array<double, ND>");
142  static_assert(std::is_same<decltype(std::declval<UncertaintyFunc>()(input)), std::array<double, ND>>::value,
143  "UncertaintyFunc must be callable with input as parameter, returning an std::array<double, ND>");
144 
145  return findBMU(weight_func(input), uncertainty_func(input));
146 }
147 
148 }
149 }
150