forked from UNN/2026-rff_mp
[2] experimental module and plotting
This commit is contained in:
parent
641e1a8aac
commit
cb5e43f857
|
|
@ -3,6 +3,9 @@ import os
|
||||||
from collections import deque
|
from collections import deque
|
||||||
import heapq
|
import heapq
|
||||||
import time
|
import time
|
||||||
|
import csv
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
# ---------- 1. Модель клетки и лабиринта ----------
|
# ---------- 1. Модель клетки и лабиринта ----------
|
||||||
class Tile:
|
class Tile:
|
||||||
|
|
@ -343,66 +346,182 @@ class MoveAction(Action):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# ---------- 7. Главный интерактивный цикл (коммит №4) ----------
|
# ---------- 7. Экспериментальные функции ----------
|
||||||
if __name__ == "__main__":
|
def run_benchmark(maze_file, strategy, runs=5):
|
||||||
# Загружаем лабиринт (предполагается, что файл maze/maze1.txt существует)
|
|
||||||
loader = TextLabyrinthLoader()
|
loader = TextLabyrinthLoader()
|
||||||
lab = loader.load("maze/maze1.txt")
|
lab = loader.load(maze_file)
|
||||||
|
total_time = 0.0
|
||||||
|
total_visited = 0
|
||||||
|
total_len = 0
|
||||||
|
for _ in range(runs):
|
||||||
|
solver = LabyrinthSolver(lab)
|
||||||
|
solver.set_strategy(strategy)
|
||||||
|
stats = solver.solve()
|
||||||
|
if stats:
|
||||||
|
total_time += stats['time_ms']
|
||||||
|
total_visited += stats['visited']
|
||||||
|
total_len += stats['length']
|
||||||
|
return {
|
||||||
|
'time_ms': total_time / runs,
|
||||||
|
'visited': total_visited / runs,
|
||||||
|
'length': total_len / runs
|
||||||
|
}
|
||||||
|
|
||||||
player = Walker(lab.start_tile, lab)
|
|
||||||
view = ConsoleRenderer(player)
|
|
||||||
view.notify("maze_loaded", lab)
|
|
||||||
|
|
||||||
solver = LabyrinthSolver(lab)
|
def make_plots(results):
|
||||||
solver.attach(view)
|
mazes = list({r['maze'] for r in results})
|
||||||
|
algos = ['BFS', 'DFS', 'AStar']
|
||||||
|
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
|
||||||
|
x = np.arange(len(mazes))
|
||||||
|
width = 0.25
|
||||||
|
|
||||||
print("\n УПРАВЛЕНИЕ:")
|
for i, algo in enumerate(algos):
|
||||||
print(" H (влево) J (вниз) K (вверх) L (вправо)")
|
times = []
|
||||||
print(" U - отменить ход Q - выход")
|
for m in mazes:
|
||||||
print("\n АВТОПОИСК:")
|
val = next((r['time_ms'] for r in results if r['maze'] == m and r['algo'] == algo), 0)
|
||||||
print(" B - BFS D - DFS A - A*")
|
times.append(val)
|
||||||
print("\n" + "=" * 50)
|
axes[0].bar(x + i*width, times, width, label=algo)
|
||||||
|
axes[0].set_xlabel('Лабиринт')
|
||||||
|
axes[0].set_ylabel('Время (мс)')
|
||||||
|
axes[0].set_title('Сравнение времени выполнения')
|
||||||
|
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)
|
||||||
|
|
||||||
command_stack = []
|
for i, algo in enumerate(algos):
|
||||||
while True:
|
visited_vals = []
|
||||||
key = input("\n Команда > ").lower()
|
for m in mazes:
|
||||||
if key == 'q':
|
val = next((r['visited'] for r in results if r['maze'] == m and r['algo'] == algo), 0)
|
||||||
print("\n До свидания!")
|
visited_vals.append(val)
|
||||||
break
|
axes[1].bar(x + i*width, visited_vals, width, label=algo)
|
||||||
elif key == 'b':
|
axes[1].set_xlabel('Лабиринт')
|
||||||
solver.set_strategy(BFS())
|
axes[1].set_ylabel('Посещено клеток')
|
||||||
stats = solver.solve()
|
axes[1].set_title('Сравнение посещённых клеток')
|
||||||
if stats:
|
axes[1].set_xticks(x + width)
|
||||||
print(f"\n BFS: время={stats['time_ms']:.3f}мс, посещено={stats['visited']}, длина={stats['length']}")
|
axes[1].set_xticklabels(mazes, rotation=45, ha='right')
|
||||||
elif key == 'd':
|
axes[1].legend()
|
||||||
solver.set_strategy(DFS())
|
axes[1].grid(True, alpha=0.3)
|
||||||
stats = solver.solve()
|
|
||||||
print(f"\n DFS: время={stats['time_ms']:.3f}мс, посещено={stats['visited']}, длина={stats['length']}")
|
for i, algo in enumerate(algos):
|
||||||
elif key == 'a':
|
lengths = []
|
||||||
solver.set_strategy(AStar())
|
for m in mazes:
|
||||||
stats = solver.solve()
|
val = next((r['length'] for r in results if r['maze'] == m and r['algo'] == algo), 0)
|
||||||
print(f"\n A*: время={stats['time_ms']:.3f}мс, посещено={stats['visited']}, длина={stats['length']}")
|
lengths.append(val)
|
||||||
elif key in ['h', 'j', 'k', 'l']:
|
axes[2].bar(x + i*width, lengths, width, label=algo)
|
||||||
dirs = {'h': (-1,0), 'l': (1,0), 'k': (0,-1), 'j': (0,1)}
|
axes[2].set_xlabel('Лабиринт')
|
||||||
act = MoveAction(player, dirs[key][0], dirs[key][1], lab)
|
axes[2].set_ylabel('Длина пути')
|
||||||
if act.do():
|
axes[2].set_title('Сравнение длины пути')
|
||||||
command_stack.append(act)
|
axes[2].set_xticks(x + width)
|
||||||
view.notify("player_moved", lab)
|
axes[2].set_xticklabels(mazes, rotation=45, ha='right')
|
||||||
if player.current == lab.exit_tile:
|
axes[2].legend()
|
||||||
print("\n ПОЗДРАВЛЯЮ! ВЫ НАШЛИ ВЫХОД!")
|
axes[2].grid(True, alpha=0.3)
|
||||||
print(f" Сделано ходов: {len(command_stack)}")
|
|
||||||
break
|
plt.tight_layout()
|
||||||
|
plt.savefig('performance_comparison.png', dpi=150, bbox_inches='tight')
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
# ---------- 8. Главный блок ----------
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) > 1 and sys.argv[1] == 'experiment':
|
||||||
|
# Режим экспериментов
|
||||||
|
test_mazes = [
|
||||||
|
("maze/maze1.txt", "Small 10x6"),
|
||||||
|
("maze/maze10x10.txt", "Medium 10x10"),
|
||||||
|
("maze/maze20x20.txt", "Large 20x20"),
|
||||||
|
("maze/maze_empty.txt", "Empty 15x15"),
|
||||||
|
("maze/maze_no_exit.txt", "No exit 10x10")
|
||||||
|
]
|
||||||
|
strategies = [
|
||||||
|
("BFS", BFS()),
|
||||||
|
("DFS", DFS()),
|
||||||
|
("AStar", AStar())
|
||||||
|
]
|
||||||
|
results = []
|
||||||
|
for maze_path, maze_name in test_mazes:
|
||||||
|
print(f"Тестируем {maze_name}...")
|
||||||
|
for algo_name, algo in strategies:
|
||||||
|
try:
|
||||||
|
stats = run_benchmark(maze_path, algo, runs=3)
|
||||||
|
results.append({
|
||||||
|
'maze': maze_name,
|
||||||
|
'algo': algo_name,
|
||||||
|
'time_ms': stats['time_ms'],
|
||||||
|
'visited': stats['visited'],
|
||||||
|
'length': stats['length']
|
||||||
|
})
|
||||||
|
print(f" {algo_name}: время={stats['time_ms']:.3f}мс, посещено={stats['visited']:.0f}, длина={stats['length']:.0f}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" {algo_name}: ошибка - {e}")
|
||||||
|
# Сохраняем CSV
|
||||||
|
with open('experiment_results.csv', 'w', newline='', encoding='utf-8') as f:
|
||||||
|
writer = csv.DictWriter(f, fieldnames=['maze', 'algo', 'time_ms', 'visited', 'length'])
|
||||||
|
writer.writeheader()
|
||||||
|
writer.writerows(results)
|
||||||
|
# Строим графики
|
||||||
|
if results:
|
||||||
|
make_plots(results)
|
||||||
|
print("\nРезультаты сохранены в experiment_results.csv и performance_comparison.png")
|
||||||
|
else:
|
||||||
|
# Интерактивный режим
|
||||||
|
loader = TextLabyrinthLoader()
|
||||||
|
lab = loader.load("maze/maze1.txt")
|
||||||
|
|
||||||
|
player = Walker(lab.start_tile, lab)
|
||||||
|
view = ConsoleRenderer(player)
|
||||||
|
view.notify("maze_loaded", lab)
|
||||||
|
|
||||||
|
solver = LabyrinthSolver(lab)
|
||||||
|
solver.attach(view)
|
||||||
|
|
||||||
|
print("\n УПРАВЛЕНИЕ:")
|
||||||
|
print(" H (влево) J (вниз) K (вверх) L (вправо)")
|
||||||
|
print(" U - отменить ход Q - выход")
|
||||||
|
print("\n АВТОПОИСК:")
|
||||||
|
print(" B - BFS D - DFS A - A*")
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
|
||||||
|
command_stack = []
|
||||||
|
while True:
|
||||||
|
key = input("\n Команда > ").lower()
|
||||||
|
if key == 'q':
|
||||||
|
print("\n До свидания!")
|
||||||
|
break
|
||||||
|
elif key == 'b':
|
||||||
|
solver.set_strategy(BFS())
|
||||||
|
stats = solver.solve()
|
||||||
|
if stats:
|
||||||
|
print(f"\n BFS: время={stats['time_ms']:.3f}мс, посещено={stats['visited']}, длина={stats['length']}")
|
||||||
|
elif key == 'd':
|
||||||
|
solver.set_strategy(DFS())
|
||||||
|
stats = solver.solve()
|
||||||
|
print(f"\n DFS: время={stats['time_ms']:.3f}мс, посещено={stats['visited']}, длина={stats['length']}")
|
||||||
|
elif key == 'a':
|
||||||
|
solver.set_strategy(AStar())
|
||||||
|
stats = solver.solve()
|
||||||
|
print(f"\n A*: время={stats['time_ms']:.3f}мс, посещено={stats['visited']}, длина={stats['length']}")
|
||||||
|
elif key in ['h', 'j', 'k', 'l']:
|
||||||
|
dirs = {'h': (-1,0), 'l': (1,0), 'k': (0,-1), 'j': (0,1)}
|
||||||
|
act = MoveAction(player, dirs[key][0], dirs[key][1], lab)
|
||||||
|
if act.do():
|
||||||
|
command_stack.append(act)
|
||||||
|
view.notify("player_moved", lab)
|
||||||
|
if player.current == lab.exit_tile:
|
||||||
|
print("\n ПОЗДРАВЛЯЮ! ВЫ НАШЛИ ВЫХОД!")
|
||||||
|
print(f" Сделано ходов: {len(command_stack)}")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("\n Туда нельзя – стена!")
|
||||||
|
elif key == 'u':
|
||||||
|
if command_stack:
|
||||||
|
cmd = command_stack.pop()
|
||||||
|
cmd.undo()
|
||||||
|
view.notify("player_moved", lab)
|
||||||
|
print("\n Отмена последнего хода")
|
||||||
|
else:
|
||||||
|
print("\n Нечего отменять")
|
||||||
else:
|
else:
|
||||||
print("\n Туда нельзя – стена!")
|
print("\n Неизвестная команда. Используйте h,j,k,l, u, b, d, a, q")
|
||||||
elif key == 'u':
|
|
||||||
if command_stack:
|
|
||||||
cmd = command_stack.pop()
|
|
||||||
cmd.undo()
|
|
||||||
view.notify("player_moved", lab)
|
|
||||||
print("\n Отмена последнего хода")
|
|
||||||
else:
|
|
||||||
print("\n Нечего отменять")
|
|
||||||
else:
|
|
||||||
print("\n Неизвестная команда. Используйте h,j,k,l, u, b, d, a, q")
|
|
||||||
|
|
||||||
print("\n Игра окончена. Спасибо!")
|
print("\n Игра окончена. Спасибо!")
|
||||||
Loading…
Reference in New Issue
Block a user