Theoretica
A C++ numerical and automatic mathematical library
distance.h
Go to the documentation of this file.
1 
7 
8 #ifndef THEORETICA_DISTANCE_H
9 #define THEORETICA_DISTANCE_H
10 
11 #include "./vec.h"
12 #include "./algebra.h"
13 #include "../core/constants.h"
14 #include "../core/core_traits.h"
15 #include "../core/real_analysis.h"
16 #include "../complex/complex_analysis.h"
17 
18 
19 namespace theoretica {
20 
21  namespace algebra {
22 
23 
25 
26 
33  template<typename Vector>
34  inline real lp_norm(const Vector& v, unsigned int p) {
35 
36  real sum = 0;
37 
38  for (unsigned int i = 0; i < v.size(); ++i)
39  sum += pow(abs(v[i]), p);
40 
41  return root(sum, p);
42  }
43 
44 
50  template<typename Vector>
51  inline real l1_norm(const Vector& v) {
52 
53  real sum = 0;
54 
55  for (unsigned int i = 0; i < v.size(); ++i)
56  sum += abs(v[i]);
57 
58  return sum;
59  }
60 
66  template<typename Vector>
67  inline real l2_norm(const Vector& v) {
68 
69  auto sum = pair_inner_product(v[0], v[0]);
70 
71  for (unsigned int i = 1; i < v.size(); ++i)
72  sum += pair_inner_product(v[i], v[i]);
73 
74  return real(sqrt(sum));
75  }
76 
77 
83  template<typename Vector>
84  inline real linf_norm(const Vector& v) {
85 
86  real res = abs(v[0]);
87 
88  for (unsigned int i = 1; i < v.size(); ++i)
89  res = max(res, abs(v[i]));
90 
91  return res;
92  }
93 
94 
96 
97 
104  template<typename Vector>
105  inline real euclidean_distance(const Vector& v1, const Vector& v2) {
106 
107  if(v1.size() != v2.size()) {
108  TH_MATH_ERROR("euclidean_distance", v1.size(), INVALID_ARGUMENT);
109  return nan();
110  }
111 
112  return l2_norm(v1 - v2);
113  }
114 
115 
122  template<unsigned int N>
123  inline real distance(const vec<real, N>& v1, const vec<real, N>& v2) {
124  return euclidean_distance(v1, v2);
125  }
126 
127 
135  return abs(a - b);
136  }
137 
138 
145  inline real distance(real a, real b) {
146  return euclidean_distance(a, b);
147  }
148 
149 
156  template<typename T>
158  return (z1 - z2).norm();
159  }
160 
161 
169  template<typename Vector>
170  inline real minkowski_distance(const Vector& v1, const Vector& v2, unsigned int p) {
171 
172  if(v1.size() != v2.size()) {
173  TH_MATH_ERROR("minkowski_distance", v1.size(), INVALID_ARGUMENT);
174  return nan();
175  }
176 
177  return lp_norm(v1 - v2, p);
178  }
179 
180 
188  inline real minkowski_distance(real a, real b, unsigned int p) {
189  return root(pow(abs(b - a), p), p);
190  }
191 
192 
199  template<typename Vector, typename T = real>
200  inline auto hermitian_distance(const Vector& v1, const Vector& v2) {
201 
202  if(v1.size() != v2.size()) {
203  TH_MATH_ERROR("hermitian_distance", v1.size(), INVALID_ARGUMENT);
204  return complex<T>(nan());
205  }
206 
207  complex<T> sum = 0;
208 
209  for (size_t i = 0; i < v1.size(); ++i) {
210  const complex<T> diff = v1[i] - conjugate(v2[i]);
211  sum += diff * diff.conjugate();
212  }
213 
214  return sqrt(sum);
215  }
216 
217 
224  template<unsigned int N, typename T>
226  const vec<complex<T>, N>& v1, const vec<complex<T>, N>& v2) {
227 
228  return hermitian_distance<vec<complex<T>, N>, T>(v1, v2);
229  }
230 
231 
238  template<typename Vector>
239  inline real manhattan_distance(const Vector& v1, const Vector& v2) {
240 
241  if(v1.size() != v2.size()) {
242  TH_MATH_ERROR("manhattan_distance", v1.size(), INVALID_ARGUMENT);
243  return nan();
244  }
245 
246  return l1_norm(v1 - v2);
247  }
248 
249 
256  template<typename Vector>
257  inline real chebyshev_distance(const Vector& v1, const Vector& v2) {
258 
259  if(v1.size() != v2.size()) {
260  TH_MATH_ERROR("chebyshev_distance", v1.size(), INVALID_ARGUMENT);
261  return nan();
262  }
263 
264  return linf_norm(v1 - v2);
265  }
266 
267 
275  template<typename Vector>
277  const Vector& v1, const Vector& v2, real tolerance = MACH_EPSILON) {
278 
279  if(v1.size() != v2.size()) {
280  TH_MATH_ERROR("discrete_distance", v1.size(), INVALID_ARGUMENT);
281  return nan();
282  }
283 
284  bool diff = false;
285 
286  for (size_t i = 0; i < v1.size(); ++i) {
287 
288  // The vectors differ if a pair of elements differs
289  // more than the given tolerance
290  if(abs(v1[i] - v2[i]) > tolerance) {
291  diff = true;
292  break;
293  }
294  }
295 
296  return diff ? 1 : 0;
297  }
298 
299 
305  template<typename Vector>
306  inline real canberra_distance(const Vector& v1, const Vector& v2) {
307 
308  if(v1.size() != v2.size()) {
309  TH_MATH_ERROR("canberra_distance", v1.size(), INVALID_ARGUMENT);
310  return nan();
311  }
312 
313  real sum = 0;
314 
315  for (size_t i = 0; i < v1.size(); ++i)
316  sum += abs(v1[i] - v2[i]) / (abs(v1[i]) + abs(v2[i]));
317 
318  return sum;
319  }
320 
321 
327  template<typename Vector>
328  inline real cosine_distance(const Vector& v1, const Vector& v2) {
329 
330  if(v1.size() != v2.size()) {
331  TH_MATH_ERROR("cosine_distance", v1.size(), INVALID_ARGUMENT);
332  return nan();
333  }
334 
335  real product = 0;
336  real sum_sqr_x = 0;
337  real sum_sqr_y = 0;
338 
339  for (size_t i = 0; i < v1.size(); ++i) {
340  product += v1[i] * v2[i];
341  sum_sqr_x += square(v1[i]);
342  sum_sqr_y += square(v2[i]);
343  }
344 
345  return product / sqrt(sum_sqr_x * sum_sqr_y);
346  }
347 
348 
356  template<typename Vector>
358  const Vector& v1, const Vector& v2, real tolerance = MACH_EPSILON) {
359 
360  if(v1.size() != v2.size()) {
361  TH_MATH_ERROR("hamming_distance", v1.size(), INVALID_ARGUMENT);
362  return nan();
363  }
364 
365  unsigned int count = 0;
366 
367  // Count how many elements differ to some tolerance
368  for (unsigned int i = 0; i < v1.size(); ++i)
369  if(abs(v1[i] - v2[i]) > tolerance)
370  count++;
371 
372  return count;
373  }
374  }
375 }
376 
377 #endif
Linear algebra routines.
Complex number in algebraic form .
Definition: complex.h:26
complex conjugate() const
Compute the conjugate of the complex number.
Definition: complex.h:122
A statically allocated N-dimensional vector with elements of the given type.
Definition: vec.h:88
#define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION)
TH_MATH_ERROR is a macro which throws exceptions or modifies errno (depending on which compiling opti...
Definition: error.h:219
real l2_norm(const Vector &v)
Compute the L2 norm of a vector: .
Definition: distance.h:67
real discrete_distance(const Vector &v1, const Vector &v2, real tolerance=MACH_EPSILON)
Compute the discrete distance between two vectors.
Definition: distance.h:276
real l1_norm(const Vector &v)
Compute the L1 norm of a vector: .
Definition: distance.h:51
real minkowski_distance(const Vector &v1, const Vector &v2, unsigned int p)
Compute the Minkowski distance between two vectors: .
Definition: distance.h:170
real manhattan_distance(const Vector &v1, const Vector &v2)
Compute the Manhattan distance between two vectors: .
Definition: distance.h:239
real euclidean_distance(const Vector &v1, const Vector &v2)
Distances.
Definition: distance.h:105
real cosine_distance(const Vector &v1, const Vector &v2)
Compute the cosine distance between two vectors.
Definition: distance.h:328
auto pair_inner_product(const Type &v_i, const Type &w_i)
Compute the contribution of the inner product between a pair of elements of two vectors,...
Definition: algebra.h:252
auto hermitian_distance(const Vector &v1, const Vector &v2)
Compute the Hermitian distance between two vectors: .
Definition: distance.h:200
real linf_norm(const Vector &v)
Compute the Linf norm of a vector: .
Definition: distance.h:84
real canberra_distance(const Vector &v1, const Vector &v2)
Compute the Canberra distance between two vectors.
Definition: distance.h:306
real lp_norm(const Vector &v, unsigned int p)
Norms.
Definition: distance.h:34
real hamming_distance(const Vector &v1, const Vector &v2, real tolerance=MACH_EPSILON)
Compute the Hamming distance between two vectors.
Definition: distance.h:357
real distance(const vec< real, N > &v1, const vec< real, N > &v2)
Compute the Euclidean distance between two vectors: .
Definition: distance.h:123
real chebyshev_distance(const Vector &v1, const Vector &v2)
Compute the Chebyshev distance between two vectors: .
Definition: distance.h:257
Main namespace of the library which contains all functions and objects.
Definition: algebra.h:27
double real
A real number, defined as a floating point type.
Definition: constants.h:188
dual2 sqrt(dual2 x)
Compute the square root of a second order dual number.
Definition: dual2_functions.h:54
dual2 abs(dual2 x)
Compute the absolute value of a second order dual number.
Definition: dual2_functions.h:183
auto sum(const Vector &X)
Compute the sum of a vector of real values using pairwise summation to reduce round-off error.
Definition: dataset.h:219
dual2 conjugate(dual2 x)
Return the conjugate of a second order dual number.
Definition: dual2_functions.h:35
auto max(const Vector &X)
Finds the maximum value inside a dataset.
Definition: dataset.h:330
constexpr real MACH_EPSILON
Machine epsilon for the real type.
Definition: constants.h:197
real root(real x, int n)
Compute the n-th root of x.
Definition: real_analysis.h:813
auto product(const Vector &X)
Compute the product of a set of values.
Definition: dataset.h:29
dual2 square(dual2 x)
Return the square of a second order dual number.
Definition: dual2_functions.h:23
real nan()
Return a quiet NaN number in floating point representation.
Definition: error.h:54
dual2 pow(dual2 x, int n)
Compute the n-th power of a second order dual number.
Definition: dual2_functions.h:41
Vector class and operations.