forked from UNN/2026-rff_mp
feat: add experiment benchmarks and Facade entry point
This commit is contained in:
parent
f16b87c034
commit
59410050ca
0
lomakinae/docs/data/02/src/__init__.py
Normal file
0
lomakinae/docs/data/02/src/__init__.py
Normal file
69
lomakinae/docs/data/02/src/experiment.py
Normal file
69
lomakinae/docs/data/02/src/experiment.py
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
import csv
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Adjust sys.path to allow imports from src when run directly
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent
|
||||||
|
sys.path.append(str(BASE_DIR.parent))
|
||||||
|
|
||||||
|
from src.builder import TextFileMazeBuilder
|
||||||
|
from src.solver import MazeSolver
|
||||||
|
from src.strategies import AStarStrategy, BFSStrategy, DFSStrategy
|
||||||
|
|
||||||
|
MAZE_DIR = BASE_DIR / "mazes"
|
||||||
|
|
||||||
|
|
||||||
|
def run_benchmarks():
|
||||||
|
builder = TextFileMazeBuilder()
|
||||||
|
strategies = [
|
||||||
|
("BFS", BFSStrategy()),
|
||||||
|
("DFS", DFSStrategy()),
|
||||||
|
("A*", AStarStrategy()),
|
||||||
|
]
|
||||||
|
|
||||||
|
results = []
|
||||||
|
|
||||||
|
for maze_path in sorted(MAZE_DIR.glob("*.txt")):
|
||||||
|
maze_name = maze_path.stem
|
||||||
|
try:
|
||||||
|
maze = builder.build_from_file(maze_path)
|
||||||
|
except Exception as e:
|
||||||
|
continue
|
||||||
|
|
||||||
|
solver = MazeSolver(maze)
|
||||||
|
|
||||||
|
for strat_name, strat in strategies:
|
||||||
|
solver.set_strategy(strat)
|
||||||
|
|
||||||
|
times = []
|
||||||
|
stats = None
|
||||||
|
for _ in range(10):
|
||||||
|
stats = solver.solve()
|
||||||
|
times.append(stats.time_ms)
|
||||||
|
|
||||||
|
avg_time = sum(times) / len(times)
|
||||||
|
|
||||||
|
results.append(
|
||||||
|
{
|
||||||
|
"maze": maze_name,
|
||||||
|
"strategy": strat_name,
|
||||||
|
"time_ms": avg_time,
|
||||||
|
"visited_cells": stats.visited_cells,
|
||||||
|
"path_length": stats.path_length,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
csv_path = BASE_DIR.parent / "results.csv"
|
||||||
|
with open(csv_path, "w", newline="", encoding="utf-8") as f:
|
||||||
|
writer = csv.DictWriter(
|
||||||
|
f,
|
||||||
|
fieldnames=["maze", "strategy", "time_ms", "visited_cells", "path_length"],
|
||||||
|
)
|
||||||
|
writer.writeheader()
|
||||||
|
writer.writerows(results)
|
||||||
|
|
||||||
|
print(f"Benchmark results stored in {csv_path}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run_benchmarks()
|
||||||
13
lomakinae/docs/data/02/src/facade.py
Normal file
13
lomakinae/docs/data/02/src/facade.py
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
from .experiment import run_benchmarks
|
||||||
|
from .plots import generate_plots
|
||||||
|
|
||||||
|
|
||||||
|
class MazeTestingFacade:
|
||||||
|
def run_full_diagnostic(self):
|
||||||
|
print("Запуск экспериментов...")
|
||||||
|
run_benchmarks()
|
||||||
|
|
||||||
|
print("\nГенерация графиков...")
|
||||||
|
generate_plots()
|
||||||
|
|
||||||
|
print("\nГотово!")
|
||||||
92
lomakinae/docs/data/02/src/plots.py
Normal file
92
lomakinae/docs/data/02/src/plots.py
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
import csv
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent
|
||||||
|
|
||||||
|
|
||||||
|
def generate_plots():
|
||||||
|
csv_path = BASE_DIR.parent / "results.csv"
|
||||||
|
if not csv_path.exists():
|
||||||
|
print(f"Error: {csv_path} not found. Run experiment.py first.")
|
||||||
|
return
|
||||||
|
|
||||||
|
results = []
|
||||||
|
with open(csv_path, "r", encoding="utf-8") as f:
|
||||||
|
reader = csv.DictReader(f)
|
||||||
|
for row in reader:
|
||||||
|
results.append(
|
||||||
|
{
|
||||||
|
"maze": row["maze"],
|
||||||
|
"strategy": row["strategy"],
|
||||||
|
"time_ms": float(row["time_ms"]),
|
||||||
|
"visited_cells": int(row["visited_cells"]),
|
||||||
|
"path_length": int(row["path_length"]),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Sort mazes by requested logical order: no_exit, empty, then by size (NxN)
|
||||||
|
unique_mazes = list(dict.fromkeys(r["maze"] for r in results))
|
||||||
|
|
||||||
|
def get_sort_key(m_name):
|
||||||
|
name = m_name.lower()
|
||||||
|
if "no_exit" in name or "noexit" in name:
|
||||||
|
return 0
|
||||||
|
if "empty" in name:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
match = re.search(r"(\d+)x\d+", name)
|
||||||
|
if match:
|
||||||
|
return 100 + int(match.group(1))
|
||||||
|
|
||||||
|
return 999
|
||||||
|
|
||||||
|
maze_files_keys = sorted(unique_mazes, key=get_sort_key)
|
||||||
|
|
||||||
|
fig, axes = plt.subplots(
|
||||||
|
len(maze_files_keys), 3, figsize=(18, 3 * len(maze_files_keys))
|
||||||
|
)
|
||||||
|
|
||||||
|
for idx, maze_name in enumerate(maze_files_keys):
|
||||||
|
maze_res = [r for r in results if r["maze"] == maze_name]
|
||||||
|
if not maze_res:
|
||||||
|
continue
|
||||||
|
|
||||||
|
strats = [r["strategy"] for r in maze_res]
|
||||||
|
times = [r["time_ms"] for r in maze_res]
|
||||||
|
visited = [r["visited_cells"] for r in maze_res]
|
||||||
|
path_lens = [r["path_length"] for r in maze_res]
|
||||||
|
|
||||||
|
x = np.arange(len(strats))
|
||||||
|
|
||||||
|
# Check if axes is 1D or 2D depending on number of mazes
|
||||||
|
ax_time = axes[0] if len(maze_files_keys) == 1 else axes[idx, 0]
|
||||||
|
ax_visited = axes[1] if len(maze_files_keys) == 1 else axes[idx, 1]
|
||||||
|
ax_path = axes[2] if len(maze_files_keys) == 1 else axes[idx, 2]
|
||||||
|
|
||||||
|
ax_time.bar(x, times, color=["red", "green", "blue"])
|
||||||
|
ax_time.set_xticks(x)
|
||||||
|
ax_time.set_xticklabels(strats)
|
||||||
|
ax_time.set_title(f"{maze_name}: Execution Time (ms)")
|
||||||
|
|
||||||
|
ax_visited.bar(x, visited, color=["red", "green", "blue"])
|
||||||
|
ax_visited.set_xticks(x)
|
||||||
|
ax_visited.set_xticklabels(strats)
|
||||||
|
ax_visited.set_title(f"{maze_name}: Visited Cells")
|
||||||
|
|
||||||
|
ax_path.bar(x, path_lens, color=["red", "green", "blue"])
|
||||||
|
ax_path.set_xticks(x)
|
||||||
|
ax_path.set_xticklabels(strats)
|
||||||
|
ax_path.set_title(f"{maze_name}: Path Length")
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
chart_path = BASE_DIR.parent / "benchmark_charts.png"
|
||||||
|
plt.savefig(chart_path)
|
||||||
|
print(f"Charts exported to {chart_path}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
generate_plots()
|
||||||
Loading…
Reference in New Issue
Block a user