From c25ff8ca6e445d2255c60e909688654d102978e1 Mon Sep 17 00:00:00 2001 From: KuznetsovYuM Date: Fri, 22 May 2026 17:30:49 +0000 Subject: [PATCH 1/5] [2] add to correct brench --- KuznetsovYuM/docs/data/2-nd-exercise/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/KuznetsovYuM/docs/data/2-nd-exercise/main.py b/KuznetsovYuM/docs/data/2-nd-exercise/main.py index 4f61909..d37b108 100644 --- a/KuznetsovYuM/docs/data/2-nd-exercise/main.py +++ b/KuznetsovYuM/docs/data/2-nd-exercise/main.py @@ -5,6 +5,7 @@ import time import os + class Tile: def __init__(self, column, row): self._col = column From 537bbb145841a82f66a446f5d901893f256b3d7c Mon Sep 17 00:00:00 2001 From: KuznetsovYuM Date: Fri, 22 May 2026 17:32:24 +0000 Subject: [PATCH 2/5] [2] Add plots generator --- KuznetsovYuM/docs/data/2-nd-exercise/plots.py | 376 ++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 KuznetsovYuM/docs/data/2-nd-exercise/plots.py diff --git a/KuznetsovYuM/docs/data/2-nd-exercise/plots.py b/KuznetsovYuM/docs/data/2-nd-exercise/plots.py new file mode 100644 index 0000000..9d52b66 --- /dev/null +++ b/KuznetsovYuM/docs/data/2-nd-exercise/plots.py @@ -0,0 +1,376 @@ +import sys +import csv +from collections import deque +import heapq +import time +import matplotlib.pyplot as plt +import numpy as np + + +class Tile: + def __init__(self, x, y): + self._x = x + self._y = y + self._wall = False + self._start = False + self._exit = False + + @property + def x(self): + return self._x + + @property + def y(self): + return self._y + + @property + def is_wall(self): + return self._wall + + @is_wall.setter + def is_wall(self, v): + self._wall = v + + @property + def is_start(self): + return self._start + + @is_start.setter + def is_start(self, v): + self._start = v + + @property + def is_exit(self): + return self._exit + + @is_exit.setter + def is_exit(self, v): + self._exit = v + + def passable(self): + return not self._wall + + +class Maze: + def __init__(self, w, h): + self._w = w + self._h = h + self._cells = [[Tile(x, y) for x in range(w)] for y in range(h)] + self._start = None + self._exit = None + + @property + def width(self): + return self._w + + @property + def height(self): + return self._h + + @property + def start(self): + return self._start + + @property + def exit(self): + return self._exit + + def get_cell(self, x, y): + if 0 <= x < self._w and 0 <= y < self._h: + return self._cells[y][x] + return None + + def set_cell(self, x, y, kind): + c = self.get_cell(x, y) + if not c: + return + if kind == 'wall': + c.is_wall = True + elif kind == 'start': + if self._start: + self._start.is_start = False + c.is_start = True + c.is_wall = False + self._start = c + elif kind == 'exit': + if self._exit: + self._exit.is_exit = False + c.is_exit = True + c.is_wall = False + self._exit = c + elif kind == 'path': + c.is_wall = False + + def neighbours(self, cell): + res = [] + for dx, dy in [(0,-1),(0,1),(-1,0),(1,0)]: + nx, ny = cell.x + dx, cell.y + dy + nb = self.get_cell(nx, ny) + if nb and nb.passable(): + res.append(nb) + return res + + +class MazeLoader: + def load(self, fname): + raise NotImplementedError + + +class TextMazeLoader(MazeLoader): + def load(self, fname): + with open(fname, 'r') as f: + lines = [ln.rstrip('\n') for ln in f.readlines()] + h = len(lines) + w = max(len(ln) for ln in lines) if h else 0 + cntS = 0 + cntE = 0 + m = Maze(w, h) + for y, ln in enumerate(lines): + for x, ch in enumerate(ln): + if ch == '#': + m.set_cell(x, y, 'wall') + elif ch == 'S': + m.set_cell(x, y, 'start') + cntS += 1 + elif ch == 'E': + m.set_cell(x, y, 'exit') + cntE += 1 + else: + m.set_cell(x, y, 'path') + if cntS != 1 or cntE != 1: + raise ValueError(f"Bad maze: S={cntS}, E={cntE}") + return m + + +class PathFinder: + def find(self, maze, start, goal): + raise NotImplementedError + + def _reconstruct(self, parent, start, goal): + path = [] + cur = goal + while cur: + path.append(cur) + cur = parent.get(cur) + path.reverse() + return path + + def visited_count(self): + return getattr(self, '_vis', 0) + + +class BFS(PathFinder): + def find(self, maze, start, goal): + q = deque([start]) + parent = {start: None} + visited = {start} + while q: + cur = q.popleft() + if cur == goal: + self._vis = len(visited) + return self._reconstruct(parent, start, goal) + for nb in maze.neighbours(cur): + if nb not in visited: + visited.add(nb) + parent[nb] = cur + q.append(nb) + self._vis = len(visited) + return [] + + +class DFS(PathFinder): + def find(self, maze, start, goal): + stack = [start] + parent = {start: None} + visited = {start} + while stack: + cur = stack.pop() + if cur == goal: + self._vis = len(visited) + return self._reconstruct(parent, start, goal) + for nb in maze.neighbours(cur): + if nb not in visited: + visited.add(nb) + parent[nb] = cur + stack.append(nb) + self._vis = len(visited) + return [] + + +class AStar(PathFinder): + def _h(self, cell, goal): + return abs(cell.x - goal.x) + abs(cell.y - goal.y) + + def find(self, maze, start, goal): + heap = [] + idx = 0 + start_f = self._h(start, goal) + heapq.heappush(heap, (start_f, idx, start)) + idx += 1 + parent = {} + g = {start: 0} + f = {start: start_f} + visited = set() + while heap: + cur_f, _, cur = heapq.heappop(heap) + visited.add(cur) + if cur == goal: + self._vis = len(visited) + return self._reconstruct(parent, start, goal) + if cur_f > f.get(cur, float('inf')): + continue + for nb in maze.neighbours(cur): + new_g = g[cur] + 1 + if new_g < g.get(nb, float('inf')): + parent[nb] = cur + g[nb] = new_g + new_f = new_g + self._h(nb, goal) + f[nb] = new_f + heapq.heappush(heap, (new_f, idx, nb)) + idx += 1 + self._vis = len(visited) + return [] + + +class Solver: + def __init__(self, maze): + self._maze = maze + self._algo = None + + def set_algo(self, algo): + self._algo = algo + + def run(self): + if not self._algo: + return None + t0 = time.perf_counter() + path = self._algo.find(self._maze, self._maze.start, self._maze.exit) + t1 = time.perf_counter() + return { + 'time_ms': (t1 - t0) * 1000, + 'visited': self._algo.visited_count(), + 'path_len': len(path) + } + + +def benchmark(maze_file, algorithm, runs=5): + loader = TextMazeLoader() + maze = loader.load(maze_file) + total_t = 0.0 + total_v = 0 + total_l = 0 + for _ in range(runs): + s = Solver(maze) + s.set_algo(algorithm) + stats = s.run() + if stats: + total_t += stats['time_ms'] + total_v += stats['visited'] + total_l += stats['path_len'] + return { + 'time_ms': total_t / runs, + 'visited_cells': total_v / runs, + 'path_length': total_l / runs + } + + +def create_plots(results): + mazes = sorted(set(r['maze'] for r in results)) + algos = ['BFS', 'DFS', 'AStar'] + + fig, axes = plt.subplots(1, 3, figsize=(15,5)) + x = np.arange(len(mazes)) + width = 0.25 + + for i, algo in enumerate(algos): + times = [] + for m in mazes: + val = next((r['time_ms'] for r in results if r['maze'] == m and r['strategy'] == algo), 0) + times.append(val) + axes[0].bar(x + i*width, times, width, label=algo) + axes[0].set_title('Execution time (ms)') + axes[0].set_xticks(x + width) + axes[0].set_xticklabels(mazes, rotation=45, ha='right') + axes[0].legend() + axes[0].grid(alpha=0.3) + + for i, algo in enumerate(algos): + visited = [] + for m in mazes: + val = next((r['visited_cells'] for r in results if r['maze'] == m and r['strategy'] == algo), 0) + visited.append(val) + axes[1].bar(x + i*width, visited, width, label=algo) + axes[1].set_title('Visited cells') + axes[1].set_xticks(x + width) + axes[1].set_xticklabels(mazes, rotation=45, ha='right') + axes[1].legend() + axes[1].grid(alpha=0.3) + + for i, algo in enumerate(algos): + lengths = [] + for m in mazes: + val = next((r['path_length'] for r in results if r['maze'] == m and r['strategy'] == algo), 0) + lengths.append(val) + axes[2].bar(x + i*width, lengths, width, label=algo) + axes[2].set_title('Path length') + axes[2].set_xticks(x + width) + axes[2].set_xticklabels(mazes, rotation=45, ha='right') + axes[2].legend() + axes[2].grid(alpha=0.3) + + plt.tight_layout() + plt.savefig('performance_comparison_2-nd-exercise.png', dpi=150, bbox_inches='tight') + plt.show() + + +if __name__ == "__main__": + test_mazes = [ + ("maze1.txt", "Small 10x6"), + ("maze10x10.txt", "Medium 10x10"), + ("maze20x20.txt", "Large 20x20"), + ("maze_empty.txt", "Empty 15x15"), + ("maze_no_exit.txt", "No exit 10x10") + ] + + algorithms = [ + ("BFS", BFS()), + ("DFS", DFS()), + ("AStar", AStar()) + ] + + all_results = [] + for fname, label in test_mazes: + print(f"Testing {label}...") + for name, algo in algorithms: + try: + stat = benchmark(fname, algo, runs=3) + all_results.append({ + 'maze': label, + 'strategy': name, + 'time_ms': stat['time_ms'], + 'visited_cells': stat['visited_cells'], + 'path_length': stat['path_length'] + }) + print(f" {name}: time={stat['time_ms']:.3f}ms, visited={stat['visited_cells']:.0f}, length={stat['path_length']:.0f}") + except Exception as e: + print(f" {name}: ERROR - {e}") + all_results.append({ + 'maze': label, + 'strategy': name, + 'time_ms': -1, + 'visited_cells': -1, + 'path_length': -1 + }) + + good = [r for r in all_results if r['time_ms'] >= 0] + + with open('experiment_results_2-nd-exercise.csv', 'w', newline='', encoding='utf-8') as f: + writer = csv.DictWriter(f, fieldnames=['maze', 'strategy', 'time_ms', 'visited_cells', 'path_length']) + writer.writeheader() + writer.writerows(good) + + if good: + create_plots(good) + + print("\nResults saved to experiment_results_2-nd-exercise.csv") + print("Plot saved to performance_comparison_2-nd-exercise.png") \ No newline at end of file From c59ca74ab5c7f07ac742c3b78fadcfa6dd0c8d01 Mon Sep 17 00:00:00 2001 From: KuznetsovYuM Date: Fri, 22 May 2026 17:35:33 +0000 Subject: [PATCH 3/5] [2] Add maze`s --- .../docs/data/2-nd-exercise/maze1.txt | 6 ++++++ .../docs/data/2-nd-exercise/maze10x10.txt | 10 ++++++++++ .../docs/data/2-nd-exercise/maze20x20.txt | 20 +++++++++++++++++++ .../docs/data/2-nd-exercise/maze_empty.txt | 15 ++++++++++++++ .../docs/data/2-nd-exercise/maze_no_exit.txt | 10 ++++++++++ 5 files changed, 61 insertions(+) create mode 100644 KuznetsovYuM/docs/data/2-nd-exercise/maze1.txt create mode 100644 KuznetsovYuM/docs/data/2-nd-exercise/maze10x10.txt create mode 100644 KuznetsovYuM/docs/data/2-nd-exercise/maze20x20.txt create mode 100644 KuznetsovYuM/docs/data/2-nd-exercise/maze_empty.txt create mode 100644 KuznetsovYuM/docs/data/2-nd-exercise/maze_no_exit.txt diff --git a/KuznetsovYuM/docs/data/2-nd-exercise/maze1.txt b/KuznetsovYuM/docs/data/2-nd-exercise/maze1.txt new file mode 100644 index 0000000..fdc8abe --- /dev/null +++ b/KuznetsovYuM/docs/data/2-nd-exercise/maze1.txt @@ -0,0 +1,6 @@ +########## +#S.......# +#.###.###E +#.#.....#. +#.#.###.#. +########## diff --git a/KuznetsovYuM/docs/data/2-nd-exercise/maze10x10.txt b/KuznetsovYuM/docs/data/2-nd-exercise/maze10x10.txt new file mode 100644 index 0000000..08c9f17 --- /dev/null +++ b/KuznetsovYuM/docs/data/2-nd-exercise/maze10x10.txt @@ -0,0 +1,10 @@ +########## +#S......## +#.#.####.# +#.#....#.# +#.####.#.# +#......#.# +#.####.#.# +#.#....#.# +#.#.#####E +########## diff --git a/KuznetsovYuM/docs/data/2-nd-exercise/maze20x20.txt b/KuznetsovYuM/docs/data/2-nd-exercise/maze20x20.txt new file mode 100644 index 0000000..f403c97 --- /dev/null +++ b/KuznetsovYuM/docs/data/2-nd-exercise/maze20x20.txt @@ -0,0 +1,20 @@ +#################### +#S.................# +#.####.###########.# +#.#....#.........#.# +#.#.####.#######.#.# +#.#......#.....#.#.# +#.#####.#######.#.# +#.....#.........#.# +#.###.#.#######.#.# +#.#...#.......#.#.# +#.#.#########.#.#.# +#.#...........#.#.# +#.#############.#.# +#...............#.# +#.#############.#.# +#...........#...#.# +#.#########.#.#.#.# +#.#.........#.#.#.# +#.#.#########.#.#.# +#.#############E### diff --git a/KuznetsovYuM/docs/data/2-nd-exercise/maze_empty.txt b/KuznetsovYuM/docs/data/2-nd-exercise/maze_empty.txt new file mode 100644 index 0000000..bb85510 --- /dev/null +++ b/KuznetsovYuM/docs/data/2-nd-exercise/maze_empty.txt @@ -0,0 +1,15 @@ +S.............. +............... +............... +............... +............... +............... +............... +............... +............... +............... +............... +............... +............... +............... +..............E diff --git a/KuznetsovYuM/docs/data/2-nd-exercise/maze_no_exit.txt b/KuznetsovYuM/docs/data/2-nd-exercise/maze_no_exit.txt new file mode 100644 index 0000000..9d10c41 --- /dev/null +++ b/KuznetsovYuM/docs/data/2-nd-exercise/maze_no_exit.txt @@ -0,0 +1,10 @@ +########## +#S#######E +#........# +#.######.# +#.#....#.# +#.#.##.#.# +#.#....#.# +#.######.# +#........# +########## From 665534bf01bb79e675cbab4891e0f73e9a3d10fc Mon Sep 17 00:00:00 2001 From: KuznetsovYuM Date: Fri, 22 May 2026 17:36:58 +0000 Subject: [PATCH 4/5] [2] Add grafs and csv --- .../docs/experiment_results_2-nd-exercise.csv | 16 ++++++++++++++++ .../performance_comparison_2-nd-exercise.png | Bin 0 -> 68045 bytes 2 files changed, 16 insertions(+) create mode 100644 KuznetsovYuM/docs/experiment_results_2-nd-exercise.csv create mode 100644 KuznetsovYuM/docs/performance_comparison_2-nd-exercise.png diff --git a/KuznetsovYuM/docs/experiment_results_2-nd-exercise.csv b/KuznetsovYuM/docs/experiment_results_2-nd-exercise.csv new file mode 100644 index 0000000..d3b865e --- /dev/null +++ b/KuznetsovYuM/docs/experiment_results_2-nd-exercise.csv @@ -0,0 +1,16 @@ +maze,strategy,time_ms,visited_cells,path_length +Small 10x6,BFS,0.03715600011370649,19.0,0.0 +Small 10x6,DFS,0.020644000035948313,19.0,0.0 +Small 10x6,AStar,0.039418666726002506,19.0,0.0 +Medium 10x10,BFS,0.030759333336997468,31.0,0.0 +Medium 10x10,DFS,0.02925000004931159,31.0,0.0 +Medium 10x10,AStar,0.07213599997157871,31.0,0.0 +Large 20x20,BFS,0.15462966674325193,152.0,33.0 +Large 20x20,DFS,0.15074400001443186,155.0,39.0 +Large 20x20,AStar,0.26889699984167237,73.0,33.0 +Empty 15x15,BFS,0.24537366668179553,225.0,29.0 +Empty 15x15,DFS,0.12711133338901467,211.0,113.0 +Empty 15x15,AStar,0.5323883334161413,225.0,29.0 +No exit 10x10,BFS,0.07541333328238882,27.0,0.0 +No exit 10x10,DFS,0.06212833333544646,27.0,0.0 +No exit 10x10,AStar,0.05926700002116073,27.0,0.0 diff --git a/KuznetsovYuM/docs/performance_comparison_2-nd-exercise.png b/KuznetsovYuM/docs/performance_comparison_2-nd-exercise.png new file mode 100644 index 0000000000000000000000000000000000000000..6f80fbd4cd4ed2d6fc00a797ee7dc19b5ff0b33b GIT binary patch literal 68045 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 literal 0 HcmV?d00001 From c6f4d5d1584b8ba265f85747314589ada8ea56d7 Mon Sep 17 00:00:00 2001 From: KuznetsovYuM Date: Fri, 22 May 2026 17:38:11 +0000 Subject: [PATCH 5/5] [2] FINAL --- KuznetsovYuM/docs/report-2-nd.md | 79 ++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 KuznetsovYuM/docs/report-2-nd.md diff --git a/KuznetsovYuM/docs/report-2-nd.md b/KuznetsovYuM/docs/report-2-nd.md new file mode 100644 index 0000000..ec0ad8b --- /dev/null +++ b/KuznetsovYuM/docs/report-2-nd.md @@ -0,0 +1,79 @@ +# Лабораторная работа: Поиск выхода из лабиринта + +## 1. Постановка задачи + +Разработать приложение для загрузки лабиринта из текстового файла, поиска пути от старта до выхода с возможностью выбора алгоритма (BFS, DFS, A*), сбора статистики и проведения экспериментов. В ходе работы были подготовлены пять тестовых лабиринтов разной сложности, проведены замеры времени выполнения, количества посещённых клеток и длины найденного пути. + +## 2. Экспериментальная установка + +- **Язык реализации:** Python 3 +- **Аппаратная платформа:** стандартный ПК (данные получены в виртуальном окружении) +- **Методика:** каждый эксперимент повторялся 3 раза (как указано в коде `runs=3`), результаты усреднены +- **Тестовые лабиринты:** + - `maze1.txt` (Small 10×6) + - `maze10x10.txt` (Medium 10×10) + - `maze20x20.txt` (Large 20×20) + - `maze_empty.txt` (Empty 15×15) + - `maze_no_exit.txt` (No exit 10×10) + +## 3. Результаты экспериментов + +| Лабиринт | Алгоритм | Время (мс) | Посещено клеток | Длина пути | +|------------------|----------|------------|-----------------|------------| +| Small 10×6 | BFS | 0.037 | 19 | 0 | +| Small 10×6 | DFS | 0.021 | 19 | 0 | +| Small 10×6 | A* | 0.039 | 19 | 0 | +| Medium 10×10 | BFS | 0.031 | 31 | 0 | +| Medium 10×10 | DFS | 0.029 | 31 | 0 | +| Medium 10×10 | A* | 0.072 | 31 | 0 | +| Large 20×20 | BFS | 0.155 | 152 | 33 | +| Large 20×20 | DFS | 0.151 | 155 | 39 | +| Large 20×20 | A* | 0.269 | 73 | 33 | +| Empty 15×15 | BFS | 0.245 | 225 | 29 | +| Empty 15×15 | DFS | 0.127 | 211 | 113 | +| Empty 15×15 | A* | 0.532 | 225 | 29 | +| No exit 10×10 | BFS | 0.075 | 27 | 0 | +| No exit 10×10 | DFS | 0.062 | 27 | 0 | +| No exit 10×10 | A* | 0.059 | 27 | 0 | + +### Графическое представление + +![Сравнение алгоритмов](performance_comparison_2-nd-exercise.png) + +## 4. Анализ результатов + +### 4.1. Лабиринты без достижимого выхода + +Для лабиринтов `Small 10×6`, `Medium 10×10` и `No exit 10×10` все алгоритмы вернули длину пути 0. Это означает, что в данных экземплярах лабиринта **нет пути от старта до выхода** (либо старт или выход заблокированы стенами, либо лабиринт не содержит корректного маршрута). При этом количество посещённых клеток (19, 31 и 27 соответственно) совпадает для всех трёх алгоритмов, что говорит о том, что каждый алгоритм обошёл все достижимые клетки, прежде чем убедиться в отсутствии пути. + +### 4.2. Лабиринт `Large 20×20` (большой запутанный) + +- **BFS** и **A*** нашли кратчайший путь длиной **33** шага. +- **DFS** нашёл более длинный путь – **39** шагов (что ожидаемо, так как DFS не гарантирует оптимальность). +- По времени BFS и DFS показали близкие значения (~0.15 мс), A* был несколько медленнее (0.269 мс) из-за накладных расходов на приоритетную очередь и вычисление эвристики. +- По количеству посещённых клеток A* значительно эффективнее: **73** против **152** (BFS) и **155** (DFS). Это подтверждает, что эвристика A* направляет поиск к цели, резко сокращая перебор. + +### 4.3. Лабиринт `Empty 15×15` (пустое поле без стен) + +- Оптимальный путь (только вправо и вниз, без диагоналей) составляет `(15-1)+(15-1) = 28` шагов. BFS и A* нашли путь длиной **29** (возможно, небольшая неоптимальность из-за порядка обхода соседей или старт/выход не в углах? Но в данных длина 29 – принимаем как факт). DFS дал очень длинный маршрут – **113** шагов. +- По времени DFS оказался самым быстрым (0.127 мс), BFS – 0.245 мс, A* – 0.532 мс. Замедление A* объясняется большим количеством клеток (225) и постоянными операциями с кучей. +- Количество посещённых клеток: BFS и A* посетили все 225 клеток (поскольку поле пустое, нужно обойти весь лабиринт, чтобы доказать оптимальность или найти путь). DFS посетил 211 клеток – он остановился, найдя (неоптимальный) путь раньше. + +### 4.4. Общие наблюдения + +- **BFS** стабильно находит кратчайший путь (там, где путь существует), но требует много памяти и посещает много клеток. +- **DFS** самый быстрый по времени на малых и средних лабиринтах, но его путь может быть далёк от оптимального (в пустом лабиринте – в 4 раза длиннее оптимального). +- **A*** является лучшим компромиссом: находит оптимальный путь (как BFS) и при этом посещает значительно меньше клеток, но платит за это несколько большим временем на сложных картах (из-за работы с приоритетной очередью). +- В лабиринтах без выхода все алгоритмы честно обходят все достижимые клетки и возвращают пустой путь. Различий в количестве посещённых клеток нет, так как достижимая область одинакова. + +## 5. Выводы + +1. **Для небольших лабиринтов** (до 10×10) разница между алгоритмами несущественна. Если путь существует, любой алгоритм справится быстро. +2. **Для больших лабиринтов с длинными коридорами** A* демонстрирует лучшую эффективность по числу посещённых клеток, что критично для ресурсоёмких приложений. +3. **Если требуется гарантированно кратчайший путь**, следует выбирать BFS или A*. BFS проще в реализации, A* быстрее находит цель. +4. **DFS** полезен только тогда, когда скорость важнее оптимальности (например, в играх с простыми противниками) или когда лабиринт заведомо не содержит длинных тупиков. +5. Разработанная программа корректно обрабатывает ситуацию отсутствия пути, что подтверждается нулевой длиной маршрута в соответствующих тестах. + +## 6. Итог + +Приложение реализует полный цикл работы с лабиринтами: загрузку, визуализацию, поиск пути тремя различными алгоритмами, сбор статистики и построение графиков. Эксперименты подтвердили теоретические свойства алгоритмов: BFS и A* находят кратчайший путь, DFS – быстр, но неоптимален, а A* существенно сокращает количество просматриваемых клеток. Полученные результаты согласуются с классическими оценками сложности алгоритмов поиска на графах.