Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RuntimeError when removing agents from model with new schedulers #1959

Closed
quaquel opened this issue Jan 12, 2024 · 3 comments
Closed

RuntimeError when removing agents from model with new schedulers #1959

quaquel opened this issue Jan 12, 2024 · 3 comments

Comments

@quaquel
Copy link
Member

quaquel commented Jan 12, 2024

Describe the bug
WolfSheep and similar models where agents are removed during agent.step throw a Runtime Error:

RuntimeError: dictionary changed size during iteration

The cause is quite straightforward: in AgentSet.do, one iterates over the agents. If do triggers the removal of agents that are in the AgentSet over which you are iterating, you get the error.

Expected behavior
The Runtime error should not occur

Proposed fix
Change line 254 in agent.py to res = [getattr(agent, method_name)(*args, **kwargs) for agent in list(self._agents)]. You no longer get the error by turning the keys into a list and iterating over this list. This is also identical to how the error was prevented in the 2.1.5 version of the schedulers.

In addition, it would be good to also add an explicit unit test for this error so that it won't happen in the future. Something like below should be all that is needed

MockAgent(agent):
    def step(self):
        self.model.remove()

agents = [MockAgent(i, mockmodel) for i in range(10)]
agentset = AgentSet(agents, mockmodel)
agentset.do("step")

To Reproduce
Run WolfSheep with the latest stable version of MESA

@rht
Copy link
Contributor

rht commented Jan 12, 2024

An attempt to fix was made at #1958.

@quaquel
Copy link
Member Author

quaquel commented Jan 13, 2024

I have done some additional diagnostics on this.

Specifically, with respect to the WolfSheep model, there are two ways in which the scheduler can be changed while iterating over it. First, the error happens because a sheep or wolf is born and added to the model. Second, the error happens when a wolf or sheep dies and thus is removed from the model.

WeakkeyDict runs with a form of protection. See StackOverflow for more details. If I change, in the example model, the code from self.model.schedule.remove to self.remove, this prevents errors because a wolf or sheep has died. However, this proper fix is not backward compatible and can only be relied upon partially.

What remains, thus, is the addition of new agents while iterating. Casting the keys to list or copying them before iterating solves this problem but can trigger other errors as discussed in #1958.

In short, the error is triggered when explicitly calling AgentSet.add and AgentSet.remove while iterating over the AgentSet.

@quaquel
Copy link
Member Author

quaquel commented Jan 13, 2024

closed by #1960

@quaquel quaquel closed this as completed Jan 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants