Alexandria 2.25.0
SDC-CH common library for the Euclid project
NeihbourhoodFunc.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2012-2021 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
20#include <cmath>
21#include <algorithm> // std::max
22
23namespace Euclid {
24namespace SOM {
25namespace NeighborhoodFunc {
26
27Signature linearUnitDisk(double initial_radius) {
28 double r_square = initial_radius * initial_radius;
30 std::size_t iteration, std::size_t total_iterations) -> double {
31 double iter_factor = 1.0 * (total_iterations - iteration) / total_iterations;
32 iter_factor = iter_factor * iter_factor; // We compare the squared distances
33 double x = bmu.first - cell.first;
34 double y = bmu.second - cell.second;
35 double dist_square = x * x + y * y;
36 if (dist_square < r_square * iter_factor) {
37 return 1.;
38 } else {
39 return 0.;
40 }
41 };
42}
43
44Signature kohonen(std::size_t x_size, std::size_t y_size, double sigma_cutoff_mult) {
45
46 double init_sigma = std::max(x_size, y_size) / 2.;
48 double cutoff_mult_square = sigma_cutoff_mult * sigma_cutoff_mult;
49
50 return [init_sigma, sigma_buffer, cutoff_mult_square](std::pair<std::size_t, std::size_t> bmu,
52 std::size_t total_iterations) mutable -> double {
53 // If we have new iteration we recompute the sigma, otherwise we use the already
54 // calculated one
55 if (std::get<0>(sigma_buffer) != iteration || std::get<1>(sigma_buffer) != total_iterations) {
56 std::get<0>(sigma_buffer) = iteration;
57 std::get<1>(sigma_buffer) = total_iterations;
58 double time_constant = total_iterations / std::log(init_sigma);
59 std::get<2>(sigma_buffer) = init_sigma * std::exp(-1. * iteration / time_constant);
60 }
61 double sigma_square = std::get<2>(sigma_buffer) * std::get<2>(sigma_buffer);
62
63 double x = static_cast<double>(bmu.first) - cell.first;
64 double y = static_cast<double>(bmu.second) - cell.second;
65 double dist_square = x * x + y * y;
66
67 if (dist_square < cutoff_mult_square * sigma_square) {
68 return std::exp(-1. * dist_square / (2. * sigma_square));
69 } else {
70 return 0.;
71 }
72 };
73}
74
75} // namespace NeighborhoodFunc
76} // namespace SOM
77} // namespace Euclid
T exp(T... args)
T log(T... args)
T max(T... args)
ELEMENTS_API Signature linearUnitDisk(double initial_radius)
ELEMENTS_API Signature kohonen(std::size_t x_size, std::size_t y_size, double sigma_cutoff_mult=1.)