diff --git a/astar2.py b/astar2.py index 415e2c5..2bab99d 100644 --- a/astar2.py +++ b/astar2.py @@ -263,6 +263,22 @@ class SweeperAgent: a_column = column location = tuple([a_row, a_column]) allowed_points.add(location) + + @staticmethod + def set_allowed_for_genetic(allowed_points, map_location): + temp_map = [list(item) for item in SweeperAgent.loadMap(map_location)] + + a_row = 0 + a_column = 0 + + for row in range(MAP_SIZE): + for column, pos in enumerate(temp_map[row]): + if pos == "." or pos == 'x': + a_row = row + a_column = column + location = tuple([a_row, a_column]) + allowed_points.add(location) + @staticmethod def set_puddles(puddle_points): @@ -351,6 +367,34 @@ class SweeperAgent: return orientation + @staticmethod + def run_manual(self, + given_orientation, + given_goal_orientation, + x_my_location, + y_my_location, + x_goal_location, + y_goal_location, + map_location + ): + + self.orientation = given_orientation + goal_orientation = given_goal_orientation + + SweeperAgent.set_allowed(self.set_allowed_for_genetic(map_location)) + + x = x_my_location + y = y_my_location + + x1 = x_goal_location + x2 = y_goal_location + + agent_position = AgentPosition(x, y, self.orientation) + goal_position = AgentPosition(x1, x2, goal_orientation) + + return len(self.plan_route(agent_position, goal_position, self.allowed_points, self.puddle_points)) + + @staticmethod def run(self): diff --git a/genetic.py b/genetic.py new file mode 100644 index 0000000..03936db --- /dev/null +++ b/genetic.py @@ -0,0 +1,278 @@ +import random + +class Genetic(): + pass + + + + + + + def calc_cost(self, mines_list): + self.mined_tile_count = len(mines_list) + total_cost = 0 + i = 0 + while i < (self.mined_tile_count - 1): + total_cost = total_cost + self.manhattan_cost_counter(mines_list, i) + i = i + 1 + + return total_cost + + def manhattan_cost_counter(self, mines_list, i): + + + x1, y1 = mines_list[i][0], mines_list[i][1] + x2, y2 = mines_list[i+1][0], mines_list[i+1][1] + + + return abs(x2 - x1) + abs(y2 - y1) + + def population_initialization(self, mines_list, i): + first_mine = mines_list[0] + x = len(mines_list)-1 + shuffled_coordinates = [] + while x > 0: + shuffled_coordinates.append(mines_list[x]) + x = x - 1 + + mine_chromosome = [] + while i > 0: + child = random.sample(shuffled_coordinates, len(shuffled_coordinates)) + child.insert(0, first_mine) + #child.insert(x, first_mine) + mine_chromosome.append(child) + i = i - 1 + return mine_chromosome + + def fitness_function(self, generations): + total_cost = 0 + chromosome_count = 0 + chromosome_costs = [] + y = 0 + #problem - wyjście poza liste + if len(generations) == 0: + return + + first_cost = self.calc_cost(generations[y]) + cheapest_chromosome = generations[y] + lowest_cost = first_cost + highest_cost = first_cost + for i in generations: + chromosome_costs.append(self.calc_cost(i)) + total_cost = total_cost + self.calc_cost(i) + chromosome_count = chromosome_count + 1 + if self.calc_cost(i) < lowest_cost: + lowest_cost = self.calc_cost(i) + cheapest_chromosome = i + if self.calc_cost(i) > highest_cost: + highest_cost = self.calc_cost(i) + + average_fitness = total_cost/chromosome_count + chromosome_fitness = [] + total_chromosome_fitness = 0 + l = 0 + for i in chromosome_costs: + chromosome_fitness.append(round(((average_fitness/chromosome_costs[l])*10), 2)) + total_chromosome_fitness += round(((average_fitness/chromosome_costs[l])*10),2) + l = l + 1 + + return(chromosome_fitness, lowest_cost, highest_cost, average_fitness, cheapest_chromosome) + + + def fitness_population_selection(self, first_generation, chromosome_fitness): + x = len(chromosome_fitness) + roulette_table = [] + average_population = [] + i = 0 + interval = 0 + while x > 0: + interval = interval + chromosome_fitness[i] + roulette_table.append(round(interval, 2)) + x = x - 1 + i = i + 1 + x = len(chromosome_fitness)/2 + max = roulette_table[i - 1] + while x > 0: + i = 0 + n = random.uniform(0, max) + while n > roulette_table[i]: + i = i + 1 + average_population.append(first_generation[i]) + x = x - 1 + return average_population + + def crossover(self, average_population): + post_crossover_population = [] + x = len(average_population) - 1 + if x <= 0: + print("no enough chromosomes to crossover") + return + while x > 0: + parent_1 = average_population[x] + parent_2 = average_population[x-1] + child_1 = [] + child_2 = [] + crossover_decision = random.randint(1, 100) + if (crossover_decision < 11) and (parent_1 != parent_2): + crossover_point = random.randint(1, (len(average_population[x])-3)) + l = 0 + k = crossover_point + while k >= 0: + child_1.append(parent_1[l]) + l = l + 1 + k = k - 1 + k = crossover_point + while k < (len(parent_1) - 1): + for i in parent_2: + if i not in child_1: + child_1.append(i) + k = k + 1 + + l = 0 + k = crossover_point + while k >= 0: + child_2.append(parent_2[l]) + l = l + 1 + k = k - 1 + k = crossover_point + while k >= 0: + child_2.append(parent_2[l]) + l = l + 1 + k = k - 1 + k = crossover_point + while k < (len(parent_1) - 1): + for i in parent_1: + if i not in child_2: + child_2.append(i) + k = k + 1 + #child_1.append(0) + #child_2.append(0) + else: + child_1 = parent_1 + child_2 = parent_2 + post_crossover_population.append(child_1) + post_crossover_population.append(child_2) + x = x - 1 + + return post_crossover_population + + def mutation(self, post_crossover_popualtion): + k = len(post_crossover_popualtion) - 1 + while k >= 0: + mutation_decision = random.randint(0, 100) + if mutation_decision < 3: + mutated_chromosome = post_crossover_popualtion[k] + post_crossover_popualtion.remove(mutated_chromosome) + l = len(mutated_chromosome) - 1 + + x = random.randint(1, l) + y = random.randint(1, l) + while x == y: + y = random.randint(1, l) + replacement = mutated_chromosome[x] + mutated_chromosome[y] = replacement + + post_crossover_popualtion.insert(k, mutated_chromosome) + + k = k - 1 + post_mutation_population = post_crossover_popualtion + + return post_mutation_population + + def optimize(self, post_mutation_population, mine_list): + post_optimization_population = post_mutation_population + i = len(post_mutation_population) + l = 1 + while l < i: + k = 1 + while k >= 0: + if post_mutation_population[l] == post_mutation_population[k - 1]: + post_optimization_population.remove(post_mutation_population[k-1]) + x = len(mine_list) - 2 + shuffled_coordinates = [] + while x > 0: + shuffled_coordinates.append(mine_list[x]) + x = x - 1 + x = len(mine_list) - 1 + new_chromosome = random.sample(shuffled_coordinates, len(shuffled_coordinates)) + new_chromosome.insert(0, mine_list[0]) + new_chromosome.insert(x, mine_list[0]) + post_optimization_population.append(new_chromosome) + + k = k - 1 + l = l + 1 + return post_optimization_population + + def genetic_algorythm(self, coordinates): + self.full_cost = self.calc_cost(coordinates) + self.first_generation = self.population_initialization(coordinates,10) + self.fitness, self.lowest_cost, self.highest_cost, self.average_fitness_of_first_genetation, self.cheapest_individual = self.fitness_function(self.first_generation) + self.average_population = self.fitness_population_selection(self.first_generation, self.fitness) + self.population_after_crossover = self.crossover(self.average_population) + + + if self.population_after_crossover == None: + print("Finished in " + str(self.which_generation) + "generations") + return + + self.population_after_mutation = self.mutation(self.population_after_crossover) + self.population_after_optimization = self.optimize(self.population_after_mutation, coordinates) + self.max_cost = self.highest_cost + self.min_cost = self.lowest_cost + self.cheapest_route = self.cheapest_individual + i = 2 + self.which_generation = 1 + while i < 41: + print(" ") + print("***********") + print("Generation " + str(i)) + print("***********") + print(" ") + + if self.fitness_function(self.population_after_optimization) == None: + return + + self.fitness, self.lowest_cost, self.highest_cost, self.average_fitness_of_first_genetation, self.cheapest_individual = self.fitness_function(self.population_after_optimization) + if self.highest_cost > self.max_cost: + self.max_cost = self.highest_cost + if self.lowest_cost < self.min_cost: + self.min_cost = self.lowest_cost + self.cheapest_route = self.cheapest_individual + self.which_generation = i + print("New lowest cost: " + str(self.min_cost)) + print("New cheapest route: " + str(self.cheapest_route)) + + self.average_population = self.fitness_population_selection(self.population_after_mutation, self.fitness) + + self.population_after_crossover = self.crossover(self.average_population) + + if self.population_after_crossover == None: + print("Finished") + return + + self.population_after_mutation = self.mutation(self.population_after_crossover) + self.population_after_optimization = self.optimize(self.population_after_mutation, coordinates) + i = i + 1 + if(self.min_cost)/(self.average_fitness_of_first_genetation) < (0.7): + print("Finished after " + str(i)+ " generations") + break + print("Average fitness of first generation: " + str(self.average_fitness_of_first_genetation)) + print("Relation of efficiency growth: " + str((self.min_cost)/(self.average_fitness_of_first_genetation))) + print("Lowest cost is " + str(self.min_cost)) + print("Cheapest route is: " + str(self.cheapest_route)) + + def run(self): + Mines = [[1,1], + [2,4], + [3,1], + [4,7], + [5,3], + [7,6]] + + self.genetic_algorythm(Mines) + + + + + + \ No newline at end of file diff --git a/genetic3.py b/genetic3.py new file mode 100644 index 0000000..6155890 --- /dev/null +++ b/genetic3.py @@ -0,0 +1,106 @@ +import numpy as np +import math +import random +from geneticalgorithm import geneticalgorithm as ga +from astar2 import * + + +class Mine(): + def __init__(self, row, column): + self.row = row + self.columnt = column + + + + + +class GeneticalWithLib(): + + Miasta = [[0, 130, 180, 300], + [130, 0, 320, 350], + [180, 320, 0, 360], + [300, 350, 360, 0]] + #Miasta = [[0, 2, 6, 3, 7], + # [2, 0, 6, 4, 8], + # [6, 6, 0, 5, 8], + # [3, 4, 5, 0, 9], + # [7, 8, 8, 9, 0]] + + self.mine_points = set() + + + def getCoordinates(self): + temp_map = [list(item) for item in SweeperAgent.loadMap('genetic_maps/map1.txt')] + + a_row = 0 + a_column = 0 + + for row in range(MAP_SIZE): + for column, pos in enumerate(temp_map[row]): + if pos == "m" : + a_row = row + a_column = column + location = tuple([a_row, a_column]) + self.mine_points.add(location) + + def setDistance(self): + pass + + + def fillDistanceMatrix(self): + pass + + + + def f(X): + for i in range(len(Miasta[0])): + if X[i] not in Miasta[i]: + return np.sum(X)+12000 + for i in range(len(Miasta[0])): + if i == 0: + if (X[0]-X[len(Miasta[0])-1]) == 0: + return np.sum(X)+12000 + else: + if abs(X[i]-X[i-1]) == 0: + return np.sum(X)+12000 + if i != len(Miasta[0])-1: + if abs(X[i+1]-X[i-1]) == 0: + return np.sum(X)+12000 + var = [] + for j in range(len(Miasta[0])): + var.append(0) + for i in range(len(Miasta[0])): + var[Miasta[i].index(X[i])] += 1 + for s in var: + if s != 1: + return np.sum(X)+9000 + return np.sum(X) + + varbound = np.array([[130,300], + [130,350], + [180,360], + [300,360]]) + + #varbound = np.array([[2,7], + # [2,8], + # [5,8], + # [4,9], + # [7,9]]) + + algorithm_param = {'max_num_iteration': 3000,\ + 'population_size':100,\ + 'mutation_probability':0.1,\ + 'elit_ratio': 0.01,\ + 'crossover_probability': 0.5,\ + 'parents_portion': 0.3,\ + 'crossover_type':'uniform',\ + 'max_iteration_without_improv':None} + + model=ga(function=f,\ + dimension=len(Miasta[0]),\ + variable_type='int',\ + variable_boundaries=varbound,\ + algorithm_parameters=algorithm_param) + + model.run() + #print(f([180, 350, 180, 350])) \ No newline at end of file diff --git a/genetic_maps/map1.txt b/genetic_maps/map1.txt new file mode 100644 index 0000000..9eb11d0 --- /dev/null +++ b/genetic_maps/map1.txt @@ -0,0 +1,8 @@ +x...... +...x... +x...... +......x +..x.... +....... +.....x. + diff --git a/main.py b/main.py index 86ae369..21ebbe5 100644 --- a/main.py +++ b/main.py @@ -17,6 +17,8 @@ from astar2 import * from pizza import * from learning import * from nn import * +from genetic import * +#from genetic3 import * #from csv_writer import * @@ -153,6 +155,16 @@ class Game: player_moves = SweeperAgent.run(agent) self.graph_move(player_moves) self.wentyl_bezpieczenstwa = 1 + if event.key == pg.K_F8 and self.wentyl_bezpieczenstwa == 0: + #print("pressed") + genetic_runner = Genetic() + genetic_runner.run() + self.wentyl_bezpieczenstwa = 1 + if event.key == pg.K_F9 and self.wentyl_bezpieczenstwa == 0: + #genetic_lib_runner = GeneticalWithLib() + #genetic_lib_runner.run() + self.wentyl_bezpieczenstwa = 1 +