Skip to content

Commit 6ea0077

Browse files
committed
Merge pull request #170 from projectmesa/staged_activation.166
Adding multi-stage activation.
2 parents 9665361 + 99e7ca3 commit 6ea0077

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed

mesa/time.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,58 @@ def step(self):
133133
agent.advance(self.model)
134134
self.steps += 1
135135
self.time += 1
136+
137+
138+
class StagedActivation(BaseScheduler):
139+
'''
140+
A scheduler which allows agent activation to be divided into several stages
141+
instead of a single `step` method. All agents execute one stage before
142+
moving on to the next.
143+
144+
Agents must have all the stage methods implemented. Stage methods take a
145+
model object as their only argument.
146+
147+
This schedule tracks steps and time separately. Time advances in fractional
148+
increments of 1 / (# of stages), meaning that 1 step = 1 unit of time.
149+
'''
150+
151+
stage_list = []
152+
shuffle = False
153+
shuffle_between_stages = False
154+
stage_time = 1
155+
156+
def __init__(self, model, stage_list=["step"], shuffle=False,
157+
shuffle_between_stages=False):
158+
'''
159+
Create an empty Staged Activation schedule.
160+
161+
Args:
162+
model: Model object associated with the schedule.
163+
stage_list: List of strings of names of stages to run, in the
164+
order to run them in.
165+
shuffle: If True, shuffle the order of agents each step.
166+
shuffle_between_stages: If True, shuffle the agents after each
167+
stage; otherwise, only shuffle at the start
168+
of each step.
169+
'''
170+
super().__init__(model)
171+
self.stage_list = stage_list
172+
self.shuffle = shuffle
173+
self.shuffle_between_stages = shuffle_between_stages
174+
self.stage_time = 1 / len(self.stage_list)
175+
176+
def step(self):
177+
'''
178+
Executes all the stages of all agents.
179+
'''
180+
181+
if self.shuffle:
182+
random.shuffle(self.agents)
183+
for stage in self.stage_list:
184+
for agent in self.agents:
185+
getattr(agent, stage)(self.model) # Run stage
186+
if self.shuffle_between_stages:
187+
random.shuffle(self.agents)
188+
self.time += self.stage_time
189+
190+
self.steps += 1

tests/test_time.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
'''
2+
Test the advanced schedulers.
3+
'''
4+
5+
import unittest
6+
from mesa import Model, Agent
7+
from mesa.time import StagedActivation
8+
9+
10+
class MockStagedAgent(Agent):
11+
'''
12+
Minimalistic agent for testing purposes.
13+
'''
14+
15+
def __init__(self, name):
16+
self.unique_id = name
17+
18+
def stage_one(self, model):
19+
model.log.append(self.unique_id + "_1")
20+
21+
def stage_two(self, model):
22+
model.log.append(self.unique_id + "_2")
23+
24+
25+
class MockModel(Model):
26+
27+
def __init__(self, shuffle):
28+
self.log = []
29+
model_stages = ["stage_one", "stage_two"]
30+
self.schedule = StagedActivation(self, model_stages, shuffle=shuffle)
31+
32+
# Make agents
33+
for name in ["A", "B"]:
34+
agent = MockStagedAgent(name)
35+
self.schedule.add(agent)
36+
37+
def step(self):
38+
self.schedule.step()
39+
40+
41+
class TestStagedActivation(unittest.TestCase):
42+
'''
43+
Test the staged activation.
44+
'''
45+
46+
expected_output = ["A_1", "B_1", "A_2", "B_2"]
47+
48+
def test_no_shuffle(self):
49+
'''
50+
Testing staged activation without shuffling.
51+
'''
52+
model = MockModel(False)
53+
model.step()
54+
assert model.log == self.expected_output
55+
56+
def test_shuffle(self):
57+
'''
58+
Test staged activation with shuffling
59+
'''
60+
model = MockModel(True)
61+
model.step()
62+
for output in self.expected_output[:2]:
63+
assert output in model.log[:2]
64+
for output in self.expected_output[2:]:
65+
assert output in model.log[2:]

0 commit comments

Comments
 (0)