我正在尝试实现功能。它的工作应该是这样的:
- 需要两个列表。
- 标记一些索引,最好是居中的几个。
- parent 双方都交换了标记的索引。
- 其他索引按顺序转到其父元素。
- 如果相同的元素已存在于该父元素中,它会映射并检查其他父元素相同的元素所在的位置并转到那里。
import random
def pm(indA, indB):
size = min(len(indA), len(indB))
c1, c2 = [0] * size, [0] * size
# Initialize the position of each indices in the individuals
for i in range(1,size):
c1[indA[i]] = i
c2[indB[i]] = i
crosspoint1 = random.randint(0, size)
crosspoint2 = random.randint(0, size - 1)
if crosspoint2 >= crosspoint1:
crosspoint2 += 1
else: # Swap the two cx points
crosspoint1, crosspointt2 = crosspoint2, crosspoint1
for i in range(crosspoint1, crosspoint2):
# Keep track of the selected values
temp1 = indA[i]
temp2 = indB[i]
# Swap the matched value
indA[i], indA[c1[temp2]] = temp2, temp1
indB[i], indB[c2[temp1]] = temp1, temp2
# Position bookkeeping
c1[temp1], c1[temp2] = c1[temp2], c1[temp1]
c2[temp1], c2[temp2] = c2[temp2], c2[temp1]
return indA, indB
a,b = pm([3, 4, 8, 2, 7, 1, 6, 5],[4, 2, 5, 1, 6, 8, 3, 7])
错误:
in pm
c1[indA[i]] = i
IndexError: list assignment index out of range
最佳答案
不确定您的代码中是否还有其他错误(我没有运行它),但这是对此的解释。在Python(与大多数其他语言一样)中,列表(更精确地说是序列)索引基于0 :
>>> l = [1, 2, 3, 4, 5, 6] >>> >>> for e in l: ... print(e, l.index(e)) ... 1 0 2 1 3 2 4 3 5 4 6 5 >>> >>> l[0] 1 >>> l[5] 6 >>> l[6] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: list index out of range
总结您的问题:
- 您的 indA 和 indB 列表各有 6 个元素 ([1..6]),它们的索引为:[ 0..5]
- 您的 c1 和 c2 列表也有 6 个元素(索引也是 [0..5])
- 但是,您使用 #1. 中的值作为 #2. 列表中的索引,并且值 6 是一个问题,因为没有这样的索引
要解决您的问题,您应该使用有效的索引值。要么:
在 indA 和 indB 中设置正确的值(这是我选择的值):
a, b = pmxCrossover([0, 3, 1, 2, 5, 4], [4, 0, 2, 3, 5, 1])
无论何时遇到indA或indB值时减去1 em> 用作索引:
c1[indA[i] - 1] = i
作为一般建议:每当遇到错误时,请在错误行之前添加打印语句(从中打印(部分)内容) ,这可能会给您提供一些线索,帮助您自己解决问题。
@EDIT0
发布原始代码(稍加修改的版本),并进行索引转换:
- 在算法之前:(从每个元素中)减去 1 以获得有效索引
- 算法结束后:加 1 回到基于 1 的索引
code00.py:
#!/usr/bin/env python3
import sys
import random
def pmx_crossover(ind_a, ind_b):
size = min(len(ind_a), len(ind_b))
c1, c2 = [0] * size, [0] * size
# Initialize the position of each indices in the individuals
for i in range(1, size):
c1[ind_a[i]] = i
c2[ind_b[i]] = i
# Choose crossover points
crosspoint1 = random.randint(0, size)
crosspoint2 = random.randint(0, size - 1)
if crosspoint2 >= crosspoint1:
crosspoint2 += 1
else: # Swap the two cx points
crosspoint1, crosspointt2 = crosspoint2, crosspoint1
# Apply crossover between cx points
for i in range(crosspoint1, crosspoint2):
# Keep track of the selected values
temp1 = ind_a[i]
temp2 = ind_b[i]
# Swap the matched value
ind_a[i], ind_a[c1[temp2]] = temp2, temp1
ind_b[i], ind_b[c2[temp1]] = temp1, temp2
# Position bookkeeping
c1[temp1], c1[temp2] = c1[temp2], c1[temp1]
c2[temp1], c2[temp2] = c2[temp2], c2[temp1]
return ind_a, ind_b
def main():
#initial_a, initial_b = [1, 2, 3, 4, 5, 6, 7, 8], [3, 7, 5, 1, 6, 8, 2, 4]
initial_a, initial_b = [1, 4, 2, 3, 6, 5], [5, 1, 3, 4, 6, 2]
index_offset = 1
temp_a = [i - index_offset for i in initial_a]
temp_b = [i - index_offset for i in initial_b]
a, b = pmx_crossover(temp_a, temp_b)
final_a = [i + index_offset for i in a]
final_b = [i + index_offset for i in b]
print("Initial: {0:}, {1:}".format(initial_a, initial_b))
print("Final: {0:}, {1:}".format(final_a, final_b))
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main()
print("\nDone.")
输出(可能性之一(由于random.randint
)):
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q058424002]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32 Initial: [1, 4, 2, 3, 6, 5], [5, 1, 3, 4, 6, 2] Final: [1, 3, 2, 4, 6, 5], [5, 1, 4, 3, 6, 2] Done.
关于python - Python索引错误: list assignment index out of range ,,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58424002/