324 lines
22 KiB
Plaintext
324 lines
22 KiB
Plaintext
{
|
|
"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": 85,
|
|
"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": 86,
|
|
"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": 87,
|
|
"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": 88,
|
|
"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": 89,
|
|
"id": "ece3a6c8-aa1d-49a8-9f4c-06ebff72f991",
|
|
"metadata": {
|
|
"editable": true,
|
|
"slideshow": {
|
|
"slide_type": ""
|
|
},
|
|
"tags": []
|
|
},
|
|
"outputs": [
|
|
{
|
|
"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"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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",
|
|
"text/plain": [
|
|
"<Figure size 640x480 with 1 Axes>"
|
|
]
|
|
},
|
|
"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
|
|
}
|