我是python的新手,我正在尝试实现遗传算法,但需要一些操作的代码帮助。
我用这种方式制定了问题:
I
由一串M
整数e
中的每个元素I
的值均为0到N
N
必须至少出现一次I
e
的值并不重要,只要每个唯一值元素都采用相同的唯一值(将它们视为类标签)e
小于或等于N
N
对于每个I
应用交叉操作后,我可能会生成违反这些约束中的一个或多个的子项,因此我需要找到一种方法来重新编号元素,以便它们保留其属性,但符合约束条件。
例如:
parent_1 (N=5): [1 3 5 4 2 1|0 0 5 2]
parent_2 (N=3): [2 0 1 3 0 1|0 2 1 3]
*** crossover applied at "|" ***
child_1: [1 3 5 4 2 1 0 2 1 3]
child_2: [2 0 1 3 0 1 0 0 5 2]
child_1
显然仍满足所有约束条件,因为N = 5且所有值0-5在数组中至少出现一次。
问题在于孩子2 - 如果我们使用max(child_2)
计算N的方式得到值5,但如果我们计算唯一值的数量那么N = 4,这是什么值N应该是。我所要求的(以非常漫长的方式,被授予)是一种良好的,pythonic的方式:
child_2: [2 0 1 3 0 1 0 0 5 2]
*** some python magic ***
child_2': [2 0 1 3 0 1 0 0 4 2]
*or*
child_2'': [0 1 2 3 1 2 1 1 4 0]
child_2''
用于说明值本身并不重要,只要唯一值的每个元素映射到相同的值,就会满足约束。
这是我到目前为止所尝试的内容:
value_map = []
for el in child:
if el not in value_map:
value_map.append(el)
for ii in range(0,len(child)):
child[ii] = value_map.index(child[ii])
这种方法可以工作并返回类似于child_2''
的结果,但我无法想象它在字符串上迭代两次的方式非常有效,所以我想知道是否有人对如何有任何建议使它变得更好。
谢谢,对于这么简单的问题这么长的帖子感到抱歉!
答案 0 :(得分:2)
您需要多次迭代列表,我不认为有任何解决方法。毕竟,在开始更改元素(第二遍)之前,首先必须确定不同元素的数量(第一遍)。但是请注意,由于重复调用index
和not in
,在列表中有O(n),因此根据不同元素的数量,最多可能有O(n ^ 2)
或者,您可以为dict
使用list
代替value_map
。字典比列表具有更快的查找速度,因此,复杂性应该确实在O(n)的数量级上。您可以使用(1)字典理解来确定旧值到新值的映射,以及(2)用于创建更新子项的列表理解。
value_map = {el: i for i, el in enumerate(set(child))}
child2 = [value_map[el] for el in child]
使用for
循环就地更改孩子。
for i, el in enumerate(child):
child[i] = value_map[el]
答案 1 :(得分:1)
您可以使用以下单循环执行此操作:
value_map = []
result = []
for el in child:
if el not in value_map:
value_map.append(el)
result.append(value_map.index(el))
答案 2 :(得分:1)
我能想到的一个解决方案是:
这会强制你通过数组两次,但它应该比你的例子更快(这会强迫你在每次迭代时遍历数组的每个元素的value_map
)
child = [2, 0, 1, 3, 0, 1, 0, 0, 5, 2]
used = set(child)
N = len(used) - 1
unused = set(xrange(N+1)) - used
value_map = dict()
for i, e in enumerate(child):
if e <= N:
continue
if e not in value_map:
value_map[e] = unused.pop()
child[i] = value_map[e]
print child # [2, 0, 1, 3, 0, 1, 0, 0, 4, 2]
答案 3 :(得分:0)
>>> child = [2, 0, 1, 3, 0, 1, 0, 0, 5, 2]
>>>
>>> value_map = []
>>> for i in range(len(child)):
... el = child[i]
... if el not in value_map:
... value_map.append(el)
... child[i] = value_map.index(el)
...
>>> child
[0, 1, 2, 3, 1, 2, 1, 1, 4, 0]
答案 4 :(得分:0)
我相信这是有效的,虽然我没有测试它超过问题中给出的单个案例。
唯一困扰我的是value_map
在代码中出现三次......
def renumber(individual):
"""
>>> renumber([2, 0, 1, 3, 0, 1, 0, 0, 4, 2])
[0, 1, 2, 3, 1, 2, 1, 1, 4, 0]
"""
value_map = {}
return [value_map.setdefault(e, len(value_map)) for e in individual]