-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Scheduler: track agents with dict instead of list #386
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
Changes from all commits
9bb249d
5790512
fcf8b86
c18aa50
17ed18b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,7 +43,7 @@ def __init__(self, model): | |
| self.model = model | ||
| self.steps = 0 | ||
| self.time = 0 | ||
| self.agents = [] | ||
| self.agents = {} | ||
|
|
||
| def add(self, agent): | ||
| """ Add an Agent object to the schedule. | ||
|
|
@@ -53,7 +53,7 @@ def add(self, agent): | |
| have a step() method. | ||
|
|
||
| """ | ||
| self.agents.append(agent) | ||
| self.agents[agent.unique_id] = agent | ||
|
|
||
| def remove(self, agent): | ||
| """ Remove all instances of a given agent from the schedule. | ||
|
|
@@ -62,19 +62,19 @@ def remove(self, agent): | |
| agent: An agent object. | ||
|
|
||
| """ | ||
| while agent in self.agents: | ||
| self.agents.remove(agent) | ||
| del self.agents[agent.unique_id] | ||
|
|
||
| def step(self): | ||
| """ Execute the step of all the agents, one at a time. """ | ||
| for agent in self.agents[:]: | ||
| agent.step() | ||
| agent_keys = list(self.agents.keys()) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, in all the places where |
||
| for agent_key in agent_keys: | ||
| self.agents[agent_key].step() | ||
| self.steps += 1 | ||
| self.time += 1 | ||
|
|
||
| def get_agent_count(self): | ||
| """ Returns the current number of agents in the queue. """ | ||
| return len(self.agents) | ||
| return len(self.agents.keys()) | ||
|
|
||
|
|
||
| class RandomActivation(BaseScheduler): | ||
|
|
@@ -92,9 +92,11 @@ def step(self): | |
| random order. | ||
|
|
||
| """ | ||
| random.shuffle(self.agents) | ||
| for agent in self.agents[:]: | ||
| agent.step() | ||
| agent_keys = list(self.agents.keys()) | ||
| random.shuffle(agent_keys) | ||
|
|
||
| for agent_key in agent_keys: | ||
| self.agents[agent_key].step() | ||
| self.steps += 1 | ||
| self.time += 1 | ||
|
|
||
|
|
@@ -109,10 +111,11 @@ class SimultaneousActivation(BaseScheduler): | |
| """ | ||
| def step(self): | ||
| """ Step all agents, then advance them. """ | ||
| for agent in self.agents[:]: | ||
| agent.step() | ||
| for agent in self.agents[:]: | ||
| agent.advance() | ||
| agent_keys = list(self.agents.keys()) | ||
| for agent_key in agent_keys: | ||
| self.agents[agent_key].step() | ||
| for agent_key in agent_keys: | ||
| self.agents[agent_key].advance() | ||
| self.steps += 1 | ||
| self.time += 1 | ||
|
|
||
|
|
@@ -151,13 +154,14 @@ def __init__(self, model, stage_list=None, shuffle=False, | |
|
|
||
| def step(self): | ||
| """ Executes all the stages for all agents. """ | ||
| agent_keys = list(self.agents.keys()) | ||
| if self.shuffle: | ||
| random.shuffle(self.agents) | ||
| random.shuffle(agent_keys) | ||
| for stage in self.stage_list: | ||
| for agent in self.agents[:]: | ||
| getattr(agent, stage)() # Run stage | ||
| for agent_key in agent_keys: | ||
| getattr(self.agents[agent_key], stage)() # Run stage | ||
| if self.shuffle_between_stages: | ||
| random.shuffle(self.agents) | ||
| random.shuffle(agent_keys) | ||
| self.time += self.stage_time | ||
|
|
||
| self.steps += 1 | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC the ordering is non-deterministic in
python<3.6. Yet deterministic execution is crucial in scientific simulations.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that preserving order is important. I'm not sure whether in Python <3.6 iterating over
values()is guaranteed to preserve order any better than just iterating over the keys, and/or for that order to be the same as the order in which the agents were added (which should be the default non-random behavior).Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A sure-fire fix is to use
collections.OrderedDict. But this will be slower since in Python 3 it is not written in C. But correctness > speed in this case.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it has to be a
defaultdict+collections.OrderedDict.