2 * Copyright (C) 2012-2022 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/ImplTools.h"
29template <typename DistFunc>
30SOM<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)
35 // Initialize all the grid cells using the given function
36 for (auto array : m_cells) {
37 for (auto& w : array) {
42} // end of namespace SOM_impl
44template <typename DistFunc>
45const std::pair<std::size_t, std::size_t>& SOM<DistFunc>::getSize() const {
49template <typename DistFunc>
50std::size_t SOM<DistFunc>::getDimensions() const {
54template <typename DistFunc>
55auto SOM<DistFunc>::operator()(std::size_t x, std::size_t y) -> reference_type {
59template <typename DistFunc>
60auto SOM<DistFunc>::operator()(std::size_t x, std::size_t y) const -> const reference_type {
64template <typename DistFunc>
65typename SOM<DistFunc>::iterator SOM<DistFunc>::begin() {
66 return m_cells.begin();
69template <typename DistFunc>
70typename SOM<DistFunc>::iterator SOM<DistFunc>::end() {
74template <typename DistFunc>
75typename SOM<DistFunc>::const_iterator SOM<DistFunc>::begin() const {
76 return m_cells.begin();
79template <typename DistFunc>
80typename SOM<DistFunc>::const_iterator SOM<DistFunc>::end() const {
84template <typename DistFunc>
85typename SOM<DistFunc>::const_iterator SOM<DistFunc>::cbegin() {
86 return m_cells.cbegin();
89template <typename DistFunc>
90typename SOM<DistFunc>::const_iterator SOM<DistFunc>::cend() {
91 return m_cells.cend();
96template <typename DistFunc>
97std::tuple<std::size_t, std::size_t, double>
98findBMU_impl(const SOM<DistFunc>& som,
99 std::function<double(const GridContainer::VectorValueProxy<double>&)> dist_func) {
100 auto result_iter = som.begin();
101 double closest_distance = std::numeric_limits<double>::max();
102 for (auto iter = som.begin(); iter != som.end(); ++iter) {
103 double dist = dist_func(*iter);
104 if (dist < closest_distance) {
106 closest_distance = dist;
109 return std::make_tuple(result_iter.template axisValue<0>(), result_iter.template axisValue<1>(), closest_distance);
112} // end of namespace SOM_impl
114template <typename DistFunc>
115std::tuple<std::size_t, std::size_t, double> SOM<DistFunc>::findBMU(const std::vector<double>& input) const {
116 assert(input.size() == m_dimensions);
117 DistFunc dist_func{};
118 return SOM_impl::findBMU_impl<DistFunc>(
119 *this, [&dist_func, &input](const GridContainer::VectorValueProxy<double>& cell) -> double {
120 return dist_func.distance(cell.begin(), cell.end(), input.begin());
124template <typename DistFunc>
125std::tuple<std::size_t, std::size_t, double> SOM<DistFunc>::findBMU(const std::vector<double>& input,
126 const std::vector<double>& uncertainties) const {
127 assert(input.size() == uncertainties.size() && input.size() == m_dimensions);
128 DistFunc dist_func{};
129 return SOM_impl::findBMU_impl<DistFunc>(
130 *this, [&dist_func, &input, &uncertainties](const GridContainer::VectorValueProxy<double>& cell) -> double {
131 return dist_func.distance(cell.begin(), cell.end(), input.begin(), uncertainties.begin());
135template <typename DistFunc>
136template <typename InputType, typename WeightFunc>
137std::tuple<std::size_t, std::size_t, double> SOM<DistFunc>::findBMU(const InputType& input,
138 WeightFunc weight_func) const {
140 static_assert(std::is_same<decltype(std::declval<WeightFunc>()(input)), std::vector<double>>::value,
141 "WeightFunc must be callable with input as parameter, returning an std::vector<double>");
143 return findBMU(weight_func(input));
146template <typename DistFunc>
147template <typename InputType, typename WeightFunc, typename UncertaintyFunc>
148std::tuple<std::size_t, std::size_t, double> SOM<DistFunc>::findBMU(const InputType& input, WeightFunc weight_func,
149 UncertaintyFunc uncertainty_func) const {
151 static_assert(std::is_same<decltype(std::declval<WeightFunc>()(input)), std::vector<double>>::value,
152 "WeightFunc must be callable with input as parameter, returning an std::vector<double>");
153 static_assert(std::is_same<decltype(std::declval<UncertaintyFunc>()(input)), std::vector<double>>::value,
154 "UncertaintyFunc must be callable with input as parameter, returning an std::vector<double>");
156 return findBMU(weight_func(input), uncertainty_func(input));