import pandas as pd import matplotlib.pyplot as plt import numpy as np # Настройка русских шрифтов plt.rcParams['font.family'] = 'DejaVu Sans' plt.rcParams['axes.unicode_minus'] = False def load_and_prepare_data(filename='experiment_results.csv'): """Загрузка данных из CSV и подготовка.""" df = pd.read_csv(filename, delimiter=';') # Преобразование типов (если нужно) numeric_cols = ['avg_time_ms', 'std_time_ms', 'avg_visited', 'avg_path_len'] for col in numeric_cols: df[col] = pd.to_numeric(df[col], errors='coerce') return df def plot_time_comparison(df): """График 1: Сравнение времени выполнения по лабиринтам.""" fig, ax = plt.subplots(figsize=(12, 6)) maze_types = df['maze_type'].unique() strategies = df['strategy'].unique() x = np.arange(len(maze_types)) width = 0.2 colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728'] for i, strategy in enumerate(strategies): strategy_data = df[df['strategy'] == strategy] times = [] errors = [] for maze in maze_types: row = strategy_data[strategy_data['maze_type'] == maze] if not row.empty: times.append(row['avg_time_ms'].values[0]) errors.append(row['std_time_ms'].values[0]) else: times.append(0) errors.append(0) bars = ax.bar(x + i*width, times, width, label=strategy, color=colors[i], yerr=errors, capsize=3) ax.set_xlabel('Тип лабиринта', fontsize=12) ax.set_ylabel('Время выполнения (мс)', fontsize=12) ax.set_title('Сравнение времени выполнения алгоритмов поиска пути', fontsize=14) ax.set_xticks(x + width * 1.5) ax.set_xticklabels(maze_types, rotation=45, ha='right') ax.legend() ax.grid(True, alpha=0.3, axis='y') plt.tight_layout() plt.savefig('time_comparison.png', dpi=150) plt.show() def plot_visited_cells(df): """График 2: Количество посещённых клеток.""" fig, ax = plt.subplots(figsize=(12, 6)) maze_types = df['maze_type'].unique() strategies = df['strategy'].unique() x = np.arange(len(maze_types)) width = 0.2 for i, strategy in enumerate(strategies): strategy_data = df[df['strategy'] == strategy] visited = [] for maze in maze_types: row = strategy_data[strategy_data['maze_type'] == maze] if not row.empty: visited.append(row['avg_visited'].values[0]) else: visited.append(0) ax.bar(x + i*width, visited, width, label=strategy) ax.set_xlabel('Тип лабиринта', fontsize=12) ax.set_ylabel('Количество посещённых клеток', fontsize=12) ax.set_title('Сравнение количества посещённых клеток', fontsize=14) ax.set_xticks(x + width * 1.5) ax.set_xticklabels(maze_types, rotation=45, ha='right') ax.legend() ax.grid(True, alpha=0.3, axis='y') plt.tight_layout() plt.savefig('visited_cells.png', dpi=150) plt.show() def plot_path_length(df): """График 3: Длина найденного пути.""" fig, ax = plt.subplots(figsize=(12, 6)) # Исключаем лабиринты без выхода (где путь = 0) df_filtered = df[df['avg_path_len'] > 0] maze_types = df_filtered['maze_type'].unique() strategies = df_filtered['strategy'].unique() x = np.arange(len(maze_types)) width = 0.2 for i, strategy in enumerate(strategies): strategy_data = df_filtered[df_filtered['strategy'] == strategy] path_lengths = [] for maze in maze_types: row = strategy_data[strategy_data['maze_type'] == maze] if not row.empty: path_lengths.append(row['avg_path_len'].values[0]) else: path_lengths.append(0) ax.bar(x + i*width, path_lengths, width, label=strategy) ax.set_xlabel('Тип лабиринта', fontsize=12) ax.set_ylabel('Длина пути (количество клеток)', fontsize=12) ax.set_title('Сравнение длины найденного пути', fontsize=14) ax.set_xticks(x + width * 1.5) ax.set_xticklabels(maze_types, rotation=45, ha='right') ax.legend() ax.grid(True, alpha=0.3, axis='y') plt.tight_layout() plt.savefig('path_length.png', dpi=150) plt.show() def plot_time_per_maze(df): """График 4: Для каждого лабиринта - сравнение стратегий.""" maze_types = df['maze_type'].unique() strategies = df['strategy'].unique() for maze in maze_types: fig, ax = plt.subplots(figsize=(10, 6)) maze_data = df[df['maze_type'] == maze] times = maze_data['avg_time_ms'].values errors = maze_data['std_time_ms'].values strategy_names = maze_data['strategy'].values bars = ax.bar(strategy_names, times, yerr=errors, capsize=5, color=['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728']) ax.set_xlabel('Алгоритм', fontsize=12) ax.set_ylabel('Время выполнения (мс)', fontsize=12) ax.set_title(f'Сравнение алгоритмов на лабиринте: {maze}', fontsize=14) ax.grid(True, alpha=0.3, axis='y') # Добавление значений на столбцы for bar, time_val in zip(bars, times): height = bar.get_height() ax.text(bar.get_x() + bar.get_width()/2., height + max(errors)/2, f'{time_val:.1f}', ha='center', va='bottom', fontsize=10) plt.tight_layout() plt.savefig(f'time_{maze}.png', dpi=150) plt.show() def plot_visited_per_maze(df): """График 5: Для каждого лабиринта - посещённые клетки.""" maze_types = df['maze_type'].unique() for maze in maze_types: fig, ax = plt.subplots(figsize=(10, 6)) maze_data = df[df['maze_type'] == maze] visited = maze_data['avg_visited'].values strategy_names = maze_data['strategy'].values bars = ax.bar(strategy_names, visited, color=['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728']) ax.set_xlabel('Алгоритм', fontsize=12) ax.set_ylabel('Количество посещённых клеток', fontsize=12) ax.set_title(f'Посещённые клетки на лабиринте: {maze}', fontsize=14) ax.grid(True, alpha=0.3, axis='y') # Добавление значений на столбцы for bar, val in zip(bars, visited): height = bar.get_height() ax.text(bar.get_x() + bar.get_width()/2., height, f'{int(val)}', ha='center', va='bottom', fontsize=10) plt.tight_layout() plt.savefig(f'visited_{maze}.png', dpi=150) plt.show() def plot_efficiency_ratio(df): """График 6: Эффективность (время на клетку пути).""" fig, ax = plt.subplots(figsize=(12, 6)) # Исключаем лабиринты без пути df_filtered = df[(df['avg_path_len'] > 0) & (df['avg_time_ms'] > 0)].copy() df_filtered['efficiency'] = df_filtered['avg_time_ms'] / df_filtered['avg_path_len'] maze_types = df_filtered['maze_type'].unique() strategies = df_filtered['strategy'].unique() x = np.arange(len(maze_types)) width = 0.2 for i, strategy in enumerate(strategies): strategy_data = df_filtered[df_filtered['strategy'] == strategy] efficiency = [] for maze in maze_types: row = strategy_data[strategy_data['maze_type'] == maze] if not row.empty: efficiency.append(row['efficiency'].values[0]) else: efficiency.append(0) ax.bar(x + i*width, efficiency, width, label=strategy) ax.set_xlabel('Тип лабиринта', fontsize=12) ax.set_ylabel('Время на клетку пути (мс/клетку)', fontsize=12) ax.set_title('Эффективность алгоритмов (время на единицу длины пути)', fontsize=14) ax.set_xticks(x + width * 1.5) ax.set_xticklabels(maze_types, rotation=45, ha='right') ax.legend() ax.grid(True, alpha=0.3, axis='y') plt.tight_layout() plt.savefig('efficiency_ratio.png', dpi=150) plt.show() def main(): """Основная функция: загрузка данных и построение всех графиков.""" try: df = load_and_prepare_data('experiment_results.csv') print("Данные успешно загружены") print(f"Найдено {len(df)} записей") print("\nСтруктура данных:") print(df.head()) print("\nПостроение графиков...") # Базовые графики plot_time_comparison(df) plot_visited_cells(df) plot_path_length(df) # Детальные графики по каждому лабиринту plot_time_per_maze(df) plot_visited_per_maze(df) # Аналитические графики plot_efficiency_ratio(df) print("\nВсе графики сохранены в текущей директории:") print(" - time_comparison.png") print(" - visited_cells.png") print(" - path_length.png") print(" - time_{maze}.png (для каждого лабиринта)") print(" - visited_{maze}.png (для каждого лабиринта)") print(" - efficiency_ratio.png") print(" - summary_heatmap.png") except FileNotFoundError: print("Ошибка: файл experiment_results.csv не найден") print("Сначала запустите основной скрипт для генерации результатов") except Exception as e: print(f"Ошибка: {e}") import traceback traceback.print_exc() if __name__ == "__main__": main()