forked from UNN/2026-rff_mp
Реализован Этап 5
This commit is contained in:
parent
107d5cbd61
commit
74928a997a
4
MusinAA/task2/mazeObjects/path.py
Normal file
4
MusinAA/task2/mazeObjects/path.py
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
class Path:
|
||||||
|
def __init__(self, array:list[Cell]|None, visited_cells:int):
|
||||||
|
self.array = array
|
||||||
|
self.visited_cells = visited_cells
|
||||||
43
MusinAA/task2/mazeSolver.py
Normal file
43
MusinAA/task2/mazeSolver.py
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
from task2.mazeObjects.maze import Maze
|
||||||
|
from task2.mazeObjects.cell import Cell
|
||||||
|
from task2.strategyObjects.pathFindingStrategy import PathFindingStrategy
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
class SearchStats:
|
||||||
|
"""Время выполнения в миллисекундах, количество посещённых клеток, длина найденного пути"""
|
||||||
|
def __init__(self, path: list[Cell]|None, duration:float, visited_cells:int, path_len:int, strategy_name:str):
|
||||||
|
self.duration = duration
|
||||||
|
self.visited_cells = visited_cells
|
||||||
|
self.path_len = path_len
|
||||||
|
self.path = path
|
||||||
|
self.strategy_name = strategy_name
|
||||||
|
|
||||||
|
class MazeSolver:
|
||||||
|
"""
|
||||||
|
MazeSolver содержит поля maze и strategy.
|
||||||
|
Метод setStrategy(strategy) для динамической смены алгоритма.
|
||||||
|
Метод solve() вызывает strategy.findPath(...) и возвращает объект SearchStats (время выполнения в миллисекундах,
|
||||||
|
количество посещённых клеток, длина найденного пути).
|
||||||
|
Для замера времени используйте time.perf_counter() до и после вызова стратегии.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, maze:Maze, strategy:PathFindingStrategy):
|
||||||
|
self.maze = maze
|
||||||
|
self.strategy = strategy
|
||||||
|
|
||||||
|
def setStrategy(self, strategy:PathFindingStrategy):
|
||||||
|
self.strategy = strategy
|
||||||
|
|
||||||
|
def getStrategyName(self):
|
||||||
|
return self.strategy.__class__.__name__
|
||||||
|
|
||||||
|
def solve(self):
|
||||||
|
t_start = time.perf_counter()
|
||||||
|
path = self.strategy.findPath(self.maze, self.maze.startCell, self.maze.endCell)
|
||||||
|
duration = time.perf_counter() - t_start
|
||||||
|
|
||||||
|
path_len = len(path.array) if path.array else 0
|
||||||
|
strategy_name = self.getStrategyName()
|
||||||
|
|
||||||
|
return SearchStats(path.array, duration, path.visited_cells, path_len, strategy_name)
|
||||||
|
|
@ -6,13 +6,14 @@ from task2.strategyObjects.util import restorePath
|
||||||
|
|
||||||
from task2.mazeObjects.maze import Maze
|
from task2.mazeObjects.maze import Maze
|
||||||
from task2.mazeObjects.cell import Cell
|
from task2.mazeObjects.cell import Cell
|
||||||
|
from task2.mazeObjects.path import Path
|
||||||
|
|
||||||
class AStar(PathFindingStrategy):
|
class AStar(PathFindingStrategy):
|
||||||
"""Алгоритм с эвристикой (etc. манхэттенское расстояние) – компромисс между скоростью и оптимальностью."""
|
"""Алгоритм с эвристикой (etc. манхэттенское расстояние) – компромисс между скоростью и оптимальностью."""
|
||||||
def heuristic(self, first: Cell, second: Cell) -> int:
|
def heuristic(self, first: Cell, second: Cell) -> int:
|
||||||
return abs(first.x - second.x) + abs(first.y - second.y)
|
return abs(first.x - second.x) + abs(first.y - second.y)
|
||||||
|
|
||||||
def findPath(self, maze: Maze, start: Cell, exit: Cell):
|
def findPath(self, maze: Maze, start: Cell, exit: Cell) -> Path:
|
||||||
tie_breaker = count()
|
tie_breaker = count()
|
||||||
start_heuristic = self.heuristic(start, exit)
|
start_heuristic = self.heuristic(start, exit)
|
||||||
heap: list[tuple[int, int, int, Cell]] = [
|
heap: list[tuple[int, int, int, Cell]] = [
|
||||||
|
|
@ -29,7 +30,7 @@ class AStar(PathFindingStrategy):
|
||||||
visited.add(current)
|
visited.add(current)
|
||||||
|
|
||||||
if current == exit:
|
if current == exit:
|
||||||
return restorePath(parents, exit)
|
return Path(restorePath(parents, exit), len(visited))
|
||||||
|
|
||||||
for neighbor in maze.getNeighbors(current):
|
for neighbor in maze.getNeighbors(current):
|
||||||
tentative_score = g_score[current]
|
tentative_score = g_score[current]
|
||||||
|
|
@ -42,4 +43,4 @@ class AStar(PathFindingStrategy):
|
||||||
heap,
|
heap,
|
||||||
(priority, heuristic, next(tie_breaker), neighbor),
|
(priority, heuristic, next(tie_breaker), neighbor),
|
||||||
)
|
)
|
||||||
return []
|
return Path(None, len(visited))
|
||||||
|
|
@ -3,13 +3,14 @@ from task2.strategyObjects.util import restorePath
|
||||||
|
|
||||||
from task2.mazeObjects.maze import Maze
|
from task2.mazeObjects.maze import Maze
|
||||||
from task2.mazeObjects.cell import Cell
|
from task2.mazeObjects.cell import Cell
|
||||||
|
from task2.mazeObjects.path import Path
|
||||||
|
|
||||||
import queue
|
import queue
|
||||||
|
|
||||||
class BFS(PathFindingStrategy):
|
class BFS(PathFindingStrategy):
|
||||||
"""Поиск в ширину – гарантирует кратчайший путь по количеству шагов.
|
"""Поиск в ширину – гарантирует кратчайший путь по количеству шагов.
|
||||||
Возвращает None, если пути нет"""
|
Возвращает None, если пути нет"""
|
||||||
def findPath(self, maze: Maze, start: Cell, exit: Cell):
|
def findPath(self, maze: Maze, start: Cell, exit: Cell) -> Path:
|
||||||
visited = dict()
|
visited = dict()
|
||||||
parents = dict()
|
parents = dict()
|
||||||
q = queue.Queue()
|
q = queue.Queue()
|
||||||
|
|
@ -31,4 +32,5 @@ class BFS(PathFindingStrategy):
|
||||||
visited[hood] = visited[current] + 1
|
visited[hood] = visited[current] + 1
|
||||||
parents[hood] = current
|
parents[hood] = current
|
||||||
q.put(hood)
|
q.put(hood)
|
||||||
return restorePath(parents, exit)
|
|
||||||
|
return Path(restorePath(parents, exit), len(visited))
|
||||||
|
|
@ -3,12 +3,12 @@ from task2.strategyObjects.util import restorePath
|
||||||
|
|
||||||
from task2.mazeObjects.maze import Maze
|
from task2.mazeObjects.maze import Maze
|
||||||
from task2.mazeObjects.cell import Cell
|
from task2.mazeObjects.cell import Cell
|
||||||
|
from task2.mazeObjects.path import Path
|
||||||
|
|
||||||
class DFS(PathFindingStrategy):
|
class DFS(PathFindingStrategy):
|
||||||
"""Поиск в глубину – быстрый, но не обязательно кратчайший.
|
"""Поиск в глубину – быстрый, но не обязательно кратчайший.
|
||||||
Возвращает None, если пути нет"""
|
Возвращает None, если пути нет"""
|
||||||
def findPath(self, maze: Maze, start: Cell, exit: Cell):
|
def findPath(self, maze: Maze, start: Cell, exit: Cell) -> Path:
|
||||||
visited = dict()
|
visited = dict()
|
||||||
parents = dict()
|
parents = dict()
|
||||||
stack = []
|
stack = []
|
||||||
|
|
@ -31,4 +31,4 @@ class DFS(PathFindingStrategy):
|
||||||
parents[hood] = current
|
parents[hood] = current
|
||||||
stack.append(hood)
|
stack.append(hood)
|
||||||
|
|
||||||
return restorePath(parents, exit)
|
return Path(restorePath(parents, exit), len(visited))
|
||||||
|
|
@ -2,12 +2,13 @@ from abc import ABC, abstractmethod
|
||||||
|
|
||||||
from task2.mazeObjects.maze import Maze
|
from task2.mazeObjects.maze import Maze
|
||||||
from task2.mazeObjects.cell import Cell
|
from task2.mazeObjects.cell import Cell
|
||||||
|
from task2.mazeObjects.path import Path
|
||||||
|
|
||||||
class PathFindingStrategy(ABC):
|
class PathFindingStrategy(ABC):
|
||||||
"""Интерфейс PathFindingStrategy с методом findPath(maze, start, exit),
|
"""Интерфейс PathFindingStrategy с методом findPath(maze, start, exit),
|
||||||
возвращающим список клеток пути (от старта до выхода включительно) или пустой список, если пути нет."""
|
возвращающим список клеток пути (от старта до выхода включительно) или пустой список, если пути нет."""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def findPath(self, maze: Maze, start: Cell, exit: Cell):
|
def findPath(self, maze: Maze, start: Cell, exit: Cell) -> Path:
|
||||||
"""Возвращает список клеток пути от старта до выхода включительно. Пути нет - пустой список."""
|
"""Возвращает список клеток пути от старта до выхода включительно. Пути нет - пустой список."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
Loading…
Reference in New Issue
Block a user