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