diff --git a/python/pathfinding_demo.ipynb b/python/pathfinding_demo.ipynb index c76475c..3945409 100644 --- a/python/pathfinding_demo.ipynb +++ b/python/pathfinding_demo.ipynb @@ -13,24 +13,75 @@ "source": [ "# Pathfinding demo\n", "\n", - "## List of methods\n", + "Pathfinding is the task of finding shortest (or any) path from one point to the other [1]. Majority of practically used pathfinding methods are based on graph search, e.g. representing the map as a graph (e.g. grid of nodes covering the map) and finding (shortest) path between nodes on this graph. Edges between the nodes may have some cost, which represents length or difficulty of getting from one node to the other.\n", "\n", - "Non-exhaustive list of methods follows.\n", + "## Brief overview of methods\n", "\n", - "$V$ is the set of all vertices; $E$ is the set of all edges; $|V|$ is the size of the set\n", + "### Graph-based\n", "\n", - "1. Depth-first search\n", - " - s\n", - "1. [Bellman-Ford algorithm](https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm)\n", - " - exhaustive method\n", - " - $O(|V|*|E|)$\n", + "Before we can use graph-based search, we have to map the graph nodes and edges to the positions in the world. This may be as simple as creating regular grid, or more efficiently create nodes only in some critical points in the world map. We can also use 3D space (navmeshes in games: jumps, climbing, ...).\n", + "The less nodes there are, the faster the search. \n", + "\n", + "* Depth-first search\n", + "* Breadth-first search\n", + " * does not take the cost into account\n", + " * can be used to create flow fields and distance maps\n", + " * useful for efficiently calculating paths for many agents with one destination\n", + "* Dijkstra\n", + " * similar to BFS, but takes edge cost into account\n", + " * prioritizes search to the direction of lesser cost\n", + "* Greedy Best-First search (GBFS)\n", + " * similar to BFS, but uses some heuristic to prioritize search\n", + " * this may be e.g. manhattan distance to the destination\n", + " * may get a bit \"stuck\" if there are obstacles\n", + "* A*\n", + " * combines GBFS and Dijkstra\n", + " * priority is the sum of heuristic and the cost-so-far\n", + " * usually the best option \n", + "\n", + "There are many possible modifications and optimizations to these methods. Graph-based methods may also be combined with non-graph ones (e.g. having one unit in RTS search the path using A*, and all the other units within a group attracted to it using potential field).\n", + "\n", + "### Non-graph based\n", + "\n", + "* Gradient descent\n", + " * Optimizes paths by following the steepest descent in a potential field\n", + "* Potential field methods\n", + " * Simulate attractive forces toward goals and repulsive forces from obstacles\n", + "* Straight-line or Euclidean paths\n", + " * Simply connect points directly, often with collision checks; basic for open spaces but may require smoothing for obstacles.\n", + "\n", + "## Selecting a method\n", + "\n", + "Selecting a method depends on several factors:\n", + "\n", + "* use case\n", + " * what \"world\" are we navigating in: is it possible to represent it efficiently as a graph?\n", + " * if we do just one-off calculation, or if we intend to do that very often\n", + " * if we do \"one source, one destination\", \"one source, all destinations\", \"all sources, one destination\" or \"all sources, all destinations\" - see [this article](https://www.redblobgames.com/pathfinding/tower-defense/) \n", + " * if there are moving obstacles\n", + "* performance requirements: how fast we want to calculate the path, how often we do it\n", + "* memory requirements: some methods are more memory-intensive\n", + "\n", + "## Sources\n", + "\n", + "[[1] Wikipedia on pathfinding](https://en.wikipedia.org/wiki/Pathfinding)\n", + "\n", + "[Redblobgames](https://www.redblobgames.com/) has excellent set of articles about pathfinding and other related topics for game development.\n", + "\n", + "## List of implemented methods\n", + "\n", + "This Python demo implements few of the described methods.\n", + "\n", + "1. Breadth-first search\n", "2. Dijkstra\n", - "3. A*" + "3. Greedy Best-First search (GBFS)\n", + "4. A*\n", + "\n" ] }, { "cell_type": "code", - "execution_count": 85, + "execution_count": 7, "id": "fbdf9d2c-d050-4744-b559-abc71e550725", "metadata": { "editable": true, @@ -47,12 +98,17 @@ "\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", - "from typing import Protocol, Optional" + "import time\n", + "import random\n", + "from typing import Optional, NewType, Any\n", + "from abc import ABC, abstractmethod\n", + "from queue import Queue, PriorityQueue\n", + "from dataclasses import dataclass, field" ] }, { "cell_type": "code", - "execution_count": 86, + "execution_count": 8, "id": "c704cf15-95fa-49c1-af1b-c99f7b5c8b95", "metadata": { "editable": true, @@ -67,57 +123,104 @@ "# Type and interfaces definition\n", "#\n", "\n", - "type Point2D = tuple[int, int] # tuple(x, y)\n", + "Point2D = NewType(\"Point2D\", tuple[int, int])\n", + "# type Point2D = tuple[int, int] # tuple(x, y)\n", "type Path = list[Point2D]\n", - "type ElapsedTime_ns = float # nanoseconds\n", - "type VisitedNodeCount = int\n", "\n", "class Map:\n", " \"\"\"\n", " 2D map consisting of cells with given cost\n", " \"\"\"\n", - " array: np.array\n", + " # array not defined as private, as plotting utilities work with it directly\n", + " array: np.ndarray\n", + " _visited_nodes: int\n", "\n", " def __init__(self, width: int, height: int) -> None:\n", " assert width > 0\n", " assert height > 0\n", - " self.array = np.zeros((width, height), dtype=np.float64)\n", + " rows = height\n", + " cols = width\n", + " self.array = np.zeros((rows, cols), dtype=np.float64)\n", + " self._visited_nodes = 0\n", "\n", " def Randomize(self, low: float = 0.0, high: float = 1.0) -> None:\n", " self.array = np.random.uniform(low, high, self.array.shape)\n", "\n", - " def GetCost(self, point: Point2D) -> float:\n", - " return self.array[point]\n", - " \n", " def IsPointValid(self, point: Point2D) -> bool:\n", - " ...\n", + " x, y = point\n", + " y_max, x_max = self.array.shape\n", + " x_in_bounds = (0 <= x < x_max) \n", + " y_in_bounds = (0 <= y < y_max) \n", + " return x_in_bounds and y_in_bounds\n", " \n", - " def GetNeighbours(self) -> list[Point2D]:\n", - " ...\n", - "\n", - " \n", - "\n", - "class PathFinder(Protocol):\n", - " def SetMap(m: Map) -> None:\n", - " ...\n", - "\n", - " def CalculatePath(start: Point2D, end: Point2D) -> Path:\n", + " def GetNeighbours(self, center_point: Point2D) -> list[Point2D]:\n", " \"\"\"\n", - " Calculate path on a given map.\n", - " Note: map must be set first using SetMap (or using constructor)\n", + " Get list of neighboring points (without actually visiting them)\n", " \"\"\"\n", + " points: list[Point2D] = []\n", + " x_center, y_center = center_point\n", + " for x in range(-1,2):\n", + " for y in range(-1,2):\n", + " if x == 0 and y == 0:\n", + " continue\n", + " p = Point2D((x + x_center, y + y_center))\n", + " if self.IsPointValid(p):\n", + " points.append(p)\n", + " return points\n", + " \n", + " def GetPointCost(self, point: Point2D) -> float:\n", + " x, y = point\n", + " row, col = y, x\n", + " return self.array[(row, col)]\n", + " \n", + " def GetPathCost(self, path: Path) -> float:\n", + " return sum([self.GetPointCost(p) for p in path])\n", "\n", - " def GetStats() -> (ElapsedTime_ns, VisitedNodeCount):\n", + " def ResetVisitedCount(self) -> None:\n", + " self._visited_nodes = 0\n", + "\n", + " def GetVisitedCount(self) -> int:\n", + " return self._visited_nodes\n", + "\n", + " def Visit(self, point: Point2D) -> float:\n", " \"\"\"\n", - " Return performance stats for the last calculation:\n", - " - elapsed time in nanoseconds,\n", - " - number of visited nodes during search\n", - " \"\"\"\n" + " Visit the node and return its cost\n", + " \"\"\"\n", + " if not self.IsPointValid(point):\n", + " raise ValueError(\"Point out of bounds\")\n", + " self._visited_nodes += 1\n", + " return self.GetPointCost(point)\n", + "\n", + " def CreateMaze(self, wall_probability: float = 0.3) -> None:\n", + " \"\"\"\n", + " Note: generated with Grok\n", + " Generate a simple maze on the map.\n", + " - Borders are set as walls (cost 1000).\n", + " - Internal cells are randomly set to 1 (path) or 1000 (wall) based on wall_probability.\n", + "\n", + " Args:\n", + " wall_probability (float): Probability (0-1) that an internal cell becomes a wall.\n", + " \"\"\"\n", + " rows, cols = self.array.shape\n", + "\n", + " # Set borders to walls (cost 1000)\n", + " self.array[0, :] = 1000 # Top row\n", + " self.array[-1, :] = 1000 # Bottom row\n", + " self.array[:, 0] = 1000 # Left column\n", + " self.array[:, -1] = 1000 # Right column\n", + "\n", + " # Set internal cells randomly\n", + " for y in range(1, rows - 1): # Skip borders\n", + " for x in range(1, cols - 1):\n", + " if random.random() < wall_probability:\n", + " self.array[y, x] = 1000 # Wall\n", + " else:\n", + " self.array[y, x] = 1 # Normal tile\n" ] }, { "cell_type": "code", - "execution_count": 87, + "execution_count": 9, "id": "043a1f1c-a7a7-4f24-b69c-c6c809830111", "metadata": { "editable": true, @@ -136,19 +239,20 @@ " _axes: Optional[plt.Axes]\n", " _cmap: plt.Colormap\n", " _cmap_counter: int\n", - " \n", + "\n", " def __init__(self):\n", " self._axes = None\n", " self._cmap = plt.get_cmap('tab10')\n", " self._cmap_counter = 0\n", - " \n", + "\n", " def DrawMap(self, m: Map):\n", " M, N = m.array.shape\n", " _, ax = plt.subplots()\n", - " ax.imshow(m.array, cmap='terrain', origin='lower', interpolation='none')\n", + " ax.imshow(m.array, cmap='gist_earth', origin='lower', interpolation='none')\n", " self._axes = ax\n", "\n", " def DrawPath(self, path: Path, label: str = \"Path\"):\n", + "\n", " \"\"\"\n", " Draw path on a map. Note that DrawMap has to be called first\n", " \"\"\"\n", @@ -159,12 +263,26 @@ " self._axes.plot(xs, ys, 'o-', color=color, label=label)\n", " self._axes.plot(xs[0], ys[0], 'o', color='lime', markersize=8) # starting point\n", " self._axes.plot(xs[-1], ys[-1], 'o', color='magenta', markersize=8) # end point\n", - " " + " self._axes.legend()\n", + "\n", + "\n", + "#\n", + "# Utilities and helper classes\n", + "#\n", + "\n", + "@dataclass(order=True)\n", + "class PrioritizedItem:\n", + " \"\"\"\n", + " Helper class for wrapping items in the PriorityQueue,\n", + " so that it can compare items with priority\n", + " \"\"\"\n", + " item: Any = field(compare=False)\n", + " priority: float\n" ] }, { "cell_type": "code", - "execution_count": 88, + "execution_count": 10, "id": "859c64f4-e65c-4905-a775-c6f17542eac8", "metadata": {}, "outputs": [], @@ -173,47 +291,232 @@ "# Method: depth-first search\n", "#\n", "\n", - "class DFS:\n", + "#\n", + "# Pathfinding implementations\n", + "#\n", "\n", - " name = \"Depth First Search\"\n", + "class PathFinderBase(ABC):\n", + " name: str\n", " _map: Optional[Map]\n", - " \n", + " _elapsed_time_ns: int\n", + " _visited_node_count: int\n", + "\n", " def __init__(self) -> None:\n", " self._map = None\n", - " \n", + " self._elapsed_time_ns = 0\n", + " self._visited_node_count = 0\n", + "\n", + "\n", " def SetMap(self, m: Map) -> None:\n", " self._map = m\n", - " \n", - " def CalculatePath(self, start: Point2D, end: Point2D) -> Path:\n", - " assert m is not None, \"SetMap must be called first\"\n", - " return [(0,0), (5,5), (6,6), (1,9)]\n", "\n", - " def GetStats(self) -> (ElapsedTime_ns, VisitedNodeCount):\n", - " return 150.0, 42\n", + " def CalculatePath(self, start: Point2D, end: Point2D) -> Optional[Path]:\n", + " \"\"\"\n", + " Calculate path on a given map.\n", + " Note: map must be set first using SetMap\n", + " \"\"\"\n", + " assert self._map is not None, \"SetMap must be called first\"\n", + " self._map.ResetVisitedCount()\n", + " start_time = time.perf_counter_ns()\n", + " res = self._CalculatePath(start, end)\n", + " stop_time = time.perf_counter_ns()\n", + " self._elapsed_time_ns = stop_time - start_time\n", + " self._visited_node_count = self._map.GetVisitedCount()\n", + " return res\n", + "\n", + " @abstractmethod\n", + " def _CalculatePath(self, start: Point2D, end: Point2D) -> Optional[Path]:\n", + " \"\"\"\n", + " This method must be implemented by the derived classes\n", + " \"\"\"\n", + "\n", + " def GetStats(self) -> tuple[int, int]:\n", + " \"\"\"\n", + " Return performance stats for the last calculation:\n", + " - elapsed time in nanoseconds,\n", + " - number of visited nodes during search\n", + " \"\"\"\n", + " return self._elapsed_time_ns, self._visited_node_count\n", "\n", "\n", - "class BFS:\n", + "class BFS(PathFinderBase):\n", + " \"\"\"\n", + " Iterative breadth-first search\n", + " Finds optimal path and creates flow-field, does not take the node cost into account.\n", + " This would be good match for static maps with lots of agents with one\n", + " destination.\n", + " Compared to A*, this is more computationally expensive if we only want\n", + " to find path for one agent.\n", + " \"\"\"\n", "\n", " name = \"Breadth First Search\"\n", - " _map: Optional[Map]\n", - " \n", - " def __init__(self) -> None:\n", - " self._map = None\n", - " \n", - " def SetMap(self, m: Map) -> None:\n", - " self._map = m\n", - " \n", - " def CalculatePath(self, start: Point2D, end: Point2D) -> Path:\n", - " assert m is not None, \"SetMap must be called first\"\n", - " return [(0,0), (1,0), (2,0), (3,0)]\n", + " # flow field and distance map\n", + " _came_from: dict[Point2D, Point2D]\n", + " _distance: dict[Point2D, float]\n", "\n", - " def GetStats(self) -> (ElapsedTime_ns, VisitedNodeCount):\n", - " return 300.0, 21" + " def _CalculatePath(self, start_point: Point2D, end_point: Point2D) -> Optional[Path]:\n", + " frontier: Queue[Point2D] = Queue()\n", + " frontier.put(start_point)\n", + " self._came_from: dict[Point2D, Optional[Point2D]] = { start_point: None }\n", + " self._distance: dict[Point2D, float] = { start_point: 0.0 }\n", + "\n", + " # build flow field\n", + " early_exit = False\n", + " while not frontier.empty() and not early_exit:\n", + " current = frontier.get()\n", + " for next_point in self._map.GetNeighbours(current):\n", + " if next_point not in self._came_from:\n", + " frontier.put(next_point)\n", + " self._distance[next_point] = self._distance[current] + 1.0\n", + " _ = self._map.Visit(next_point) # visit only to track visited node count\n", + " self._came_from[next_point] = current\n", + " if next_point == end_point:\n", + " # early exit - if you want to build the whole flow field, remove this\n", + " early_exit = True\n", + " break\n", + " # find actual path\n", + " path: Path = []\n", + " current = end_point\n", + " path.append(current)\n", + " while self._came_from[current] is not None:\n", + " current = self._came_from[current]\n", + " path.append(current)\n", + " path.reverse()\n", + " return path\n", + "\n", + "\n", + "class DijkstraAlgorithm(PathFinderBase):\n", + " \"\"\"\n", + " Dijsktra's algorithm (Uniform Cost Search)\n", + " Like BFS, but takes into account cost of nodes\n", + " (priority for the search being the distance from the start)\n", + " \"\"\"\n", + "\n", + " name = \"Dijkstra's Algorithm\"\n", + "\n", + " def _CalculatePath(self, start_point: Point2D, end_point: Point2D) -> Optional[Path]:\n", + " frontier: PriorityQueue[PrioritizedItem] = PriorityQueue()\n", + " came_from: dict[Point2D, Optional[Point2D]] = {start_point: None}\n", + " cost_so_far: dict[Point2D, float] = {start_point: 0.0}\n", + "\n", + " frontier.put(PrioritizedItem(start_point, 0.0))\n", + " while not frontier.empty():\n", + " current = frontier.get().item\n", + " if current == end_point:\n", + " # early exit - remove if you want to build the whole flow map\n", + " break\n", + " for next_point in self._map.GetNeighbours(current):\n", + " new_cost = cost_so_far[current] + self._map.Visit(next_point)\n", + " if next_point not in cost_so_far or new_cost < cost_so_far[next_point]:\n", + " cost_so_far[next_point] = new_cost\n", + " priority = new_cost\n", + " frontier.put(PrioritizedItem(next_point, priority))\n", + " came_from[next_point] = current\n", + " # build the actual path\n", + " path: Path = []\n", + " current = end_point\n", + " path.append(current)\n", + " while came_from[current] is not None:\n", + " current = came_from[current]\n", + " path.append(current)\n", + " path.reverse()\n", + " return path\n", + " \n", + "\n", + "class GBFS(PathFinderBase):\n", + " \"\"\"\n", + " Like Dijsktra's Algorithm, but uses some heuristic as a priority \n", + " instead of the cost of the node\n", + " \"\"\"\n", + " \n", + " name = \"Greedy Best First Search\"\n", + "\n", + " @staticmethod\n", + " def heuristic(a: Point2D, b: Point2D) -> float:\n", + " # for now we use Manhattan distance, although\n", + " # it is probably not entirely correct, given that\n", + " # we can also move diagonally in the grid\n", + " # TODO a problem for future me\n", + " x_a, y_a = a\n", + " x_b, y_b = b\n", + " return abs(x_a - x_b) + abs(y_a - y_b)\n", + "\n", + " def _CalculatePath(self, start_point: Point2D, end_point: Point2D) -> Optional[Path]:\n", + " frontier: PriorityQueue[PrioritizedItem] = PriorityQueue()\n", + " came_from: dict[Point2D, Optional[Point2D]] = {start_point: None}\n", + " \n", + " frontier.put(PrioritizedItem(start_point, 0.0))\n", + " # create the flow field\n", + " while not frontier.empty():\n", + " current = frontier.get().item\n", + " if current == end_point:\n", + " # early exit\n", + " break\n", + " for next_point in self._map.GetNeighbours(current):\n", + " if next_point not in came_from:\n", + " priority = self.heuristic(end_point, next_point)\n", + " frontier.put(PrioritizedItem(next_point, priority))\n", + " _ = self._map.Visit(next_point) # visit only to track visited node count\n", + " came_from[next_point] = current\n", + " # create the actual path\n", + " path: Path = [end_point]\n", + " while came_from[current] is not None:\n", + " current = came_from[current]\n", + " path.append(current)\n", + " path.reverse()\n", + " return path\n", + "\n", + "\n", + "class A_star(PathFinderBase):\n", + " \"\"\"\n", + " Combines Dijsktra's Algorithm and GBFS:\n", + " priority is the sum of the heuristic and distance from the start\n", + " \"\"\"\n", + "\n", + " name = \"A*\"\n", + "\n", + " @staticmethod\n", + " def heuristic(a: Point2D, b: Point2D) -> float:\n", + " # for now we use Manhattan distance, although\n", + " # it is probably not entirely correct, given that\n", + " # we can also move diagonally in the grid\n", + " # TODO a problem for future me\n", + " x_a, y_a = a\n", + " x_b, y_b = b\n", + " return abs(x_a - x_b) + abs(y_a - y_b)\n", + "\n", + " def _CalculatePath(self, start_point: Point2D, end_point: Point2D) -> Optional[Path]:\n", + " frontier: PriorityQueue[PrioritizedItem] = PriorityQueue()\n", + " came_from: dict[Point2D, Optional[Point2D]] = { start_point: None }\n", + " cost_so_far: dict[Point2D, float] = { start_point: 0.0 }\n", + "\n", + " frontier.put(PrioritizedItem(start_point, 0.0))\n", + " while not frontier.empty():\n", + " current = frontier.get().item\n", + " if current == end_point:\n", + " # early exit\n", + " break\n", + " for next_point in self._map.GetNeighbours(current):\n", + " new_cost = cost_so_far[current] + self._map.Visit(next_point)\n", + " if next_point not in cost_so_far or new_cost < cost_so_far[next_point]:\n", + " cost_so_far[next_point] = new_cost\n", + " priority = new_cost + self.heuristic(end_point, next_point)\n", + " frontier.put(PrioritizedItem(next_point, priority))\n", + " came_from[next_point] = current\n", + " # create the actual path\n", + " path: Path = [end_point]\n", + " current = end_point\n", + " while came_from[current] is not None:\n", + " current = came_from[current]\n", + " path.append(current)\n", + " path.reverse()\n", + " return path\n", + "\n" ] }, { "cell_type": "code", - "execution_count": 89, + "execution_count": 11, "id": "ece3a6c8-aa1d-49a8-9f4c-06ebff72f991", "metadata": { "editable": true, @@ -227,13 +530,15 @@ "name": "stdout", "output_type": "stream", "text": [ - "Breadth First Search : took 300.0 ns, visited 21 nodes\n", - "Depth First Search : took 150.0 ns, visited 42 nodes\n" + "Breadth First Search : took 1.941 ms, visited 561 nodes, cost 17012.00\n", + "Dijkstra's Algorithm : took 2.708 ms, visited 2925 nodes, cost 2027.00\n", + "Greedy Best First Search: took 0.268 ms, visited 120 nodes, cost 10019.00\n", + "A* : took 0.370 ms, visited 275 nodes, cost 2028.00\n" ] }, { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -243,31 +548,34 @@ } ], "source": [ - "# Define the map and start/stop points\n", - "m = Map(10, 10)\n", - "m.Randomize()\n", - "starting_point: Point2D = (0,0)\n", - "end_point: Point2D = (9,9)\n", + " # Define the map and start/stop points\n", + "m = Map(30,20)\n", + "#m.Randomize()\n", + "m.CreateMaze()\n", + "starting_point: Point2D = Point2D((29,19))\n", + "end_point: Point2D = Point2D((1,1))\n", "\n", - "#\n", - "# Calculate paths using various methods and visualize them\n", - "#\n", - "\n", - "path_finder_classes: list[PathFinder] = {\n", - " DFS, BFS\n", - "}\n", + "path_finder_classes: list[type[PathFinderBase]] = [\n", + " BFS,\n", + " DijkstraAlgorithm,\n", + " GBFS,\n", + " A_star,\n", + "]\n", "\n", "v = Visualizer()\n", "v.DrawMap(m)\n", "\n", - "for pt in path_finder_classes:\n", - " path_finder = pt()\n", + "for pfc in path_finder_classes:\n", + " path_finder = pfc()\n", " path_finder.SetMap(m)\n", " path = path_finder.CalculatePath(starting_point, end_point)\n", " elapsed_time, visited_nodes = path_finder.GetStats()\n", - " print(f\"{path_finder.name:22}: took {elapsed_time} ns, visited {visited_nodes} nodes\")\n", - " v.DrawPath(path)\n", - "\n" + " if path is not None: \n", + " cost = m.GetPathCost(path)\n", + " print(f\"{path_finder.name:24}: took {elapsed_time/1e6:.3f} ms, visited {visited_nodes} nodes, cost {cost:.2f}\")\n", + " v.DrawPath(path, label=path_finder.name)\n", + " else:\n", + " print(f\"{path_finder.name}: No path found\")\n" ] }, {