Я унаследовал часть кода Python, который использует DEAP, с выбором турнира для управления шагом кроссовера:
#Early in the code
toolbox.register("select", tools.selTournament, tournsize=tournsize)
#Then later...
popu = toolbox.select(popu, k=len(popu))
popu = [toolbox.clone(ind) for ind in popu]
for child1, child2 in zip(popu[::2], popu[1::2]):
toolbox.mate(child1, child2)
del child1.fitness.values, child2.fitness.values
Мне кажется, что это не имеет защиты для человека, которого пересекают - над собой, и я хотел бы избежать этой возможности.
Концептуально, это достаточно просто, но я не уверен, как реализовать это в Python.
Возможное решение 1: (см. Обновление ниже)
popu = toolbox.select(popu, k=len(popu))
for ind in range(1, len(popu), 2):
while popu[ind] == popu[ind-1]:
popu[ind] = toolbox.select(popu, k=1)
popu = [toolbox.clone(ind) for ind in popu]
for child1, child2 in zip(popu[::2], popu[1::2]):
toolbox.mate(child1, child2)
del child1.fitness.values, child2.fitness.values
* Если возможен повторный выбор дубликатов по одному, я думаю, что установка дедупликации до клонирования верна, но я не уверен на 100%.
Возможное решение 2, чуть более грубая сила:
popu = toolbox.select(popu, k=len(popu))
for ind in range(1, len(popu), 2):
while popu[ind] == popu[ind-1]:
popu[ind] = popu[random.randint(0,len(popu)-1)]
popu = [toolbox.clone(ind) for ind in popu]
for child1, child2 in zip(popu[::2], popu[1::2]):
toolbox.mate(child1, child2)
del child1.fitness.values, child2.fitness.values
Должны ли работать один или оба из них (с учетом того, что повторный выбор происходит в нужном месте)?
ОБНОВЛЕНИЕ:
Возможное решение № 1 необходимо изменить. Так как toolbox.select возвращает список, отдельный элемент popu должен быть установлен как элемент списка, а не весь список, даже когда список имеет длину 1. Вероятно, проще показать решение, чем записывать его в проза ...
Пересмотренное возможное решение 1:
popu = toolbox.select(popu, k=len(popu))
for ind in range(1, len(popu), 2):
while popu[ind] == popu[ind-1]:
repopu = toolbox.select(popu, k=1)
popu[ind] = repopu[0]
popu = [toolbox.clone(ind) for ind in popu]
for child1, child2 in zip(popu[::2], popu[1::2]):
toolbox.mate(child1, child2)
del child1.fitness.values, child2.fitness.values
Это, по крайней мере, выводит нас из стадии «это не кр sh», но делает ли это то, что мы хотим ?