2 * Copyright (C) 2012-2020 Euclid Science Ground Segment
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)
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
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
24 #include "SOM/_impl/ImplTools.h"
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) {
33 // Initialize all the grid cells using the given function
34 for (auto& array : m_cells) {
35 for (auto& w : array) {
40 } // end of namespace SOM_impl
42 template <std::size_t ND, typename DistFunc>
43 const std::pair<std::size_t, std::size_t>& SOM<ND, DistFunc>::getSize() const {
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) {
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 {
57 template <std::size_t ND, typename DistFunc>
58 typename SOM<ND, DistFunc>::iterator SOM<ND, DistFunc>::begin() {
59 return m_cells.begin();
62 template <std::size_t ND, typename DistFunc>
63 typename SOM<ND, DistFunc>::iterator SOM<ND, DistFunc>::end() {
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();
72 template <std::size_t ND, typename DistFunc>
73 typename SOM<ND, DistFunc>::const_iterator SOM<ND, DistFunc>::end() const {
77 template <std::size_t ND, typename DistFunc>
78 typename SOM<ND, DistFunc>::const_iterator SOM<ND, DistFunc>::cbegin() {
79 return m_cells.cbegin();
82 template <std::size_t ND, typename DistFunc>
83 typename SOM<ND, DistFunc>::const_iterator SOM<ND, DistFunc>::cend() {
84 return m_cells.cend();
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) {
98 closest_distance = dist;
101 return std::make_tuple(result_iter.template axisValue<0>(), result_iter.template axisValue<1>(), closest_distance);
104 } // end of namespace SOM_impl
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);
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);
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 {
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>");
131 return findBMU(weight_func(input));
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 {
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>");
145 return findBMU(weight_func(input), uncertainty_func(input));