Skip to content

Commit e897839

Browse files
authored
Moving examples to use the new discrete spaces (#198)
1 parent e23b804 commit e897839

File tree

11 files changed

+175
-335
lines changed

11 files changed

+175
-335
lines changed

examples/advanced/epstein_civil_violence/epstein_civil_violence/agent.py

Lines changed: 22 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,23 @@
33
import mesa
44

55

6-
class Citizen(mesa.Agent):
6+
class EpsteinAgent(mesa.experimental.cell_space.CellAgent):
7+
def update_neighbors(self):
8+
"""
9+
Look around and see who my neighbors are
10+
"""
11+
self.neighborhood = self.cell.get_neighborhood(radius=self.vision)
12+
13+
self.neighbors = self.neighborhood.agents
14+
self.empty_neighbors = [c for c in self.neighborhood if c.is_empty]
15+
16+
17+
class Citizen(EpsteinAgent):
718
"""
819
A member of the general population, may or may not be in active rebellion.
920
Summary of rule: If grievance - risk > threshold, rebel.
1021
1122
Attributes:
12-
x, y: Grid coordinates
1323
hardship: Agent's 'perceived hardship (i.e., physical or economic
1424
privation).' Exogenous, drawn from U(0,1).
1525
regime_legitimacy: Agent's perception of regime legitimacy, equal
@@ -30,7 +40,6 @@ class Citizen(mesa.Agent):
3040
def __init__(
3141
self,
3242
model,
33-
pos,
3443
hardship,
3544
regime_legitimacy,
3645
risk_aversion,
@@ -40,7 +49,7 @@ def __init__(
4049
"""
4150
Create a new Citizen.
4251
Args:
43-
x, y: Grid coordinates
52+
model: the model to which the agent belongs
4453
hardship: Agent's 'perceived hardship (i.e., physical or economic
4554
privation).' Exogenous, drawn from U(0,1).
4655
regime_legitimacy: Agent's perception of regime legitimacy, equal
@@ -53,8 +62,6 @@ def __init__(
5362
model: model instance
5463
"""
5564
super().__init__(model)
56-
self.breed = "citizen"
57-
self.pos = pos
5865
self.hardship = hardship
5966
self.regime_legitimacy = regime_legitimacy
6067
self.risk_aversion = risk_aversion
@@ -79,32 +86,21 @@ def step(self):
7986
self.condition = "Active"
8087
else:
8188
self.condition = "Quiescent"
82-
if self.model.movement and self.empty_neighbors:
83-
new_pos = self.random.choice(self.empty_neighbors)
84-
self.model.grid.move_agent(self, new_pos)
8589

86-
def update_neighbors(self):
87-
"""
88-
Look around and see who my neighbors are
89-
"""
90-
self.neighborhood = self.model.grid.get_neighborhood(
91-
self.pos, moore=True, radius=self.vision
92-
)
93-
self.neighbors = self.model.grid.get_cell_list_contents(self.neighborhood)
94-
self.empty_neighbors = [
95-
c for c in self.neighborhood if self.model.grid.is_cell_empty(c)
96-
]
90+
if self.model.movement and self.empty_neighbors:
91+
new_cell = self.random.choice(self.empty_neighbors)
92+
self.move_to(new_cell)
9793

9894
def update_estimated_arrest_probability(self):
9995
"""
10096
Based on the ratio of cops to actives in my neighborhood, estimate the
10197
p(Arrest | I go active).
10298
"""
103-
cops_in_vision = len([c for c in self.neighbors if c.breed == "cop"])
99+
cops_in_vision = len([c for c in self.neighbors if isinstance(c, Cop)])
104100
actives_in_vision = 1.0 # citizen counts herself
105101
for c in self.neighbors:
106102
if (
107-
c.breed == "citizen"
103+
isinstance(c, Citizen)
108104
and c.condition == "Active"
109105
and c.jail_sentence == 0
110106
):
@@ -114,7 +110,7 @@ def update_estimated_arrest_probability(self):
114110
)
115111

116112

117-
class Cop(mesa.Agent):
113+
class Cop(EpsteinAgent):
118114
"""
119115
A cop for life. No defection.
120116
Summary of rule: Inspect local vision and arrest a random active agent.
@@ -126,7 +122,7 @@ class Cop(mesa.Agent):
126122
able to inspect
127123
"""
128124

129-
def __init__(self, model, pos, vision):
125+
def __init__(self, model, vision):
130126
"""
131127
Create a new Cop.
132128
Args:
@@ -136,8 +132,6 @@ def __init__(self, model, pos, vision):
136132
model: model instance
137133
"""
138134
super().__init__(model)
139-
self.breed = "cop"
140-
self.pos = pos
141135
self.vision = vision
142136

143137
def step(self):
@@ -149,7 +143,7 @@ def step(self):
149143
active_neighbors = []
150144
for agent in self.neighbors:
151145
if (
152-
agent.breed == "citizen"
146+
isinstance(agent, Citizen)
153147
and agent.condition == "Active"
154148
and agent.jail_sentence == 0
155149
):
@@ -161,16 +155,4 @@ def step(self):
161155
arrestee.condition = "Quiescent"
162156
if self.model.movement and self.empty_neighbors:
163157
new_pos = self.random.choice(self.empty_neighbors)
164-
self.model.grid.move_agent(self, new_pos)
165-
166-
def update_neighbors(self):
167-
"""
168-
Look around and see who my neighbors are.
169-
"""
170-
self.neighborhood = self.model.grid.get_neighborhood(
171-
self.pos, moore=True, radius=self.vision
172-
)
173-
self.neighbors = self.model.grid.get_cell_list_contents(self.neighborhood)
174-
self.empty_neighbors = [
175-
c for c in self.neighborhood if self.model.grid.is_cell_empty(c)
176-
]
158+
self.move_to(new_pos)

examples/advanced/epstein_civil_violence/epstein_civil_violence/model.py

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ def __init__(
5959
self.max_iters = max_iters
6060
self.iteration = 0
6161

62-
self.grid = mesa.space.SingleGrid(width, height, torus=True)
62+
self.grid = mesa.experimental.cell_space.OrthogonalMooreGrid(
63+
(width, height), capacity=1, torus=True
64+
)
6365

6466
model_reporters = {
6567
"Quiescent": lambda m: self.count_type_citizens(m, "Quiescent"),
@@ -68,9 +70,9 @@ def __init__(
6870
"Cops": self.count_cops,
6971
}
7072
agent_reporters = {
71-
"x": lambda a: a.pos[0],
72-
"y": lambda a: a.pos[1],
73-
"breed": lambda a: a.breed,
73+
"x": lambda a: a.cell.coordinate[0],
74+
"y": lambda a: a.cell.coordinate[1],
75+
"breed": lambda a: type(a).__name__,
7476
"jail_sentence": lambda a: getattr(a, "jail_sentence", None),
7577
"condition": lambda a: getattr(a, "condition", None),
7678
"arrest_probability": lambda a: getattr(a, "arrest_probability", None),
@@ -81,22 +83,21 @@ def __init__(
8183
if self.cop_density + self.citizen_density > 1:
8284
raise ValueError("Cop density + citizen density must be less than 1")
8385

84-
for contents, (x, y) in self.grid.coord_iter():
86+
for cell in self.grid.all_cells:
8587
if self.random.random() < self.cop_density:
86-
cop = Cop(self, (x, y), vision=self.cop_vision)
87-
self.grid[x][y] = cop
88+
cop = Cop(self, vision=self.cop_vision)
89+
cop.move_to(cell)
8890

8991
elif self.random.random() < (self.cop_density + self.citizen_density):
9092
citizen = Citizen(
9193
self,
92-
(x, y),
9394
hardship=self.random.random(),
9495
regime_legitimacy=self.legitimacy,
9596
risk_aversion=self.random.random(),
9697
threshold=self.active_threshold,
9798
vision=self.citizen_vision,
9899
)
99-
self.grid[x][y] = citizen
100+
citizen.move_to(cell)
100101

101102
self.running = True
102103
self.datacollector.collect(self)
@@ -117,34 +118,29 @@ def count_type_citizens(model, condition, exclude_jailed=True):
117118
"""
118119
Helper method to count agents by Quiescent/Active.
119120
"""
120-
count = 0
121-
for agent in model.agents:
122-
if agent.breed == "cop":
123-
continue
124-
if exclude_jailed and agent.jail_sentence > 0:
125-
continue
126-
if agent.condition == condition:
127-
count += 1
128-
return count
121+
citizens = model.agents_by_type[Citizen]
122+
123+
if exclude_jailed:
124+
return len(
125+
[
126+
c
127+
for c in citizens
128+
if (c.condition == condition) and (c.jail_sentence == 0)
129+
]
130+
)
131+
else:
132+
return len([c for c in citizens if c.condition == condition])
129133

130134
@staticmethod
131135
def count_jailed(model):
132136
"""
133137
Helper method to count jailed agents.
134138
"""
135-
count = 0
136-
for agent in model.agents:
137-
if agent.breed == "citizen" and agent.jail_sentence > 0:
138-
count += 1
139-
return count
139+
return len([a for a in model.agents_by_type[Citizen] if a.jail_sentence > 0])
140140

141141
@staticmethod
142142
def count_cops(model):
143143
"""
144144
Helper method to count jailed agents.
145145
"""
146-
count = 0
147-
for agent in model.agents:
148-
if agent.breed == "cop":
149-
count += 1
150-
return count
146+
return len(model.agents_by_type[Cop])

examples/advanced/pd_grid/pd_grid/agent.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import mesa
1+
from mesa.experimental.cell_space import CellAgent
22

33

4-
class PDAgent(mesa.Agent):
4+
class PDAgent(CellAgent):
55
"""Agent member of the iterated, spatial prisoner's dilemma model."""
66

77
def __init__(self, model, starting_move=None):
@@ -22,14 +22,15 @@ def __init__(self, model, starting_move=None):
2222
self.next_move = None
2323

2424
@property
25-
def isCooroperating(self):
25+
def is_cooroperating(self):
2626
return self.move == "C"
2727

2828
def step(self):
2929
"""Get the best neighbor's move, and change own move accordingly
3030
if better than own score."""
3131

32-
neighbors = self.model.grid.get_neighbors(self.pos, True, include_center=True)
32+
# neighbors = self.model.grid.get_neighbors(self.pos, True, include_center=True)
33+
neighbors = [*list(self.cell.neighborhood.agents), self]
3334
best_neighbor = max(neighbors, key=lambda a: a.score)
3435
self.next_move = best_neighbor.move
3536

@@ -41,7 +42,7 @@ def advance(self):
4142
self.score += self.increment_score()
4243

4344
def increment_score(self):
44-
neighbors = self.model.grid.get_neighbors(self.pos, True)
45+
neighbors = self.cell.neighborhood.agents
4546
if self.model.activation_order == "Simultaneous":
4647
moves = [neighbor.next_move for neighbor in neighbors]
4748
else:

examples/advanced/pd_grid/pd_grid/model.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import mesa
2+
from mesa.experimental.cell_space import OrthogonalMooreGrid
23

34
from .agent import PDAgent
45

@@ -25,15 +26,18 @@ def __init__(
2526
Determines the agent activation regime.
2627
payoffs: (optional) Dictionary of (move, neighbor_move) payoffs.
2728
"""
28-
super().__init__()
29+
super().__init__(seed=seed)
2930
self.activation_order = activation_order
30-
self.grid = mesa.space.SingleGrid(width, height, torus=True)
31+
self.grid = OrthogonalMooreGrid((width, height), torus=True)
32+
33+
if payoffs is not None:
34+
self.payoff = payoffs
3135

3236
# Create agents
3337
for x in range(width):
3438
for y in range(height):
3539
agent = PDAgent(self)
36-
self.grid.place_agent(agent, (x, y))
40+
agent.cell = self.grid[(x, y)]
3741

3842
self.datacollector = mesa.DataCollector(
3943
{

examples/advanced/sugarscape_g1mt/sugarscape_g1mt/model.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import mesa
44
import numpy as np
5+
from mesa.experimental.cell_space import OrthogonalVonNeumannGrid
56

67
from .resource_agents import Resource
78
from .trader_agents import Trader
@@ -69,7 +70,7 @@ def __init__(
6970
self.running = True
7071

7172
# initiate mesa grid class
72-
self.grid = mesa.space.MultiGrid(self.width, self.height, torus=False)
73+
self.grid = OrthogonalVonNeumannGrid((self.width, self.height), torus=False)
7374
# initiate datacollector
7475
self.datacollector = mesa.DataCollector(
7576
model_reporters={
@@ -88,11 +89,10 @@ def __init__(
8889
sugar_distribution = np.genfromtxt(Path(__file__).parent / "sugar-map.txt")
8990
spice_distribution = np.flip(sugar_distribution, 1)
9091

91-
for _, (x, y) in self.grid.coord_iter():
92-
max_sugar = sugar_distribution[x, y]
93-
max_spice = spice_distribution[x, y]
94-
resource = Resource(self, max_sugar, max_spice)
95-
self.grid.place_agent(resource, (x, y))
92+
for cell in self.grid.all_cells:
93+
max_sugar = sugar_distribution[cell.coordinate]
94+
max_spice = spice_distribution[cell.coordinate]
95+
Resource(self, max_sugar, max_spice, cell)
9696

9797
for _ in range(self.initial_population):
9898
# get agent position
@@ -111,18 +111,18 @@ def __init__(
111111
)
112112
# give agents vision
113113
vision = int(self.random.uniform(self.vision_min, self.vision_max + 1))
114+
115+
cell = self.grid[(x, y)]
114116
# create Trader object
115-
trader = Trader(
117+
Trader(
116118
self,
117-
moore=False,
119+
cell,
118120
sugar=sugar,
119121
spice=spice,
120122
metabolism_sugar=metabolism_sugar,
121123
metabolism_spice=metabolism_spice,
122124
vision=vision,
123125
)
124-
# place agent
125-
self.grid.place_agent(trader, (x, y))
126126

127127
def step(self):
128128
"""

examples/advanced/sugarscape_g1mt/sugarscape_g1mt/resource_agents.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
1-
import mesa
1+
from mesa.experimental.cell_space import FixedAgent
22

33

4-
class Resource(mesa.Agent):
4+
class Resource(FixedAgent):
55
"""
66
Resource:
77
- contains an amount of sugar and spice
88
- grows 1 amount of sugar at each turn
99
- grows 1 amount of spice at each turn
1010
"""
1111

12-
def __init__(self, model, max_sugar, max_spice):
12+
def __init__(self, model, max_sugar, max_spice, cell):
1313
super().__init__(model)
1414
self.sugar_amount = max_sugar
1515
self.max_sugar = max_sugar
1616
self.spice_amount = max_spice
1717
self.max_spice = max_spice
18+
self.cell = cell
1819

1920
def step(self):
2021
"""

0 commit comments

Comments
 (0)