{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "c7d4d33a-ead6-4906-b307-e357ba0995e2", "metadata": {}, "outputs": [], "source": [ "import csv\n", "import time\n", "from typing import List, Dict, Any\n", "from modelsMaze import Maze\n", "from strategiesBfs_strategy import BFSStrategy\n", "from strategiesDfs_strategy import DFSStrategy\n", "from strategiesA_star_strategy import AStarStrategy\n", "from solverMaze_solver import MazeSolver\n", "\n", "class Benchmark:\n", " \"\"\"Экспериментальное сравнение алгоритмов.\"\"\"\n", " \n", " def __init__(self):\n", " self.strategies = [\n", " BFSStrategy(),\n", " DFSStrategy(),\n", " AStarStrategy(),\n", " ]\n", " self.results: List[Dict[str, Any]] = []\n", " \n", " def run_on_maze(self, maze: Maze, maze_name: str, iterations: int = 5) -> List[Dict]:\n", " \"\"\"Запустить все стратегии на одном лабиринте.\"\"\"\n", " results = []\n", " \n", " for strategy in self.strategies:\n", " solver = MazeSolver(maze, strategy)\n", " \n", " times = []\n", " visited_counts = []\n", " path_lengths = []\n", " path_found = False\n", " \n", " for i in range(iterations):\n", " # Сбрасываем состояние стратегии для честного замера\n", " # (кэш посещённых клеток не должен влиять)\n", " start_time = time.perf_counter()\n", " path = strategy.find_path(maze, maze.start_cell, maze.exit_cell)\n", " end_time = time.perf_counter()\n", " \n", " times.append((end_time - start_time) * 1000)\n", " visited_counts.append(getattr(strategy, 'last_visited_count', 0))\n", " path_lengths.append(len(path))\n", " path_found = len(path) > 0\n", " \n", " result = {\n", " 'maze': maze_name,\n", " 'algorithm': strategy.name,\n", " 'avg_time_ms': sum(times) / len(times),\n", " 'min_time_ms': min(times),\n", " 'max_time_ms': max(times),\n", " 'avg_visited': sum(visited_counts) / len(visited_counts),\n", " 'avg_path_length': sum(path_lengths) / len(path_lengths),\n", " 'path_found': path_found,\n", " 'iterations': iterations\n", " }\n", " results.append(result)\n", " self.results.append(result)\n", " \n", " return results\n", " \n", " def save_to_csv(self, filename: str = \"benchmark_results.csv\") -> None:\n", " \"\"\"Сохранить результаты в CSV.\"\"\"\n", " if not self.results:\n", " print(\"Нет результатов для сохранения\")\n", " return\n", " \n", " fieldnames = ['maze', 'algorithm', 'avg_time_ms', 'min_time_ms', \n", " 'max_time_ms', 'avg_visited', 'avg_path_length', \n", " 'path_found', 'iterations']\n", " \n", " with open(filename, 'w', newline='', encoding='utf-8') as f:\n", " writer = csv.DictWriter(f, fieldnames=fieldnames)\n", " writer.writeheader()\n", " writer.writerows(self.results)\n", " \n", " print(f\"Результаты сохранены в {filename}\")\n", " \n", " def print_summary(self) -> None:\n", " \"\"\"Вывести сводку результатов.\"\"\"\n", " print(\"РЕЗУЛЬТАТЫ ЭКСПЕРИМЕНТОВ\")\n", " \n", " current_maze = None\n", " for r in self.results:\n", " if r['maze'] != current_maze:\n", " current_maze = r['maze']\n", " print(f\"\\n--- Лабиринт: {current_maze} ---\")\n", " \n", " status = \" НАЙДЕН\" if r['path_found'] else \" НЕ НАЙДЕН\"\n", " print(f\" {r['algorithm']:6} | Время: {r['avg_time_ms']:8.2f} мс | \"\n", " f\"Посещено: {r['avg_visited']:8.1f} | \"\n", " f\"Путь: {r['avg_path_length']:6.1f} | {status}\")\n", " \n", " " ] } ], "metadata": { "kernelspec": { "display_name": "Python [conda env:base] *", "language": "python", "name": "conda-base-py" }, "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.9" } }, "nbformat": 4, "nbformat_minor": 5 }