104 lines
3.5 KiB
Python
104 lines
3.5 KiB
Python
import csv
|
||
import os
|
||
|
||
try:
|
||
import matplotlib.pyplot as plt
|
||
import matplotlib.patches as mpatches
|
||
HAS_MPL = True
|
||
except ImportError:
|
||
HAS_MPL = False
|
||
print("⚠️ matplotlib не установлен: pip install matplotlib\n")
|
||
|
||
CSV_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'results.csv')
|
||
OUT_DIR = os.path.dirname(os.path.abspath(__file__))
|
||
|
||
COLORS = {'BFS': '#4E9AF1', 'DFS': '#F4845F', 'A*': '#6BCB77'}
|
||
STRATEGIES = ['BFS', 'DFS', 'A*']
|
||
METRICS = [
|
||
('время_мс', 'Среднее время (мс)'),
|
||
('посещено_клеток', 'Посещено клеток'),
|
||
('длина_пути', 'Длина пути (шагов)'),
|
||
]
|
||
|
||
|
||
def load_csv(path):
|
||
data = {}
|
||
with open(path, newline='', encoding='utf-8') as f:
|
||
reader = csv.DictReader(f)
|
||
for row in reader:
|
||
key = (row['лабиринт'], row['стратегия'])
|
||
data[key] = {
|
||
'время_мс': float(row['время_мс']),
|
||
'посещено_клеток': float(row['посещено_клеток']),
|
||
'длина_пути': float(row['длина_пути']),
|
||
}
|
||
return data
|
||
|
||
|
||
def get_mazes(data):
|
||
seen = []
|
||
for (maze, _) in data:
|
||
if maze not in seen:
|
||
seen.append(maze)
|
||
return seen
|
||
|
||
|
||
def plot_by_metric(data):
|
||
mazes = get_mazes(data)
|
||
x = range(len(mazes))
|
||
w = 0.25
|
||
|
||
for metric_key, metric_label in METRICS:
|
||
fig, ax = plt.subplots(figsize=(12, 5))
|
||
fig.suptitle(f'{metric_label} по лабиринтам', fontweight='bold')
|
||
|
||
for i, strat in enumerate(STRATEGIES):
|
||
vals = [data.get((m, strat), {}).get(metric_key, 0) for m in mazes]
|
||
offset = [xi + (i - 1) * w for xi in x]
|
||
bars = ax.bar(offset, vals, width=w,
|
||
label=strat, color=COLORS[strat], edgecolor='white')
|
||
for bar, val in zip(bars, vals):
|
||
if val > 0:
|
||
ax.text(bar.get_x() + bar.get_width() / 2,
|
||
bar.get_height() + max(vals) * 0.01,
|
||
f'{val:.1f}', ha='center', va='bottom', fontsize=7)
|
||
|
||
ax.set_xticks(list(x))
|
||
ax.set_xticklabels(mazes, rotation=15, ha='right', fontsize=9)
|
||
ax.set_ylabel(metric_label)
|
||
ax.legend()
|
||
ax.grid(axis='y', alpha=0.3)
|
||
|
||
safe = metric_key.replace('_', '-')
|
||
out = os.path.join(OUT_DIR, f'chart_{safe}.png')
|
||
plt.tight_layout()
|
||
plt.savefig(out, dpi=150, bbox_inches='tight')
|
||
print(f"✅ График сохранён: {out}")
|
||
plt.show()
|
||
|
||
|
||
def print_table(data):
|
||
print(f"\n{'Лабиринт':<20} {'Алгоритм':<6} "
|
||
f"{'Время мс':>10} {'Посещено':>10} {'Путь':>6}")
|
||
print('-' * 56)
|
||
for (maze, strat), vals in sorted(data.items()):
|
||
print(f"{maze:<20} {strat:<6} "
|
||
f"{vals['время_мс']:>10.3f} "
|
||
f"{vals['посещено_клеток']:>10.0f} "
|
||
f"{vals['длина_пути']:>6.0f}")
|
||
|
||
|
||
if __name__ == '__main__':
|
||
if not os.path.exists(CSV_PATH):
|
||
print(f"❌ Файл не найден: {CSV_PATH}")
|
||
print(" Сначала запустите: python benchmark.py")
|
||
exit(1)
|
||
|
||
data = load_csv(CSV_PATH)
|
||
print_table(data)
|
||
|
||
if HAS_MPL:
|
||
plot_by_metric(data)
|
||
else:
|
||
print("\n💡 Установите matplotlib: pip install matplotlib")
|