main.py added
This commit is contained in:
parent
3c644d29b0
commit
f26da8a6cc
165
svetlakovkyu/02/main.py
Normal file
165
svetlakovkyu/02/main.py
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
import csv
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "codes"))
|
||||
|
||||
from maze import TextFileMazeBuilder, MazeSolver, BFSStrategy, DFSStrategy, AStarStrategy
|
||||
from maze_generator import generate_all
|
||||
|
||||
try:
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib
|
||||
matplotlib.use("Agg")
|
||||
HAS_PLT = True
|
||||
except ImportError:
|
||||
HAS_PLT = False
|
||||
|
||||
BASE_DIR = os.path.dirname(__file__)
|
||||
MAZES_DIR = os.path.join(BASE_DIR, "mazes")
|
||||
RESULTS_DIR = os.path.join(BASE_DIR, "results")
|
||||
RUNS = 7
|
||||
|
||||
MAZE_FILES = [
|
||||
("small", "small.txt"),
|
||||
("medium", "medium.txt"),
|
||||
("large", "large.txt"),
|
||||
("empty", "empty.txt"),
|
||||
("no_exit", "no_exit.txt"),
|
||||
]
|
||||
|
||||
|
||||
def run():
|
||||
os.makedirs(RESULTS_DIR, exist_ok=True)
|
||||
|
||||
if not os.path.exists(MAZES_DIR) or not os.listdir(MAZES_DIR):
|
||||
generate_all(MAZES_DIR)
|
||||
|
||||
strategies = [BFSStrategy(), DFSStrategy(), AStarStrategy()]
|
||||
builder = TextFileMazeBuilder()
|
||||
all_results = []
|
||||
|
||||
for label, filename in MAZE_FILES:
|
||||
path = os.path.join(MAZES_DIR, filename)
|
||||
if not os.path.exists(path):
|
||||
continue
|
||||
|
||||
maze = builder.build_from_file(path)
|
||||
print(f"\nMaze: {label} ({maze.width}x{maze.height})")
|
||||
|
||||
solver = MazeSolver(maze, strategies[0])
|
||||
|
||||
for strategy in strategies:
|
||||
solver.set_strategy(strategy)
|
||||
times, visited_list, lengths = [], [], []
|
||||
|
||||
for _ in range(RUNS):
|
||||
stats = solver.solve()
|
||||
times.append(stats.time_ms)
|
||||
visited_list.append(stats.visited)
|
||||
lengths.append(stats.path_length)
|
||||
|
||||
avg_time = sum(times) / RUNS
|
||||
avg_visited = sum(visited_list) / RUNS
|
||||
avg_len = sum(lengths) / RUNS
|
||||
|
||||
found = f"length={avg_len:.0f}" if avg_len > 0 else "not found"
|
||||
print(f" {strategy.name:<6} time={avg_time:.4f} ms visited={avg_visited:.0f} {found}")
|
||||
|
||||
all_results.append({
|
||||
"maze": label,
|
||||
"strategy": strategy.name,
|
||||
"time_ms": round(avg_time, 4),
|
||||
"visited_cells": round(avg_visited, 1),
|
||||
"path_length": round(avg_len, 1),
|
||||
})
|
||||
|
||||
save_csv(all_results)
|
||||
save_plots(all_results)
|
||||
show_sample()
|
||||
print("\nDone. See results/ and docs/")
|
||||
|
||||
|
||||
def save_csv(results):
|
||||
path = os.path.join(RESULTS_DIR, "results_maze.csv")
|
||||
with open(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"\nCSV saved: {path}")
|
||||
|
||||
|
||||
def save_plots(results):
|
||||
if not HAS_PLT:
|
||||
return
|
||||
|
||||
mazes = list(dict.fromkeys(r["maze"] for r in results))
|
||||
strategies = list(dict.fromkeys(r["strategy"] for r in results))
|
||||
colors = ["#2196F3", "#FF5722", "#4CAF50"]
|
||||
|
||||
def val(maze, strat, key):
|
||||
for r in results:
|
||||
if r["maze"] == maze and r["strategy"] == strat:
|
||||
return float(r[key])
|
||||
return 0.0
|
||||
|
||||
metrics = [
|
||||
("time_ms", "Time (ms)"),
|
||||
("visited_cells", "Visited cells"),
|
||||
("path_length", "Path length"),
|
||||
]
|
||||
|
||||
fig, axes = plt.subplots(
|
||||
len(metrics), len(mazes),
|
||||
figsize=(3.5 * len(mazes), 4 * len(metrics))
|
||||
)
|
||||
|
||||
def fmt(v):
|
||||
if v == 0:
|
||||
return "0"
|
||||
if v >= 100:
|
||||
return f"{v:.0f}"
|
||||
if v >= 1:
|
||||
return f"{v:.2f}"
|
||||
return f"{v:.3f}"
|
||||
|
||||
for row_i, (key, ylabel) in enumerate(metrics):
|
||||
for col_i, maze in enumerate(mazes):
|
||||
ax = axes[row_i][col_i]
|
||||
vals = [val(maze, s, key) for s in strategies]
|
||||
bars = ax.bar(strategies, vals, color=colors[:len(strategies)])
|
||||
if row_i == 0:
|
||||
ax.set_title(maze, fontsize=9)
|
||||
if col_i == 0:
|
||||
ax.set_ylabel(ylabel)
|
||||
for bar, v in zip(bars, vals):
|
||||
ax.text(
|
||||
bar.get_x() + bar.get_width() / 2,
|
||||
bar.get_height() * 1.02,
|
||||
fmt(v), ha="center", va="bottom", fontsize=7
|
||||
)
|
||||
ax.tick_params(axis="x", labelsize=8)
|
||||
|
||||
plt.tight_layout()
|
||||
out = os.path.join(RESULTS_DIR, "benchmark_plot.png")
|
||||
plt.savefig(out, dpi=120)
|
||||
plt.close()
|
||||
print(f"Chart saved: {out}")
|
||||
|
||||
|
||||
def show_sample():
|
||||
path = os.path.join(MAZES_DIR, "sample.txt")
|
||||
if not os.path.exists(path):
|
||||
return
|
||||
builder = TextFileMazeBuilder()
|
||||
maze = builder.build_from_file(path)
|
||||
solver = MazeSolver(maze, BFSStrategy())
|
||||
stats = solver.solve()
|
||||
print("\nSample maze with BFS path:")
|
||||
print(maze.render(path=stats.path))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
Loading…
Reference in New Issue
Block a user