From ed41333e87a9d39d56a50b9dbbb0029e03c05215 Mon Sep 17 00:00:00 2001 From: coolneng Date: Thu, 17 Jun 2021 19:15:50 +0200 Subject: [PATCH] Implement mutation operator --- src/genetic_algorithm.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/genetic_algorithm.py b/src/genetic_algorithm.py index 8dbd6d4..89de321 100644 --- a/src/genetic_algorithm.py +++ b/src/genetic_algorithm.py @@ -1,6 +1,7 @@ from numpy import sum, append, arange, delete, where from numpy.random import randint, choice, shuffle, random from pandas import DataFrame +from math import ceil def get_row_distance(source, destination, data): @@ -16,9 +17,7 @@ def compute_distance(element, solution, data): distinct_elements = solution.query(f"point != {element}") for _, item in distinct_elements.iterrows(): accumulator += get_row_distance( - source=element, - destination=item.point, - data=data, + source=element, destination=item.point, data=data ) return accumulator @@ -120,16 +119,25 @@ def element_in_dataframe(solution, element): return not duplicates.empty -def mutate(solution, n, probability=0.001): - if random() > probability: - return solution - row = solution.sample() - random_element = randint(n) - while element_in_dataframe(solution=solution, element=random_element): - random_element = randint(n) - solution["point"].iloc[row.index] = random_element - solution["distance"].loc[row.index] = 0 - return solution +def select_new_gene(individual, n): + while True: + new_gene = randint(n) + if not element_in_dataframe(solution=individual, element=new_gene): + return new_gene + + +def mutate(population, n, probability=0.001): + expected_mutations = len(population) * n * probability + individuals = [] + genes = [] + for _ in range(ceil(expected_mutations)): + individuals.append(randint(n)) + genes.append(population[individuals[-1]].sample().index) + for ind, gen in zip(individuals, genes): + individual = population[ind] + individual["point"].iloc[gen] = select_new_gene(individual, n) + individual["distance"].iloc[gen] = 0 + return population def tournament_selection(solution):