3
3
from queue import Queue
4
4
5
5
6
+ def determinant_2x2 (matrix : list ):
7
+ """
8
+ Determinant for a 2x2 matrix, used for divide by zero checking
9
+
10
+ Parameters:
11
+ matrix (list): covariance matrix between given points
12
+
13
+ Returns:
14
+ float: determinant
15
+ """
16
+ return matrix [0 ][0 ] * matrix [1 ][1 ] - matrix [0 ][1 ] * matrix [1 ][0 ]
17
+
18
+
19
+ def covariance_matrix (point1 : tuple , point2 : tuple ):
20
+ """
21
+ Calculates the covariance matrix for the given points
22
+
23
+ Parameters:
24
+ point1 (tuple): x, y coordinates for node 1
25
+ point2 (tuple): x, y coordinates for node 2
26
+
27
+ Returns:
28
+ list: covariance matrix
29
+ """
30
+ x1 , y1 = point1
31
+ x2 , y2 = point2
32
+
33
+ cov_x_x = (x1 - x2 ) ** 2
34
+ cov_y_y = (y1 - y2 ) ** 2
35
+ cov_x_y = (x1 - x2 ) * (y1 - y2 )
36
+
37
+ return [[cov_x_x , cov_x_y ], [cov_x_y , cov_y_y ]]
38
+
39
+ # Mahalanobis distance
40
+
41
+
42
+ def mahalanobis (node1 : object , node2 : object ):
43
+ """
44
+ Calculates the Mahalanobis distance between two nodes.
45
+
46
+ Parameters:
47
+ node1 (Node): The first node.
48
+ node2 (Node): The second node.
49
+
50
+ Returns:
51
+ float: The Mahalanobis distance between the two nodes.
52
+ """
53
+ matrix = covariance_matrix (node1 .get_pos (), node2 .get_pos ())
54
+
55
+ # Checking for potential divide by zero errors
56
+ if determinant_2x2 (matrix ) < 1e-10 :
57
+ return float ("inf" )
58
+
59
+ # Getting the difference between the two nodes' respective x and y values
60
+ diff = [a - b for a , b in zip (node1 .get_pos (), node2 .get_pos ())]
61
+
62
+ result = 0
63
+ for i , d in enumerate (diff ):
64
+ result += d * d / matrix [i ][i ]
65
+ return math .sqrt (result )
66
+
67
+
68
+ # Minkowski distance
69
+ def minkowski (node1 : object , node2 : object , p : int or float ):
70
+ x1 , y1 = node1 .get_pos ()
71
+ x2 , y2 = node2 .get_pos ()
72
+
73
+ d1 = abs (x1 - x2 )** p
74
+ d2 = abs (y1 - y2 )** p
75
+
76
+ return (d1 + d2 )** (1 / p )
77
+
78
+
6
79
# Chebyshev distance
7
80
def chebyshev (node1 : object , node2 : object ):
8
81
"""
@@ -57,7 +130,7 @@ def euclidean(node1: object, node2: object):
57
130
return math .sqrt ((x1 - x2 ) ** 2 + (y1 - y2 ) ** 2 )
58
131
59
132
60
- def heuristic (type : str , node1 : object , node2 : object ):
133
+ def heuristic (type : str , node1 : object , node2 : object , * args ):
61
134
"""
62
135
Calculate the heuristic distance between two nodes.
63
136
@@ -66,6 +139,7 @@ def heuristic(type: str, node1: object, node2: object):
66
139
Valid options are "euclidean" and "manhattan".
67
140
node1 (Node): The first node.
68
141
node2 (Node): The second node.
142
+ *args (list): additional arguments for different heuristics
69
143
70
144
Returns:
71
145
float: The heuristic distance between the two nodes.
@@ -77,6 +151,10 @@ def heuristic(type: str, node1: object, node2: object):
77
151
return euclidean (node1 , node2 )
78
152
case "manhattan" :
79
153
return manhattan (node1 , node2 )
154
+ case "minkowski" :
155
+ return minkowski (node1 , node2 , args [0 ])
156
+ case "mahalanobis" :
157
+ return mahalanobis (node1 , node2 )
80
158
case _:
81
159
return manhattan (node1 , node2 )
82
160
0 commit comments