Рефакторинг всего и готовый отчёт

This commit is contained in:
oSTEVEo 2026-05-25 03:00:00 +03:00
parent 9849075a38
commit 3d9390a894
19 changed files with 1087 additions and 80 deletions

903
MusinAA/docs/Report 2.ipynb Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,13 +0,0 @@
Алгоритм,Лабиринт,Время (мс),Посещённые клетки,Длинна пути
BFS,50x50,3.2134529003087664,720,431
BFS,10x10,0.2288821000547614,53,23
BFS,5x5,0.035640300302475225,8,7
BFS,100x100,11.366462300065905,2495,1171
DFS,50x50,1.7320569000730757,747,431
DFS,10x10,0.0645840002107434,35,31
DFS,5x5,0.015984299898264,8,7
DFS,100x100,8.414763500331901,3219,1243
AStar,50x50,1.8410825001410558,509,455
AStar,10x10,0.1062644998455653,23,23
AStar,5x5,0.03181890006089816,8,7
AStar,100x100,6.592893099877983,1286,1171
1 Алгоритм Лабиринт Время (мс) Посещённые клетки Длинна пути
2 BFS 50x50 3.2134529003087664 720 431
3 BFS 10x10 0.2288821000547614 53 23
4 BFS 5x5 0.035640300302475225 8 7
5 BFS 100x100 11.366462300065905 2495 1171
6 DFS 50x50 1.7320569000730757 747 431
7 DFS 10x10 0.0645840002107434 35 31
8 DFS 5x5 0.015984299898264 8 7
9 DFS 100x100 8.414763500331901 3219 1243
10 AStar 50x50 1.8410825001410558 509 455
11 AStar 10x10 0.1062644998455653 23 23
12 AStar 5x5 0.03181890006089816 8 7
13 AStar 100x100 6.592893099877983 1286 1171

View File

@ -0,0 +1,16 @@
Алгоритм,Лабиринт,Время (мс),Посещённые клетки,Длинна пути
BFS,10x10,0.4038135000882903,53,23
BFS,5x5,0.07533170064562,8,7
BFS,100x100,17.14356810080062,2495,1171
BFS,50x50,3.010086300491821,640,427
BFS,25x25,1.0405578999780118,232,173
DFS,10x10,0.07943829987198114,35,31
DFS,5x5,0.018403499416308478,8,7
DFS,100x100,8.430859900545329,3219,1243
DFS,50x50,2.0664067997131497,995,435
DFS,25x25,0.5787261994555593,316,173
AStar,10x10,0.0671462003083434,23,23
AStar,5x5,0.022370600345311686,8,7
AStar,100x100,4.951790099585196,1286,1171
AStar,50x50,2.081632300541969,496,427
AStar,25x25,0.5791453000711044,186,177
1 Алгоритм Лабиринт Время (мс) Посещённые клетки Длинна пути
2 BFS 10x10 0.4038135000882903 53 23
3 BFS 5x5 0.07533170064562 8 7
4 BFS 100x100 17.14356810080062 2495 1171
5 BFS 50x50 3.010086300491821 640 427
6 BFS 25x25 1.0405578999780118 232 173
7 DFS 10x10 0.07943829987198114 35 31
8 DFS 5x5 0.018403499416308478 8 7
9 DFS 100x100 8.430859900545329 3219 1243
10 DFS 50x50 2.0664067997131497 995 435
11 DFS 25x25 0.5787261994555593 316 173
12 AStar 10x10 0.0671462003083434 23 23
13 AStar 5x5 0.022370600345311686 8 7
14 AStar 100x100 4.951790099585196 1286 1171
15 AStar 50x50 2.081632300541969 496 427
16 AStar 25x25 0.5791453000711044 186 177

View File

@ -0,0 +1,7 @@
Алгоритм,Лабиринт,Время (мс),Посещённые клетки,Длинна пути
BFS,maze_25x25_wo_exit,1.9682294001540868,338,-1
BFS,maze_25x25_empty,4.574537699954817,625,49
DFS,maze_25x25_wo_exit,0.719102000221028,338,-1
DFS,maze_25x25_empty,0.903778699648683,625,337
AStar,maze_25x25_wo_exit,1.0117966015968705,338,-1
AStar,maze_25x25_empty,0.21763520016975235,49,49
1 Алгоритм Лабиринт Время (мс) Посещённые клетки Длинна пути
2 BFS maze_25x25_wo_exit 1.9682294001540868 338 -1
3 BFS maze_25x25_empty 4.574537699954817 625 49
4 DFS maze_25x25_wo_exit 0.719102000221028 338 -1
5 DFS maze_25x25_empty 0.903778699648683 625 337
6 AStar maze_25x25_wo_exit 1.0117966015968705 338 -1
7 AStar maze_25x25_empty 0.21763520016975235 49 49

View File

@ -1,6 +1,7 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from itertools import product from itertools import product
import sys import sys
import os.path as path
from task2.mazeObjects.maze import Maze from task2.mazeObjects.maze import Maze
from task2.mazeObjects.cell import Cell from task2.mazeObjects.cell import Cell
@ -18,8 +19,8 @@ class TextFileMazeBuilder(MazeBuilder):
задаёт координаты и флаги, задаёт координаты и флаги,
после чего возвращает готовый Maze.""" после чего возвращает готовый Maze."""
start = {'x': 0, 'y': 0} start:dict
end = {'x': 0, 'y': 0} end:dict
def _cellStrategy(self, letter: str) -> Cell: def _cellStrategy(self, letter: str) -> Cell:
if letter == '#': if letter == '#':
@ -63,7 +64,9 @@ class TextFileMazeBuilder(MazeBuilder):
cell.y = y cell.y = y
array[y][x] = cell array[y][x] = cell
except IndexError: except IndexError:
raise ValueError(f"Строка {x+1} имеет длину {len(rows[x])}, ожидалось {width}") raise ValueError(f"В файле {filename}: Строка {y+1} имеет длину {len(rows[y])}, ожидалось {width}")
return Maze(array, self.start, self.end) maze_name, _ = path.splitext(path.basename(filename))
return Maze(array, self.start, self.end, name=maze_name)

View File

@ -0,0 +1,25 @@
S # # #
# ##### # # # ####### #
# # # # # #
#### # ##### # # #######
# # # # # # #
## # # # ##### ### # # #
# # # # # # # # #
### # # # # ### # # # #
# # # # # # # #
# ### # # ### ### # ####
# # # # # # #
### # # # ####### #####
# # # #
# ################# ###
# # # #
# # # ####### ####### ##
# # # # #
### ##### # ### ### ###
# # # # # #
# # # ##### # # #######
# # # # # #
##### # ####### # ### ##
# # # # # # #
#### # # # ### ##### # #
# # # E

View File

@ -0,0 +1,50 @@
S # # # # # # #
### # ##### # ### ### # # ### # # ### # ### # # #
# # # # # # # # # # # # # # #
####### # # ####### ##### # ##### ####### ### ###
# # # # # # # # # #
### # ##### ### # ### # # ##### # ############# #
# # # # # # # # # # # # #
# ### # # ### ############# # # ##### ##### # # #
# # # # # # # # # # # # # #
#### ##### # ### # ##### # # ##### # ### # ##### #
# # # # # # # # # # # #
### ####### ####### # ####### # ##### # ### ### #
# # # # # # # # # # # #
####### # # # ### ##### # ##### ### # ### #######
# # # # # # # # # # # # #
## ### ####### ### # # ### # # # # ### # ### ### #
# # # # # # # # # # # #
####### # ##### ####### ### ######### ##### ### #
# # # # # # # # # # #
#### # # ### ##### ####### # # # ### # # # ### # #
# # # # # # # # # # # # # # # #
# # # ### # # # # # # ### ####### # ##### # ### #
# # # # # # # # # # # # # # # #
# # # ### ######### # # ### # # # ##### # # # ###
# # # # # # # # # # # # #
####### ### # ### ####### # # ##### # ######### #
# # # # # # # # # # # # #
########### ### ### ### # ### # # ##### # ### # #
# # # # # # # # # # # # # #
### # ### ### ####### ### # ### # # # ####### # #
# # # # # # # # # # # # # # # #
## # ### # # ### # # # # # # # # # ### # ### ### #
# # # # # # # # # # # # # # # # # #
##### # # ##### # # # ####### # ### # # # ### # #
# # # # # # # # # # # # # # #
# # # ### # ### ########### # ##### # ### # # ###
# # # # # # # # # # # # #
#### ##### # # ### ### # ##### # ##### # #########
# # # # # # # # # # #
# ### ##### ### ### # ### ########### ######### #
# # # # # # # # # #
### # ##### # # ##### # ####### # ### ### # #####
# # # # # # # # # # #
## ##### # ### ### # ##### ####### # # ######### #
# # # # # # # # # # # #
### # ##### # # ##### # ### ##### ##### ####### #
# # # # # # # # # # #
# ########### ########### ##### ####### # ### # #
# # # #
################################################ E

View File

@ -1,50 +0,0 @@
S # # # #
####### ### # # ########### ##### # ##### ##### #
# # # # # # # # # #
## # # ### ####### ##### ####### # ### ######### #
# # # # # # # # # # # # #
####### # # # # ### ##### # ### ### # # # # ### #
# # # # # # # # # # # # # # # # #
# ### # ### # ### ### # # ### ### ####### # # ###
# # # # # # # # # # # # # #
# # ############# # ### ### # ######### # # ### #
# # # # # # # # #
########### ########### # ##### ### ### # # # ###
# # # # # # # # # # # # # #
# # ####### # ### # ##### ### ### ### ### # # # #
# # # # # # # # # # # # # # # #
###### ### ### # # # # # # # ### ### ##### # # # #
# # # # # # # # # # # # # # #
### # # ######### ### # # # # ####### ##### # # #
# # # # # # # # # # # # # #
### ### # ##### # # ######### # # # # ##### # # #
# # # # # # # # # # # #
## # ######### # # ### ### # ### ######### ##### #
# # # # # # # # # # # #
##### # ### # ### ##### # # # ####### ##### # # #
# # # # # # # # # # # # # # #
## # ##### # # ##### ##### ### ### # ### # # # ###
# # # # # # # # # # # # #
##### # ### # # ##### ### # ### ######### # #####
# # # # # # # # # # #
# ####### ######### ### ####### # # ####### ### #
# # # # # # # # # # # # # #
# # ####### # # ##### # # ### ### # # # # ##### #
# # # # # # # # # # # # # # # #
# ##### # ####### # # # # # ### # ### # # # ### #
# # # # # # # # # # # # # # #
# ########### # ### ####### ### # ### # # # # # #
# # # # # # # # # # # # #
# # ####### ##### ########### ##### # # ##### # #
# # # # # # # # # # #
### ### ### # ############### # # # ##### ### ###
# # # # # # # # # # # # # #
# ### ### # ### ##### # # # # # ##### # ### # # #
# # # # # # # # # # # # # #
# # ####### # ### ######### ######### ### # # # #
# # # # # # # # # # # # # # #
##### # ####### # # # ### # # # # # ### ### # # #
# # # # # # # # # # # # # # #
## ### ##### ####### ### # # ### ##### # ### ### #
# # # #
################################################ E

View File

@ -0,0 +1,25 @@
S
E

View File

@ -0,0 +1,25 @@
S # # #
# ##### # # # ####### #
# # # # # #
#### # ##### # # #######
# # # # # # #
## # # # ##### ### # # #
# # # # # # # # #
### # # # # ### # # # #
# # # # # # # #
# ### # # ### ### # ####
# # # # # # #
### # # # ####### #####
# # # #
# ################# ###
# # # #
# # # ####### ####### ##
# # # # #
### ##### # ### ### ###
# # # # # #
# # # ##### # # #######
# # # # # #
##### # ####### # ### ##
# # # # # # #
#### # # # ### ##### # #
# # # #

View File

@ -7,13 +7,14 @@ class Maze:
getCell(x, y), getNeighbors(cell) возвращает список соседних проходимых клеток getCell(x, y), getNeighbors(cell) возвращает список соседних проходимых клеток
(вверх, вниз, влево, вправо, если в пределах границ и не стена).""" (вверх, вниз, влево, вправо, если в пределах границ и не стена)."""
def __init__(self, mazeArray: list[list[Cell]], start: dict, end: dict) -> None: def __init__(self, mazeArray: list[list[Cell]], start: dict, end: dict, name:str="") -> None:
self.mazeArray = mazeArray self.mazeArray = mazeArray
self.height = len(mazeArray) # X self.height = len(mazeArray) # X
self.width = len(mazeArray[0]) # Y self.width = len(mazeArray[0]) # Y
self.startCell = self.getCell(start['x'], start['y']) self.startCell = self.getCell(start['x'], start['y'])
self.endCell = self.getCell(end['x'], end['y']) self.endCell = self.getCell(end['x'], end['y'])
self.name = name
def getCell(self, x: int, y: int): def getCell(self, x: int, y: int):
return self.mazeArray[y][x] return self.mazeArray[y][x]

View File

@ -58,7 +58,7 @@ class MazeSolver(Subject):
path = self.strategy.findPath(self._maze, self._maze.startCell, self._maze.endCell) path = self.strategy.findPath(self._maze, self._maze.startCell, self._maze.endCell)
duration = (time.perf_counter() - t_start) * 1000 duration = (time.perf_counter() - t_start) * 1000
path_len = len(path.array) if path.array else 0 path_len = len(path.array) if path.array else -1
strategy_name = self.getStrategyName() strategy_name = self.getStrategyName()
stats = SearchStats(path.array, duration, path.visited_cells, path_len, strategy_name) stats = SearchStats(path.array, duration, path.visited_cells, path_len, strategy_name)

View File

@ -29,7 +29,7 @@ class AStar(PathFindingStrategy):
continue continue
visited.add(current) visited.add(current)
if current == exit: if current.isExit:
return Path(restorePath(parents, exit), len(visited)) return Path(restorePath(parents, exit), len(visited))
for neighbor in maze.getNeighbors(current): for neighbor in maze.getNeighbors(current):

View File

@ -19,11 +19,14 @@ class BFS(PathFindingStrategy):
visited[start] = 0 visited[start] = 0
parents[start] = None parents[start] = None
found_exit = False
while not q.empty(): while not q.empty():
current = q.get() current = q.get()
# Условие нахождение выхода # Условие нахождение выхода
if current == exit: break if current.isExit:
found_exit = True
break
# Перебор соседей # Перебор соседей
for hood in maze.getNeighbors(current): for hood in maze.getNeighbors(current):
@ -33,4 +36,8 @@ class BFS(PathFindingStrategy):
parents[hood] = current parents[hood] = current
q.put(hood) q.put(hood)
return Path(restorePath(parents, exit), len(visited)) if not found_exit:
path_list = None
else:
path_list = restorePath(parents, exit)
return Path(path_list, len(visited))

View File

@ -17,11 +17,14 @@ class DFS(PathFindingStrategy):
visited[start] = 0 visited[start] = 0
parents[start] = None parents[start] = None
found_exit = False
while stack: while stack:
current = stack.pop() current = stack.pop()
# Условие нахождение выхода # Условие нахождение выхода
if current == exit: break if current.isExit:
found_exit = True
break
# Перебор соседей # Перебор соседей
for hood in maze.getNeighbors(current): for hood in maze.getNeighbors(current):
@ -31,4 +34,8 @@ class DFS(PathFindingStrategy):
parents[hood] = current parents[hood] = current
stack.append(hood) stack.append(hood)
return Path(restorePath(parents, exit), len(visited)) if not found_exit:
path_list = None
else:
path_list = restorePath(parents, exit)
return Path(path_list, len(visited))

View File

@ -18,13 +18,13 @@ class Tester():
лабиринт,стратегия,время_мс,посещено_клеток,длина_пути.""" лабиринт,стратегия,время_мс,посещено_клеток,длина_пути."""
result:list[SearchStats] result:list[SearchStats]
def __init__(self, builder:MazeBuilder, writefile:str): def __init__(self, builder:MazeBuilder, writefile:str):
self.builder = builder self._builder = builder
self.writefile = writefile self.writefile = "../" + writefile
def setTestingDirectory(self, directory:str): def setTestingDirectory(self, directory:str):
if directory[-1] != "/": if directory[-1] != "/":
directory += "/" directory += "/"
self._directory = directory self._directory = "../" + directory
def _getMazes(self) -> list[Maze]: def _getMazes(self) -> list[Maze]:
arr = [] arr = []
@ -32,7 +32,7 @@ class Tester():
only_txt_files = [f for f in files if os.path.isfile(os.path.join(self._directory, f)) and os.path.splitext(f)[1] == ".txt"] only_txt_files = [f for f in files if os.path.isfile(os.path.join(self._directory, f)) and os.path.splitext(f)[1] == ".txt"]
for f in only_txt_files: for f in only_txt_files:
arr.append(builder.buildFromFile(os.path.join(self._directory, f))) arr.append(self._builder.buildFromFile(os.path.join(self._directory, f)))
return arr return arr
def _solveAvg(self, solver: MazeSolver): def _solveAvg(self, solver: MazeSolver):
@ -68,15 +68,16 @@ class Tester():
for maze in arr: for maze in arr:
solver.setMaze(maze) solver.setMaze(maze)
self.result.append(self._solveAvg(solver)) self.result.append(self._solveAvg(solver))
self.result[-1].maze_name = f"{maze.height}x{maze.width}" self.result[-1].maze_name = maze.name
return self.result return self.result
if __name__ == "__main__": if __name__ == "__main__":
exit()
from task2.mazeBuilder import TextFileMazeBuilder from task2.mazeBuilder import TextFileMazeBuilder
builder = TextFileMazeBuilder() builder = TextFileMazeBuilder()
tester = Tester(builder, "docs/data/mazeRezults.csv") tester = Tester(builder, "docs/data/task2/results.csv")
tester.setTestingDirectory("task2/mazeExamples") tester.setTestingDirectory("task2/mazeExamples")
tester.test() tester.test()
tester.saveCSV() tester.saveCSV()