[英]Genetic algorithm - ordered crossover in python
我已经在python 3中实现了遗传算法,并在代码审查中发布了一个问题,但没有答案,这主要是因为我的算法运行非常缓慢。 通过有选择地注释掉我代码的不同部分,我缩小了代码的这一部分(交叉算法)的瓶颈:
def crossover(self, mum, dad):
"""Implements ordered crossover"""
size = len(mum.vertices)
# Choose random start/end position for crossover
alice, bob = [-1] * size, [-1] * size
start, end = sorted([random.randrange(size) for _ in range(2)])
# Replicate mum's sequence for alice, dad's sequence for bob
for i in range(start, end + 1):
alice[i] = mum.vertices[i]
bob[i] = dad.vertices[i]
# # Fill the remaining position with the other parents' entries
# current_dad_position, current_mum_position = 0, 0
#
# for i in chain(range(start), range(end + 1, size)):
#
# while dad.vertices[current_dad_position] in alice:
# current_dad_position += 1
#
# while mum.vertices[current_mum_position] in bob:
# current_mum_position += 1
#
# alice[i] = dad.vertices[current_dad_position]
# bob[i] = mum.vertices[current_mum_position]
#
# # Return twins
# return graph.Tour(self.g, alice), graph.Tour(self.g, bob)
return mum, dad
被注释掉的部分使我的程序运行时间从〜7秒变为5-6分钟(我正在运行GA的5000次迭代)。 有什么方法可以更有效地执行此有序交叉吗?
对于那些不熟悉的人,我正在实现基于订单的交叉(OX2)。 给定两个连续整数数组(父级),则选择两个随机的开始/结束位置。
mum = 4 9 2 8 3 1 5 7 6
dad = 6 4 1 3 7 2 8 5 9
^ ^
start end
然后,两个孩子共享结果切片:
child 1 = _ _ 2 8 3 1 _ _ _
child 2 = _ _ 1 3 7 2 _ _ _
^ ^
现在,只要避免重复,其余插槽将按照其他父项的出现顺序填充。 因此,由于孩子1的切片取自妈妈,因此其余条目均取自父亲。 首先我们取6,然后取4,然后我们取7(不取1和3,因为它们已经出现在妈妈的孩子1中),然后取5,然后取9。
child 1 = 6 4 2 8 3 1 7 5 9
同样
child 2 = 4 9 1 3 7 2 8 5 6
这就是我在函数中实现的。
我只能猜测您的问题在于以下事实:您的while循环和其中的增量不限于vertices
矢量的实际大小,请设置硬限制并再次测试:
while current_dad_position < size and dad.vertices[current_dad_position] in alice:
current_dad_position += 1
while current_mom_position < size and mum.vertices[current_mum_position] in bob:
current_mum_position += 1
我不得不说这不一定会产生唯一的解决方案,因为我不知道如果没有足够的唯一唯一奇异顶点可供选择,那么算法将如何工作,因为它们违反了您的“而不是另一个”父母的限制。
对于任何对此进行测试的人,我建议您使用一个简单的示例输入来完成您的代码,而不要注释掉所讨论的代码,而应在注释中标记其BEGIN和END。
知道问题是建筑的唯一可解决的知识,这就是它的样子:
import random
import numpy as np
def crossover(mum, dad):
"""Implements ordered crossover"""
size = len(mum.vertices)
# Choose random start/end position for crossover
alice, bob = [-1] * size, [-1] * size
start, end = sorted([random.randrange(size) for _ in range(2)])
# Replicate mum's sequence for alice, dad's sequence for bob
alice_inherited = []
bob_inherited = []
for i in range(start, end + 1):
alice[i] = mum.vertices[i]
bob[i] = dad.vertices[i]
alice_inherited.append(mum.vertices[i])
bob_inherited.append(dad.vertices[i])
print(alice, bob)
#Fill the remaining position with the other parents' entries
current_dad_position, current_mum_position = 0, 0
fixed_pos = list(range(start, end + 1))
i = 0
while i < size:
if i in fixed_pos:
i += 1
continue
test_alice = alice[i]
if test_alice==-1: #to be filled
dad_trait = dad.vertices[current_dad_position]
while dad_trait in alice_inherited:
current_dad_position += 1
dad_trait = dad.vertices[current_dad_position]
alice[i] = dad_trait
alice_inherited.append(dad_trait)
#repeat block for bob and mom
i +=1
return alice, bob
与
class Mum():
def __init__(self):
self.vertices =[ 4, 9, 2, 8, 3, 1, 5, 7, 6 ]
class Dad():
def __init__(self):
self.vertices = [ 6 , 4 , 1 , 3 , 7 , 2 , 8 , 5 , 9 ]
mum = Mum()
dad = Dad()
a, b = crossover(mum, dad)
# a = [6, 4, 2, 8, 3, 1, 5, 7, 9]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.