我刚刚开始研究一个简单的遗传算法,它带有一堆点,每个点都有一系列移动指令。这些指令是一个整数列表,我将其与字典进行比较:movekey = {1:(1,1),2:(1,0),3:(1,-1),4:(0,-1),5:(-1,-1),6:(-1,0),7:(-1,1),8:(0,1)}
(其中每个元组都是x
和y
值的变化)。每个人都是一个列表列表,一个列表具有当前位置,另一个列表是其移动列表ex:[[0, 0], [4, 4, 8, 1, 7]]
。然后创建一组这些个体的列表以形成群体(代码中为pop
)。
创建初始种群的功能是:
def createinitpop(size):
pop = []
for i in range(size): pop.append([origin,[random.randint(1,8) for i in range(5)]])
#the variable origin is preset to be [0,0]
return pop
然后,为了将所有个体移动一步,我使用此功能:
def movedots(pop):
for i in pop:
print('i:',i)
i[0][0]+= movekey[i[1][step]][0]
# the 'step' referenced here begins at zero and counts up, i've only run it on step 0
i[0][1] += movekey[i[1][step]][1]
print('i:', i)
return pop
问题在于,当我运行第二个函数时,每次迭代都会更改总体中的所有个体。 (但是我已经发现,当我将一个示例群体硬编码到movedots
函数中时,它可以正常工作)。以下是两个人运行这两个函数的结果(两个人都被打印出来)
[[[0, 0], [6, 5, 2, 1, 8]], [[0, 0], [4, 7, 2, 1, 1]]]
i: [[0, 0], [6, 5, 2, 1, 8]]
i: [[-1, 0], [6, 5, 2, 1, 8]]
i: [[-1, 0], [4, 7, 2, 1, 1]]
i: [[-1, -1], [4, 7, 2, 1, 1]]
[[[-1, -1], [6, 5, 2, 1, 8]], [[-1, -1], [4, 7, 2, 1, 1]]]
理想情况下,最后一行中个人的位置应该不同,因为他们的第一个动作不同,但正如您所看到的,第三个i
与第二个i
相同,这表明它使用相同的值。
我不知道我是否只是不理解列表是如何工作的,或者我是否遗漏了一些愚蠢的东西。
答案 0 :(得分:0)
你指出了两个对同一个地方的引用:
for i in range(size): pop.append([origin,[random.randint(1,8) for i in range(5)]])
您现在有三个对相同列表的引用。当您从三个通道中的任何一个更改它时,您可以更改每个通道的数据。尝试隐式复制操作:
for i in range(size): pop.append([origin[:], ...
这将为您的每个嵌套引用提供origin
的浅(一级)副本。