diff --git a/MylnikovAS/task_2/docs/data/results_all.csv b/MylnikovAS/task_2/docs/data/results_all.csv new file mode 100644 index 0000000..8ec170b --- /dev/null +++ b/MylnikovAS/task_2/docs/data/results_all.csv @@ -0,0 +1,21 @@ +labyrint,strategy,time_ms,passed_cells,path_length +Small (10x10),BFS,0.1973,59,27 +Small (10x10),DFS,0.1615,49,27 +Small (10x10),AStar,0.2375,50,27 +Small (10x10),Dijkstra,0.2487,60,27 +Empty (50x50),BFS,8.3316,2500,99 +Empty (50x50),DFS,4.6278,1275,1275 +Empty (50x50),AStar,17.5549,2500,99 +Empty (50x50),Dijkstra,14.7128,2500,99 +Middle with dead ends (50x50),BFS,4.8741,1420,1083 +Middle with dead ends (50x50),DFS,4.3282,1275,1275 +Middle with dead ends (50x50),AStar,7.1452,1404,1083 +Middle with dead ends (50x50),Dijkstra,6.0643,1420,1083 +Big (100x100),BFS,17.0733,5590,199 +Big (100x100),DFS,15.1471,4933,4519 +Big (100x100),AStar,31.4644,5140,199 +Big (100x100),Dijkstra,26.7258,5590,199 +Without exit (10x10),BFS,0.0140,5,0 +Without exit (10x10),DFS,0.0124,5,0 +Without exit (10x10),AStar,0.0164,5,0 +Without exit (10x10),Dijkstra,0.0143,5,0 diff --git a/MylnikovAS/task_2/docs/data/steps_4_and_exp.py b/MylnikovAS/task_2/docs/data/steps_4_and_exp.py new file mode 100644 index 0000000..101f773 --- /dev/null +++ b/MylnikovAS/task_2/docs/data/steps_4_and_exp.py @@ -0,0 +1,192 @@ +class SearchStats: + def __init__(self, timeMs: float, visitedCells: int, pathLength: int): + self.timeMs = timeMs + self.visitedCells = visitedCells + self.pathLength = pathLength + + +class MazeSolver: + def __init__(self, maze: Maze, strategy: PathFindingStrategy): + self.maze = maze + self.strategy = strategy + self.observers = [] + + def setStrategy(self, strategy: PathFindingStrategy): + self.strategy = strategy + + def addObserver(self, observer): + self.observers.append(observer) + + def _notify(self, event: str): + for obs in self.observers: + obs.update(event) + + def solve(self) -> tuple: + self._notify("Поиск начат") + start_time = time.perf_counter() + + path = self.strategy.findPath(self.maze, self.maze.start, self.maze.exit) + + end_time = time.perf_counter() + time_ms = (end_time - start_time) * 1000 + + stats = SearchStats(time_ms, self.strategy.visited_count, len(path)) + self._notify("Поиск завершен") + return path, stats + + +class Observer(ABC): + @abstractmethod + def update(self, event: str): + pass + + +class ConsoleView(Observer): + def update(self, event: str): + pass + + def render(self, maze: Maze, path: list): + path_set = set(path) + for y in range(maze.height): + row = "" + for x in range(maze.width): + cell = maze.getCell(x, y) + if cell == maze.start: + row += "S" + elif cell == maze.exit: + row += "E" + elif cell in path_set: + row += "*" + elif cell.isWall: + row += "#" + elif cell.weight == 3: + row += "W" # Болото + elif cell.weight == 2: + row += "D" # Песок + else: + row += "." + print(row) + + +def get_test_mazes(): + builder = TextMazeBuilder() + mazes = {} + + small = [ + "S.........", + "#####.####", + "..........", + "####.#####", + "..........", + "#.#######.", + "..........", + "######.###", + "..........", + "........XE" + ] + small[-1] = small[-1].replace('X', '.') + mazes["Small (10x10)"] = builder.buildFromStringList(small) + + empty = ["." * 50 for _ in range(50)] + empty_list = list(empty) + empty_list[0] = "S" + empty_list[0][1:] + empty_list[-1] = empty_list[-1][:-1] + "E" + mazes["Empty (50x50)"] = builder.buildFromStringList(empty_list) + + medium = [] + for y in range(50): + if y == 0: + row = "S" + "." * 49 + elif y == 49: + row = "." * 49 + "E" + elif y % 2 == 1: + row = "#" * 45 + "." * 5 if y % 4 == 1 else "." * 5 + "#" * 45 + else: + row = "." * 50 + medium.append(row) + mazes["Middle with dead ends (50x50)"] = builder.buildFromStringList(medium) + + large = [] + for y in range(100): + if y == 0: row = "S" + "." * 99 + elif y == 99: row = "." * 99 + "E" + elif y % 2 == 1: + row = ("#" * 9 + ".") * 10 + else: + row = "." * 100 + large.append(row) + mazes["Big (100x100)"] = builder.buildFromStringList(large) + + no_exit = [ + "S....#....", + "##########", + "##########", + "##########", + "##########", + "##########", + "##########", + "##########", + "##########", + "######...E" + ] + mazes["Without exit (10x10)"] = builder.buildFromStringList(no_exit) + + + return mazes + + +def main(): + mazes = get_test_mazes() + + strategies = { + "BFS": BFSStrategy(), + "DFS": DFSStrategy(), + "AStar": AStarStrategy(), + "Dijkstra": DijkstraStrategy() + } + + output_rows = [] + + print("Запуск всех тестов...") + print("-" * 70) + + for maze_name, maze in mazes.items(): + print(f"Testing: {maze_name}") + + for strat_name, strategy in strategies.items(): + + solver = MazeSolver(maze, strategy) + + runs = 5 + total_time = 0 + path = [] + stats = None + + for _ in range(runs): + path, stats = solver.solve() + total_time += stats.timeMs + + avg_time = total_time / runs + + output_rows.append([ + maze_name, + strat_name, + f"{avg_time:.4f}", + stats.visitedCells, + stats.pathLength + ]) + + print( + f" -> {strat_name}: Time: {avg_time:.3f}ms | Passed cells: {stats.visitedCells} | Path length: {stats.pathLength}") + print("-" * 70) + + with open("results_all.csv", "w", newline="", encoding="utf-8") as csvfile: + writer = csv.writer(csvfile) + writer.writerow(["labyrint", "strategy", "time_ms", "passed_cells", "path_length"]) + writer.writerows(output_rows) + + print("Все замеры успешно выполнены! Результаты сохранены в 'results_all.csv'") + + +if __name__ == "__main__": + main() \ No newline at end of file