我对 python 相当陌生,正在尝试实现遗传算法,但需要一些操作代码方面的帮助。

我以这种方式表述了这个问题:

  • 每个单独的 I 由一串 M 整数表示
  • e 中的每个元素 I 取值从 0 到 N
  • 从 0 开始的每个数字 - 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 在数组中至少出现一次。

    问题在于 child 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'' 的结果,但我无法想象它在字符串上迭代两次的方式非常有效,所以我想知道是否有人对如何改进它有任何建议。

    谢谢,很抱歉为这么简单的问题写了这么长的帖子!

    最佳答案

    您将需要多次迭代列表,我认为没有办法解决这个问题。毕竟,您首先必须确定不同元素的数量(第一遍),然后才能开始更改元素(第二遍)。但是请注意,根据不同元素的数量,由于重复调用 indexnot in ,您可能拥有最多 O(n^2) 的元素,它们在列表中具有 O(n)。

    或者,您可以为 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 循环就地更改 child 。
    for i, el in enumerate(child):
        child[i] = value_map[el]
    

    关于python - 对数组中的元素重新编号的有效方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29770741/

    10-11 22:22
    查看更多