# experiments.py import time import csv from typing import List, Dict from maze_model import Maze from maze_builder import TextFileMazeBuilder from pathfinding_strategies import BFSStrategy, DFSStrategy, AStarStrategy from maze_solver import MazeSolver, SearchStats class ExperimentRunner: def __init__(self): self.builder = TextFileMazeBuilder() self.strategies = [ BFSStrategy(), DFSStrategy(), AStarStrategy(), ] self.results: List[Dict] = [] def create_test_maze_file(self, filename: str, maze_data: List[str]) -> None: with open(filename, 'w', encoding='utf-8') as f: f.write('\n'.join(maze_data)) def generate_simple_maze(self) -> List[str]: maze = [ "S E", " ", " ", " ", " ", " ", " ", " ", " ", " " ] return maze def generate_complex_maze(self, size: int = 50) -> List[str]: import random random.seed(42) maze = [] for y in range(size): row = [] for x in range(size): if (x == 0 and y == 0): row.append('S') elif (x == size - 1 and y == size - 1): row.append('E') elif random.random() < 0.3: # 30% стен row.append('#') else: row.append(' ') maze.append(''.join(row)) for i in range(size): if maze[i][0] == '#': row = list(maze[i]) row[0] = ' ' maze[i] = ''.join(row) if maze[0][i] == '#': row = list(maze[0]) row[i] = ' ' maze[0] = ''.join(row) return maze def generate_empty_maze(self, size: int = 50) -> List[str]: maze = [] for y in range(size): row = [] for x in range(size): if x == 0 and y == 0: row.append('S') elif x == size - 1 and y == size - 1: row.append('E') else: row.append(' ') maze.append(''.join(row)) return maze def generate_no_exit_maze(self, size: int = 20) -> List[str]: maze = [] for y in range(size): row = [] for x in range(size): if x == 0 and y == 0: row.append('S') elif x == size - 1 and y == size - 1: row.append('#') # Выход заблокирован else: row.append('#') # Всё стены maze.append(''.join(row)) # выход в тупике row = list(maze[size - 1]) row[size - 1] = 'E' maze[size - 1] = ''.join(row) return maze def run_experiment(self, maze_name: str, maze_data: List[str], num_runs: int = 5) -> List[Dict]: filename = f"test_{maze_name}.txt" self.create_test_maze_file(filename, maze_data) maze = self.builder.build_from_file(filename) results = [] for strategy in self.strategies: solver = MazeSolver(maze, strategy) times = [] path_lengths = [] for run in range(num_runs): stats = solver.solve() times.append(stats.time_ms) path_lengths.append(stats.path_length) avg_time = sum(times) / len(times) avg_path_length = sum(path_lengths) / len(path_lengths) result = { 'maze': maze_name, 'strategy': strategy.name, 'avg_time_ms': round(avg_time, 3), 'min_time_ms': round(min(times), 3), 'max_time_ms': round(max(times), 3), 'path_length': int(avg_path_length) if avg_path_length else 0, 'path_found': avg_path_length > 0 } results.append(result) print(f"{maze_name} - {strategy.name}: " f"{avg_time:.3f} мс, путь: {int(avg_path_length)}") return results def run_all_experiments(self): experiments = [ ("simple_10x10", self.generate_simple_maze()), ("complex_50x50", self.generate_complex_maze(50)), ("large_100x100", self.generate_complex_maze(100)), ("empty_50x50", self.generate_empty_maze(50)), ("no_exit_20x20", self.generate_no_exit_maze(20)) ] all_results = [] for name, data in experiments: print(f"\n Лабиринт: {name} ---") results = self.run_experiment(name, data) all_results.extend(results) self.save_to_csv(all_results, "experiment_results.csv") return all_results def save_to_csv(self, results: List[Dict], filename: str): if not results: return with open(filename, 'w', newline='', encoding='utf-8') as csvfile: fieldnames = results[0].keys() writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() writer.writerows(results) def print_analysis(results: List[Dict]): # Группировка mazes = set(r['maze'] for r in results) for maze in sorted(mazes): print(f"\nЛабиринт: {maze}") print("-" * 40) maze_results = [r for r in results if r['maze'] == maze] #по времени sorted_results = sorted(maze_results, key=lambda x: x['avg_time_ms']) for r in sorted_results: status = "✓" if r['path_found'] else "✗" print(f" {status} {r['strategy']:8} | " f"Время: {r['avg_time_ms']:8.3f} мс | " f"Путь: {r['path_length']:4} шагов") # Определяем лучший fastest = sorted_results[0] print(f"\n → Самый быстрый: {fastest['strategy']} " f"({fastest['avg_time_ms']:.3f} мс)")