mutations geneticAlg

This commit is contained in:
Mateusz Dokowicz 2023-06-16 03:22:30 +02:00
parent 74fd6d9263
commit a404e70058
4 changed files with 62 additions and 25 deletions

View File

@ -1,6 +1,9 @@
import copy
import random import random
import configparser import configparser
import math import math
import pygame
from domain.entities.entity import Entity from domain.entities.entity import Entity
@ -9,6 +12,7 @@ config.read("config.ini")
from domain.world import World from domain.world import World
from AI_brain.rotate_and_go_aStar import RotateAndGoAStar, State from AI_brain.rotate_and_go_aStar import RotateAndGoAStar, State
from random import randint
hits = 0 hits = 0
@ -44,9 +48,7 @@ class Path:
permutation = generate_random_permutation(len(dusts)) permutation = generate_random_permutation(len(dusts))
self.permutation = permutation self.permutation = permutation
self.walk = addStartAndStation( self.walk = addStartAndStation(permutation)
permutation, config.getint("CONSTANT", "BananaFilling")
)
def calculate_distance(self, world: World): def calculate_distance(self, world: World):
distance = 0 distance = 0
@ -145,8 +147,8 @@ def generate_random_permutation(n):
# BUG solution: inverse direction at the last step # BUG solution: inverse direction at the last step
def addStartAndStation(permutation: list[int], bananaFilling: int): def addStartAndStation(permutation: list[int]):
frequency = math.ceil(100 / bananaFilling) frequency = math.ceil(100 / config.getint("CONSTANT", "BananaFilling"))
numer_of_stops = math.ceil(len(permutation) / frequency) numer_of_stops = math.ceil(len(permutation) / frequency)
walk = permutation.copy() walk = permutation.copy()
@ -186,6 +188,16 @@ class GeneticAlgorytm:
path.calculate_distance(self.world) path.calculate_distance(self.world)
self.paths.append(path) self.paths.append(path)
def print_top(self):
print(
"Best path: ",
self.best_path.walk,
"Distance: ",
self.best_path.distance,
)
for path in self.paths[1:]:
print(path.walk, path.distance)
def evaluate_population(self): def evaluate_population(self):
self.paths.sort(key=lambda x: x.distance, reverse=False) self.paths.sort(key=lambda x: x.distance, reverse=False)
@ -207,9 +219,7 @@ class GeneticAlgorytm:
if item not in child.permutation: if item not in child.permutation:
child.permutation.append(item) child.permutation.append(item)
child.walk = addStartAndStation( child.walk = addStartAndStation(child.permutation)
child.permutation, config.getint("CONSTANT", "BananaFilling")
)
child.calculate_distance(self.world) child.calculate_distance(self.world)
@ -220,7 +230,6 @@ class GeneticAlgorytm:
for i in range(self.iteration_number): for i in range(self.iteration_number):
self.crossover() self.crossover()
# self.mutate()
self.evaluate_population() self.evaluate_population()
self.best_real_path = self.paths[0].get_real_path(self.world) self.best_real_path = self.paths[0].get_real_path(self.world)
@ -229,6 +238,25 @@ class GeneticAlgorytm:
print(hits / (misses + hits)) print(hits / (misses + hits))
def mutate(self, mutant: Path) -> Path:
random_number = randint(0, len(mutant.permutation) - 1)
random_number2 = random_number
while random_number == random_number2:
random_number2 = randint(0, len(mutant.permutation) - 1)
mutant.permutation[random_number], mutant.permutation[random_number2] = (
mutant.permutation[random_number2],
mutant.permutation[random_number],
)
if tuple(mutant.permutation) in self.checked_permutations:
return self.mutate(mutant)
mutant.walk = addStartAndStation(mutant.permutation)
mutant.calculate_distance(self.world)
return mutant
def crossover(self): def crossover(self):
for i in range(self.descendants_number): for i in range(self.descendants_number):
parent1 = self.paths[random.randint(0, self.population_size - 1)] parent1 = self.paths[random.randint(0, self.population_size - 1)]
@ -244,4 +272,10 @@ class GeneticAlgorytm:
self.checked_permutations[tuple(child.permutation)] = True self.checked_permutations[tuple(child.permutation)] = True
self.paths.append(child) self.paths.append(child)
mutant = Path()
mutant.permutation = child.permutation.copy()
mutant = self.mutate(mutant)
self.checked_permutations[tuple(mutant.permutation)] = True
self.paths.append(mutant)
self.evaluate_population() self.evaluate_population()

View File

@ -4,12 +4,12 @@ movement = robot
#accept: human, robot #accept: human, robot
[CONSTANT] [CONSTANT]
NumberOfBananas = 5 NumberOfBananas = 15
NumberOfEarrings = 3 NumberOfEarrings = 0
NumberOfPlants = 5 NumberOfPlants = 5
BananaFilling = 25 BananaFilling = 25
RobotStartPosition = 1, 1 RobotStartPosition = 5, 5
DockStationStartPosition = 9, 8 DockStationStartPosition = 5, 6
#9,8 #9,8
[NEURAL_NETWORK] [NEURAL_NETWORK]
@ -21,6 +21,6 @@ mode = full_clean
[GENETIC_ALGORITHM] [GENETIC_ALGORITHM]
PopulationSize = 20 PopulationSize = 20
DescendantsNumber = 5 DescendantsNumber = 6
MutationProbability = 0.1 MutationProbability = 0.3
IterationNumber = 100 IterationNumber = 1_000

View File

@ -27,6 +27,7 @@ class VacuumMoveCommand(Command):
if self.vacuum.get_container_filling() < 100: if self.vacuum.get_container_filling() < 100:
self.vacuum.increase_container_filling() self.vacuum.increase_container_filling()
self.world.delete_entities_at_Of_type(item.x, item.y, item.type) self.world.delete_entities_at_Of_type(item.x, item.y, item.type)
self.world.dust[end_x][end_y].remove(item)
if self.world.is_docking_station_at(end_x, end_y): if self.world.is_docking_station_at(end_x, end_y):
self.vacuum.dump_trash() self.vacuum.dump_trash()

20
main.py
View File

@ -70,11 +70,7 @@ class Main:
genetic_searcher = GeneticAlgorytm(self.world) genetic_searcher = GeneticAlgorytm(self.world)
genetic_searcher.run() genetic_searcher.run()
print( genetic_searcher.print_top()
str(genetic_searcher.best_path.walk)
+ ": "
+ str(genetic_searcher.best_distance)
)
robot_actions = genetic_searcher.best_path.real_path robot_actions = genetic_searcher.best_path.real_path
@ -190,9 +186,15 @@ def generate_world(tiles_x: int, tiles_y: int) -> World:
world.add_entity(Entity(9, 3, "PLANT3")) world.add_entity(Entity(9, 3, "PLANT3"))
numberOfEarrings = config.getint("CONSTANT", "NumberOfEarrings") numberOfEarrings = config.getint("CONSTANT", "NumberOfEarrings")
world.add_entity(Earring(9, 7)) for _ in range(numberOfEarrings):
world.add_entity(Earring(5, 5)) temp_x = randint(0, tiles_x - 1)
world.add_entity(Earring(4, 6)) temp_y = randint(0, tiles_y - 1)
while world.is_entity_at(temp_x, temp_y):
temp_x = randint(0, tiles_x - 1)
temp_y = randint(0, tiles_y - 1)
world.add_entity(Earring(temp_x, temp_y))
for _ in range(config.getint("CONSTANT", "NumberOfBananas")): for _ in range(config.getint("CONSTANT", "NumberOfBananas")):
temp_x = randint(0, tiles_x - 1) temp_x = randint(0, tiles_x - 1)
@ -248,7 +250,7 @@ def generate_world(tiles_x: int, tiles_y: int) -> World:
if world.garbage_at(x, y): if world.garbage_at(x, y):
world.costs[x][y] = 1 world.costs[x][y] = 1
else: else:
world.costs[x][y] = 10 world.costs[x][y] = 2
return world return world