From f71aa2e1e2b8fd967fc55d0c89a3078417720a50 Mon Sep 17 00:00:00 2001 From: coolneng Date: Sat, 19 Jun 2021 19:13:14 +0200 Subject: [PATCH] Fix uniform crossover operator --- src/genetic_algorithm.py | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/genetic_algorithm.py b/src/genetic_algorithm.py index dedba02..cae5eb1 100644 --- a/src/genetic_algorithm.py +++ b/src/genetic_algorithm.py @@ -49,10 +49,11 @@ def evaluate_individual(individual, data): def select_distinct_genes(matching_genes, parents, m): - cutoff = randint(m) - distinct_indexes = delete(arange(m), matching_genes) - first_parent_genes = parents[0].point.iloc[distinct_indexes[cutoff:]] - second_parent_genes = parents[1].point.iloc[distinct_indexes[:cutoff]] + first_parent = parents[0].query("point not in @matching_genes") + second_parent = parents[1].query("point not in @matching_genes") + cutoff = randint(len(first_parent.point.values)) + first_parent_genes = first_parent.point.values[cutoff:] + second_parent_genes = second_parent.point.values[:cutoff] return first_parent_genes, second_parent_genes @@ -67,23 +68,26 @@ def select_random_genes(matching_genes, parents, m): def repair_offspring(offspring, parents, m): while len(offspring) != m: if len(offspring) > m: - best_index = offspring["distance"].astype(float).idxmax() + best_index = offspring["distance"].idxmax() offspring.drop(index=best_index, inplace=True) elif len(offspring) < m: random_parent = parents[randint(len(parents))] - best_index = random_parent["distance"].astype(float).idxmax() - best_point = random_parent["point"].loc[best_index] + while True: + best_index = random_parent["distance"].idxmax() + best_point = random_parent["point"].loc[best_index] + random_parent.drop(index=best_index, inplace=True) + if not any(offspring["point"].isin([best_point])): + break offspring = offspring.append( - {"point": best_point, "distance": 0}, ignore_index=True + {"point": best_point, "distance": 0, "fitness": 0}, ignore_index=True ) - random_parent.drop(index=best_index, inplace=True) return offspring def get_matching_genes(parents): - first_parent = parents[0].point - second_parent = parents[1].point - return where(first_parent == second_parent) + first_parent = parents[0].point.values + second_parent = parents[1].point.values + return where(first_parent == second_parent)[0] def populate_offspring(values): @@ -99,8 +103,7 @@ def populate_offspring(values): def uniform_crossover(parents, m): - matching_indexes = get_matching_genes(parents) - matching_genes = parents[0].point.iloc[matching_indexes] + matching_genes = get_matching_genes(parents) first_genes, second_genes = select_distinct_genes(matching_genes, parents, m) offspring = populate_offspring(values=[matching_genes, first_genes, second_genes]) viable_offspring = repair_offspring(offspring, parents, m) @@ -116,9 +119,13 @@ def position_crossover(parents, m): def crossover(mode, parents, m): + split_parents = [parents[i : i + 2] for i in range(0, len(parents), 2)] if mode == "uniform": - return uniform_crossover(parents, m) - return position_crossover(parents, m) + crossover_func = partial(uniform_crossover, m=m) + else: + crossover_func = partial(position_crossover, m=m) + offspring = [*map(crossover_func, split_parents)] + return offspring def element_in_dataframe(individual, element):