Загрузить файлы в «dyachenkoas/docs/data2»

This commit is contained in:
dyachenkoas 2026-05-24 18:11:24 +00:00
parent 8353478190
commit 9ef6acffb0
3 changed files with 441 additions and 0 deletions

View File

@ -0,0 +1,16 @@
лабиринт,стратегия,время_мс,посещено_клеток,длина_пути
Empty,BFS,0.158,162,26
Empty,DFS,0.096,162,94
Empty,AStar,0.290,162,26
Large,BFS,0.194,220,75
Large,DFS,0.073,77,75
Large,AStar,0.337,216,75
Medium,BFS,0.156,179,34
Medium,DFS,0.038,44,38
Medium,AStar,0.140,85,34
No Exit,BFS,0.001,0,0
No Exit,DFS,0.000,0,0
No Exit,AStar,0.000,0,0
Small,BFS,0.022,22,16
Small,DFS,0.016,19,16
Small,AStar,0.033,21,16
1 лабиринт стратегия время_мс посещено_клеток длина_пути
2 Empty BFS 0.158 162 26
3 Empty DFS 0.096 162 94
4 Empty AStar 0.290 162 26
5 Large BFS 0.194 220 75
6 Large DFS 0.073 77 75
7 Large AStar 0.337 216 75
8 Medium BFS 0.156 179 34
9 Medium DFS 0.038 44 38
10 Medium AStar 0.140 85 34
11 No Exit BFS 0.001 0 0
12 No Exit DFS 0.000 0 0
13 No Exit AStar 0.000 0 0
14 Small BFS 0.022 22 16
15 Small DFS 0.016 19 16
16 Small AStar 0.033 21 16

View File

@ -0,0 +1,425 @@
import sys
import os
import time
import csv
from collections import deque
import heapq
import matplotlib.pyplot as plt
import numpy as np
# ========== Модель данных ==========
class Tile:
def __init__(self, x, y):
self._x = x
self._y = y
self._wall = False
self._entry = False
self._goal = False
@property
def x(self): return self._x
@property
def y(self): return self._y
@property
def is_wall(self): return self._wall
@is_wall.setter
def is_wall(self, value): self._wall = value
@property
def is_entry(self): return self._entry
@is_entry.setter
def is_entry(self, value): self._entry = value
@property
def is_goal(self): return self._goal
@is_goal.setter
def is_goal(self, value): self._goal = value
def can_walk(self):
return not self._wall
class Labyrinth:
def __init__(self, width, height):
self._width = width
self._height = height
self._grid = [[Tile(x, y) for x in range(width)] for y in range(height)]
self._start = None
self._exit = None
@property
def width(self): return self._width
@property
def height(self): return self._height
@property
def start(self): return self._start
@property
def exit(self): return self._exit
def tile_at(self, x, y):
if 0 <= x < self._width and 0 <= y < self._height:
return self._grid[y][x]
return None
def configure_tile(self, x, y, kind):
tile = self.tile_at(x, y)
if tile is None:
return
if kind == 'wall':
tile.is_wall = True
elif kind == 'entry':
if self._start:
self._start.is_entry = False
tile.is_entry = True
tile.is_wall = False
self._start = tile
elif kind == 'goal':
if self._exit:
self._exit.is_goal = False
tile.is_goal = True
tile.is_wall = False
self._exit = tile
elif kind == 'floor':
tile.is_wall = False
def neighbours(self, tile):
res = []
for dx, dy in ((0, -1), (0, 1), (-1, 0), (1, 0)):
nb = self.tile_at(tile.x + dx, tile.y + dy)
if nb and nb.can_walk():
res.append(nb)
return res
# ========== Загрузка из файла ==========
class TextLabyrinthBuilder:
def build(self, filename):
with open(filename, 'r', encoding='utf-8') as f:
lines = [line.rstrip('\n') for line in f]
h = len(lines)
w = max(len(l) for l in lines) if h else 0
lab = Labyrinth(w, h)
for y, row in enumerate(lines):
for x, ch in enumerate(row):
if ch == '#':
lab.configure_tile(x, y, 'wall')
elif ch == 'S':
lab.configure_tile(x, y, 'entry')
elif ch == 'E':
lab.configure_tile(x, y, 'goal')
elif ch == ' ':
lab.configure_tile(x, y, 'floor')
return lab
# ========== Алгоритмы поиска ==========
class BFS_Pathfinder:
def find_path(self, lab, start, goal):
if goal is None:
self._visited = 0
return []
q = deque([start])
preds = {start: None}
seen = {start}
while q:
cur = q.popleft()
if cur == goal:
self._visited = len(seen)
return self._build_path(preds, start, goal)
for nb in lab.neighbours(cur):
if nb not in seen:
seen.add(nb)
preds[nb] = cur
q.append(nb)
self._visited = len(seen)
return []
def _build_path(self, preds, start, goal):
path = []
cur = goal
while cur is not None:
path.append(cur)
cur = preds.get(cur)
path.reverse()
return path
@property
def visited_count(self):
return getattr(self, '_visited', 0)
class DFS_Pathfinder:
def find_path(self, lab, start, goal):
if goal is None:
self._visited = 0
return []
stack = [start]
preds = {start: None}
seen = {start}
while stack:
cur = stack.pop()
if cur == goal:
self._visited = len(seen)
return self._build_path(preds, start, goal)
for nb in lab.neighbours(cur):
if nb not in seen:
seen.add(nb)
preds[nb] = cur
stack.append(nb)
self._visited = len(seen)
return []
def _build_path(self, preds, start, goal):
path = []
cur = goal
while cur is not None:
path.append(cur)
cur = preds.get(cur)
path.reverse()
return path
@property
def visited_count(self):
return getattr(self, '_visited', 0)
class AStar_Pathfinder:
def _heuristic(self, a, b):
return abs(a.x - b.x) + abs(a.y - b.y)
def find_path(self, lab, start, goal):
if goal is None:
self._visited = 0
return []
heap = []
cnt = 0
f_start = self._heuristic(start, goal)
heapq.heappush(heap, (f_start, cnt, start))
cnt += 1
preds = {}
g = {start: 0}
f = {start: f_start}
seen = set()
while heap:
cur_f, _, cur = heapq.heappop(heap)
seen.add(cur)
if cur == goal:
self._visited = len(seen)
return self._build_path(preds, start, goal)
if cur_f > f.get(cur, float('inf')):
continue
for nb in lab.neighbours(cur):
tent_g = g[cur] + 1
if tent_g < g.get(nb, float('inf')):
preds[nb] = cur
g[nb] = tent_g
new_f = tent_g + self._heuristic(nb, goal)
f[nb] = new_f
heapq.heappush(heap, (new_f, cnt, nb))
cnt += 1
self._visited = len(seen)
return []
def _build_path(self, preds, start, goal):
path = []
cur = goal
while cur is not None:
path.append(cur)
cur = preds.get(cur)
path.reverse()
return path
@property
def visited_count(self):
return getattr(self, '_visited', 0)
class LabyrinthSolver:
def __init__(self, lab):
self._lab = lab
self._strategy = None
def set_strategy(self, strategy):
self._strategy = strategy
def solve(self):
start_t = time.perf_counter()
path = self._strategy.find_path(self._lab, self._lab.start, self._lab.exit)
elapsed = (time.perf_counter() - start_t) * 1000
return {
'time_ms': elapsed,
'visited': self._strategy.visited_count,
'length': len(path)
}
# ========== Графики ==========
def create_charts(results, save_filename='maze_performance.png'):
mazes = list(set([r['maze'] for r in results]))
strategies = ['BFS', 'DFS', 'AStar']
data = {s: {m: None for m in mazes} for s in strategies}
for r in results:
data[r['strategy']][r['maze']] = r
times = {s: [data[s][m]['time_ms'] for m in mazes] for s in strategies}
visited = {s: [data[s][m]['visited_cells'] for m in mazes] for s in strategies}
lengths = {s: [data[s][m]['path_length'] for m in mazes] for s in strategies}
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
x = np.arange(len(mazes))
width = 0.25
# Время
axes[0].bar(x - width, times['BFS'], width, label='BFS', color='blue', alpha=0.7)
axes[0].bar(x, times['DFS'], width, label='DFS', color='green', alpha=0.7)
axes[0].bar(x + width, times['AStar'], width, label='A*', color='red', alpha=0.7)
axes[0].set_xlabel('Лабиринты')
axes[0].set_ylabel('Время (мс)')
axes[0].set_title('Время выполнения алгоритмов')
axes[0].set_xticks(x)
axes[0].set_xticklabels(mazes, rotation=15, ha='right', fontsize=8)
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# Посещённые клетки
axes[1].bar(x - width, visited['BFS'], width, label='BFS', color='blue', alpha=0.7)
axes[1].bar(x, visited['DFS'], width, label='DFS', color='green', alpha=0.7)
axes[1].bar(x + width, visited['AStar'], width, label='A*', color='red', alpha=0.7)
axes[1].set_xlabel('Лабиринты')
axes[1].set_ylabel('Количество клеток')
axes[1].set_title('Посещённые клетки')
axes[1].set_xticks(x)
axes[1].set_xticklabels(mazes, rotation=15, ha='right', fontsize=8)
axes[1].legend()
axes[1].grid(True, alpha=0.3)
# Длина пути
axes[2].bar(x - width, lengths['BFS'], width, label='BFS', color='blue', alpha=0.7)
axes[2].bar(x, lengths['DFS'], width, label='DFS', color='green', alpha=0.7)
axes[2].bar(x + width, lengths['AStar'], width, label='A*', color='red', alpha=0.7)
axes[2].set_xlabel('Лабиринты')
axes[2].set_ylabel('Длина пути')
axes[2].set_title('Длина найденного пути')
axes[2].set_xticks(x)
axes[2].set_xticklabels(mazes, rotation=15, ha='right', fontsize=8)
axes[2].legend()
axes[2].grid(True, alpha=0.3)
plt.suptitle('Сравнение алгоритмов поиска пути', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.savefig(save_filename, dpi=300, bbox_inches='tight')
print(f"\nГрафик сохранён в файл: {save_filename}")
plt.show()
# ========== Основная программа ==========
def main():
print('\n' + '=' * 60)
print('ПОИСК ВЫХОДА ИЗ ЛАБИРИНТА')
print('Сравнение алгоритмов BFS, DFS и A*')
print('=' * 60)
# Находим все txt файлы в текущей директории
maze_files = [f for f in os.listdir('.') if f.endswith('.txt') and f.startswith('maze_')]
if not maze_files:
print("\nНет файлов с лабиринтами (maze_*.txt)")
return
print(f"\nНайдено лабиринтов: {len(maze_files)}")
for f in maze_files:
print(f" - {f}")
strategies = [
('BFS', BFS_Pathfinder()),
('DFS', DFS_Pathfinder()),
('AStar', AStar_Pathfinder())
]
all_results = []
builder = TextLabyrinthBuilder()
for maze_file in sorted(maze_files):
maze_name = maze_file.replace('.txt', '').replace('maze_', '').replace('_', ' ').title()
print(f"\nОбработка лабиринта: {maze_name}")
lab = builder.build(maze_file)
for sname, strat in strategies:
solver = LabyrinthSolver(lab)
solver.set_strategy(strat)
stats = solver.solve()
all_results.append({
'maze': maze_name,
'strategy': sname,
'time_ms': stats['time_ms'],
'visited_cells': stats['visited'],
'path_length': stats['length']
})
status = "Найден" if stats['length'] > 0 else "Не найден"
print(f" {sname}: {status} (время: {stats['time_ms']:.3f} мс, посещено: {stats['visited']}, длина: {stats['length']})")
# Сохранение в CSV
print('\n' + '=' * 60)
print('СОХРАНЕНИЕ РЕЗУЛЬТАТОВ В CSV')
print('=' * 60)
csv_filename = 'experiment_results.csv'
with open(csv_filename, 'w', newline='', encoding='utf-8') as csvfile:
fieldnames = ['лабиринт', 'стратегия', 'время_мс', 'посещено_клеток', 'длина_пути']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for result in all_results:
writer.writerow({
'лабиринт': result['maze'],
'стратегия': result['strategy'],
'время_мс': f"{result['time_ms']:.3f}",
'посещено_клеток': result['visited_cells'],
'длина_пути': result['path_length']
})
print(f"\nРезультаты сохранены в файл: {csv_filename}")
# Вывод таблицы в консоль
print('\n' + '=' * 100)
print('ТАБЛИЦА РЕЗУЛЬТАТОВ')
print('=' * 100)
print(f"{'Лабиринт':<20} {'Стратегия':<10} {'Время (мс)':<12} {'Посещено':<12} {'Длина пути':<12}")
print('-' * 100)
for r in all_results:
print(f"{r['maze']:<20} {r['strategy']:<10} {r['time_ms']:<12.3f} {r['visited_cells']:<12.0f} {r['path_length']:<12.0f}")
print('=' * 100)
# Создание графика
print('\nСОЗДАНИЕ ГРАФИКА...')
create_charts(all_results, 'maze_performance.png')
# Статистика
print('\n' + '=' * 60)
print('СТАТИСТИКА')
print('=' * 60)
for strategy in ['BFS', 'DFS', 'AStar']:
strategy_results = [r for r in all_results if r['strategy'] == strategy and r['path_length'] > 0]
if strategy_results:
avg_time = sum(r['time_ms'] for r in strategy_results) / len(strategy_results)
avg_visited = sum(r['visited_cells'] for r in strategy_results) / len(strategy_results)
avg_length = sum(r['path_length'] for r in strategy_results) / len(strategy_results)
print(f'\n{strategy}:')
print(f' Среднее время: {avg_time:.3f} мс')
print(f' Среднее посещено: {avg_visited:.0f} клеток')
print(f' Средняя длина пути: {avg_length:.1f}')
print('\n' + '=' * 60)
print('ГОТОВО')
print(f'Результаты сохранены в:')
print(f' - {csv_filename} (таблица)')
print(f' - maze_performance.png (график)')
print('=' * 60)
if __name__ == '__main__':
main()

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB