Skip to content

Commit c4091c7

Browse files
authoredNov 16, 2024··
Add Minkowski distance algorithm (#497)
1 parent 87776ee commit c4091c7

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using NUnit.Framework;
2+
using Algorithms.LinearAlgebra.Distances;
3+
using FluentAssertions;
4+
using System;
5+
6+
namespace Algorithms.Tests.LinearAlgebra.Distances;
7+
8+
public class MinkowskiTests
9+
{
10+
[TestCase(new[] { 2.0, 3.0 }, new[] { -1.0, 5.0 }, 1, 5.0)] // Simulate Manhattan condition
11+
[TestCase(new[] { 7.0, 4.0, 3.0 }, new[] { 17.0, 6.0, 2.0 }, 2, 10.247)] // Simulate Euclidean condition
12+
[TestCase(new[] { 1.0, 2.0, 3.0, 4.0 }, new[] { 1.75, 2.25, -3.0, 0.5 }, 20, 6.0)] // Simulate Chebyshev condition
13+
[TestCase(new[] { 1.0, 1.0, 9.0 }, new[] { 2.0, 2.0, -5.2 }, 3, 14.2)]
14+
[TestCase(new[] { 1.0, 2.0, 3.0 }, new[] { 1.0, 2.0, 3.0 }, 5, 0.0)]
15+
public void DistanceTest(double[] point1, double[] point2, int order, double expectedDistance)
16+
{
17+
Minkowski.Distance(point1, point2, order).Should().BeApproximately(expectedDistance, 0.01);
18+
}
19+
20+
[TestCase(new[] { 2.0, 3.0 }, new[] { -1.0 }, 2)]
21+
[TestCase(new[] { 1.0 }, new[] { 1.0, 2.0, 3.0 }, 1)]
22+
[TestCase(new[] { 1.0, 1.0 }, new[] { 2.0, 2.0 }, 0)]
23+
public void DistanceThrowsArgumentExceptionOnInvalidInput(double[] point1, double[] point2, int order)
24+
{
25+
Action action = () => Minkowski.Distance(point1, point2, order);
26+
action.Should().Throw<ArgumentException>();
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.Linq;
3+
4+
namespace Algorithms.LinearAlgebra.Distances;
5+
6+
/// <summary>
7+
/// Implementation of Minkowski distance.
8+
/// It is the sum of the lengths of the projections of the line segment between the points onto the
9+
/// coordinate axes, raised to the power of the order and then taking the p-th root.
10+
/// For the case of order = 1, the Minkowski distance degenerates to the Manhattan distance,
11+
/// for order = 2, the usual Euclidean distance is obtained and for order = infinity, the Chebyshev distance is obtained.
12+
/// </summary>
13+
public static class Minkowski
14+
{
15+
/// <summary>
16+
/// Calculate Minkowski distance for two N-Dimensional points.
17+
/// </summary>
18+
/// <param name="point1">First N-Dimensional point.</param>
19+
/// <param name="point2">Second N-Dimensional point.</param>
20+
/// <param name="order">Order of the Minkowski distance.</param>
21+
/// <returns>Calculated Minkowski distance.</returns>
22+
public static double Distance(double[] point1, double[] point2, int order)
23+
{
24+
if (order < 1)
25+
{
26+
throw new ArgumentException("The order must be greater than or equal to 1.");
27+
}
28+
29+
if (point1.Length != point2.Length)
30+
{
31+
throw new ArgumentException("Both points should have the same dimensionality");
32+
}
33+
34+
// distance = (|x1-y1|^p + |x2-y2|^p + ... + |xn-yn|^p)^(1/p)
35+
return Math.Pow(point1.Zip(point2, (x1, x2) => Math.Pow(Math.Abs(x1 - x2), order)).Sum(), 1.0 / order);
36+
}
37+
}

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ find more than one implementation for the same objective but using different alg
6161
* [Chebyshev](./Algorithms/LinearAlgebra/Distances/Chebyshev.cs)
6262
* [Euclidean](./Algorithms/LinearAlgebra/Distances/Euclidean.cs)
6363
* [Manhattan](./Algorithms/LinearAlgebra/Distances/Manhattan.cs)
64+
* [Minkowski](./Algorithms/LinearAlgebra/Distances/Minkowski.cs)
6465
* [Eigenvalue](./Algorithms/LinearAlgebra/Eigenvalue)
6566
* [Power Iteration](./Algorithms/LinearAlgebra/Eigenvalue/PowerIteration.cs)
6667
* [Modular Arithmetic](./Algorithms/ModularArithmetic)

0 commit comments

Comments
 (0)
Please sign in to comment.