From 00237cd2b2decfe3dd2f4afbcc56dfde65e876ed Mon Sep 17 00:00:00 2001 From: dbring Date: Sun, 8 Oct 2023 14:16:31 -0700 Subject: [PATCH 1/3] Added the Minkowski distance function --- maths/minkowski_distance.py | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 maths/minkowski_distance.py diff --git a/maths/minkowski_distance.py b/maths/minkowski_distance.py new file mode 100644 index 000000000000..3043ffabfb1b --- /dev/null +++ b/maths/minkowski_distance.py @@ -0,0 +1,41 @@ +def minkowski_distance( + point_a: list[float], + point_b: list[float], + order: int, +) -> float: + """ + This function calculates the Minkowski distance for a given order between + two n-dimensional points represented as lists. For the case of order = 1, + the Minkowski distance degenerates to the Manhattan distance. For + order = 2, the usual Euclidean distance is obtained. + + https://en.wikipedia.org/wiki/Minkowski_distance + + >>> minkowski_distance([1.0, 1.0], [2.0, 2.0], 1) + 2.0 + >>> minkowski_distance([1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], 2) + 8.0 + >>> minkowski_distance([1.0], [2.0], -1) + Traceback (most recent call last): + ... + Exception: The order must be greater than or equal to 1. + >>> minkowski_distance([1.0], [1.0, 2.0], 1) + Traceback (most recent call last): + ... + Exception: Both points must have the same dimension. + """ + if order < 1: + raise Exception("The order must be greater than or equal to 1.") + + if len(point_a) != len(point_b): + raise Exception("Both points must have the same dimension.") + + return float( + sum(abs(a - b) ** order for a, b in zip(point_a, point_b)) ** (1 / order) + ) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 8789275cf9716cfa13c7801b3eed9354e1d294c5 Mon Sep 17 00:00:00 2001 From: dbring Date: Mon, 9 Oct 2023 12:59:10 -0700 Subject: [PATCH 2/3] Made error handling more precise --- maths/minkowski_distance.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/maths/minkowski_distance.py b/maths/minkowski_distance.py index 3043ffabfb1b..ffc239e7d1e3 100644 --- a/maths/minkowski_distance.py +++ b/maths/minkowski_distance.py @@ -18,21 +18,19 @@ def minkowski_distance( >>> minkowski_distance([1.0], [2.0], -1) Traceback (most recent call last): ... - Exception: The order must be greater than or equal to 1. + ValueError: The order must be greater than or equal to 1. >>> minkowski_distance([1.0], [1.0, 2.0], 1) Traceback (most recent call last): ... - Exception: Both points must have the same dimension. + ValueError: Both points must have the same dimension. """ if order < 1: - raise Exception("The order must be greater than or equal to 1.") + raise ValueError("The order must be greater than or equal to 1.") if len(point_a) != len(point_b): - raise Exception("Both points must have the same dimension.") + raise ValueError("Both points must have the same dimension.") - return float( - sum(abs(a - b) ** order for a, b in zip(point_a, point_b)) ** (1 / order) - ) + return sum(abs(a - b) ** order for a, b in zip(point_a, point_b)) ** (1 / order) if __name__ == "__main__": From d9472f75fab296818b275c10fa80e9280b011852 Mon Sep 17 00:00:00 2001 From: dbring Date: Mon, 9 Oct 2023 15:30:01 -0700 Subject: [PATCH 3/3] Added note about floating point errors and corresponding doctest --- maths/minkowski_distance.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/maths/minkowski_distance.py b/maths/minkowski_distance.py index ffc239e7d1e3..3237124e8d36 100644 --- a/maths/minkowski_distance.py +++ b/maths/minkowski_distance.py @@ -11,10 +11,16 @@ def minkowski_distance( https://en.wikipedia.org/wiki/Minkowski_distance + Note: due to floating point calculation errors the output of this + function may be inaccurate. + >>> minkowski_distance([1.0, 1.0], [2.0, 2.0], 1) 2.0 >>> minkowski_distance([1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], 2) 8.0 + >>> import numpy as np + >>> np.isclose(5.0, minkowski_distance([5.0], [0.0], 3)) + True >>> minkowski_distance([1.0], [2.0], -1) Traceback (most recent call last): ...