IndexError: индекс назначения списка вне диапазона, Python - PullRequest
2 голосов
/ 17 октября 2019

Я пытаюсь достичь функциональности. Это должно работать следующим образом:

  1. Требуется два списка.
  2. Отметьте некоторые индексы, желательно несколько по центру.
  3. Оба родителя переключают помеченные индексы.
  4. Другие индексы последовательно идут к своему родительскому элементу.
  5. Если тот же элемент уже присутствует в этом родительском элементе, он сопоставляется и проверяет, где другиеродительский же элемент был и есть там.
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

Ответы [ 2 ]

2 голосов
/ 17 октября 2019

Не уверен, есть ли другие ошибки в вашем коде (я не запускал его), но вот объяснение этому. В 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

Подведем итог вашей проблемы:

  1. В ваших списках indA и indB есть по 6 элементов (* 1021)* [1..6] ) и их индексы: [0..5]
  2. Ваши c1 и c2 списки также имеют 6 элементов (индексы также [0..5] )
  3. Но вы используете в качестве индексов значения от # 1. в списках от # 2. , а значение 6 является проблемой, так как такого индекса нет

Чтобы исправить вашу проблему, вы должны использовать допустимые значения индекса. Либо:

  • Иметь правильные значения в indA и indB (это то, что я выбрал):

    a, b = pmxCrossover([0, 3, 1, 2, 5, 4], [4, 0, 2, 3, 5, 1])
    
  • Вычитать 1 , везде, где встречаются значения от indA или indB используется в качестве индексов:

    c1[indA[i] - 1] = i
    

В качестве общего совета: при возникновении ошибок добавьте print операторов перед неисправная строка (печатая (частично) материал из нее), и это может дать вам подсказки, которые могут привести к решению проблемы самостоятельно.

@ EDIT0

Posting (слегка измененная версияиз) исходный код с преобразованием индекса:

  • Перед алгоритмом: вычтите 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.
0 голосов
/ 17 октября 2019

c1 выходит за пределы диапазона, потому что в вашем for для четвертого индекса значение indA [4] равно 6. А диапазон индекса c1 равен 0-5 (его длина равна 6).

С c1[indA[i]] = i вы пытаетесь сделать c1[6] = 4

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...