main
Gasper Spagnolo 2022-11-12 17:04:54 +01:00
parent 59b97ca607
commit 2e053488fd
5 changed files with 155078 additions and 1327 deletions

8
a1/code/generate_mazes.sh Executable file
View File

@ -0,0 +1,8 @@
!#/bin/bash
# loop from 10 to 1000 in steps of 10
for i in {10..1000..10}
do
# generate a maze of size i
./maze_generator.py $i >> mazes_harder.txt
done

View File

@ -18,31 +18,46 @@ def fitness_func(path, solution_idx):
if path[maze.start_pos] == 1 and path[maze.end_pos] == 1: if path[maze.start_pos] == 1 and path[maze.end_pos] == 1:
fitness += 300 fitness += 300
# Check if there is a valid path # Check if there is a valid path
complete_path = maze.walk_through_maze(path) # First check if there is a path from start to end
complete_path_len = len(complete_path) paths = []
complete_path = maze.walk_through_maze(path, maze.end_pos)
paths.extend(complete_path)
# Check how many treasures are found # Then for each treasure find a path from start to treasure
treasures_found = 0 treasures_found = 0
for move in complete_path: if complete_path != []:
if move in maze.treasures: for treasure in maze.treasures:
treasures_found += 1 treasure_path = maze.walk_through_maze(path, treasure)
if treasure_path != []:
fitness += treasures_found * 1000 treasures_found += 1
paths.extend(treasure_path)
# Remove duplicates
path = list(set(paths))
path_len = len(path)
# Set the first path found as the shotest one # Set the first path found as the shotest one
if maze.shortest_path == [] and complete_path_len > 0 and treasures_found >= len(maze.treasures) // 2: if maze.shortest_path == [] and path_len > 0 and treasures_found >= len(maze.treasures) // 2:
maze.adjust_weights(complete_path) fitness += treasures_found * 1000
print('First path found') print('First path found')
fitness += 1000 * len(maze.treasures) maze.shortest_path = path
maze.shortest_path = complete_path maze.treasures_found = treasures_found
maze.adjust_weights(complete_path)
#Check if the current path is shorter than the shortest one #Check if the current path is shorter than the shortest one
if complete_path_len != 0 and complete_path_len < len(maze.shortest_path) and treasures_found >= len(maze.treasures) // 2: elif treasures_found > maze.treasures_found and path_len > 0:
print('Found a better path') fitness += 1000 * treasures_found
fitness += 1000 * len(maze.treasures) print('Path with more treasures found!')
maze.shortest_path = complete_path maze.shortest_path = path
maze.treasures_found = treasures_found
maze.adjust_weights(complete_path) maze.adjust_weights(complete_path)
elif path_len < len(maze.shortest_path) and treasures_found > maze.treasures_found and path_len > 0:
fitness += 1000 * treasures_found
print('Path with less steps found!')
maze.shortest_path = path
maze.treasures_found = treasures_found
maze.adjust_weights(complete_path)
maze.ga_iteration += 1 maze.ga_iteration += 1
return fitness return fitness
@ -83,8 +98,9 @@ class Maze:
self.treasures = treasures self.treasures = treasures
self.shortest_path = shortest_path self.shortest_path = shortest_path
self.ga_iteration = 0 self.ga_iteration = 0
self.initial_population_size = 1000 self.initial_population_size = 400
self.clusters = [] self.clusters = []
self.treasures_found = 0
def run_genetic_algorithm(self): def run_genetic_algorithm(self):
# Set global punish matrix # Set global punish matrix
@ -94,7 +110,7 @@ class Maze:
self.locate_treasure_clusters() self.locate_treasure_clusters()
ga_instance = pygad.GA(num_genes=punish_matrix.size, ga_instance = pygad.GA(num_genes=punish_matrix.size,
num_generations=50, num_generations=10,
sol_per_pop=self.initial_population_size, sol_per_pop=self.initial_population_size,
num_parents_mating=200, num_parents_mating=200,
gene_type=np.uint8, gene_type=np.uint8,
@ -112,10 +128,9 @@ class Maze:
print("The shortest path is", self.shortest_path, self.ga_iteration) print("The shortest path is", self.shortest_path, self.ga_iteration)
print("The best solution is", solution.reshape(self.punish_matrix.shape))
self.print_shortest_path() self.print_shortest_path()
def walk_through_maze(self, solution_matrix): def walk_through_maze(self, solution_matrix, finish_coordinates):
queue = [[self.start_pos]] queue = [[self.start_pos]]
def add_to_queue(full_path, x, y): def add_to_queue(full_path, x, y):
@ -130,7 +145,7 @@ class Maze:
while queue != []: while queue != []:
full_path = queue.pop() full_path = queue.pop()
x, y = full_path[-1] x, y = full_path[-1]
if(self.maze[x][y] == 'E'): if((x, y) == finish_coordinates):
return full_path return full_path
if x + 1 < len(self.maze) : if x + 1 < len(self.maze) :
if solution_matrix[x+1, y] == 1 and is_valid_move(x+1, y): if solution_matrix[x+1, y] == 1 and is_valid_move(x+1, y):
@ -195,7 +210,7 @@ class Maze:
def locate_treasure_clusters(self): def locate_treasure_clusters(self):
# Find treasoure neighbours # Find treasoure neighbours
max_cluster_size = int(self.mutation_matrix.shape[0] * 4) max_cluster_size = int(self.mutation_matrix.shape[0])
clusters = [] clusters = []
for treasure in self.treasures: for treasure in self.treasures:
queue = [[treasure]] queue = [[treasure]]
@ -235,8 +250,6 @@ class Maze:
# Now prepare clusters for mutation # Now prepare clusters for mutation
mutation_clusters = clusters.copy() mutation_clusters = clusters.copy()
print(clusters)
for i in range(len(clusters)): for i in range(len(clusters)):
for j, (x, y) in enumerate(clusters[i]): for j, (x, y) in enumerate(clusters[i]):
mutation_clusters[i][j] = x * self.mutation_matrix.shape[0] + y mutation_clusters[i][j] = x * self.mutation_matrix.shape[0] + y

0
a1/code/maze_generator.py Normal file → Executable file
View File

File diff suppressed because it is too large Load Diff

155033
a1/code/time Normal file

File diff suppressed because it is too large Load Diff