Skip to content

Commit 05809c0

Browse files
authored
Merge pull request #66 from w9PcJLyb/fix-heuristic
fix heuristic in a weighted graph
2 parents 89ca95c + 6f7096f commit 05809c0

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

pathfinding/core/grid.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def build_nodes(
2020
use_matrix = (isinstance(matrix, (tuple, list))) or \
2121
(USE_NUMPY and isinstance(matrix, np.ndarray) and matrix.size > 0)
2222

23+
min_weight = float("inf")
2324
for y in range(height):
2425
nodes.append([])
2526
for x in range(width):
@@ -32,9 +33,13 @@ def build_nodes(
3233
weight = float(matrix[y][x]) if use_matrix else 1
3334
walkable = weight <= 0.0 if inverse else weight > 0
3435

36+
if walkable and weight < min_weight:
37+
min_weight = weight
38+
3539
nodes[y].append(GridNode(
3640
x=x, y=y, walkable=walkable, weight=weight, grid_id=grid_id))
37-
return nodes
41+
42+
return nodes, min_weight
3843

3944

4045
class Grid:
@@ -56,10 +61,11 @@ def __init__(
5661
self.height = len(matrix)
5762
self.width = self.width = len(matrix[0]) if self.height > 0 else 0
5863
if self.width > 0 and self.height > 0:
59-
self.nodes = build_nodes(
64+
self.nodes, self._min_weight = build_nodes(
6065
self.width, self.height, matrix, inverse, grid_id)
6166
else:
6267
self.nodes = [[]]
68+
self._min_weight = float("inf")
6369

6470
def set_passable_left_right_border(self):
6571
self.passable_left_right_border = True
@@ -306,3 +312,25 @@ def __repr__(self):
306312
"""
307313
return f"<{self.__class__.__name__} " \
308314
f"width={self.width} height={self.height}>"
315+
316+
@property
317+
def min_weight(self) -> float:
318+
return self._min_weight
319+
320+
def update_node(self, x, y, *, weight=None, walkable=None):
321+
node = self.node(x, y)
322+
323+
if weight is None:
324+
weight = node.weight
325+
326+
if walkable is None:
327+
walkable = node.walkable
328+
329+
if walkable:
330+
if weight <= 0:
331+
raise ValueError("Weight of a walkable node must be positive")
332+
if weight < self._min_weight:
333+
self._min_weight = weight
334+
335+
node.weight = weight
336+
node.walkable = walkable

pathfinding/finder/finder.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ def apply_heuristic(self, node_a, node_b, heuristic=None, graph=None):
7575

7676
nh = heuristic(dx, dy)
7777
# in a weighted graph we also need to multiply the calculated
78-
# value with the weight of the node
78+
# value with the minimum weight of the graph
7979
if self.weighted:
80-
nh *= node_a.weight
80+
nh *= graph.min_weight
8181
return nh
8282
else:
8383
return heuristic(dx, dy)

test/path_test_scenarios.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,20 @@
119119
"expectedDiagonalLength": 12,
120120
"inverse": false,
121121
"weighted": true
122+
},
123+
{
124+
"name": "s8",
125+
"startX": 0,
126+
"startY": 0,
127+
"endX": 3,
128+
"endY": 0,
129+
"matrix": [
130+
[1, 2, 1, 1],
131+
[1, 1, 1, 1]
132+
],
133+
"expectedLength": 4,
134+
"expectedDiagonalLength": 4,
135+
"inverse": false,
136+
"weighted": true
122137
}
123138
]

0 commit comments

Comments
 (0)