PrimitiveSimilarity.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cmath>
5
7{
8 namespace
9 {
10 template <typename ValueT>
11 float normalizedAbsDistanceSimilarity(ValueT oldValue, ValueT newValue)
12 {
13 const double oldAsDouble = static_cast<double>(oldValue);
14 const double newAsDouble = static_cast<double>(newValue);
15 const double denom =
16 std::max(std::max(std::abs(oldAsDouble), std::abs(newAsDouble)), 0.0001);
17
18 return static_cast<float>(1.0 - (std::abs(oldAsDouble - newAsDouble) / denom));
19 }
20
21 // taken from https://github.com/guilhermeagostinelli/levenshtein/blob/master/levenshtein.cpp
22 int levenshteinDist(const std::string& word1, const std::string& word2) {
23 const int size1 = word1.size();
24 const int size2 = word2.size();
25 std::vector<std::vector<int>> verif(size1 + 1, std::vector<int>(size2 + 1));
26
27 // If one of the words has zero length, the distance is equal to the size of the other word.
28 if (size1 == 0)
29 return size2;
30 if (size2 == 0)
31 return size1;
32
33 // Sets the first row and the first column of the verification matrix with the numerical order from 0 to the length of each word.
34 for (int i = 0; i <= size1; i++)
35 verif[i][0] = i;
36 for (int j = 0; j <= size2; j++)
37 verif[0][j] = j;
38
39 // Verification step / matrix filling.
40 for (int i = 1; i <= size1; i++) {
41 for (int j = 1; j <= size2; j++) {
42 // Sets the modification cost.
43 // 0 means no modification (i.e. equal letters) and 1 means that a modification is needed (i.e. unequal letters).
44 int cost = (word2[j - 1] == word1[i - 1]) ? 0 : 1;
45
46 // Sets the current position of the matrix as the minimum value between a (deletion), b (insertion) and c (substitution).
47 // a = the upper adjacent value plus 1: verif[i - 1][j] + 1
48 // b = the left adjacent value plus 1: verif[i][j - 1] + 1
49 // c = the upper left adjacent value plus the modification cost: verif[i - 1][j - 1] + cost
50 verif[i][j] = std::min(
51 std::min(verif[i - 1][j] + 1, verif[i][j - 1] + 1),
52 verif[i - 1][j - 1] + cost
53 );
54 }
55 }
56
57 // The last position of the matrix will contain the Levenshtein distance.
58 return verif[size1][size2];
59 }
60 }
61
62 float
63 calculateSimilarity(const aron::data::Bool& oldValue, const aron::data::Bool& newValue)
64 {
65 return oldValue.getValue() == newValue.getValue() ? 1.0f : 0.0f;
66 }
67
68 float
69 calculateSimilarity(const aron::data::Int& oldValue, const aron::data::Int& newValue)
70 {
71 return normalizedAbsDistanceSimilarity(oldValue.getValue(), newValue.getValue());
72 }
73
74 float
75 calculateSimilarity(const aron::data::Long& oldValue, const aron::data::Long& newValue)
76 {
77 return normalizedAbsDistanceSimilarity(oldValue.getValue(), newValue.getValue());
78 }
79
80 float
82 {
83 return normalizedAbsDistanceSimilarity(oldValue.getValue(), newValue.getValue());
84 }
85
86 float
88 {
89 return normalizedAbsDistanceSimilarity(oldValue.getValue(), newValue.getValue());
90 }
91
92 float
94 {
95 const std::string& oldString = oldValue.getValue();
96 const std::string& newString = newValue.getValue();
97 const float denom =
98 std::max(static_cast<float>(std::max(oldString.size(), newString.size())), 0.0001f);
99
100 return 1.0f - (static_cast<float>(levenshteinDist(oldString, newString)) / denom);
101 }
102}
103
float calculateSimilarity(const aron::data::Bool &oldValue, const aron::data::Bool &newValue)