Fix uniform crossover operator

This commit is contained in:
coolneng 2021-06-19 19:13:14 +02:00
parent 04fd66425e
commit f71aa2e1e2
Signed by: coolneng
GPG Key ID: 9893DA236405AF57
1 changed files with 23 additions and 16 deletions

View File

@ -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):