Search code examples
python-3.xlistloopsneural-networkevolutionary-algorithm

Python NeuroEvolutionProject: ValueError: list.remove(x): x not in list (when x is, in fact, in the list)


I'm working on a neuroevolution project in which there is an array full of active entities and dead entities. When the active entities die, they are removed from the active list and placed into the dead list. I frequently have this error when removing an entity from the active list: ValueError:

ValueError: list.remove(x): x not in list

Note that these lists are filled and emptied hundreds of times during execution. This code is run during every frame, so these lists are looped over thousands of times during each execution. This error is not thrown in every generation. It seems to happen randomly at different points during execution.

Code Example:

for entity in self.active:
    entity.updatePosition()
    #bla bla bla unimportant...
    if entity.goesOutOfBounds():
        self.dead.append(entity)
        self.active.remove(entity)

If I can provide any additional info please ask :)


Solution

  • Mutating a list that you are iterating over is a recipe for disaster. Consider the following simple case:

    entities = [1,2,3,4,5]
    for entity in entities:
        entities.remove(entity)
    

    You would expect that every entity should be removed. But if you check the entities list after running the above code:

    print(entities)
    

    [2, 4]

    Obviously not the intended outcome.

    I would begin by refactoring your code so that your are not mutating self.active withing the for entity in self.active loop. Perhaps store a temporary list of items to remove, and then remove them all once you've exited that for entity in self.active: loop:

    to_remove = []
    for entity in self.active:
        entity.updatePosition()
        #bla bla bla unimportant...
        if entity.goesOutOfBounds():
            to_remove.append(entity)
    for entity in to_remove:
        self.active.remove(entity)
    

    Or you could run for entity in self.active[:]: to create a shallow copy of the list to iterate over:

    for entity in self.active[:]:
        entity.updatePosition()
        #bla bla bla unimportant...
        if entity.goesOutOfBounds():
            self.dead.append(entity)
            self.active.remove(entity)
    

    You should probably profile these different options to see which is more performant for your situation.

    From the provided code, I can't see exactly how your error is arising. But there is a lot of code that you haven't provided that could be contributing (i.e. #bla bla bla unimportant). I suspect your issue might lie in what I've outlined above.