mirror of
https://github.com/kuhyx/WUT_Computer_Science.git
synced 2026-07-06 20:23:10 +02:00
Merge branch 'main' of https://github.com/kuchyx/EARIN
This commit is contained in:
commit
3d30e1a5fc
61
lab1/main.py
61
lab1/main.py
@ -100,16 +100,17 @@ class MazeSolver:
|
|||||||
for neighbor in self.get_neighbors(current):
|
for neighbor in self.get_neighbors(current):
|
||||||
if neighbor not in visited:
|
if neighbor not in visited:
|
||||||
new_path = path + [neighbor]
|
new_path = path + [neighbor]
|
||||||
heuristic, heuristic_time = self.heuristic_manhattan(neighbor)
|
heuristic, heuristic_time = self.heuristic_euclidean(
|
||||||
|
neighbor)
|
||||||
heuristic_total_time += heuristic_time
|
heuristic_total_time += heuristic_time
|
||||||
heuristics_called += 1
|
heuristics_called += 1
|
||||||
heapq.heappush(
|
heapq.heappush(
|
||||||
queue, (heuristic, neighbor, new_path)
|
queue, (heuristic, neighbor, new_path)
|
||||||
)
|
)
|
||||||
if not self.test:
|
if not self.test:
|
||||||
print_maze(self.maze, new_path)
|
print_maze(self.maze, path, visited)
|
||||||
print()
|
print()
|
||||||
return path, heuristic_total_time, heuristics_called
|
return path, visited, heuristic_total_time, heuristics_called
|
||||||
|
|
||||||
def solve(self):
|
def solve(self):
|
||||||
"""Solves the maze"""
|
"""Solves the maze"""
|
||||||
@ -120,7 +121,7 @@ class MazeSolver:
|
|||||||
# push onto the queue (which becomes heapq), element containing values
|
# push onto the queue (which becomes heapq), element containing values
|
||||||
# we use heapq so the element with lowest heuristic value will always
|
# we use heapq so the element with lowest heuristic value will always
|
||||||
# be at the top of heap
|
# be at the top of heap
|
||||||
heuristic = self.heuristic_manhattan(self.start)
|
heuristic = self.heuristic_euclidean(self.start)
|
||||||
heapq.heappush(
|
heapq.heappush(
|
||||||
queue, (heuristic, self.start, [self.start])
|
queue, (heuristic, self.start, [self.start])
|
||||||
)
|
)
|
||||||
@ -138,7 +139,8 @@ class MazeSolver:
|
|||||||
def heuristic_manhattan(self, position):
|
def heuristic_manhattan(self, position):
|
||||||
"""Heuristic function that uses Manhattan distance"""
|
"""Heuristic function that uses Manhattan distance"""
|
||||||
start_time = time.perf_counter()
|
start_time = time.perf_counter()
|
||||||
heuristic = abs(position[0] - self.end[0]) + abs(position[1] - self.end[1])
|
heuristic = abs(position[0] - self.end[0]) + \
|
||||||
|
abs(position[1] - self.end[1])
|
||||||
end_time = time.perf_counter()
|
end_time = time.perf_counter()
|
||||||
heuristic_time = end_time - start_time
|
heuristic_time = end_time - start_time
|
||||||
return heuristic, heuristic_time
|
return heuristic, heuristic_time
|
||||||
@ -149,13 +151,14 @@ class MazeSolver:
|
|||||||
"""Heuristic function that uses Euclidean distance"""
|
"""Heuristic function that uses Euclidean distance"""
|
||||||
start_time = time.perf_counter()
|
start_time = time.perf_counter()
|
||||||
heuristic = (
|
heuristic = (
|
||||||
abs(position[0] - self.end[0]) ** 2 + abs(position[1] - self.end[1]) ** 2
|
abs(position[0] - self.end[0]) ** 2 +
|
||||||
|
abs(position[1] - self.end[1]) ** 2
|
||||||
) ** 0.5
|
) ** 0.5
|
||||||
end_time = time.perf_counter()
|
end_time = time.perf_counter()
|
||||||
heuristic_time = end_time - start_time
|
heuristic_time = end_time - start_time
|
||||||
return heuristic, heuristic_time
|
return heuristic, heuristic_time
|
||||||
|
|
||||||
def heuristic_random(self):
|
def heuristic_random(self, position):
|
||||||
"""Heuristic function that just returns random value between 0 and 1"""
|
"""Heuristic function that just returns random value between 0 and 1"""
|
||||||
start_time = time.perf_counter()
|
start_time = time.perf_counter()
|
||||||
heuristic = random()
|
heuristic = random()
|
||||||
@ -180,14 +183,18 @@ def load_maze(maze_file_name):
|
|||||||
return maze
|
return maze
|
||||||
|
|
||||||
|
|
||||||
def print_maze(maze, path=None):
|
def print_maze(maze, path=None, visited=None):
|
||||||
"""Prints the maze"""
|
"""Prints the maze"""
|
||||||
if path is None:
|
if path is None:
|
||||||
path = []
|
path = []
|
||||||
|
if visited is None:
|
||||||
|
visited = []
|
||||||
for row_i, row in enumerate(maze):
|
for row_i, row in enumerate(maze):
|
||||||
for col_i, cell in enumerate(row):
|
for col_i, cell in enumerate(row):
|
||||||
if (row_i, col_i) in path:
|
if (row_i, col_i) in path and cell == " ":
|
||||||
print("*", end="")
|
print("*", end="")
|
||||||
|
elif (row_i, col_i) in visited and cell == " ":
|
||||||
|
print("·", end="")
|
||||||
else:
|
else:
|
||||||
print(cell, end="")
|
print(cell, end="")
|
||||||
print()
|
print()
|
||||||
@ -203,16 +210,21 @@ def create_maze_folder(solved):
|
|||||||
os.mkdir(folder_name)
|
os.mkdir(folder_name)
|
||||||
return folder_name
|
return folder_name
|
||||||
|
|
||||||
def save_maze(maze, solved=True, path=None, saved_file="Maze", iteration=0):
|
|
||||||
|
def save_maze(maze, solved=True, path=None, visited=None, saved_file="Maze", iteration=0):
|
||||||
"""Saves maze from array to txt file"""
|
"""Saves maze from array to txt file"""
|
||||||
folder_name = create_maze_folder(solved)
|
folder_name = create_maze_folder(solved)
|
||||||
with open(f"{folder_name}/{iteration}{saved_file}", "w", encoding="utf8") as maze_file:
|
|
||||||
if path is None:
|
if path is None:
|
||||||
path = []
|
path = []
|
||||||
|
if visited is None:
|
||||||
|
visited = []
|
||||||
|
with open(f"{folder_name}/{iteration}{os.path.basename(saved_file)}", "w", encoding="utf8") as maze_file:
|
||||||
for row_i, row in enumerate(maze):
|
for row_i, row in enumerate(maze):
|
||||||
for col_i, cell in enumerate(row):
|
for col_i, cell in enumerate(row):
|
||||||
if (row_i, col_i) in path:
|
if (row_i, col_i) in path and cell == " ":
|
||||||
maze_file.write("*")
|
maze_file.write("*")
|
||||||
|
elif (row_i, col_i) in visited and cell == " ":
|
||||||
|
maze_file.write("·")
|
||||||
else:
|
else:
|
||||||
maze_file.write(cell)
|
maze_file.write(cell)
|
||||||
if solved:
|
if solved:
|
||||||
@ -220,6 +232,7 @@ def save_maze(maze, solved=True, path=None, saved_file="Maze", iteration=0):
|
|||||||
if not solved:
|
if not solved:
|
||||||
maze_file.write("\n")
|
maze_file.write("\n")
|
||||||
|
|
||||||
|
|
||||||
def fill_generated_maze(hor, ver, width):
|
def fill_generated_maze(hor, ver, width):
|
||||||
""" Fills generated maze array from horizontal and vertical lines """
|
""" Fills generated maze array from horizontal and vertical lines """
|
||||||
maze_data = ""
|
maze_data = ""
|
||||||
@ -231,6 +244,7 @@ def fill_generated_maze(hor, ver, width):
|
|||||||
maze_data = "".join(maze_data_list)
|
maze_data = "".join(maze_data_list)
|
||||||
return maze_data
|
return maze_data
|
||||||
|
|
||||||
|
|
||||||
def make_maze(width=16, height=8):
|
def make_maze(width=16, height=8):
|
||||||
""" generate maze with given width and height """
|
""" generate maze with given width and height """
|
||||||
vis = [[0] * width + [1] for _ in range(height)] + [[1] * (width + 1)]
|
vis = [[0] * width + [1] for _ in range(height)] + [[1] * (width + 1)]
|
||||||
@ -249,15 +263,18 @@ def make_maze(width=16, height=8):
|
|||||||
if vis[y_coordinate_neighbor][x_coordinate_neighbor]:
|
if vis[y_coordinate_neighbor][x_coordinate_neighbor]:
|
||||||
continue
|
continue
|
||||||
if x_coordinate_neighbor == x_coordinate:
|
if x_coordinate_neighbor == x_coordinate:
|
||||||
hor[max(y_coordinate, y_coordinate_neighbor)][x_coordinate] = "# "
|
hor[max(y_coordinate, y_coordinate_neighbor)
|
||||||
|
][x_coordinate] = "# "
|
||||||
if y_coordinate_neighbor == y_coordinate:
|
if y_coordinate_neighbor == y_coordinate:
|
||||||
ver[y_coordinate][max(x_coordinate, x_coordinate_neighbor)] = " "
|
ver[y_coordinate][max(
|
||||||
|
x_coordinate, x_coordinate_neighbor)] = " "
|
||||||
walk(x_coordinate_neighbor, y_coordinate_neighbor)
|
walk(x_coordinate_neighbor, y_coordinate_neighbor)
|
||||||
|
|
||||||
walk(randrange(width), randrange(height))
|
walk(randrange(width), randrange(height))
|
||||||
|
|
||||||
return fill_generated_maze(hor, ver, width)
|
return fill_generated_maze(hor, ver, width)
|
||||||
|
|
||||||
|
|
||||||
def print_help():
|
def print_help():
|
||||||
"""prints help"""
|
"""prints help"""
|
||||||
print(
|
print(
|
||||||
@ -277,6 +294,7 @@ python main.py -g --generate [NUMBER] - generates as many mazes as entered in
|
|||||||
Number parameter and puts it in the generatedMazes folder"""
|
Number parameter and puts it in the generatedMazes folder"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_mode():
|
def test_mode():
|
||||||
""" Loads and solves multiple mazes in order to compare heuristics """
|
""" Loads and solves multiple mazes in order to compare heuristics """
|
||||||
create_maze_folder(False)
|
create_maze_folder(False)
|
||||||
@ -293,13 +311,13 @@ def test_mode():
|
|||||||
solver_test = MazeSolver(loaded_maze, TEST_MODE)
|
solver_test = MazeSolver(loaded_maze, TEST_MODE)
|
||||||
# Find path using MazeSolver solve method
|
# Find path using MazeSolver solve method
|
||||||
start_time = time.perf_counter()
|
start_time = time.perf_counter()
|
||||||
solved_path, heuristic_total_time, heuristics_called = solver_test.solve()
|
solved_path, visited, heuristic_total_time, heuristics_called = solver_test.solve()
|
||||||
heuristic_total_total_time += heuristic_total_time
|
heuristic_total_total_time += heuristic_total_time
|
||||||
all_heuristic_called += heuristics_called
|
all_heuristic_called += heuristics_called
|
||||||
end_time = time.perf_counter()
|
end_time = time.perf_counter()
|
||||||
sum_of_time += end_time - start_time
|
sum_of_time += end_time - start_time
|
||||||
sum_of_paths += len(solved_path)
|
sum_of_paths += len(solved_path)
|
||||||
save_maze(loaded_maze, True, solved_path, filename, 0)
|
save_maze(loaded_maze, True, solved_path, visited, filename, 0)
|
||||||
files_amount += 1
|
files_amount += 1
|
||||||
if files_amount == 0:
|
if files_amount == 0:
|
||||||
print("no mazes found! Generate some using python main.py -g [NUMBER]")
|
print("no mazes found! Generate some using python main.py -g [NUMBER]")
|
||||||
@ -315,6 +333,7 @@ def test_mode():
|
|||||||
all_heuristic_called: {all_heuristic_called},
|
all_heuristic_called: {all_heuristic_called},
|
||||||
average_heuristic_time: {heuristic_total_total_time / all_heuristic_called}""")
|
average_heuristic_time: {heuristic_total_total_time / all_heuristic_called}""")
|
||||||
|
|
||||||
|
|
||||||
def default():
|
def default():
|
||||||
""" Runs default operation - reads, solves and prints single maze from file """
|
""" Runs default operation - reads, solves and prints single maze from file """
|
||||||
# Open and load text file to array
|
# Open and load text file to array
|
||||||
@ -322,9 +341,10 @@ def default():
|
|||||||
# Initialize MazeSolver object with maze as parameter
|
# Initialize MazeSolver object with maze as parameter
|
||||||
solver = MazeSolver(loaded_maze, TEST_MODE)
|
solver = MazeSolver(loaded_maze, TEST_MODE)
|
||||||
# Find path using MazeSolver solve method
|
# Find path using MazeSolver solve method
|
||||||
solved_path = solver.solve()
|
solved_path, visited, _, _ = solver.solve()
|
||||||
print_maze(loaded_maze, solved_path)
|
print_maze(loaded_maze, solved_path, visited)
|
||||||
save_maze(loaded_maze, True, solved_path, FILE_NAME, 0)
|
save_maze(loaded_maze, True, solved_path, visited, FILE_NAME, 0)
|
||||||
|
|
||||||
|
|
||||||
# Ran first in the code
|
# Ran first in the code
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@ -350,7 +370,8 @@ if __name__ == "__main__":
|
|||||||
GENERATE_AMOUNT = int(sys.argv[2])
|
GENERATE_AMOUNT = int(sys.argv[2])
|
||||||
for n in range(GENERATE_AMOUNT):
|
for n in range(GENERATE_AMOUNT):
|
||||||
GENERATED_MAZE = make_maze()
|
GENERATED_MAZE = make_maze()
|
||||||
save_maze(GENERATED_MAZE, False, None, f'generated{n}.txt')
|
save_maze(GENERATED_MAZE, False, None,
|
||||||
|
None, f'generated{n}.txt')
|
||||||
sys.exit()
|
sys.exit()
|
||||||
FILE_NAME = sys.argv[1]
|
FILE_NAME = sys.argv[1]
|
||||||
default()
|
default()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user