forked from projectmesa/mesa
-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_lifespan.py
94 lines (72 loc) · 2.78 KB
/
test_lifespan.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import unittest
from mesa.time import RandomActivation
from mesa.datacollection import DataCollector
from mesa import Model, Agent
import numpy as np
class LifeTimeModel(Model):
"""Simple model for running models with a finite life"""
def __init__(self, agent_lifetime=1, n_agents=10):
super().__init__()
self.agent_lifetime = agent_lifetime
self.n_agents = n_agents
# keep track of the the remaining life of an agent and
# how many ticks it has seen
self.datacollector = DataCollector(
agent_reporters={
"remaining_life": lambda a: a.remaining_life,
"steps": lambda a: a.steps,
}
)
self.current_ID = 0
self.schedule = RandomActivation(self)
for _ in range(n_agents):
self.schedule.add(
FiniteLifeAgent(self.next_id(), self.agent_lifetime, self)
)
def step(self):
"""Add agents back to n_agents in each step"""
self.datacollector.collect(self)
self.schedule.step()
if len(self.schedule.agents) < self.n_agents:
for _ in range(self.n_agents - len(self.schedule.agents)):
self.schedule.add(
FiniteLifeAgent(self.next_id(), self.agent_lifetime, self)
)
def run_model(self, step_count=100):
for _ in range(step_count):
self.step()
class FiniteLifeAgent(Agent):
"""An agent that is supposed to live for a finite number of ticks.
Also has a 10% chance of dying in each tick.
"""
def __init__(self, unique_id, lifetime, model):
super().__init__(unique_id, model)
self.remaining_life = lifetime
self.steps = 0
self.model = model
def step(self):
inactivated = self.inactivate()
if not inactivated:
self.steps += 1 # keep track of how many ticks are seen
if np.random.binomial(1, 0.1) != 0: # 10% chance of dying
self.model.schedule.remove(self)
def inactivate(self):
self.remaining_life -= 1
if self.remaining_life < 0:
self.model.schedule.remove(self)
return True
return False
class TestAgentLifespan(unittest.TestCase):
def setUp(self):
self.model = LifeTimeModel()
self.model.run_model()
self.df = self.model.datacollector.get_agent_vars_dataframe()
self.df = self.df.reset_index()
def test_ticks_seen(self):
"""Each agent should be activated no more than one time"""
assert self.df.steps.max() == 1
def test_agent_lifetime(self):
lifetimes = self.df.groupby(["AgentID"]).agg({"Step": lambda x: len(x)})
assert lifetimes.Step.max() == 2
if __name__ == "__main__":
unittest.main()