{ "cells": [ { "cell_type": "markdown", "id": "16f8fedb-ac10-450c-b5c7-f820a985902d", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "# Pathfinding demo\n", "\n", "## List of methods\n", "\n", "Non-exhaustive list of methods follows.\n", "\n", "$V$ is the set of all vertices; $E$ is the set of all edges; $|V|$ is the size of the set\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", "2. Dijkstra\n", "3. A*" ] }, { "cell_type": "code", "execution_count": 11, "id": "fbdf9d2c-d050-4744-b559-abc71e550725", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "#\n", "# Imports\n", "#\n", "\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from typing import Protocol, Optional" ] }, { "cell_type": "code", "execution_count": 58, "id": "c704cf15-95fa-49c1-af1b-c99f7b5c8b95", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "#\n", "# Type and interfaces definition\n", "#\n", "\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", "\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", "\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", " \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", " \"\"\"\n", " Calculate path on a given map.\n", " Note: map must be set first using SetMap (or using constructor)\n", " \"\"\"\n", "\n", " def GetStats() -> (ElapsedTime_ns, VisitedNodeCount):\n", " \"\"\"\n", " Return performance stats for the last calculation:\n", " - elapsed time in nanoseconds,\n", " - number of visited nodes during search\n", " \"\"\"\n" ] }, { "cell_type": "code", "execution_count": 71, "id": "043a1f1c-a7a7-4f24-b69c-c6c809830111", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "#\n", "# Drawing utilities\n", "#\n", "\n", "class Visualizer:\n", " _axes: Optional[plt.Axes]\n", " _cmap: plt.Colormap\n", " _cmap_counter: int\n", " \n", " def __init__(self):\n", " self._axes = None\n", " self._cmap = plt.get_cmap('tab10')\n", " self._cmap_counter = 0\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", " self._axes = ax\n", "\n", " def DrawPath(self, path: Path, label: str = \"Path\"):\n", " \"\"\"\n", " Draw path on a map. Note that DrawMap has to be called first\n", " \"\"\"\n", " assert self._axes is not None, \"DrawMap must be called first\"\n", " xs, ys = zip(*path)\n", " color = self._cmap(self._cmap_counter)\n", " self._cmap_counter += 1\n", " 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", " " ] }, { "cell_type": "code", "execution_count": 79, "id": "859c64f4-e65c-4905-a775-c6f17542eac8", "metadata": {}, "outputs": [], "source": [ "#\n", "# Method: depth-first search\n", "#\n", "\n", "class DFS:\n", "\n", " name = \"Depth 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), (5,5), (6,6), (1,9)]\n", "\n", " def GetStats(self) -> (ElapsedTime_ns, VisitedNodeCount):\n", " return 150.0, 42\n", "\n", "\n", "class BFS:\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", "\n", " def GetStats(self) -> (ElapsedTime_ns, VisitedNodeCount):\n", " return 300.0, 21" ] }, { "cell_type": "code", "execution_count": 84, "id": "ece3a6c8-aa1d-49a8-9f4c-06ebff72f991", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Depth First Search : took 150.0 ns, visited 42 nodes\n", "Breadth First Search : took 300.0 ns, visited 21 nodes\n" ] }, { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "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", "\n", "#\n", "# Calculate paths using various methods and visualize them\n", "#\n", "\n", "path_finder_classes: list[PathFinder] = {\n", " DFS, BFS\n", "}\n", "\n", "v = Visualizer()\n", "v.DrawMap(m)\n", "\n", "for pt in path_finder_classes:\n", " path_finder = pt()\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" ] }, { "cell_type": "code", "execution_count": null, "id": "2ec9fb78-089d-4d51-9f16-087a04b4e8a4", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "b050caaa-d9b5-4a22-8e6d-aaccfaa4fb1b", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.7" } }, "nbformat": 4, "nbformat_minor": 5 }