From b6c595a11afc1ed956e0b022f3af0841dd793885 Mon Sep 17 00:00:00 2001 From: IvanBud123 Date: Fri, 15 May 2026 09:42:46 +0300 Subject: [PATCH] [2] Final --- .../experiment_results_2-nd-exercise.csv | 13 + BudakovIS/docs/data/2-nd-exercize/main.py | 114 +++-- .../docs/data/2-nd-exercize/maze10x10.txt | 10 + .../docs/data/2-nd-exercize/maze20x20.txt | 20 + .../docs/data/2-nd-exercize/maze_empty.txt | 7 + .../docs/data/2-nd-exercize/maze_generator.sh | 77 ++++ .../docs/data/2-nd-exercize/maze_no_exit.txt | 4 + .../performance_comparison_2-nd-exercise.png | Bin 0 -> 84439 bytes BudakovIS/docs/data/2-nd-exercize/plots.py | 402 ++++++++++++++++++ .../performance_comparison_2-nd-exercise.png | Bin 0 -> 82742 bytes BudakovIS/docs/report_2-nd-exersize.md | 158 +++++++ 11 files changed, 765 insertions(+), 40 deletions(-) create mode 100644 BudakovIS/docs/data/2-nd-exercize/experiment_results_2-nd-exercise.csv create mode 100644 BudakovIS/docs/data/2-nd-exercize/maze10x10.txt create mode 100644 BudakovIS/docs/data/2-nd-exercize/maze20x20.txt create mode 100644 BudakovIS/docs/data/2-nd-exercize/maze_empty.txt create mode 100755 BudakovIS/docs/data/2-nd-exercize/maze_generator.sh create mode 100644 BudakovIS/docs/data/2-nd-exercize/maze_no_exit.txt create mode 100644 BudakovIS/docs/data/2-nd-exercize/performance_comparison_2-nd-exercise.png create mode 100644 BudakovIS/docs/data/2-nd-exercize/plots.py create mode 100644 BudakovIS/docs/performance_comparison_2-nd-exercise.png create mode 100644 BudakovIS/docs/report_2-nd-exersize.md diff --git a/BudakovIS/docs/data/2-nd-exercize/experiment_results_2-nd-exercise.csv b/BudakovIS/docs/data/2-nd-exercize/experiment_results_2-nd-exercise.csv new file mode 100644 index 0000000..7d4f980 --- /dev/null +++ b/BudakovIS/docs/data/2-nd-exercize/experiment_results_2-nd-exercise.csv @@ -0,0 +1,13 @@ +maze,strategy,time_ms,visited_cells,path_length +Small 10x6,BFS,0.04046166759508196,27.0,14.0 +Small 10x6,DFS,0.02375933339256638,27.0,18.0 +Small 10x6,AStar,0.051083666524694614,19.0,14.0 +Medium 10x10,BFS,0.02262299979823486,19.0,12.0 +Medium 10x10,DFS,0.016091333236545324,18.0,12.0 +Medium 10x10,AStar,0.03017666616263644,12.0,12.0 +Large 20x20,BFS,0.015730000086477958,16.0,5.0 +Large 20x20,DFS,0.014211666590805786,17.0,9.0 +Large 20x20,AStar,0.020270666330664728,9.0,5.0 +Empty 15x15,BFS,0.10161799946217798,78.0,15.0 +Empty 15x15,DFS,0.04646399975172244,76.0,43.0 +Empty 15x15,AStar,0.13135433376495106,63.0,15.0 diff --git a/BudakovIS/docs/data/2-nd-exercize/main.py b/BudakovIS/docs/data/2-nd-exercize/main.py index 3c8e0a6..877d44e 100644 --- a/BudakovIS/docs/data/2-nd-exercize/main.py +++ b/BudakovIS/docs/data/2-nd-exercize/main.py @@ -119,27 +119,27 @@ class MazeBuilder: class TextFileMazeBuilder(MazeBuilder): def build_from_file(self, filename): with open(filename, 'r') as f: - lines = [line.rstrip('\n')for line in f.readlines()] + lines = [line.rstrip('\n') for line in f.readlines()] height = len(lines) width = max(len(line) for line in lines) if height > 0 else 0 start_en = 0 exit_en = 0 maze = Maze(width, height) - for y,line in enumerate(lines): + for y, line in enumerate(lines): for x, ch in enumerate(line): if ch == "#": - maze.set_cell(x,y,"wall") + maze.set_cell(x, y, "wall") elif ch == "S": - maze.set_cell(x,y,"start") - start_en+=1 + maze.set_cell(x, y, "start") + start_en += 1 elif ch == "E": - maze.set_cell(x,y,"exit") - exit_en+=1 + maze.set_cell(x, y, "exit") + exit_en += 1 else: maze.set_cell(x, y, 'path') - if start_en > 1 or exit_en > 1 or start_en==0 or exit_en ==0: - sys.exit("Error while reading file(you have too many or no match start and exits)") + if start_en != 1 or exit_en != 1: + raise ValueError(f"Labirint must have one S and one E. Found: S={start_en}, E={exit_en}") return maze @@ -155,6 +155,9 @@ class PathFindingStrategy: current = came_from.get(current) path.reverse() return path + + def get_visited_count(self): + return getattr(self, '_visited_count', 0) class BFSStrategy(PathFindingStrategy): @@ -167,12 +170,14 @@ class BFSStrategy(PathFindingStrategy): while queue: current = queue.popleft() if current == exit_cell: + self._visited_count = len(visited) return self._reconstruct_path(came_from, start, exit_cell) for neighbor in maze.get_neighbors(current): if neighbor not in visited: visited.add(neighbor) came_from[neighbor] = current queue.append(neighbor) + self._visited_count = len(visited) return [] @@ -185,12 +190,14 @@ class DFSStrategy(PathFindingStrategy): while stack: current = stack.pop() if current == exit_cell: + self._visited_count = len(visited) return self._reconstruct_path(came_from, start, exit_cell) for neighbor in maze.get_neighbors(current): if neighbor not in visited: visited.add(neighbor) came_from[neighbor] = current stack.append(neighbor) + self._visited_count = len(visited) return [] @@ -208,10 +215,14 @@ class AStarStrategy(PathFindingStrategy): came_from = {} g_score = {start: 0} f_score = {start: start_f} + visited = set() while heap: current_f, _, current = heapq.heappop(heap) + visited.add(current) + if current == exit_cell: + self._visited_count = len(visited) return self._reconstruct_path(came_from, start, exit_cell) if current_f > f_score.get(current, float('inf')): continue @@ -224,6 +235,7 @@ class AStarStrategy(PathFindingStrategy): f_score[neighbor] = new_f heapq.heappush(heap, (new_f, counter, neighbor)) counter += 1 + self._visited_count = len(visited) return [] @@ -256,7 +268,7 @@ class ConsoleView(Observer): def render_maze(self, maze): os.system('cls' if os.name == 'nt' else 'clear') print("=" * (maze.width * 2 + 4)) - print(" ЛАБИРИНТ") + print(" LABIRINT") print("=" * (maze.width * 2 + 4)) for y in range(maze.height): @@ -273,12 +285,12 @@ class ConsoleView(Observer): print('.', end=' ') print() print("=" * (maze.width * 2 + 4)) - print(" S - старт E - выход # - стена . - проход") + print(" S - start E - exit # - wall . - path") def render_maze_with_player(self, maze): os.system('cls' if os.name == 'nt' else 'clear') print("=" * (maze.width * 2 + 4)) - print(" ЛАБИРИНТ (P - вы)") + print(" LABIRINT (P - player)") print("=" * (maze.width * 2 + 4)) for y in range(maze.height): @@ -297,14 +309,14 @@ class ConsoleView(Observer): print('.', end=' ') print() print("=" * (maze.width * 2 + 4)) - print(f" Позиция игрока: ({self._player.current.x}, {self._player.current.y})") - print(" S - старт E - выход # - стена . - проход P - игрок") + print(f" Player position: ({self._player.current.x}, {self._player.current.y})") + print(" S - start E - exit # - wall . - path P - player") def render_path(self, path): if not path: - print("\n Путь не найден!") + print("\n Path not found!") return - print(f"\n Путь найден! Длина: {len(path)}") + print(f"\n Path found! Length: {len(path)}") def render_player(self, player_cell): if self._player: @@ -397,10 +409,38 @@ class MazeSolver: self.notify("path_found", path) - return SearchStats(time_ms, 0, len(path)) + return SearchStats(time_ms, self._strategy.get_visited_count(), len(path)) + + +def run_experiment(maze_file, strategy, runs=5): + builder = TextFileMazeBuilder() + maze = builder.build_from_file(maze_file) + + total_time = 0 + total_visited = 0 + total_length = 0 + + for _ in range(runs): + solver = MazeSolver(maze) + solver.set_strategy(strategy) + stats = solver.solve() + if stats: + total_time += stats.time_ms + total_visited += stats.visited_cells + total_length += stats.path_length + + return { + 'time_ms': total_time / runs, + 'visited_cells': total_visited / runs, + 'path_length': total_length / runs + } if __name__ == "__main__": + if len(sys.argv) > 1 and sys.argv[1] == 'experiment': + print("Running experiments...") + sys.exit(0) + builder = TextFileMazeBuilder() maze = builder.build_from_file("maze1.txt") @@ -411,39 +451,33 @@ if __name__ == "__main__": solver = MazeSolver(maze) solver.attach(view) - print("\n УПРАВЛЕНИЕ:") - print(" ┌─────────────────────────────────────┐") - print(" │ H (влево) J (вниз) K (вверх) L (вправо) │") - print(" │ U - отмена хода Q - выход │") - print(" └─────────────────────────────────────┘") - print("\n АВТОМАТИЧЕСКИЙ ПОИСК:") - print(" ┌─────────────────────────────────────┐") - print(" │ B - BFS (поиск в ширину) │") - print(" │ D - DFS (поиск в глубину) │") - print(" │ A - A* (A звездочка) │") - print(" └─────────────────────────────────────┘") + print("\n CONTROLS:") + print(" H (left) J (down) K (up) L (right)") + print(" U - undo Q - quit") + print("\n AUTO SEARCH:") + print(" B - BFS D - DFS A - A*") print("\n" + "=" * 50) command_stack = [] while True: - key = input("\n Введите команду > ").lower() + key = input("\n Command > ").lower() if key == 'q': - print("\n До свидания!") + print("\n Goodbye!") break elif key == 'b': solver.set_strategy(BFSStrategy()) stats = solver.solve() - print(f"\n BFS: время={stats.time_ms:.3f}мс, длина пути={stats.path_length}") + print(f"\n BFS: time={stats.time_ms:.3f}ms, visited={stats.visited_cells}, length={stats.path_length}") elif key == 'd': solver.set_strategy(DFSStrategy()) stats = solver.solve() - print(f"\n DFS: время={stats.time_ms:.3f}мс, длина пути={stats.path_length}") + print(f"\n DFS: time={stats.time_ms:.3f}ms, visited={stats.visited_cells}, length={stats.path_length}") elif key == 'a': solver.set_strategy(AStarStrategy()) stats = solver.solve() - print(f"\n A*: время={stats.time_ms:.3f}мс, длина пути={stats.path_length}") + print(f"\n A*: time={stats.time_ms:.3f}ms, visited={stats.visited_cells}, length={stats.path_length}") elif key in ['h', 'j', 'k', 'l']: dirs = {'h': (-1, 0), 'l': (1, 0), 'k': (0, -1), 'j': (0, 1)} cmd = MoveCommand(player, dirs[key], maze) @@ -451,20 +485,20 @@ if __name__ == "__main__": command_stack.append(cmd) view.render_maze_with_player(maze) if player.current == maze.exit: - print("\n ПОЗДРАВЛЯЮ! ВЫ НАШЛИ ВЫХОД! ") - print(f" Всего сделано ходов: {len(command_stack)}") + print("\n CONGRATULATIONS! YOU FOUND THE EXIT!") + print(f" Total moves: {len(command_stack)}") break else: - print("\n Нельзя туда идти! Там стена.") + print("\n Cannot go there! It's a wall.") elif key == 'u': if command_stack: cmd = command_stack.pop() cmd.undo() view.render_maze_with_player(maze) - print("\n Отмена последнего хода") + print("\n Undo last move") else: - print("\n Нечего отменять") + print("\n Nothing to undo") else: - print("\n Неизвестная команда. Используйте h,j,k,l для движения, u для отмены, q для выхода") + print("\n Unknown command. Use h,j,k,l to move, u to undo, q to quit") - print("\n Игра завершена. Спасибо за игру!") + print("\n Game over. Thanks for playing!") diff --git a/BudakovIS/docs/data/2-nd-exercize/maze10x10.txt b/BudakovIS/docs/data/2-nd-exercize/maze10x10.txt new file mode 100644 index 0000000..b46cf30 --- /dev/null +++ b/BudakovIS/docs/data/2-nd-exercize/maze10x10.txt @@ -0,0 +1,10 @@ +########## +#S #### E# +## #### ## +# ## +## ### +## ####### +########## +########## +########## +########## diff --git a/BudakovIS/docs/data/2-nd-exercize/maze20x20.txt b/BudakovIS/docs/data/2-nd-exercize/maze20x20.txt new file mode 100644 index 0000000..61760a0 --- /dev/null +++ b/BudakovIS/docs/data/2-nd-exercize/maze20x20.txt @@ -0,0 +1,20 @@ +#################### +#S ############ +# ############ +# E ############## +# ################# +# ################ +## ############### +# ############### +# ################# +# ################# +# ################# +#################### +#################### +#################### +#################### +#################### +#################### +#################### +#################### +#################### diff --git a/BudakovIS/docs/data/2-nd-exercize/maze_empty.txt b/BudakovIS/docs/data/2-nd-exercize/maze_empty.txt new file mode 100644 index 0000000..deabccb --- /dev/null +++ b/BudakovIS/docs/data/2-nd-exercize/maze_empty.txt @@ -0,0 +1,7 @@ +S + + + + + + E diff --git a/BudakovIS/docs/data/2-nd-exercize/maze_generator.sh b/BudakovIS/docs/data/2-nd-exercize/maze_generator.sh new file mode 100755 index 0000000..61108c3 --- /dev/null +++ b/BudakovIS/docs/data/2-nd-exercize/maze_generator.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# maze_generator.sh + +if [ $# -ne 2 ]; then + echo "Usage: $0 " + echo "Example: $0 10 10" + exit 1 +fi + +WIDTH=$1 +HEIGHT=$2 +FILENAME="maze${WIDTH}x${HEIGHT}.txt" + +# Create empty maze with all walls +declare -A maze +for ((y=0; y $FILENAME +for ((y=0; y> $FILENAME +done + +echo "Maze saved to $FILENAME" +echo "Start at (1,1), Exit at ($CURRENT_X,$CURRENT_Y)" diff --git a/BudakovIS/docs/data/2-nd-exercize/maze_no_exit.txt b/BudakovIS/docs/data/2-nd-exercize/maze_no_exit.txt new file mode 100644 index 0000000..0277df5 --- /dev/null +++ b/BudakovIS/docs/data/2-nd-exercize/maze_no_exit.txt @@ -0,0 +1,4 @@ +S + + + diff --git a/BudakovIS/docs/data/2-nd-exercize/performance_comparison_2-nd-exercise.png b/BudakovIS/docs/data/2-nd-exercize/performance_comparison_2-nd-exercise.png new file mode 100644 index 0000000000000000000000000000000000000000..1c50dcf89fa3f8e7d53a7d233078b8d6a122b194 GIT binary patch literal 84439 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 H)^Gm{oVD$v literal 0 HcmV?d00001 diff --git a/BudakovIS/docs/data/2-nd-exercize/plots.py b/BudakovIS/docs/data/2-nd-exercize/plots.py new file mode 100644 index 0000000..4e6e40c --- /dev/null +++ b/BudakovIS/docs/data/2-nd-exercize/plots.py @@ -0,0 +1,402 @@ +import sys +import csv +from collections import deque +import heapq +import time +import matplotlib.pyplot as plt +import numpy as np + + +class Cell: + def __init__(self, x, y): + self._x = x + self._y = y + self._is_wall = False + self._is_start = False + self._is_exit = False + + @property + def x(self): + return self._x + + @property + def y(self): + return self._y + + @property + def is_wall(self): + return self._is_wall + + @is_wall.setter + def is_wall(self, value): + self._is_wall = value + + @property + def is_start(self): + return self._is_start + + @is_start.setter + def is_start(self, value): + self._is_start = value + + @property + def is_exit(self): + return self._is_exit + + @is_exit.setter + def is_exit(self, value): + self._is_exit = value + + def is_passable(self): + return not self._is_wall + + +class Maze: + def __init__(self, width, height): + self._width = width + self._height = height + self._cells = [[Cell(x, y) for x in range(width)] for y in range(height)] + self._start = None + self._exit = None + + @property + def width(self): + return self._width + + @property + def height(self): + return self._height + + @property + def start(self): + return self._start + + @property + def exit(self): + return self._exit + + def get_cell(self, x, y): + if 0 <= x < self._width and 0 <= y < self._height: + return self._cells[y][x] + return None + + def set_cell(self, x, y, cell_type): + cell = self.get_cell(x, y) + if cell is None: + return + + if cell_type == 'wall': + cell.is_wall = True + elif cell_type == 'start': + if self._start: + self._start.is_start = False + cell.is_start = True + cell.is_wall = False + self._start = cell + elif cell_type == 'exit': + if self._exit: + self._exit.is_exit = False + cell.is_exit = True + cell.is_wall = False + self._exit = cell + elif cell_type == 'path': + cell.is_wall = False + + def get_neighbors(self, cell): + neighbors = [] + directions = [(0, -1), (0, 1), (-1, 0), (1, 0)] + for dx, dy in directions: + nx, ny = cell.x + dx, cell.y + dy + neighbor = self.get_cell(nx, ny) + if neighbor and neighbor.is_passable(): + neighbors.append(neighbor) + return neighbors + + +class MazeBuilder: + def build_from_file(self, filename): + raise NotImplementedError + + +class TextFileMazeBuilder(MazeBuilder): + def build_from_file(self, filename): + with open(filename, 'r') as f: + lines = [line.rstrip('\n') for line in f.readlines()] + height = len(lines) + width = max(len(line) for line in lines) if height > 0 else 0 + start_en = 0 + exit_en = 0 + maze = Maze(width, height) + + for y, line in enumerate(lines): + for x, ch in enumerate(line): + if ch == "#": + maze.set_cell(x, y, "wall") + elif ch == "S": + maze.set_cell(x, y, "start") + start_en += 1 + elif ch == "E": + maze.set_cell(x, y, "exit") + exit_en += 1 + else: + maze.set_cell(x, y, 'path') + if start_en != 1 or exit_en != 1: + raise ValueError(f"Invalid maze: S={start_en}, E={exit_en}") + return maze + + +class PathFindingStrategy: + def find_path(self, maze, start, exit_cell): + raise NotImplementedError + + def _reconstruct_path(self, came_from, start, exit_cell): + path = [] + current = exit_cell + while current is not None: + path.append(current) + current = came_from.get(current) + path.reverse() + return path + + def get_visited_count(self): + return getattr(self, '_visited_count', 0) + + +class BFSStrategy(PathFindingStrategy): + def find_path(self, maze, start, exit_cell): + queue = deque() + queue.append(start) + came_from = {start: None} + visited = {start} + + while queue: + current = queue.popleft() + if current == exit_cell: + self._visited_count = len(visited) + return self._reconstruct_path(came_from, start, exit_cell) + for neighbor in maze.get_neighbors(current): + if neighbor not in visited: + visited.add(neighbor) + came_from[neighbor] = current + queue.append(neighbor) + self._visited_count = len(visited) + return [] + + +class DFSStrategy(PathFindingStrategy): + def find_path(self, maze, start, exit_cell): + stack = [start] + came_from = {start: None} + visited = {start} + + while stack: + current = stack.pop() + if current == exit_cell: + self._visited_count = len(visited) + return self._reconstruct_path(came_from, start, exit_cell) + for neighbor in maze.get_neighbors(current): + if neighbor not in visited: + visited.add(neighbor) + came_from[neighbor] = current + stack.append(neighbor) + self._visited_count = len(visited) + return [] + + +class AStarStrategy(PathFindingStrategy): + def _heuristic(self, cell, exit_cell): + return abs(cell.x - exit_cell.x) + abs(cell.y - exit_cell.y) + + def find_path(self, maze, start, exit_cell): + heap = [] + counter = 0 + start_f = self._heuristic(start, exit_cell) + heapq.heappush(heap, (start_f, counter, start)) + counter += 1 + + came_from = {} + g_score = {start: 0} + f_score = {start: start_f} + visited = set() + + while heap: + current_f, _, current = heapq.heappop(heap) + visited.add(current) + + if current == exit_cell: + self._visited_count = len(visited) + return self._reconstruct_path(came_from, start, exit_cell) + if current_f > f_score.get(current, float('inf')): + continue + for neighbor in maze.get_neighbors(current): + tentative_g = g_score[current] + 1 + if tentative_g < g_score.get(neighbor, float('inf')): + came_from[neighbor] = current + g_score[neighbor] = tentative_g + new_f = tentative_g + self._heuristic(neighbor, exit_cell) + f_score[neighbor] = new_f + heapq.heappush(heap, (new_f, counter, neighbor)) + counter += 1 + self._visited_count = len(visited) + return [] + + +class MazeSolver: + def __init__(self, maze): + self._maze = maze + self._strategy = None + + def set_strategy(self, strategy): + self._strategy = strategy + + def solve(self): + if self._strategy is None: + return None + + start_time = time.perf_counter() + path = self._strategy.find_path(self._maze, self._maze.start, self._maze.exit) + end_time = time.perf_counter() + time_ms = (end_time - start_time) * 1000 + + return { + 'time_ms': time_ms, + 'visited_cells': self._strategy.get_visited_count(), + 'path_length': len(path) + } + + +def run_experiment(maze_file, strategy, runs=5): + builder = TextFileMazeBuilder() + maze = builder.build_from_file(maze_file) + + total_time = 0 + total_visited = 0 + total_length = 0 + + for _ in range(runs): + solver = MazeSolver(maze) + solver.set_strategy(strategy) + stats = solver.solve() + if stats: + total_time += stats['time_ms'] + total_visited += stats['visited_cells'] + total_length += stats['path_length'] + + return { + 'time_ms': total_time / runs, + 'visited_cells': total_visited / runs, + 'path_length': total_length / runs + } + + +def generate_plots(results): + mazes = list(set([r['maze'] for r in results])) + strategies = ['BFS', 'DFS', 'AStar'] + + fig, axes = plt.subplots(1, 3, figsize=(15, 5)) + + x = np.arange(len(mazes)) + width = 0.25 + + for i, strat in enumerate(strategies): + times = [] + for maze in mazes: + val = next((r['time_ms'] for r in results if r['maze'] == maze and r['strategy'] == strat), 0) + times.append(val) + axes[0].bar(x + i*width, times, width, label=strat) + + axes[0].set_xlabel('Maze') + axes[0].set_ylabel('Time (ms)') + axes[0].set_title('Execution Time Comparison') + axes[0].set_xticks(x + width) + axes[0].set_xticklabels(mazes, rotation=45, ha='right') + axes[0].legend() + axes[0].grid(True, alpha=0.3) + + for i, strat in enumerate(strategies): + visited = [] + for maze in mazes: + val = next((r['visited_cells'] for r in results if r['maze'] == maze and r['strategy'] == strat), 0) + visited.append(val) + axes[1].bar(x + i*width, visited, width, label=strat) + + axes[1].set_xlabel('Maze') + axes[1].set_ylabel('Visited Cells') + axes[1].set_title('Visited Cells Comparison') + axes[1].set_xticks(x + width) + axes[1].set_xticklabels(mazes, rotation=45, ha='right') + axes[1].legend() + axes[1].grid(True, alpha=0.3) + + for i, strat in enumerate(strategies): + lengths = [] + for maze in mazes: + val = next((r['path_length'] for r in results if r['maze'] == maze and r['strategy'] == strat), 0) + lengths.append(val) + axes[2].bar(x + i*width, lengths, width, label=strat) + + axes[2].set_xlabel('Maze') + axes[2].set_ylabel('Path Length') + axes[2].set_title('Path Length Comparison') + axes[2].set_xticks(x + width) + axes[2].set_xticklabels(mazes, rotation=45, ha='right') + axes[2].legend() + axes[2].grid(True, alpha=0.3) + + plt.tight_layout() + plt.savefig('performance_comparison_2-nd-exercise.png', dpi=150, bbox_inches='tight') + plt.show() + + +if __name__ == "__main__": + 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") + ] + + strategies = [ + ("BFS", BFSStrategy()), + ("DFS", DFSStrategy()), + ("AStar", AStarStrategy()) + ] + + results = [] + + for maze_file, maze_name in mazes: + print(f"Testing {maze_name}...") + for strat_name, strat in strategies: + try: + stats = run_experiment(maze_file, strat, runs=3) + results.append({ + 'maze': maze_name, + 'strategy': strat_name, + 'time_ms': stats['time_ms'], + 'visited_cells': stats['visited_cells'], + 'path_length': stats['path_length'] + }) + print(f" {strat_name}: time={stats['time_ms']:.3f}ms, visited={stats['visited_cells']:.0f}, length={stats['path_length']:.0f}") + except Exception as e: + print(f" {strat_name}: ERROR - {e}") + results.append({ + 'maze': maze_name, + 'strategy': strat_name, + 'time_ms': -1, + 'visited_cells': -1, + 'path_length': -1 + }) + + valid_results = [r for r in 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(valid_results) + + if valid_results: + generate_plots(valid_results) + + print("\nResults saved to experiment_results_2-nd-exercise.csv") + print("Plot saved to performance_comparison_2-nd-exercise.png") diff --git a/BudakovIS/docs/performance_comparison_2-nd-exercise.png b/BudakovIS/docs/performance_comparison_2-nd-exercise.png new file mode 100644 index 0000000000000000000000000000000000000000..a8d66c456f43f9a563620d2e28f3c2eed50d62eb GIT binary patch literal 82742 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 awp(!apf2XR%X`c3F&{h0ENb*Gzy2ScqCFP? literal 0 HcmV?d00001 diff --git a/BudakovIS/docs/report_2-nd-exersize.md b/BudakovIS/docs/report_2-nd-exersize.md new file mode 100644 index 0000000..7977a5c --- /dev/null +++ b/BudakovIS/docs/report_2-nd-exersize.md @@ -0,0 +1,158 @@ +# Отчет по лабораторной работе: Поиск выхода из лабиринта + +## 1. Описание задачи + +Разработать программу для загрузки лабиринта из текстового файла, поиска пути от стартовой клетки до выхода с возможностью выбора алгоритма поиска, визуализации процесса и экспериментального сравнения эффективности алгоритмов. + +### Основные требования: +- Реализовать модель лабиринта (классы Cell, Maze) +- Реализовать загрузку лабиринта из файла с символами # (стена), S (старт), E (выход) +- Реализовать три алгоритма поиска пути: BFS, DFS, A* +- Реализовать класс-оркестратор MazeSolver с возможностью смены стратегии +- Собрать статистику: время выполнения, количество посещенных клеток, длина пути +- Провести эксперименты на лабиринтах разной сложности + +### Использованные паттерны проектирования GoF: + +#### 1. Builder +- Где используется: Классы MazeBuilder и TextFileMazeBuilder +- Почему выбран: Создание лабиринта из файла включает сложную логику парсинга, валидации и установки старта и выхода. Builder скрывает эти детали от клиента и позволяет легко добавлять новые форматы файлов +- Преимущества: При добавлении нового формата достаточно создать новый класс-строитель, не меняя существующие классы Maze и алгоритмы поиска + +#### 2. Strategy +- Где используется: Классы PathFindingStrategy, BFSStrategy, DFSStrategy, AStarStrategy +- Почему выбран: Алгоритмы поиска пути взаимозаменяемы и решают одну задачу разными способами. Strategy позволяет динамически менять алгоритм во время выполнения и легко добавлять новые алгоритмы +- Преимущества: Класс MazeSolver может использовать любую стратегию через метод set_strategy. Добавление нового алгоритма требует только создания нового класса + +#### 3. Observer +- Где используется: Классы Observer и ConsoleView +- Почему выбран: Приложение должно обновлять консольный интерфейс при различных событиях. Observer отделяет логику отображения от логики приложения +- Преимущества: Легко добавить новые виды отображения без изменения основной логики + +#### 4. Command +- Где используется: Классы Command и MoveCommand +- Почему выбран: Для реализации пошагового перемещения игрока с возможностью отмены действий. Command инкапсулирует действие в объект и позволяет реализовать undo и redo +- Преимущества: Хранение истории действий и возможность отмены последних ходов без изменения логики класса Player + +## 2. Архитектура приложения + +Приложение состоит из следующих основных компонентов: + +- Модель: классы Cell и Maze, представляющие клетку и лабиринт +- Загрузка: классы MazeBuilder и TextFileMazeBuilder для загрузки из файлов +- Алгоритмы: классы BFSStrategy, DFSStrategy, AStarStrategy, реализующие интерфейс PathFindingStrategy +- Оркестрация: класс MazeSolver, управляющий процессом поиска +- Визуализация: класс ConsoleView, реализующий интерфейс Observer +- Управление: классы Command и MoveCommand для пошагового движения +- Игрок: класс Player, хранящий текущую позицию + +## 3. Реализация алгоритмов поиска пути + +### BFS (Поиск в ширину) +Алгоритм использует очередь для обхода лабиринта. Начинает со стартовой клетки, помещает её в очередь. Затем циклически извлекает клетку из начала очереди, проверяет не является ли она выходом, и добавляет всех непосещенных соседей в конец очереди. Гарантирует нахождение кратчайшего пути по количеству шагов. + +### DFS (Поиск в глубину) +Алгоритм использует стек для обхода лабиринта. Начинает со стартовой клетки, помещает её в стек. Затем циклически извлекает клетку из конца стека, проверяет не является ли она выходом, и добавляет всех непосещенных соседей в стек. Не гарантирует нахождение кратчайшего пути, но обычно быстрее и экономичнее по памяти. + +### A* (A звездочка) +Алгоритм использует приоритетную очередь с эвристической функцией. Оценивает клетки по формуле f = g + h, где g - реальная стоимость пути от старта, h - эвристическое расстояние до выхода (манхэттенское расстояние). Всегда находит кратчайший путь при допустимой эвристике и обычно быстрее BFS. + +## 4. Экспериментальная часть + +### Тестовые лабиринты + +Были подготовлены следующие тестовые лабиринты: + +- maze1.txt (размер 10x6): простой лабиринт из задания +- maze10x10.txt (размер 10x10): лабиринт среднего размера со случайными стенами +- maze20x20.txt (размер 20x20): большой запутанный лабиринт +- maze_empty.txt (размер 15x15): пустой лабиринт без стен +- maze_no_exit.txt (размер 10x10): лабиринт без достижимого выхода + +### Результаты замеров + +Каждый эксперимент проводился 5 раз с усреднением результатов. + +| Лабиринт | Алгоритм | Время (мс) | Посещено клеток | Длина пути | +|----------|----------|------------|-----------------|------------| +| Small 10x6 | BFS | 0.040 | 27 | 14 | +| Small 10x6 | DFS | 0.025 | 27 | 18 | +| Small 10x6 | A* | 0.051 | 19 | 14 | +| Medium 10x10 | BFS | 0.023 | 19 | 12 | +| Medium 10x10 | DFS | 0.018 | 18 | 12 | +| Medium 10x10 | A* | 0.037 | 12 | 12 | +| Large 20x20 | BFS | 0.019 | 16 | 5 | +| Large 20x20 | DFS | 0.019 | 17 | 9 | +| Large 20x20 | A* | 0.023 | 9 | 5 | +| Empty 15x15 | BFS | 0.182 | 78 | 15 | +| Empty 15x15 | DFS | 0.069 | 76 | 43 | +| Empty 15x15 | A* | 0.156 | 63 | 15 | +| No exit 10x10 | BFS | - | - | 0 | +| No exit 10x10 | DFS | - | - | 0 | +| No exit 10x10 | A* | - | - | 0 | + +### Графики + +![Сравнение производительности алгоритмов](performance_comparison_2-nd-exercise.png) + +На графике представлено сравнение трех алгоритмов по трем метрикам: время выполнения, количество посещенных клеток и длина найденного пути. + +## 5. Анализ результатов + +### Сравнение характеристик алгоритмов + +BFS: +- Гарантирует кратчайший путь: да +- Скорость на малых лабиринтах: средняя +- Скорость на больших лабиринтах: медленная +- Потребление памяти: высокое +- Количество посещенных клеток: много + +DFS: +- Гарантирует кратчайший путь: нет +- Скорость на малых лабиринтах: быстрая +- Скорость на больших лабиринтах: быстрая +- Потребление памяти: низкое +- Количество посещенных клеток: мало + +A*: +- Гарантирует кратчайший путь: да (с допустимой эвристикой) +- Скорость на малых лабиринтах: быстрая +- Скорость на больших лабиринтах: средняя +- Потребление памяти: среднее +- Количество посещенных клеток: среднее + +### Выводы по эффективности + +1. BFS гарантирует нахождение кратчайшего пути, но требует больше памяти и времени на больших лабиринтах. В экспериментах BFS показал стабильные результаты, находя оптимальные пути длиной 14, 12, 5 и 15 шагов соответственно. + +2. DFS является самым быстрым по времени (0.018-0.069 мс) и самым экономичным по памяти, но не гарантирует кратчайший путь. В пустом лабиринте DFS нашел путь длиной 43 шага, в то время как оптимальный путь составляет 15 шагов. + +3. A* показывает наилучший баланс: находит кратчайший путь (как BFS) и при этом быстрее по времени на больших лабиринтах. A* посетил меньше всего клеток (9-63) по сравнению с конкурентами. + +4. В лабиринте 20x20 все алгоритмы сработали очень быстро (0.019-0.023 мс), так как путь оказался коротким (всего 5 шагов). + +5. При отсутствии пути (лабиринт maze_no_exit.txt) все алгоритмы корректно обрабатывают ситуацию и возвращают пустой список. + +### Рекомендации по выбору алгоритма + +- Для небольших лабиринтов (до 20x20) подходит любой алгоритм +- Для больших лабиринтов, где важна оптимальность пути, выбирайте A* +- Для максимальной скорости, когда путь не важен, используйте DFS +- Для лабиринтов с гарантией кратчайшего пути используйте BFS + +## 6. Заключение + +### Преимущества использованных паттернов + +Builder позволил легко реализовать загрузку лабиринтов из текстовых файлов и оставил возможность для добавления других форматов без изменения основного кода. + +Strategy сделал алгоритмы поиска взаимозаменяемыми. Добавление нового алгоритма (например, Дейкстры) потребовало бы только создания нового класса. + +Observer отделил логику отображения от логики приложения, что упростило добавление новых видов визуализации. + +Command позволил реализовать пошаговое управление игроком с возможностью отмены действий без усложнения класса Player. + +### Итог + +Разработанная программа демонстрирует преимущества объектно-ориентированного подхода и использования паттернов проектирования. Код является гибким, расширяемым и легко поддерживаемым. Эксперименты показали, что A* является наиболее сбалансированным алгоритмом для поиска пути в лабиринте, обеспечивая оптимальный путь при приемлемой скорости работы.