Task 3, need to fix walk function when return home

main
Gasper Spagnolo 2022-11-12 14:32:16 +01:00
parent ae0faf5308
commit 59b97ca607
15 changed files with 2087 additions and 2853 deletions

View File

@ -74,6 +74,7 @@ class Maze:
def add_to_queue(full_path, x, y): def add_to_queue(full_path, x, y):
if (x,y) not in full_path: if (x,y) not in full_path:
full_path = full_path.copy()
full_path.append((x, y)) full_path.append((x, y))
queue.append(full_path) queue.append(full_path)

View File

@ -43,17 +43,14 @@ def on_mutation(generations, ga_instance):
# Loop through the population # Loop through the population
for i in range(len(generations)): for i in range(len(generations)):
# Firstly mutate the walls # select random number of the instances where there are walls
#generations[i] = np.random.choice([0, 1], size=len(generations[i]), replace=True) random_false_instances = np.random.choice(wall_instances, size=int(len(no_wall_instances)* random.uniform(0.01, 1.0)), replace=False)
#print(generations[i].reshape(maze.mutation_matrix.shape))
random_false_instances = np.random.choice(wall_instances, size=int(len(no_wall_instances)* random.uniform(0.01, 1)), replace=False)
# Then apply some random mutations where there are no walls
# Then randomly select random number of the instances where there are no walls # Then randomly select random number of the instances where there are no walls
random_true_instances = np.random.choice(no_wall_instances, size=int(len(no_wall_instances)* random.uniform(0.01, 1)), replace=False) random_true_instances = np.random.choice(no_wall_instances, size=int(len(no_wall_instances)* random.uniform(0.01, 1.0)), replace=False)
# Then apply those values to generation # Then apply those values to generation
generations[i][random_true_instances] = 1 generations[i][random_true_instances] = 1
generations[i][random_false_instances] = 0 generations[i][random_false_instances] = 0
#print(random_true_instances)
return generations return generations
class Maze: class Maze:
@ -65,14 +62,15 @@ class Maze:
self.mutation_matrix = mutation_matrix self.mutation_matrix = mutation_matrix
self.shortest_path = shortest_path self.shortest_path = shortest_path
self.ga_iteration = 0 self.ga_iteration = 0
self.initial_population_size = 400
def run_genetic_algorithm(self): def run_genetic_algorithm(self):
# Set global punish matrix # Set global punish matrix
punish_matrix = self.punish_matrix punish_matrix = self.punish_matrix
maze = self.maze maze = self.maze
ga_instance = pygad.GA(num_genes=punish_matrix.size, ga_instance = pygad.GA(num_genes=punish_matrix.size,
num_generations=500, num_generations=3,
sol_per_pop=400, sol_per_pop=self.initial_population_size,
num_parents_mating=200, num_parents_mating=200,
gene_type=np.uint8, gene_type=np.uint8,
fitness_func=fitness_func, fitness_func=fitness_func,
@ -81,6 +79,7 @@ class Maze:
allow_duplicate_genes=True, allow_duplicate_genes=True,
parallel_processing=1, parallel_processing=1,
mutation_type=on_mutation, mutation_type=on_mutation,
# initial_population=self.generate_initial_population(),
gene_space=[0, 1]) gene_space=[0, 1])
ga_instance.run() ga_instance.run()
@ -88,7 +87,6 @@ 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("Best solution", solution.reshape(self.punish_matrix.shape))
self.print_shortest_path() self.print_shortest_path()
def walk_through_maze(self, solution_matrix, critical_situation): def walk_through_maze(self, solution_matrix, critical_situation):
@ -134,6 +132,27 @@ class Maze:
lst[y] = 'X' lst[y] = 'X'
self.maze[x] = ''.join(lst) self.maze[x] = ''.join(lst)
self.print_maze() self.print_maze()
def generate_initial_population(self):
# Generate initial population
# Firtly find the instances where there are no walls
no_wall_instances = np.where(self.mutation_matrix.reshape(-1) == 1)[0]
wall_instances = np.where(self.mutation_matrix.reshape(-1) == 0)[0]
initial_population = np.random.choice([0, 1], size=(self.punish_matrix.size, self.initial_population_size))
for population in initial_population:
# select random number of the instances where there are walls
random_false_instances = np.random.choice(wall_instances, size=int(len(no_wall_instances)* random.uniform(0.5, 1.0)), replace=False)
# Then randomly select random number of the instances where there are no walls
random_true_instances = np.random.choice(no_wall_instances, size=int(len(no_wall_instances)* random.uniform(0.5, 1.0)), replace=False)
# Then apply those values to generation
population[random_true_instances] = 1
population[random_false_instances] = 0
print(initial_population)
return initial_population
def read_mazes(): def read_mazes():
with open('./mazes.r', 'r') as f: with open('./mazes.r', 'r') as f:
@ -172,6 +191,7 @@ def prepare_maze(maze_ix, mazes):
end_index = i, j end_index = i, j
mutation_matrix[i, j] = 1 mutation_matrix[i, j] = 1
if y == "T": if y == "T":
mutation_matrix[i, j] = 2
treasures.append((i, j)) treasures.append((i, j))
# Create maze class # Create maze class

312
a1/code/main_t3.py Normal file
View File

@ -0,0 +1,312 @@
import pygad
import numpy as np
import random
# Create a maze class
global maze_ix
def fitness_func(path, solution_idx):
maze = mazes[maze_ix]
fitness = np.sum(path * maze.punish_matrix.reshape(-1))
path = path.reshape(maze.punish_matrix.shape)
if path[maze.start_pos] == 0:
fitness -= 10000
if path[maze.end_pos] == 0:
fitness -= 10000
if path[maze.start_pos] == 1 and path[maze.end_pos] == 1:
fitness += 300
# Check if there is a valid path
complete_path = maze.walk_through_maze(path)
complete_path_len = len(complete_path)
# Check how many treasures are found
treasures_found = 0
for move in complete_path:
if move in maze.treasures:
treasures_found += 1
fitness += treasures_found * 1000
# 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:
maze.adjust_weights(complete_path)
print('First path found')
fitness += 1000 * len(maze.treasures)
maze.shortest_path = complete_path
#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:
print('Found a better path')
fitness += 1000 * len(maze.treasures)
maze.shortest_path = complete_path
maze.adjust_weights(complete_path)
maze.ga_iteration += 1
return fitness
def on_mutation(generations, ga_instance):
maze = mazes[maze_ix]
no_wall_instances = np.where(maze.mutation_matrix.reshape(-1) == 1)[0]
wall_instances = np.where(maze.mutation_matrix.reshape(-1) == 0)[0]
treasure_instances = np.where(maze.mutation_matrix.reshape(-1) == 2)[0]
cluster_instances = np.reshape(np.array(maze.clusters), -1)
# Loop through the population
for i in range(len(generations)):
# randomly select random number of the instances where there are walls
random_false_instances = np.random.choice(wall_instances, size=int(len(wall_instances)* random.uniform(0.01, 1.0)), replace=False)
# randomly select random number of the instances where there are no walls
random_true_instances = np.random.choice(no_wall_instances, size=int(len(no_wall_instances)* random.uniform(0.01, 1.0)), replace=False)
# randomly select random number of the instances where there are treasures
random_treasure_instances = np.random.choice(treasure_instances, size=int(len(treasure_instances)* random.uniform(0.01, 1.0)), replace=False)
# randomly select random number of the instances where there are clusters
random_cluster_instances = np.random.choice(cluster_instances, size=int(len(cluster_instances)* random.uniform(0.01, 1.0)), replace=False)
generations[i][random_true_instances] = 1
generations[i][random_false_instances] = 0
generations[i][random_treasure_instances] = 1
generations[i][random_cluster_instances] = 1
return generations
class Maze:
def __init__(self, maze, start_pos, end_pos, punish_matrix, mutation_matrix, treasures, shortest_path):
self.maze = maze
self.start_pos = start_pos
self.end_pos = end_pos
self.punish_matrix = punish_matrix
self.mutation_matrix = mutation_matrix
self.treasures = treasures
self.shortest_path = shortest_path
self.ga_iteration = 0
self.initial_population_size = 1000
self.clusters = []
def run_genetic_algorithm(self):
# Set global punish matrix
punish_matrix = self.punish_matrix
# Prepare treasure clusters
self.locate_treasure_clusters()
ga_instance = pygad.GA(num_genes=punish_matrix.size,
num_generations=50,
sol_per_pop=self.initial_population_size,
num_parents_mating=200,
gene_type=np.uint8,
fitness_func=fitness_func,
parent_selection_type="random",
keep_parents=2,
allow_duplicate_genes=True,
parallel_processing=1,
mutation_type=on_mutation,
initial_population=self.generate_initial_population(),
gene_space=[0, 1])
ga_instance.run()
solution, solution_fitness, solution_idx = ga_instance.best_solution()
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()
def walk_through_maze(self, solution_matrix):
queue = [[self.start_pos]]
def add_to_queue(full_path, x, y):
if (x,y) not in full_path:
full_path = full_path.copy()
full_path.append((x, y))
queue.append(full_path)
def is_valid_move(x, y):
return self.maze[x][y] == "." or self.maze[x][y] == "E" or self.maze[x][y] == "T"
while queue != []:
full_path = queue.pop()
x, y = full_path[-1]
if(self.maze[x][y] == 'E'):
return full_path
if x + 1 < len(self.maze) :
if solution_matrix[x+1, y] == 1 and is_valid_move(x+1, y):
add_to_queue(full_path, x+1, y)
if x - 1 >= 0:
if solution_matrix[x-1, y] == 1 and is_valid_move(x-1, y):
add_to_queue(full_path, x-1, y)
if y + 1 < len(self.maze) :
if solution_matrix[x, y+1] == 1 and is_valid_move(x, y+1):
add_to_queue(full_path, x, y+1)
if y - 1 >= 0:
if solution_matrix[x, y-1] == 1 and is_valid_move(x, y-1):
add_to_queue(full_path, x, y-1)
return []
def adjust_weights(self, found_path):
for (x, y) in found_path:
self.punish_matrix[x,y] += 100
def print_maze(self):
for row in self.maze:
print(' '.join(row))
def print_shortest_path(self):
for (x, y) in self.shortest_path:
if (x, y) == self.start_pos or (x, y) == self.end_pos:
continue
if (x, y) in self.treasures:
continue
lst = list(self.maze[x])
lst[y] = 'X'
self.maze[x] = ''.join(lst)
self.print_maze()
def generate_initial_population(self):
# Generate initial population
# Firtly find the instances where there are no walls
no_wall_instances = np.where(self.mutation_matrix.reshape(-1) == 1)[0]
wall_instances = np.where(self.mutation_matrix.reshape(-1) == 0)[0]
treasure_instances = np.where(self.mutation_matrix.reshape(-1) == 2)[0]
cluster_instances = np.reshape(np.array(self.clusters), -1)
initial_population = np.random.choice([0, 1], size=(self.initial_population_size, self.mutation_matrix.size))
for population in initial_population:
# select random number of the instances where there are walls
random_false_instances = np.random.choice(wall_instances, size=int(len(no_wall_instances)* random.uniform(0.5, 1.0)), replace=False)
# Randomly select random number of the instances where there are no walls
random_true_instances = np.random.choice(no_wall_instances, size=int(len(no_wall_instances)* random.uniform(0.1, 1.0)), replace=False)
# Randomly select treasure instances
random_treasure_instances = np.random.choice(treasure_instances, size=int(len(treasure_instances)* random.uniform(0.1, 1.0)), replace=False)
# Randomly select cluster instances
random_cluster_instances = np.random.choice(cluster_instances, size=int(len(cluster_instances)* random.uniform(0.1, 1.0)), replace=False)
# Then apply those values to generation
population[random_true_instances] = 1
population[random_false_instances] = 0
population[random_treasure_instances] = 1
population[random_cluster_instances] = 1
return initial_population
def locate_treasure_clusters(self):
# Find treasoure neighbours
max_cluster_size = int(self.mutation_matrix.shape[0] * 4)
clusters = []
for treasure in self.treasures:
queue = [[treasure]]
# Define add to queue function
def add_to_queue(cluster, x, y):
if (x,y) not in cluster:
cluster = cluster.copy()
cluster.append((x, y))
queue.append(cluster)
# Deine valid move function
def is_valid_move(x, y):
return self.maze[x][y] == "." or self.maze[x][y] == "E" or self.maze[x][y] == "T" or self.maze[x][y] == "S"
while queue != []:
current_cluster = queue.pop()
x, y = current_cluster[-1]
# Add cluster to clusters if we have found a big enough one
if len(current_cluster) >= max_cluster_size or (x, y) == self.end_pos or (x, y) == self.start_pos:
clusters.append(current_cluster.copy())
continue
# Add neighbours to cluster
if x + 1 < len(self.maze) :
if is_valid_move(x+1, y):
add_to_queue(current_cluster, x+1, y)
if x - 1 >= 0:
if is_valid_move(x-1, y):
add_to_queue(current_cluster, x-1, y)
if y + 1 < len(self.maze) :
if is_valid_move(x, y+1):
add_to_queue(current_cluster, x, y+1)
if y - 1 >= 0:
if is_valid_move(x, y-1):
add_to_queue(current_cluster, x, y-1)
# Now prepare clusters for mutation
mutation_clusters = clusters.copy()
print(clusters)
for i in range(len(clusters)):
for j, (x, y) in enumerate(clusters[i]):
mutation_clusters[i][j] = x * self.mutation_matrix.shape[0] + y
# Convert to numpy array
mut_clusters_np_array = []
for i in range(len(mutation_clusters)):
for j in range(len(mutation_clusters[i])):
mut_clusters_np_array.append(int(mutation_clusters[i][j]))
mut_clusters_np_array = np.array(mut_clusters_np_array)
self.clusters = mut_clusters_np_array
def read_mazes():
with open('./mazes_treasures.txt', 'r') as f:
mazes = []
maze = []
for line in f:
if line == '\n':
mazes.append(maze)
maze = []
continue
maze.append(line.strip())
return mazes
def prepare_maze(maze_ix, mazes):
maze = mazes[maze_ix]
punish_matrix = np.zeros((len(maze), len(maze)), dtype=np.int64)
mutation_matrix = np.zeros((len(maze), len(maze)), dtype=np.uint8)
start_index = 0, 0
end_index = 0, 0
treasures = []
# Initialize punish matrix and find start and end index
for i, x in enumerate(maze):
for j, y in enumerate(x):
if y == "#":
punish_matrix[i, j] = -1000
mutation_matrix[i, j] = 0
if y == ".":
punish_matrix[i, j] = +1000
mutation_matrix[i, j] = 1
if y == "S":
start_index = i, j
mutation_matrix[i, j] = 1
if y == "E":
end_index = i, j
mutation_matrix[i, j] = 1
if y == "T":
punish_matrix[i, j] = +20000
mutation_matrix[i, j] = 2
treasures.append((i, j))
# Create maze class
maze = Maze(maze, start_index, end_index, punish_matrix, mutation_matrix, treasures, [])
return maze
def main():
# Read mazes
global maze_ix, mazes
mazes = []
text_mazes = read_mazes()
for i in range(len(text_mazes)):
print('MAZE: ', i)
maze_ix = i
maze = prepare_maze(i, text_mazes)
mazes.append(maze)
maze.run_genetic_algorithm()
if __name__ == "__main__":
main()

258
a1/code/maze_generator.py Normal file
View File

@ -0,0 +1,258 @@
# Maze generator -- Randomized Prim Algorithm
## Imports
import random
import time
from colorama import init
from colorama import Fore, Back, Style
import sys
## Functions
def printMaze(maze):
maze[0][1] = 'S'
maze[height-1][width-2] = 'E'
for i in range(0, height):
for j in range(0, width):
if (maze[i][j] == 'u'):
print(Fore.WHITE + str(maze[i][j]), end="")
elif (maze[i][j] == '.'):
print(Fore.GREEN + str(maze[i][j]), end="")
else:
print(Fore.RED + str(maze[i][j]), end="")
print()
# Find number of surrounding cells
def surroundingCells(rand_wall):
s_cells = 0
if (maze[rand_wall[0]-1][rand_wall[1]] == '.'):
s_cells += 1
if (maze[rand_wall[0]+1][rand_wall[1]] == '.'):
s_cells += 1
if (maze[rand_wall[0]][rand_wall[1]-1] == '.'):
s_cells +=1
if (maze[rand_wall[0]][rand_wall[1]+1] == '.'):
s_cells += 1
return s_cells
## Main code
# Init variables
wall = '#'
cell = '.'
unvisited = 'u'
height = int(sys.argv[1])
width = int(sys.argv[1])
maze = []
# Initialize colorama
init()
# Denote all cells as unvisited
for i in range(0, height):
line = []
for j in range(0, width):
line.append(unvisited)
maze.append(line)
# Randomize starting point and set it a cell
starting_height = int(random.random()*height)
starting_width = int(random.random()*width)
if (starting_height == 0):
starting_height += 1
if (starting_height == height-1):
starting_height -= 1
if (starting_width == 0):
starting_width += 1
if (starting_width == width-1):
starting_width -= 1
# Mark it as cell and add surrounding walls to the list
maze[starting_height][starting_width] = cell
walls = []
walls.append([starting_height - 1, starting_width])
walls.append([starting_height, starting_width - 1])
walls.append([starting_height, starting_width + 1])
walls.append([starting_height + 1, starting_width])
# Denote walls in maze
maze[starting_height-1][starting_width] = '#'
maze[starting_height][starting_width - 1] = '#'
maze[starting_height][starting_width + 1] = '#'
maze[starting_height + 1][starting_width] = '#'
while (walls):
# Pick a random wall
rand_wall = walls[int(random.random()*len(walls))-1]
# Check if it is a left wall
if (rand_wall[1] != 0):
if (maze[rand_wall[0]][rand_wall[1]-1] == 'u' and maze[rand_wall[0]][rand_wall[1]+1] == '.'):
# Find the number of surrounding cells
s_cells = surroundingCells(rand_wall)
if (s_cells < 2):
# Denote the new path
maze[rand_wall[0]][rand_wall[1]] = '.'
# Mark the new walls
# Upper cell
if (rand_wall[0] != 0):
if (maze[rand_wall[0]-1][rand_wall[1]] != '.'):
maze[rand_wall[0]-1][rand_wall[1]] = '#'
if ([rand_wall[0]-1, rand_wall[1]] not in walls):
walls.append([rand_wall[0]-1, rand_wall[1]])
# Bottom cell
if (rand_wall[0] != height-1):
if (maze[rand_wall[0]+1][rand_wall[1]] != '.'):
maze[rand_wall[0]+1][rand_wall[1]] = '#'
if ([rand_wall[0]+1, rand_wall[1]] not in walls):
walls.append([rand_wall[0]+1, rand_wall[1]])
# Leftmost cell
if (rand_wall[1] != 0):
if (maze[rand_wall[0]][rand_wall[1]-1] != '.'):
maze[rand_wall[0]][rand_wall[1]-1] = '#'
if ([rand_wall[0], rand_wall[1]-1] not in walls):
walls.append([rand_wall[0], rand_wall[1]-1])
# Delete wall
for wall in walls:
if (wall[0] == rand_wall[0] and wall[1] == rand_wall[1]):
walls.remove(wall)
continue
# Check if it is an upper wall
if (rand_wall[0] != 0):
if (maze[rand_wall[0]-1][rand_wall[1]] == 'u' and maze[rand_wall[0]+1][rand_wall[1]] == '.'):
s_cells = surroundingCells(rand_wall)
if (s_cells < 2):
# Denote the new path
maze[rand_wall[0]][rand_wall[1]] = '.'
# Mark the new walls
# Upper cell
if (rand_wall[0] != 0):
if (maze[rand_wall[0]-1][rand_wall[1]] != '.'):
maze[rand_wall[0]-1][rand_wall[1]] = '#'
if ([rand_wall[0]-1, rand_wall[1]] not in walls):
walls.append([rand_wall[0]-1, rand_wall[1]])
# Leftmost cell
if (rand_wall[1] != 0):
if (maze[rand_wall[0]][rand_wall[1]-1] != '.'):
maze[rand_wall[0]][rand_wall[1]-1] = '#'
if ([rand_wall[0], rand_wall[1]-1] not in walls):
walls.append([rand_wall[0], rand_wall[1]-1])
# Rightmost cell
if (rand_wall[1] != width-1):
if (maze[rand_wall[0]][rand_wall[1]+1] != '.'):
maze[rand_wall[0]][rand_wall[1]+1] = '#'
if ([rand_wall[0], rand_wall[1]+1] not in walls):
walls.append([rand_wall[0], rand_wall[1]+1])
# Delete wall
for wall in walls:
if (wall[0] == rand_wall[0] and wall[1] == rand_wall[1]):
walls.remove(wall)
continue
# Check the bottom wall
if (rand_wall[0] != height-1):
if (maze[rand_wall[0]+1][rand_wall[1]] == 'u' and maze[rand_wall[0]-1][rand_wall[1]] == '.'):
s_cells = surroundingCells(rand_wall)
if (s_cells < 2):
# Denote the new path
maze[rand_wall[0]][rand_wall[1]] = '.'
# Mark the new walls
if (rand_wall[0] != height-1):
if (maze[rand_wall[0]+1][rand_wall[1]] != '.'):
maze[rand_wall[0]+1][rand_wall[1]] = '#'
if ([rand_wall[0]+1, rand_wall[1]] not in walls):
walls.append([rand_wall[0]+1, rand_wall[1]])
if (rand_wall[1] != 0):
if (maze[rand_wall[0]][rand_wall[1]-1] != '.'):
maze[rand_wall[0]][rand_wall[1]-1] = '#'
if ([rand_wall[0], rand_wall[1]-1] not in walls):
walls.append([rand_wall[0], rand_wall[1]-1])
if (rand_wall[1] != width-1):
if (maze[rand_wall[0]][rand_wall[1]+1] != '.'):
maze[rand_wall[0]][rand_wall[1]+1] = '#'
if ([rand_wall[0], rand_wall[1]+1] not in walls):
walls.append([rand_wall[0], rand_wall[1]+1])
# Delete wall
for wall in walls:
if (wall[0] == rand_wall[0] and wall[1] == rand_wall[1]):
walls.remove(wall)
continue
# Check the right wall
if (rand_wall[1] != width-1):
if (maze[rand_wall[0]][rand_wall[1]+1] == 'u' and maze[rand_wall[0]][rand_wall[1]-1] == '.'):
s_cells = surroundingCells(rand_wall)
if (s_cells < 2):
# Denote the new path
maze[rand_wall[0]][rand_wall[1]] = '.'
# Mark the new walls
if (rand_wall[1] != width-1):
if (maze[rand_wall[0]][rand_wall[1]+1] != '.'):
maze[rand_wall[0]][rand_wall[1]+1] = '#'
if ([rand_wall[0], rand_wall[1]+1] not in walls):
walls.append([rand_wall[0], rand_wall[1]+1])
if (rand_wall[0] != height-1):
if (maze[rand_wall[0]+1][rand_wall[1]] != '.'):
maze[rand_wall[0]+1][rand_wall[1]] = '#'
if ([rand_wall[0]+1, rand_wall[1]] not in walls):
walls.append([rand_wall[0]+1, rand_wall[1]])
if (rand_wall[0] != 0):
if (maze[rand_wall[0]-1][rand_wall[1]] != '.'):
maze[rand_wall[0]-1][rand_wall[1]] = '#'
if ([rand_wall[0]-1, rand_wall[1]] not in walls):
walls.append([rand_wall[0]-1, rand_wall[1]])
# Delete wall
for wall in walls:
if (wall[0] == rand_wall[0] and wall[1] == rand_wall[1]):
walls.remove(wall)
continue
# Delete the wall from the list anyway
for wall in walls:
if (wall[0] == rand_wall[0] and wall[1] == rand_wall[1]):
walls.remove(wall)
# Mark the remaining unvisited cells as walls
for i in range(0, height):
for j in range(0, width):
if (maze[i][j] == 'u'):
maze[i][j] = '#'
# Set entrance and exit
for i in range(0, width):
if (maze[1][i] == '.'):
maze[0][i] = '.'
break
for i in range(width-1, 0, -1):
if (maze[height-2][i] == '.'):
maze[height-1][i] = '.'
break
# Print final maze
printMaze(maze)

View File

@ -90,62 +90,3 @@
#..........###.##.## #..........###.##.##
##########E######### ##########E#########
##########
#S.......#
########.#
#..T.....#
#.########
#........#
########.#
#..T.....#
#.########
#E########
#####E####
#...#....#
#.######.#
#.#T.....#
#.###.####
#....S...#
#####.##.#
#..##.####
##....T..#
##########
###E###########
#........###..#
########.....##
#..T..##.###.##
#.###.....##..#
#.....###...###
####.####.#.###
##......#.....#
#######.#.###.#
#.........#####
#.####.S#....##
##....#.#######
#..##T........#
##...###.##.###
###############
####################
#..................#
#.##############.###
#.########.......###
#.#.T......######..#
#.##.##.##........##
#.#...#.##.######.##
#.###.#.##....T##.##
#.###..##########.##
#.####.###.........#
#.#....#...####.####
#.#.####.####.....##
#.#......#......####
#.###.####.#####...#
#.#T.....#.....#.###
#.######...#####.#.#
#.#.....##S....#.#.#
#.#########..#...T.#
#..........###.##.##
##########E#########

1303
a1/code/mazes_harder.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,59 @@
##########
#S.......#
########.#
#..T.....#
#.########
#........#
########.#
#..T.....#
#.########
#E########
#####E####
#...#....#
#.######.#
#.#T.....#
#.###.####
#....S...#
#####.##.#
#..##.####
##....T..#
##########
###E###########
#........###..#
########.....##
#..T..##.###.##
#.###.....##..#
#.....###...###
####.####.#.###
##......#.....#
#######.#.###.#
#.........#####
#.####.S#....##
##....#.#######
#..##T........#
##...###.##.###
###############
####################
#..................#
#.##############.###
#.########.......###
#.#.T......######..#
#.##.##.##........##
#.#...#.##.######.##
#.###.#.##....T##.##
#.###..##########.##
#.####.###.........#
#.#....#...####.####
#.#.####.####.....##
#.#......#......####
#.###.####.#####...#
#.#T.....#.....#.###
#.######...#####.#.#
#.#.....##S....#.#.#
#.#########..#...T.#
#..........###.##.##
##########E#########

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,26 @@
\relax \relax
\@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{1}{}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{2}{}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{\numberline {2}Solution}{1}{}\protected@file@percent } \@writefile{toc}{\contentsline {section}{\numberline {2}Solution}{2}{}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Task 1}{1}{}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Task 1}{2}{}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.1}Task description}{1}{}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.1}Task description}{2}{}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.2}Read the map into a suitable format}{2}{}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.2}Read the map into a suitable format}{2}{}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.3}Choose a suitable representation of your solutions}{2}{}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.3}Choose a suitable representation of your solutions}{3}{}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.4}Define the fitness function}{2}{}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.4}Define the fitness function}{3}{}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.5}Run the genetic algorithm with suitable settings}{3}{}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.5}Run the genetic algorithm with suitable settings}{4}{}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.6}Results}{4}{}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.6}Results}{5}{}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Solution to the first maze}}{4}{}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Solution to the first maze}}{5}{}\protected@file@percent }
\newlabel{image:task_1_maze_1}{{1}{4}} \newlabel{image:task_1_maze_1}{{1}{5}}
\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Solution to the second maze}}{5}{}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Solution to the second maze}}{5}{}\protected@file@percent }
\newlabel{image:task_1_maze_4}{{2}{5}} \newlabel{image:task_1_maze_4}{{2}{5}}
\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Solution to the fourth maze}}{5}{}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Solution to the fourth maze}}{6}{}\protected@file@percent }
\newlabel{image:task_1_maze_2}{{3}{5}} \newlabel{image:task_1_maze_2}{{3}{6}}
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Task 2}{5}{}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.2.1}Task description}{5}{}\protected@file@percent }
\@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces Example of solution using the critical section}}{6}{}\protected@file@percent } \@writefile{lof}{\contentsline {figure}{\numberline {4}{\ignorespaces Example of solution using the critical section}}{6}{}\protected@file@percent }
\newlabel{image:task_1_broken_solution.png}{{4}{6}} \newlabel{image:task_1_broken_solution.png}{{4}{6}}
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3}Task 3}{6}{}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Task 2}{7}{}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.3.1}Task description}{6}{}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {2.2.1}Task description}{7}{}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {2.4}Task 4}{6}{}\protected@file@percent } \@writefile{toc}{\contentsline {subsubsection}{\numberline {2.2.2}Mutation function}{7}{}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.4.1}Task description}{6}{}\protected@file@percent } \@writefile{toc}{\contentsline {subsection}{\numberline {2.3}Task 3}{8}{}\protected@file@percent }
\gdef \@abspage@last{7} \@writefile{toc}{\contentsline {subsubsection}{\numberline {2.3.1}Task description}{8}{}\protected@file@percent }
\@writefile{toc}{\contentsline {subsection}{\numberline {2.4}Task 4}{8}{}\protected@file@percent }
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.4.1}Task description}{8}{}\protected@file@percent }
\gdef \@abspage@last{8}

View File

@ -1,5 +1,5 @@
# Fdb version 3 # Fdb version 3
["pdflatex"] 1668174467 "solution.tex" "solution.pdf" "solution" 1668174467 ["pdflatex"] 1668248665 "solution.tex" "solution.pdf" "solution" 1668248665
"/usr/share/texmf-dist/fonts/enc/dvips/cm-super/cm-super-ts1.enc" 1650183167 2900 1537cc8184ad1792082cd229ecc269f4 "" "/usr/share/texmf-dist/fonts/enc/dvips/cm-super/cm-super-ts1.enc" 1650183167 2900 1537cc8184ad1792082cd229ecc269f4 ""
"/usr/share/texmf-dist/fonts/map/fontname/texfonts.map" 1650183167 3524 cb3e574dea2d1052e39280babc910dc8 "" "/usr/share/texmf-dist/fonts/map/fontname/texfonts.map" 1650183167 3524 cb3e574dea2d1052e39280babc910dc8 ""
"/usr/share/texmf-dist/fonts/tfm/jknappen/ec/tcrm0900.tfm" 1650183167 1536 c4f439db76ef96a9c53bc437f35ffe20 "" "/usr/share/texmf-dist/fonts/tfm/jknappen/ec/tcrm0900.tfm" 1650183167 1536 c4f439db76ef96a9c53bc437f35ffe20 ""
@ -60,8 +60,8 @@
"images/task_1_maze_1.png" 1668172516 710 43064669273650dfbed9c0cc6fabcd6f "" "images/task_1_maze_1.png" 1668172516 710 43064669273650dfbed9c0cc6fabcd6f ""
"images/task_1_maze_2.png" 1668172594 1008 3c4a6780b53a0d5f210b92134871c99b "" "images/task_1_maze_2.png" 1668172594 1008 3c4a6780b53a0d5f210b92134871c99b ""
"images/task_1_maze_4.png" 1668172642 1705 f7a57d75e6d72aea9a0ee3f665d50352 "" "images/task_1_maze_4.png" 1668172642 1705 f7a57d75e6d72aea9a0ee3f665d50352 ""
"solution.aux" 1668174467 2444 ec73992920b6701b96ff4a887373b303 "pdflatex" "solution.aux" 1668248665 2559 324baa123d44a542a7394a6f62000bfc "pdflatex"
"solution.tex" 1668174466 11592 169bf2cf5ca482b811a98bc7590e219e "" "solution.tex" 1668248663 13838 6a0310ac335345580487b2cace0bb73b ""
(generated) (generated)
"solution.aux" "solution.aux"
"solution.log" "solution.log"

View File

@ -190,6 +190,8 @@ INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmsy6.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmex10.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmex10.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm
OUTPUT solution.pdf
INPUT /var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map
INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmr12.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmr12.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm
@ -198,8 +200,6 @@ INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmtt10.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmbx12.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmbx10.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmbx10.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/jknappen/ec/tcrm1000.tfm INPUT /usr/share/texmf-dist/fonts/tfm/jknappen/ec/tcrm1000.tfm
OUTPUT solution.pdf
INPUT /var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map
INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmtt9.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmtt9.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/jknappen/ec/tcrm0900.tfm INPUT /usr/share/texmf-dist/fonts/tfm/jknappen/ec/tcrm0900.tfm
INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmti10.tfm INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmti10.tfm

View File

@ -1,4 +1,4 @@
This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022/Arch Linux) (preloaded format=pdflatex 2022.11.9) 11 NOV 2022 14:47 This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022/Arch Linux) (preloaded format=pdflatex 2022.11.9) 12 NOV 2022 11:24
entering extended mode entering extended mode
restricted \write18 enabled. restricted \write18 enabled.
file:line:error style messages enabled. file:line:error style messages enabled.
@ -148,70 +148,86 @@ Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 48
File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Live File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Live
)) [1 )) [1
{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] [2] {/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] [2] [3]
Overfull \hbox (28.27066pt too wide) in paragraph at lines 111--111 Overfull \hbox (28.27066pt too wide) in paragraph at lines 114--114
[]\OT1/cmtt/m/n/9 (critical_situation or (self.maze[x+1][y] == "." or self.maze[x+1][y] == "E")):[] []\OT1/cmtt/m/n/9 (critical_situation or (self.maze[x+1][y] == "." or self.maze[x+1][y] == "E")):[]
[] []
Overfull \hbox (28.27066pt too wide) in paragraph at lines 111--111 Overfull \hbox (28.27066pt too wide) in paragraph at lines 114--114
[]\OT1/cmtt/m/n/9 (critical_situation or (self.maze[x-1][y] == "." or self.maze[x-1][y] == "E")):[] []\OT1/cmtt/m/n/9 (critical_situation or (self.maze[x-1][y] == "." or self.maze[x-1][y] == "E")):[]
[] []
Overfull \hbox (23.54572pt too wide) in paragraph at lines 111--111 Overfull \hbox (23.54572pt too wide) in paragraph at lines 114--114
[]\OT1/cmtt/m/n/9 (critical_situation or(self.maze[x][y+1] == "." or self.maze[x][y+1] == "E")):[] []\OT1/cmtt/m/n/9 (critical_situation or(self.maze[x][y+1] == "." or self.maze[x][y+1] == "E")):[]
[] []
Overfull \hbox (28.27066pt too wide) in paragraph at lines 111--111 Overfull \hbox (28.27066pt too wide) in paragraph at lines 114--114
[]\OT1/cmtt/m/n/9 (critical_situation or (self.maze[x][y-1] == "." or self.maze[x][y-1] == "E")):[] []\OT1/cmtt/m/n/9 (critical_situation or (self.maze[x][y-1] == "." or self.maze[x][y-1] == "E")):[]
[] []
[3] [4]
<./images/task_1_maze_1.png, id=23, 55.20625pt x 75.28125pt> <./images/task_1_maze_1.png, id=26, 55.20625pt x 75.28125pt>
File: ./images/task_1_maze_1.png Graphic file (type png) File: ./images/task_1_maze_1.png Graphic file (type png)
<use ./images/task_1_maze_1.png> <use ./images/task_1_maze_1.png>
Package pdftex.def Info: ./images/task_1_maze_1.png used on input line 156. Package pdftex.def Info: ./images/task_1_maze_1.png used on input line 159.
(pdftex.def) Requested size: 28.45274pt x 38.79956pt. (pdftex.def) Requested size: 28.45274pt x 38.79956pt.
<./images/task_1_maze_2.png, id=24, 80.3pt x 106.3975pt> <./images/task_1_maze_2.png, id=27, 80.3pt x 106.3975pt>
File: ./images/task_1_maze_2.png Graphic file (type png) File: ./images/task_1_maze_2.png Graphic file (type png)
<use ./images/task_1_maze_2.png> <use ./images/task_1_maze_2.png>
Package pdftex.def Info: ./images/task_1_maze_2.png used on input line 166. Package pdftex.def Info: ./images/task_1_maze_2.png used on input line 169.
(pdftex.def) Requested size: 56.9055pt x 75.4015pt. (pdftex.def) Requested size: 56.9055pt x 75.4015pt.
<./images/task_1_maze_4.png, id=28, 115.43124pt x 153.57375pt>
LaTeX Warning: `h' float specifier changed to `ht'.
[4 <./images/task_1_maze_1.png (PNG copy)>]
<./images/task_1_maze_4.png, id=29, 115.43124pt x 153.57375pt>
File: ./images/task_1_maze_4.png Graphic file (type png) File: ./images/task_1_maze_4.png Graphic file (type png)
<use ./images/task_1_maze_4.png> <use ./images/task_1_maze_4.png>
Package pdftex.def Info: ./images/task_1_maze_4.png used on input line 178. Package pdftex.def Info: ./images/task_1_maze_4.png used on input line 181.
(pdftex.def) Requested size: 85.35826pt x 113.56311pt. (pdftex.def) Requested size: 85.35826pt x 113.56311pt.
<./images/task_1_broken_solution.png, id=30, 115.43124pt x 150.5625pt>
File: ./images/task_1_broken_solution.png Graphic file (type png)
<use ./images/task_1_broken_solution.png>
Package pdftex.def Info: ./images/task_1_broken_solution.png used on input line 187.
(pdftex.def) Requested size: 113.81102pt x 148.4485pt.
LaTeX Warning: `h' float specifier changed to `ht'. LaTeX Warning: `h' float specifier changed to `ht'.
[5 <./images/task_1_maze_2.png (PNG copy)> <./images/task_1_maze_4.png (PNG copy)>] [6 <./images/task_1_broken_solution.png (PNG copy)>] [7] (./solution.aux) ) [5 <./images/task_1_maze_1.png (PNG copy)> <./images/task_1_maze_2.png (PNG copy)>]
<./images/task_1_broken_solution.png, id=33, 115.43124pt x 150.5625pt>
File: ./images/task_1_broken_solution.png Graphic file (type png)
<use ./images/task_1_broken_solution.png>
Package pdftex.def Info: ./images/task_1_broken_solution.png used on input line 190.
(pdftex.def) Requested size: 85.35826pt x 111.33638pt.
[6 <./images/task_1_maze_4.png (PNG copy)> <./images/task_1_broken_solution.png (PNG copy)>]
Overfull \hbox (4.64594pt too wide) in paragraph at lines 238--238
[] \OT1/cmtt/m/n/9 no_wall_instances = np.where(maze.mutation_matrix.reshape(-1) == 1)[0][]
[]
Overfull \hbox (9.37088pt too wide) in paragraph at lines 238--238
[]\OT1/cmtt/m/n/9 size=int(len(no_wall_instances)* random.uniform(0.01, 1.0)), replace=False)[]
[]
Overfull \hbox (61.34528pt too wide) in paragraph at lines 238--238
[] \OT1/cmtt/m/n/9 # Then randomly select random number of the instances where there are no walls[]
[]
Overfull \hbox (9.37088pt too wide) in paragraph at lines 238--238
[]\OT1/cmtt/m/n/9 size=int(len(no_wall_instances)* random.uniform(0.01, 1.0)), replace=False)[]
[]
[7] [8] (./solution.aux) )
Here is how much of TeX's memory you used: Here is how much of TeX's memory you used:
2440 strings out of 478238 2440 strings out of 478238
37964 string characters out of 5850456 37964 string characters out of 5850456
343329 words of memory out of 5000000 344329 words of memory out of 5000000
20682 multiletter control sequences out of 15000+600000 20682 multiletter control sequences out of 15000+600000
476294 words of font info for 53 fonts, out of 8000000 for 9000 476294 words of font info for 53 fonts, out of 8000000 for 9000
1141 hyphenation exceptions out of 8191 1141 hyphenation exceptions out of 8191
55i,6n,62p,281b,316s stack positions out of 5000i,500n,10000p,200000b,80000s 55i,6n,62p,399b,317s stack positions out of 5000i,500n,10000p,200000b,80000s
{/usr/share/texmf-dist/fonts/enc/dvips/cm-super/cm-super-ts1.enc}</usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmr12.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmr17.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmr9.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmti10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmtt10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmtt9.pfb></usr/share/texmf-dist/fonts/type1/public/cm-super/sfrm0900.pfb></usr/share/texmf-dist/fonts/type1/public/cm-super/sfrm1000.pfb> {/usr/share/texmf-dist/fonts/enc/dvips/cm-super/cm-super-ts1.enc}</usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmbx12.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmr12.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmr17.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmr9.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmti10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmtt10.pfb></usr/share/texmf-dist/fonts/type1/public/amsfonts/cm/cmtt9.pfb></usr/share/texmf-dist/fonts/type1/public/cm-super/sfrm0900.pfb></usr/share/texmf-dist/fonts/type1/public/cm-super/sfrm1000.pfb>
Output written on solution.pdf (7 pages, 172599 bytes). Output written on solution.pdf (8 pages, 175065 bytes).
PDF statistics: PDF statistics:
93 PDF objects out of 1000 (max. 8388607) 96 PDF objects out of 1000 (max. 8388607)
55 compressed objects within 1 object stream 57 compressed objects within 1 object stream
0 named destinations out of 1000 (max. 500000) 0 named destinations out of 1000 (max. 500000)
21 words of extra memory for PDF output out of 10000 (max. 10000000) 21 words of extra memory for PDF output out of 10000 (max. 10000000)

Binary file not shown.

Binary file not shown.

View File

@ -8,7 +8,9 @@
Seminar Assignment 1\\ Seminar Assignment 1\\
\small Intelligent Systems - FRI} \small Intelligent Systems - FRI}
\author{Gasper Spagnolo} \author{Gasper Spagnolo}
\maketitle \section{Introduction} \maketitle
\pagebreak
\section{Introduction}
In the first seminar assignment, your goal is to use genetic algorithms to find a path out of a maze, In the first seminar assignment, your goal is to use genetic algorithms to find a path out of a maze,
represented as a vector of strings, where $\#$ characters represent walls, $.$ represent empty spaces, and represented as a vector of strings, where $\#$ characters represent walls, $.$ represent empty spaces, and
S and E represent the starting and ending points, as in a given example below: S and E represent the starting and ending points, as in a given example below:
@ -83,6 +85,7 @@ The critical section evaluation in code is done as follows:
def add_to_queue(full_path, x, y): def add_to_queue(full_path, x, y):
if (x,y) not in full_path: if (x,y) not in full_path:
full_path = full_path.copy()
full_path.append((x, y)) full_path.append((x, y))
queue.append(full_path) queue.append(full_path)
@ -120,9 +123,9 @@ I used the following settings wen running the algorithm:
So the solution is a vector of size N * M. So the solution is a vector of size N * M.
\item \begin{verbatim} num_of_generations = 1000 \end{verbatim} \item \begin{verbatim} num_of_generations = 1000 \end{verbatim}
How many generations will the algorithm run. How many generations will the algorithm run.
\item \begin{verbatim} sol_per_pop = 2 \end{verbatim} \item \begin{verbatim} sol_per_pop = 20 \end{verbatim}
Number of solutions in the population. Number of possible solutions in the population.
\item \begin{verbatim} num_parents_mating = 2 \end{verbatim} \item \begin{verbatim} num_parents_mating = 15 \end{verbatim}
Number of solutions to be selected as parents in the mating pool. Number of solutions to be selected as parents in the mating pool.
\item \begin{verbatim} keep_parents = -1 \end{verbatim} \item \begin{verbatim} keep_parents = -1 \end{verbatim}
If -1, this means all parents in the current population will be used in the next population If -1, this means all parents in the current population will be used in the next population
@ -184,7 +187,7 @@ Other mazes found also found some solutions, but they were not optimal. Or they
\begin{figure}[h] \begin{figure}[h]
\centering \centering
\includegraphics[width=4cm]{./images/task_1_broken_solution.png} \includegraphics[width=3cm]{./images/task_1_broken_solution.png}
\caption{Example of solution using the critical section} \caption{Example of solution using the critical section}
\label{image:task_1_broken_solution.png} \label{image:task_1_broken_solution.png}
\end{figure} \end{figure}
@ -192,6 +195,7 @@ Other mazes found also found some solutions, but they were not optimal. Or they
So I will try to improve them in the following sections. So I will try to improve them in the following sections.
\pagebreak
\subsection{Task 2} \subsection{Task 2}
\subsubsection{Task description} \subsubsection{Task description}
@ -202,6 +206,51 @@ Additionally, try to create a starting population in a way that takes walls into
You can base your crossover and mutation functions on existing GA library functions. You can base your crossover and mutation functions on existing GA library functions.
Modify at least one crossover or mutation function in a way that makes them more suitable for this task. Modify at least one crossover or mutation function in a way that makes them more suitable for this task.
\subsubsection{Mutation function}
I initially used the random mutation type provided by library pygad. It was not good enough for this task, because it was not taking into account the walls.
So I redefined mutation function in such way, that we add random bits where there is no wall. If there is a wall, we set random number of bits to 0.
The function is defined as follows:
\begin{small}
\begin{center}
\begin{verbatim}
def on_mutation(generations, ga_instance):
maze = mazes[maze_ix]
# Firtly find the instances where there are no walls
no_wall_instances = np.where(maze.mutation_matrix.reshape(-1) == 1)[0]
wall_instances = np.where(maze.mutation_matrix.reshape(-1) == 0)[0]
# Loop through the population
for i in range(len(generations)):
# select random number of the instances where there are walls
random_false_instances = np.random.choice(wall_instances,
size=int(len(wall_instances)* random.uniform(0.01, 1.0)), replace=False)
# Then randomly select random number of the instances where there are no walls
random_true_instances = np.random.choice(no_wall_instances,
size=int(len(no_wall_instances)* random.uniform(0.01, 1.0)), replace=False)
# Then apply those values to generation
generations[i][random_true_instances] = 1
generations[i][random_false_instances] = 0
return generations
\end{verbatim}
\end{center}
\end{small}
I also generated the initial population using the same function, but firstly I generated some random bitarrays and then applied the same function to them.
\begin{small}
\begin{center}
\begin{verbatim}
initial_population = np.random.choice([0, 1],
size=(self.punish_matrix.size, self.initial_population_size))
\end{verbatim}
\end{center}
\end{small}
The results I got using this approach were suprising! I got a perfect score on all mazes. I think that the reason for this is that the mutation function is not only taking into account the walls, but also the previous solution. The algorithm converges really fast now. In 5 generations we get a shortest path! I even generated a 10000 x 10000 maze and it solved it!
\subsection{Task 3} \subsection{Task 3}
\subsubsection{Task description} \subsubsection{Task description}