11"""Simple heap with ordering and removal."""
22import heapq
3+ from typing import Optional
34from .graph import Graph
45from .grid import Grid
56from .world import World
7+ from .node import Node
68
79
810class 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 )
0 commit comments