0

我对在 Python 中使用 DEAP 应用遗传算法很感兴趣。可以在此处查看背包的示例实现。我正在尝试创建自己的交叉函数,并且我想保留父母的长度如下:

# Crossover
def crossover(ind1, ind2):
    print len(ind1), len(ind2) #<------ length at the beginning
    temp1 = copy.deepcopy(set(ind1))
    temp2 = copy.deepcopy(set(ind2))
    uniform = list(temp1.union(temp2))
    while len(ind1) > 0:
        ind1.pop()
    while len(ind2) > 0:
        ind2.pop()
    for i in range(max_no):
        ind1.add(random.choice(uniform))
        ind2.add(random.choice(uniform))
    print len(ind1), len(ind2) #<---- length at the end
    return ind1, ind2

但是,函数开头的 ind1 和 in2 的长度与末尾的 ind1 和 ind2 的长度不同。ind1 和 ind2 开头的长度都应该等于 max_no。我希望有人能给我一个暗示为什么会这样。我很困惑。

谢谢,任何帮助将不胜感激。

编辑:这是我的突变功能。如您所见,我还试图在此处保留个人的可变长度

def mutation(individual):
    if len(individual) > 0:
        individual.remove(random.choice(list(individual)))
        individual.add(random.choice(nodes))
    return individual,
4

1 回答 1

1

您的代码主要等同于:

import random

ind1 = set(range(100))
ind2 = set(range(100)[::-1])
uniform = list(ind1.union(ind2))
max_no = 100
while len(ind1) > 0:
        ind1.pop()
while len(ind2) > 0:
    ind2.pop()
for i in range(max_no):
    ind1.add(random.choice(uniform))
    ind2.add(random.choice(uniform))

结果

>>> print(len(ind1),len(ind2))
(64, 61)

因为您的个人是集合,所以当您添加随机数时,您经常会添加两次。然后每次运行的结果集的长度都会不同,因为如果它已经在个人中,则不会添加任何内容。

要解决您的问题,您可以random.sample改用:

import random

ind1 = set(range(100))
ind2 = set(range(-100,0,-1)[::-1])
uniform = list(ind1.union(ind2))
max_no = 100
while len(ind1) > 0:
    ind1.pop()
while len(ind2) > 0:
    ind2.pop()
for x in random.sample(uniform,max_no):
    ind1.add(x)
for x in random.sample(uniform,max_no):
    ind2.add(x)

结果

>>> print(len(ind1),len(ind2))
(100, 100)

话虽如此,set个人对我来说非常痛苦。sequence个人是迄今为止最好的支持。从文档中可以明显看出,dict作为不被视为类型set的特例:dictsequence

序列

一个 iterable,它支持通过getitem () 特殊方法使用整数索引进行有效的元素访问,并定义了一个返回序列长度的len () 方法。一些内置的序列类型是 list、str、tuple 和 bytes。请注意,dict 也支持 getitem () 和len (),但被认为是映射而不是序列,因为查找使用任意不可变键而不是整数。

于 2016-11-07T13:17:47.353 回答