Skip to content

Commit 164d9e8

Browse files
JoeHelbingrht
andauthored
Bug fixes and additions to Epstein Civil Violence (#42)
* Bug fixes and additions to Epstein Civil Violence This update changes a small set of bugs that was causing the model to not exhibit the cyclical explosions of active agents seen in the original Epstein paper. It also adds some small functionality to the browser display, introducing sliders to allow the user to change model parameters on the fly, and watch a graph of agent state numbers. Bug Fixes - Fix agent state logic - Fix Moore vs Von Neuman neighborhood selection to use Epstein paper behavior - Fix agent vision bug (was 1 and not parameter `vision` when calculating neighborhood, which also fixes agent movement issue) - Fix arrestee state issue (arrestee was not being reset to "Quiescent", and so was counting as "Active" for all nearby agents) Additions and Changes - Change display of agents where jailed agents are represented by grey square box - Added sliders for model attributes Co-authored-by: rht <rhtbot@protonmail.com>
1 parent 05857c7 commit 164d9e8

File tree

3 files changed

+50
-24
lines changed

3 files changed

+50
-24
lines changed

examples/epstein_civil_violence/epstein_civil_violence/agent.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,9 @@ def step(self):
7878
self.update_neighbors()
7979
self.update_estimated_arrest_probability()
8080
net_risk = self.risk_aversion * self.arrest_probability
81-
if (
82-
self.condition == "Quiescent"
83-
and (self.grievance - net_risk) > self.threshold
84-
):
81+
if self.grievance - net_risk > self.threshold:
8582
self.condition = "Active"
86-
elif (
87-
self.condition == "Active" and (self.grievance - net_risk) <= self.threshold
88-
):
83+
else:
8984
self.condition = "Quiescent"
9085
if self.model.movement and self.empty_neighbors:
9186
new_pos = self.random.choice(self.empty_neighbors)
@@ -96,7 +91,7 @@ def update_neighbors(self):
9691
Look around and see who my neighbors are
9792
"""
9893
self.neighborhood = self.model.grid.get_neighborhood(
99-
self.pos, moore=False, radius=1
94+
self.pos, moore=True, radius=self.vision
10095
)
10196
self.neighbors = self.model.grid.get_cell_list_contents(self.neighborhood)
10297
self.empty_neighbors = [
@@ -167,6 +162,7 @@ def step(self):
167162
arrestee = self.random.choice(active_neighbors)
168163
sentence = self.random.randint(0, self.model.max_jail_term)
169164
arrestee.jail_sentence = sentence
165+
arrestee.condition = "Quiescent"
170166
if self.model.movement and self.empty_neighbors:
171167
new_pos = self.random.choice(self.empty_neighbors)
172168
self.model.grid.move_agent(self, new_pos)
@@ -176,7 +172,7 @@ def update_neighbors(self):
176172
Look around and see who my neighbors are.
177173
"""
178174
self.neighborhood = self.model.grid.get_neighborhood(
179-
self.pos, moore=False, radius=1
175+
self.pos, moore=True, radius=self.vision
180176
)
181177
self.neighbors = self.model.grid.get_cell_list_contents(self.neighborhood)
182178
self.empty_neighbors = [

examples/epstein_civil_violence/epstein_civil_violence/model.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,12 @@ def __init__(
6060
self.iteration = 0
6161
self.schedule = mesa.time.RandomActivation(self)
6262
self.grid = mesa.space.SingleGrid(width, height, torus=True)
63+
6364
model_reporters = {
6465
"Quiescent": lambda m: self.count_type_citizens(m, "Quiescent"),
6566
"Active": lambda m: self.count_type_citizens(m, "Active"),
6667
"Jailed": self.count_jailed,
68+
"Cops": self.count_cops,
6769
}
6870
agent_reporters = {
6971
"x": lambda a: a.pos[0],
@@ -123,7 +125,7 @@ def count_type_citizens(model, condition, exclude_jailed=True):
123125
for agent in model.schedule.agents:
124126
if agent.breed == "cop":
125127
continue
126-
if exclude_jailed and agent.jail_sentence:
128+
if exclude_jailed and agent.jail_sentence > 0:
127129
continue
128130
if agent.condition == condition:
129131
count += 1
@@ -136,6 +138,6 @@ def count_jailed(model):
136138
"""
137139
count = 0
138140
for agent in model.schedule.agents:
139-
if agent.breed == "citizen" and agent.jail_sentence:
141+
if agent.breed == "citizen" and agent.jail_sentence > 0:
140142
count += 1
141143
return count

examples/epstein_civil_violence/epstein_civil_violence/server.py

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
from .model import EpsteinCivilViolence
55

66
COP_COLOR = "#000000"
7-
AGENT_QUIET_COLOR = "#0066CC"
8-
AGENT_REBEL_COLOR = "#CC0000"
9-
JAIL_COLOR = "#757575"
7+
AGENT_QUIET_COLOR = "#648FFF"
8+
AGENT_REBEL_COLOR = "#FE6100"
9+
JAIL_COLOR = "#808080"
10+
JAIL_SHAPE = "rect"
1011

1112

1213
def citizen_cop_portrayal(agent):
@@ -25,29 +26,56 @@ def citizen_cop_portrayal(agent):
2526
AGENT_QUIET_COLOR if agent.condition == "Quiescent" else AGENT_REBEL_COLOR
2627
)
2728
color = JAIL_COLOR if agent.jail_sentence else color
29+
shape = JAIL_SHAPE if agent.jail_sentence else "circle"
2830
portrayal["Color"] = color
29-
portrayal["r"] = 0.8
31+
portrayal["Shape"] = shape
32+
if shape == "rect":
33+
portrayal["w"] = 0.9
34+
portrayal["h"] = 0.9
35+
else:
36+
portrayal["r"] = 0.5
37+
portrayal["Filled"] = "false"
3038
portrayal["Layer"] = 0
3139

3240
elif type(agent) is Cop:
3341
portrayal["Color"] = COP_COLOR
34-
portrayal["r"] = 0.5
42+
portrayal["r"] = 0.9
3543
portrayal["Layer"] = 1
44+
3645
return portrayal
3746

3847

3948
model_params = {
4049
"height": 40,
4150
"width": 40,
42-
"citizen_density": 0.7,
43-
"cop_density": 0.074,
44-
"citizen_vision": 7,
45-
"cop_vision": 7,
46-
"legitimacy": 0.8,
47-
"max_jail_term": 1000,
51+
"citizen_density": mesa.visualization.Slider(
52+
"Initial Agent Density", 0.7, 0.0, 0.9, 0.1
53+
),
54+
"cop_density": mesa.visualization.Slider(
55+
"Initial Cop Density", 0.04, 0.0, 0.1, 0.01
56+
),
57+
"citizen_vision": mesa.visualization.Slider("Citizen Vision", 7, 1, 10, 1),
58+
"cop_vision": mesa.visualization.Slider("Cop Vision", 7, 1, 10, 1),
59+
"legitimacy": mesa.visualization.Slider(
60+
"Government Legitimacy", 0.82, 0.0, 1, 0.01
61+
),
62+
"max_jail_term": mesa.visualization.Slider("Max Jail Term", 30, 0, 50, 1),
4863
}
49-
5064
canvas_element = mesa.visualization.CanvasGrid(citizen_cop_portrayal, 40, 40, 480, 480)
65+
chart = mesa.visualization.ChartModule(
66+
[
67+
{"Label": "Quiescent", "Color": "#648FFF"},
68+
{"Label": "Active", "Color": "#FE6100"},
69+
{"Label": "Jailed", "Color": "#808080"},
70+
],
71+
data_collector_name="datacollector",
72+
)
5173
server = mesa.visualization.ModularServer(
52-
EpsteinCivilViolence, [canvas_element], "Epstein Civil Violence", model_params
74+
EpsteinCivilViolence,
75+
[
76+
canvas_element,
77+
chart,
78+
],
79+
"Epstein Civil Violence",
80+
model_params,
5381
)

0 commit comments

Comments
 (0)