Skip to content

Commit d8c295a

Browse files
removed remove_node
1 parent adcbcb7 commit d8c295a

4 files changed

Lines changed: 34 additions & 49 deletions

File tree

pathfinding/core/heap.py

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
"""Simple heap with ordering and removal."""
22
import heapq
3+
from typing import Optional
34
from .graph import Graph
45
from .grid import Grid
56
from .world import World
7+
from .node import Node
68

79

810
class SimpleHeap:
9-
"""Simple wrapper around open_list that keeps track of order and removed
10-
nodes automatically."""
11+
"""Simple wrapper around open_list that keeps track of order."""
1112

1213
def __init__(self, node, grid):
1314
self.grid = grid
1415
self.open_list = [self._get_node_tuple(node, 0)]
15-
self.removed_node_tuples = set()
16-
self.heap_order = {}
1716
self.number_pushed = 0
1817

1918
def _get_node_tuple(self, node, heap_order):
@@ -34,28 +33,27 @@ def _get_node_id(self, node):
3433
elif isinstance(self.grid, World):
3534
return (node.x, node.y, node.grid_id)
3635

37-
def pop_node(self):
38-
"""
39-
Pops node off the heap. i.e. returns the one with the lowest f.
40-
41-
Notes:
42-
1. Checks if that values is in removed_node_tuples first, if not tries
43-
again.
44-
2. We use this approach to avoid invalidating the heap structure.
45-
"""
46-
node_tuple = heapq.heappop(self.open_list)
47-
while node_tuple in self.removed_node_tuples:
36+
def pop_node(self) -> Optional[Node]:
37+
"""Pops node off the heap. i.e. returns the one with the lowest f."""
38+
while self.open_list:
4839
node_tuple = heapq.heappop(self.open_list)
4940

50-
if isinstance(self.grid, Graph):
51-
node = self.grid.node(node_tuple[2])
52-
elif isinstance(self.grid, Grid):
53-
node = self.grid.node(node_tuple[2], node_tuple[3])
54-
elif isinstance(self.grid, World):
55-
node = self.grid.grids[
56-
node_tuple[4]].node(node_tuple[2], node_tuple[3])
57-
58-
return node
41+
if isinstance(self.grid, Graph):
42+
node = self.grid.node(node_tuple[2])
43+
elif isinstance(self.grid, Grid):
44+
node = self.grid.node(node_tuple[2], node_tuple[3])
45+
elif isinstance(self.grid, World):
46+
node = self.grid.grids[
47+
node_tuple[4]].node(node_tuple[2], node_tuple[3])
48+
49+
# node already updated with lower f, ignore
50+
f = node_tuple[0]
51+
if f > node.f:
52+
continue
53+
else:
54+
return node
55+
56+
return None
5957

6058
def push_node(self, node):
6159
"""
@@ -65,27 +63,9 @@ def push_node(self, node):
6563
"""
6664
self.number_pushed = self.number_pushed + 1
6765
node_tuple = self._get_node_tuple(node, self.number_pushed)
68-
node_id = self._get_node_id(node)
69-
70-
self.heap_order[node_id] = self.number_pushed
7166

7267
heapq.heappush(self.open_list, node_tuple)
7368

74-
def remove_node(self, node, f):
75-
"""
76-
Remove the node from the heap.
77-
78-
This just stores it in a set and we just ignore the node if it does
79-
get popped from the heap.
80-
81-
:param node: The node to remove.
82-
:param f: The old f value of the node.
83-
"""
84-
node_id = self._get_node_id(node)
85-
heap_order = self.heap_order[node_id]
86-
node_tuple = self._get_node_tuple(node, heap_order)
87-
self.removed_node_tuples.add(node_tuple)
88-
8969
def __len__(self):
9070
"""Returns the length of the open_list."""
9171
return len(self.open_list)

pathfinding/finder/finder.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ def process_node(
131131
ng = parent.g + graph.calc_cost(parent, node, self.weighted)
132132

133133
if not node.opened or ng < node.g:
134-
old_f = node.f
135134
node.g = ng
136135
node.h = node.h or self.apply_heuristic(node, end, graph=graph)
137136
# f is the estimated total cost from start to goal
@@ -144,7 +143,6 @@ def process_node(
144143
# the node can be reached with smaller cost.
145144
# Since its f value has been updated, we have to
146145
# update its position in the open list
147-
open_list.remove_node(node, old_f)
148146
open_list.push_node(node)
149147

150148
def check_neighbors(self, start, end, graph, open_list,

pytest.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[pytest]
2+
pythonpath = .
23
log_cli = 1
34
log_cli_level = INFO
45
log_cli_format = %(asctime)s.%(msecs)03d [%(levelname)8s] (%(filename)s:%(lineno)s) %(message)s

test/test_heap.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,17 @@ def test_heap():
1616
open_list.push_node(grid.node(1, 2))
1717
open_list.push_node(grid.node(1, 3))
1818

19-
# Test removal and pop
20-
assert len(open_list) == 3
21-
open_list.remove_node(grid.node(1, 2), 0)
22-
assert len(open_list) == 3
23-
2419
assert open_list.pop_node() == grid.node(1, 1)
20+
assert open_list.pop_node() == grid.node(1, 2)
2521
assert open_list.pop_node() == grid.node(1, 3)
2622
assert len(open_list) == 0
23+
24+
# Test inconsistent f
25+
test_node = grid.node(1,1)
26+
test_node.f = 1
27+
open_list.push_node(test_node)
28+
test_node.f = 0
29+
open_list.push_node(test_node)
30+
assert open_list.pop_node() == test_node
31+
assert open_list.pop_node() is None
32+
assert len(open_list) == 0

0 commit comments

Comments
 (0)