From 8c5c5c48f069c7da6b09c8cec98ab7984ab1737a Mon Sep 17 00:00:00 2001 From: HelQ Date: Wed, 7 Sep 2022 20:26:13 +0200 Subject: [PATCH] Genetics --- genetic.py | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++ main.py | 50 ++++++++++++++++++---- 2 files changed, 165 insertions(+), 8 deletions(-) create mode 100644 genetic.py diff --git a/genetic.py b/genetic.py new file mode 100644 index 0000000..23cd50b --- /dev/null +++ b/genetic.py @@ -0,0 +1,123 @@ +import random + + +class genetic: + def __init__(self, chrome): + self.chrome = chrome + self.key = 10 + self.pop_size = 50 + self.gen_max = 20 + self.length = len(chrome) - 1 + self.div = self.length // 2 + self.rand = list(range(1, self.length + 1)) + + def create_genome(self): + genome = "0" + exclusive = random.sample(self.rand, self.length) + genome += "".join(map(str, exclusive)) + return genome + + def find_fitness(self, genome): + fitness = 0 + for i in range(len(genome) - 1): + fitness += self.chrome[int(genome[i])][int(genome[i + 1])] + return fitness + + def crossOver(self, gen1, gen2): + gen = [] + for i in range(self.div): + gen.append(gen1[i]) + for i in range(self.div, self.length+1): + if gen2[i] not in gen: + gen.append(gen2[i]) + else: + j = 0 + while gen1[j] in gen: + j += 1 + gen.append(gen1[j]) + return ''.join(gen) + + def mutation(self, genome): + genome = list(genome) + while True: + gen1 = random.randint(1, self.length - 1) + gen2 = random.randint(1, self.length - 1) + if gen1 != gen2: + genome[gen1], genome[gen2] = genome[gen2], genome[gen1] + break + return ''.join(genome) + + def search(self): + gen = 1 + population = [] + + for i in range(self.pop_size): + ind = individual() + ind.genome = self.create_genome() + ind.fitness = self.find_fitness(ind.genome) + population.append(ind) + + print("First population:") + for ind in population: + print(ind.genome, ind.fitness) + + while gen <= self.gen_max: + new_population = population + + key = random.randint(0, 100) + if key > self.key: + for i in range(self.pop_size): + temp1, temp2 = random.sample(population, 2) + new_ind1 = individual() + new_ind1.genome = self.crossOver(temp1.genome, temp2.genome) + new_ind1.fitness = self.find_fitness(new_ind1.genome) + new_ind2 = individual() + new_ind2.genome = self.crossOver(temp2.genome, temp1.genome) + new_ind2.fitness = self.find_fitness(new_ind2.genome) + new_population.append(new_ind1) + new_population.append(new_ind2) + new_population.sort() + new_population.pop() + new_population.pop() + else: + print('mutation') + for i in range(self.pop_size): + temp1 = random.choice(population) + new_ind = individual() + new_ind.genome = self.mutation(temp1.genome) + new_ind.fitness = self.find_fitness(new_ind.genome) + new_population.append(new_ind) + new_population.sort() + new_population.pop() + print("\n") + print("New Generation # ", gen) + print("Genome Fitness") + + for i in range(self.pop_size): + print(new_population[i].genome, new_population[i].fitness) + + print("\n") + + gen += 1 + + ans = min(population, key=lambda x: x.fitness) + print("Final order: ", ans.genome, ans.fitness) + return ans.genome + + +class individual: + def __init__(self): + self.genome = 0 + self.fitness = 0 + + def __lt__(self, other): + return self.fitness < other.fitness + + def __gt__(self, other): + return self.fitness > other.fitness + + def __le__(self, other): + return self.fitness <= other.fitness + + def __ge__(self, other): + return self.fitness >= other.fitness diff --git a/main.py b/main.py index eef48ab..89be88e 100644 --- a/main.py +++ b/main.py @@ -7,6 +7,7 @@ from rubbish import * from tree import evaluate_values, trash_selection from truck import Truck from surface import * +from genetic import genetic RESOLUTION = 900 SIZE = 60 @@ -52,6 +53,11 @@ for i in range(15): rubbish_list.append(Rubbish(screen, j * 60, i * 60)) path = [] +gen = [(truck.y / 60, truck.x / 60)] +fl = 0 +length = [] +finalLength = [] +order = [] while True: pygame.time.delay(500) @@ -64,11 +70,40 @@ while True: i.draw_rubbish() truck.draw_truck() + # finding order to collect rubbish + if fl == 0: + for item in rubbish_list: + print(item.y / 60, item.x / 60, end='\n') + gen.append((item.y / 60, item.x / 60)) + for item1 in range(len(gen)): + for item2 in range(len(gen)): + if item1 < item2: + length.append(len(a_star(surface_list, gen[item2]).tree_search(PriorityQueue(), gen[item1], 'R'))) + else: + length.append(0) + finalLength.append(length) + length = [] + fl = 1 + for i in range(len(finalLength)): + for j in range(len(finalLength)): + if i > j: + finalLength[i][j] = finalLength[j][i] + for i in range(len(finalLength)): + for j in range(len(finalLength)): + print(finalLength[i][j], end=',') + print('') + print(finalLength) + order = genetic(finalLength).search() + order = list(map(int, order)) + order.pop(0) + for j in range(len(order)): + order[j] -= 1 + # finding a path to rubbish - if rubbish_list and not path: + if order and not path: start = (truck.y / 60, truck.x / 60) direction = truck.direction - currentRubbish = rubbish_list[0] + currentRubbish = rubbish_list[order[0]] endpoint = (currentRubbish.y / 60, currentRubbish.x / 60) # path = bfs(surface_list, endpoint).tree_search(deque(), start, direction) path = a_star(surface_list, endpoint).tree_search(PriorityQueue(), start, direction) @@ -82,8 +117,8 @@ while True: truck.change_direction(action) # the decision that takes what to do with the garbage - if not path and rubbish_list: - data = rubbish_list[0].data_for_decision_tree() + if not path and order: + data = rubbish_list[order[0]].data_for_decision_tree() print(f'----------\n' f'Characteristics of the garbage we met:\n' f'Weight:{data[0]}\nDensity:{data[1]}\n' @@ -94,12 +129,11 @@ while True: decision = trash_selection(evaluate_values(data)) if decision == [0]: print('We refused this rubbish because of bad characteristics') - rubbish_list[0].rubbish_refused() - refused_rubbish_list.append(rubbish_list[0]) + rubbish_list[order[0]].rubbish_refused() + refused_rubbish_list.append(rubbish_list[order[0]]) else: print('We take this rubbish because of good characteristics') - rubbish_list.pop(0) - + order.pop(0) pygame.display.flip() for event in pygame.event.get():