Task 3, need to fix walk function when return home
parent
ae0faf5308
commit
59b97ca607
|
@ -74,6 +74,7 @@ class Maze:
|
|||
|
||||
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)
|
||||
|
||||
|
|
|
@ -43,17 +43,14 @@ def on_mutation(generations, ga_instance):
|
|||
|
||||
# Loop through the population
|
||||
for i in range(len(generations)):
|
||||
# Firstly mutate the walls
|
||||
#generations[i] = np.random.choice([0, 1], size=len(generations[i]), replace=True)
|
||||
#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
|
||||
# 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.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)), 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
|
||||
generations[i][random_true_instances] = 1
|
||||
generations[i][random_false_instances] = 0
|
||||
#print(random_true_instances)
|
||||
|
||||
return generations
|
||||
|
||||
class Maze:
|
||||
|
@ -65,14 +62,15 @@ class Maze:
|
|||
self.mutation_matrix = mutation_matrix
|
||||
self.shortest_path = shortest_path
|
||||
self.ga_iteration = 0
|
||||
self.initial_population_size = 400
|
||||
|
||||
def run_genetic_algorithm(self):
|
||||
# Set global punish matrix
|
||||
punish_matrix = self.punish_matrix
|
||||
maze = self.maze
|
||||
ga_instance = pygad.GA(num_genes=punish_matrix.size,
|
||||
num_generations=500,
|
||||
sol_per_pop=400,
|
||||
num_generations=3,
|
||||
sol_per_pop=self.initial_population_size,
|
||||
num_parents_mating=200,
|
||||
gene_type=np.uint8,
|
||||
fitness_func=fitness_func,
|
||||
|
@ -81,6 +79,7 @@ class Maze:
|
|||
allow_duplicate_genes=True,
|
||||
parallel_processing=1,
|
||||
mutation_type=on_mutation,
|
||||
# initial_population=self.generate_initial_population(),
|
||||
gene_space=[0, 1])
|
||||
ga_instance.run()
|
||||
|
||||
|
@ -88,7 +87,6 @@ class Maze:
|
|||
|
||||
|
||||
print("The shortest path is", self.shortest_path, self.ga_iteration)
|
||||
print("Best solution", solution.reshape(self.punish_matrix.shape))
|
||||
self.print_shortest_path()
|
||||
|
||||
def walk_through_maze(self, solution_matrix, critical_situation):
|
||||
|
@ -135,6 +133,27 @@ class Maze:
|
|||
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]
|
||||
|
||||
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():
|
||||
with open('./mazes.r', 'r') as f:
|
||||
mazes = []
|
||||
|
@ -172,6 +191,7 @@ def prepare_maze(maze_ix, mazes):
|
|||
end_index = i, j
|
||||
mutation_matrix[i, j] = 1
|
||||
if y == "T":
|
||||
mutation_matrix[i, j] = 2
|
||||
treasures.append((i, j))
|
||||
|
||||
# Create maze class
|
||||
|
|
|
@ -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()
|
|
@ -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)
|
|
@ -90,62 +90,3 @@
|
|||
#..........###.##.##
|
||||
##########E#########
|
||||
|
||||
##########
|
||||
#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
|
@ -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
|
@ -1,25 +1,26 @@
|
|||
\relax
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{1}{}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {2}Solution}{1}{}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.1}Task 1}{1}{}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.1.1}Task description}{1}{}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{2}{}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {2}Solution}{2}{}\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}{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.4}Define the fitness function}{2}{}\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.6}Results}{4}{}\protected@file@percent }
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Solution to the first maze}}{4}{}\protected@file@percent }
|
||||
\newlabel{image:task_1_maze_1}{{1}{4}}
|
||||
\@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}{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}{5}{}\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}{5}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Solution to the second maze}}{5}{}\protected@file@percent }
|
||||
\newlabel{image:task_1_maze_4}{{2}{5}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces Solution to the fourth maze}}{5}{}\protected@file@percent }
|
||||
\newlabel{image:task_1_maze_2}{{3}{5}}
|
||||
\@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 {3}{\ignorespaces Solution to the fourth maze}}{6}{}\protected@file@percent }
|
||||
\newlabel{image:task_1_maze_2}{{3}{6}}
|
||||
\@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}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3}Task 3}{6}{}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.3.1}Task description}{6}{}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.4}Task 4}{6}{}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.4.1}Task description}{6}{}\protected@file@percent }
|
||||
\gdef \@abspage@last{7}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2}Task 2}{7}{}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.2.1}Task description}{7}{}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsubsection}{\numberline {2.2.2}Mutation function}{7}{}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3}Task 3}{8}{}\protected@file@percent }
|
||||
\@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}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# 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/map/fontname/texfonts.map" 1650183167 3524 cb3e574dea2d1052e39280babc910dc8 ""
|
||||
"/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_2.png" 1668172594 1008 3c4a6780b53a0d5f210b92134871c99b ""
|
||||
"images/task_1_maze_4.png" 1668172642 1705 f7a57d75e6d72aea9a0ee3f665d50352 ""
|
||||
"solution.aux" 1668174467 2444 ec73992920b6701b96ff4a887373b303 "pdflatex"
|
||||
"solution.tex" 1668174466 11592 169bf2cf5ca482b811a98bc7590e219e ""
|
||||
"solution.aux" 1668248665 2559 324baa123d44a542a7394a6f62000bfc "pdflatex"
|
||||
"solution.tex" 1668248663 13838 6a0310ac335345580487b2cace0bb73b ""
|
||||
(generated)
|
||||
"solution.aux"
|
||||
"solution.log"
|
||||
|
|
|
@ -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/amsfonts/cmextra/cmex8.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/cmbx12.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/cmbx10.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/jknappen/ec/tcrm0900.tfm
|
||||
INPUT /usr/share/texmf-dist/fonts/tfm/public/cm/cmti10.tfm
|
||||
|
|
|
@ -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
|
||||
restricted \write18 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
|
||||
)) [1
|
||||
|
||||
{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] [2]
|
||||
Overfull \hbox (28.27066pt too wide) in paragraph at lines 111--111
|
||||
{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] [2] [3]
|
||||
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")):[]
|
||||
[]
|
||||
|
||||
|
||||
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")):[]
|
||||
[]
|
||||
|
||||
|
||||
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")):[]
|
||||
[]
|
||||
|
||||
|
||||
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")):[]
|
||||
[]
|
||||
|
||||
[3]
|
||||
<./images/task_1_maze_1.png, id=23, 55.20625pt x 75.28125pt>
|
||||
[4]
|
||||
<./images/task_1_maze_1.png, id=26, 55.20625pt x 75.28125pt>
|
||||
File: ./images/task_1_maze_1.png Graphic file (type 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.
|
||||
<./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)
|
||||
<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.
|
||||
|
||||
|
||||
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>
|
||||
<./images/task_1_maze_4.png, id=28, 115.43124pt x 153.57375pt>
|
||||
File: ./images/task_1_maze_4.png Graphic file (type 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.
|
||||
<./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'.
|
||||
|
||||
[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:
|
||||
2440 strings out of 478238
|
||||
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
|
||||
476294 words of font info for 53 fonts, out of 8000000 for 9000
|
||||
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>
|
||||
Output written on solution.pdf (7 pages, 172599 bytes).
|
||||
Output written on solution.pdf (8 pages, 175065 bytes).
|
||||
PDF statistics:
|
||||
93 PDF objects out of 1000 (max. 8388607)
|
||||
55 compressed objects within 1 object stream
|
||||
96 PDF objects out of 1000 (max. 8388607)
|
||||
57 compressed objects within 1 object stream
|
||||
0 named destinations out of 1000 (max. 500000)
|
||||
21 words of extra memory for PDF output out of 10000 (max. 10000000)
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -8,7 +8,9 @@
|
|||
Seminar Assignment 1\\
|
||||
\small Intelligent Systems - FRI}
|
||||
\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,
|
||||
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:
|
||||
|
@ -83,6 +85,7 @@ The critical section evaluation in code is done as follows:
|
|||
|
||||
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)
|
||||
|
||||
|
@ -120,9 +123,9 @@ I used the following settings wen running the algorithm:
|
|||
So the solution is a vector of size N * M.
|
||||
\item \begin{verbatim} num_of_generations = 1000 \end{verbatim}
|
||||
How many generations will the algorithm run.
|
||||
\item \begin{verbatim} sol_per_pop = 2 \end{verbatim}
|
||||
Number of solutions in the population.
|
||||
\item \begin{verbatim} num_parents_mating = 2 \end{verbatim}
|
||||
\item \begin{verbatim} sol_per_pop = 20 \end{verbatim}
|
||||
Number of possible solutions in the population.
|
||||
\item \begin{verbatim} num_parents_mating = 15 \end{verbatim}
|
||||
Number of solutions to be selected as parents in the mating pool.
|
||||
\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
|
||||
|
@ -184,7 +187,7 @@ Other mazes found also found some solutions, but they were not optimal. Or they
|
|||
|
||||
\begin{figure}[h]
|
||||
\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}
|
||||
\label{image:task_1_broken_solution.png}
|
||||
\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.
|
||||
|
||||
\pagebreak
|
||||
\subsection{Task 2}
|
||||
|
||||
\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.
|
||||
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}
|
||||
|
||||
\subsubsection{Task description}
|
||||
|
|
Loading…
Reference in New Issue