2026-rff_mp/SobolevNS/docs/data/task2_maze/plot_results.py

100 lines
3.8 KiB
Python
Raw Normal View History

2026-05-22 10:46:32 +00:00
"""plot_results.py - графики для эксперимента с лабиринтами."""
import csv
import os
import matplotlib.pyplot as plt
import numpy as np
CSV = "docs/data/results.csv"
PLOTS = "docs/data/plots"
os.makedirs(PLOTS, exist_ok=True)
def load_means():
"""Возвращает dict[(maze, strategy)] = (time_ms, visited, path_len, cost)."""
out = {}
with open(CSV, encoding="utf-8") as f:
rows = list(csv.reader(f))
start = next(i for i, r in enumerate(rows) if r and r[0] == "--- СРЕДНИЕ ---") + 2
for r in rows[start:]:
if not r:
continue
maze, strat, t, vis, plen, cost = r
out[(maze, strat)] = (float(t), int(vis), int(plen), int(cost))
return out
MAZES = ["small_10x10", "medium_51x51", "large_101x101",
"empty_30x30", "nopath_15x15",
"weighted_31x31", "weighted_choice"]
STRATEGIES = ["BFS", "DFS", "A*", "Dijkstra"]
COLORS = {"BFS": "#3498db", "DFS": "#e67e22", "A*": "#2ecc71", "Dijkstra": "#9b59b6"}
def grouped_bar(means, idx, ylabel, title, fname, log=True):
x = np.arange(len(MAZES))
w = 0.2
fig, ax = plt.subplots(figsize=(11, 5))
for i, s in enumerate(STRATEGIES):
vals = [means[(m, s)][idx] for m in MAZES]
bars = ax.bar(x + (i - 1.5) * w, vals, w, label=s, color=COLORS[s], alpha=0.9)
for b, v in zip(bars, vals):
ax.text(b.get_x() + b.get_width() / 2, b.get_height(),
f"{v:g}", ha="center", va="bottom", fontsize=7, rotation=0)
ax.set_xticks(x)
ax.set_xticklabels(MAZES, rotation=20, ha="right")
ax.set_ylabel(ylabel)
ax.set_title(title)
if log:
ax.set_yscale("log")
ax.legend()
ax.grid(axis="y", linestyle="--", alpha=0.4)
plt.tight_layout()
p = os.path.join(PLOTS, fname)
plt.savefig(p, dpi=130)
plt.close()
print("saved:", p)
def weighted_choice_chart(means):
"""Отдельный график для weighted_choice: путь vs стоимость."""
strategies = STRATEGIES
lengths = [means[("weighted_choice", s)][2] for s in strategies]
costs = [means[("weighted_choice", s)][3] for s in strategies]
x = np.arange(len(strategies))
w = 0.35
fig, ax = plt.subplots(figsize=(7.5, 4.5))
b1 = ax.bar(x - w/2, lengths, w, label="длина пути (клеток)",
color="#3498db", alpha=0.9)
b2 = ax.bar(x + w/2, costs, w, label="стоимость пути (сумма весов)",
color="#e74c3c", alpha=0.9)
for bars in (b1, b2):
for bar in bars:
ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height(),
f"{bar.get_height():.0f}", ha="center", va="bottom", fontsize=9)
ax.set_xticks(x); ax.set_xticklabels(strategies)
ax.set_title("weighted_choice: BFS/DFS режут через болото,\n"
"Dijkstra/A* находят более дешёвый обход")
ax.set_ylabel("значение")
ax.legend()
ax.grid(axis="y", linestyle="--", alpha=0.4)
plt.tight_layout()
p = os.path.join(PLOTS, "weighted_choice_compare.png")
plt.savefig(p, dpi=130)
plt.close()
print("saved:", p)
def main():
means = load_means()
grouped_bar(means, 0, "Время, мс (среднее по 7 запускам, лог. шкала)",
"Время поиска пути", "time_compare.png", log=True)
grouped_bar(means, 1, "Число посещённых клеток (лог. шкала)",
"Сколько клеток посетил алгоритм", "visited_compare.png", log=True)
grouped_bar(means, 2, "Длина пути (клеток)",
"Длина найденного пути", "path_compare.png", log=False)
weighted_choice_chart(means)
if __name__ == "__main__":
main()