Added early exit to BFS, added Dijkstra class

This commit is contained in:
Jan Mrna 2025-09-20 14:54:29 +02:00
parent b7ccb7c2cc
commit 0cd01ece0c

View File

@ -205,8 +205,9 @@ class DFS(PathFinderBase):
class BFS(PathFinderBase): class BFS(PathFinderBase):
""" """
Iterative breadh-first search. Finds optimal path and creates flow-field, Iterative breadth-first search
so it would be good match for static maps with lots of agents with one Finds optimal path and creates flow-field, does not take the node cost into account.
This would be good match for static maps with lots of agents with one
destination. destination.
Compared to A*, this is more computationally expensive if we only want Compared to A*, this is more computationally expensive if we only want
to find path for one agent. to find path for one agent.
@ -224,14 +225,19 @@ class BFS(PathFinderBase):
self._distance: dict[Point2D, float] = { end_point: 0.0 } self._distance: dict[Point2D, float] = { end_point: 0.0 }
# build "flow map" # build "flow map"
while not frontier.empty(): early_exit = False
while not frontier.empty() and not early_exit:
current = frontier.get() current = frontier.get()
for next_point in self._map.GetNeighbours(current): for next_point in self._map.GetNeighbours(current):
if next_point not in self._came_from: if next_point not in self._came_from:
frontier.put(next_point) frontier.put(next_point)
#self._distance[next_point] = self._distance[current] + 1.0 self._distance[next_point] = self._distance[current] + 1.0
self._distance[next_point] = self._distance[current] + self._map.Visit(next_point) _ = self._map.Visit(next_point) # visit only to track visited node count
self._came_from[next_point] = current self._came_from[next_point] = current
if next_point == start_point:
# early exit - if you want to build the whole flow field, remove this
early_exit = True
break
# find actual path # find actual path
path: Path = [] path: Path = []
current = start_point current = start_point
@ -242,10 +248,22 @@ class BFS(PathFinderBase):
return path return path
class Dijkstra(PathFinderBase):
"""
Like BFS, but takes into account cost of nodes
"""
name = "Dijkstra"
def _CalculatePath(self, start_point: Point2D, end_point: Point2D) -> Optional[Path]:
...
class A_star(PathFinderBase): class A_star(PathFinderBase):
name = "A*" name = "A*"
def _CalculatePath(self, start_point: Point2D, end_point: Point2D) -> Optional[Path]:
...
# #
# Calculate paths using various methods and visualize them # Calculate paths using various methods and visualize them
# #
@ -254,12 +272,14 @@ def main():
# Define the map and start/stop points # Define the map and start/stop points
m = Map(15,10) m = Map(15,10)
m.Randomize() m.Randomize()
starting_point: Point2D = Point2D((14,8)) starting_point: Point2D = Point2D((1,1))
end_point: Point2D = Point2D((1,1)) end_point: Point2D = Point2D((5,5))
path_finder_classes: list[type[PathFinderBase]] = [ path_finder_classes: list[type[PathFinderBase]] = [
DFS, DFS,
BFS, BFS,
Dijkstra,
A_star
] ]
v = Visualizer() v = Visualizer()