Mesa 3.2.0.dev0__py3-none-any.whl → 3.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of Mesa might be problematic. Click here for more details.
- mesa/__init__.py +1 -1
- mesa/agent.py +9 -7
- mesa/datacollection.py +1 -1
- mesa/examples/README.md +1 -1
- mesa/examples/__init__.py +2 -0
- mesa/examples/advanced/alliance_formation/Readme.md +50 -0
- mesa/examples/advanced/alliance_formation/__init__ .py +0 -0
- mesa/examples/advanced/alliance_formation/agents.py +20 -0
- mesa/examples/advanced/alliance_formation/app.py +71 -0
- mesa/examples/advanced/alliance_formation/model.py +184 -0
- mesa/examples/advanced/epstein_civil_violence/app.py +11 -11
- mesa/examples/advanced/pd_grid/Readme.md +4 -6
- mesa/examples/advanced/pd_grid/app.py +10 -11
- mesa/examples/advanced/sugarscape_g1mt/Readme.md +4 -5
- mesa/examples/advanced/sugarscape_g1mt/app.py +34 -16
- mesa/examples/advanced/wolf_sheep/Readme.md +2 -17
- mesa/examples/advanced/wolf_sheep/app.py +21 -18
- mesa/examples/basic/boid_flockers/Readme.md +6 -1
- mesa/examples/basic/boid_flockers/app.py +15 -11
- mesa/examples/basic/boltzmann_wealth_model/Readme.md +2 -12
- mesa/examples/basic/boltzmann_wealth_model/app.py +39 -32
- mesa/examples/basic/conways_game_of_life/Readme.md +1 -9
- mesa/examples/basic/conways_game_of_life/app.py +13 -16
- mesa/examples/basic/schelling/Readme.md +2 -10
- mesa/examples/basic/schelling/agents.py +9 -3
- mesa/examples/basic/schelling/app.py +50 -3
- mesa/examples/basic/schelling/model.py +2 -0
- mesa/examples/basic/schelling/resources/blue_happy.png +0 -0
- mesa/examples/basic/schelling/resources/blue_unhappy.png +0 -0
- mesa/examples/basic/schelling/resources/orange_happy.png +0 -0
- mesa/examples/basic/schelling/resources/orange_unhappy.png +0 -0
- mesa/examples/basic/virus_on_network/Readme.md +0 -4
- mesa/examples/basic/virus_on_network/app.py +31 -14
- mesa/experimental/__init__.py +2 -2
- mesa/experimental/continuous_space/continuous_space.py +1 -1
- mesa/experimental/meta_agents/__init__.py +25 -0
- mesa/experimental/meta_agents/meta_agent.py +387 -0
- mesa/model.py +3 -3
- mesa/space.py +4 -1
- mesa/visualization/__init__.py +2 -0
- mesa/visualization/backends/__init__.py +23 -0
- mesa/visualization/backends/abstract_renderer.py +97 -0
- mesa/visualization/backends/altair_backend.py +440 -0
- mesa/visualization/backends/matplotlib_backend.py +419 -0
- mesa/visualization/components/__init__.py +28 -8
- mesa/visualization/components/altair_components.py +86 -0
- mesa/visualization/components/matplotlib_components.py +4 -2
- mesa/visualization/components/portrayal_components.py +120 -0
- mesa/visualization/mpl_space_drawing.py +292 -129
- mesa/visualization/solara_viz.py +274 -32
- mesa/visualization/space_drawers.py +797 -0
- mesa/visualization/space_renderer.py +399 -0
- {mesa-3.2.0.dev0.dist-info → mesa-3.3.0.dist-info}/METADATA +13 -4
- {mesa-3.2.0.dev0.dist-info → mesa-3.3.0.dist-info}/RECORD +57 -40
- mesa/examples/advanced/sugarscape_g1mt/tests.py +0 -69
- {mesa-3.2.0.dev0.dist-info → mesa-3.3.0.dist-info}/WHEEL +0 -0
- {mesa-3.2.0.dev0.dist-info → mesa-3.3.0.dist-info}/licenses/LICENSE +0 -0
- {mesa-3.2.0.dev0.dist-info → mesa-3.3.0.dist-info}/licenses/NOTICE +0 -0
|
@@ -14,29 +14,14 @@ The model is tests and demonstrates several Mesa concepts and features:
|
|
|
14
14
|
- Writing a model composed of multiple files.
|
|
15
15
|
- Dynamically adding and removing agents from the schedule
|
|
16
16
|
|
|
17
|
-
## Installation
|
|
18
|
-
|
|
19
|
-
To install the dependencies use pip and the requirements.txt in this directory. e.g.
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
# First, we clone the Mesa repo
|
|
23
|
-
$ git clone https://github.com/projectmesa/mesa.git
|
|
24
|
-
$ cd mesa
|
|
25
|
-
# Then we cd to the example directory
|
|
26
|
-
$ cd examples/wolf_sheep
|
|
27
|
-
$ pip install -r requirements.txt
|
|
28
|
-
```
|
|
29
|
-
|
|
30
17
|
## How to Run
|
|
31
18
|
|
|
32
|
-
To run the model interactively,
|
|
19
|
+
To run the model interactively, in this directory, run the following command
|
|
33
20
|
|
|
34
21
|
```
|
|
35
|
-
$
|
|
22
|
+
$ solara run app.py
|
|
36
23
|
```
|
|
37
24
|
|
|
38
|
-
Then open your browser to [http://127.0.0.1:8521/](http://127.0.0.1:8521/) and press Reset, then Run.
|
|
39
|
-
|
|
40
25
|
## Files
|
|
41
26
|
|
|
42
27
|
* ``wolf_sheep/random_walk.py``: This defines the ``RandomWalker`` agent, which implements the behavior of moving randomly across a grid, one cell at a time. Both the Wolf and Sheep agents will inherit from it.
|
|
@@ -5,34 +5,32 @@ from mesa.visualization import (
|
|
|
5
5
|
CommandConsole,
|
|
6
6
|
Slider,
|
|
7
7
|
SolaraViz,
|
|
8
|
+
SpaceRenderer,
|
|
8
9
|
make_plot_component,
|
|
9
|
-
make_space_component,
|
|
10
10
|
)
|
|
11
|
+
from mesa.visualization.components import AgentPortrayalStyle
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
def wolf_sheep_portrayal(agent):
|
|
14
15
|
if agent is None:
|
|
15
16
|
return
|
|
16
17
|
|
|
17
|
-
portrayal =
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
portrayal = AgentPortrayalStyle(
|
|
19
|
+
size=50,
|
|
20
|
+
marker="o",
|
|
21
|
+
zorder=2,
|
|
22
|
+
)
|
|
20
23
|
|
|
21
24
|
if isinstance(agent, Wolf):
|
|
22
|
-
portrayal
|
|
23
|
-
portrayal["marker"] = "o"
|
|
24
|
-
portrayal["zorder"] = 2
|
|
25
|
+
portrayal.update(("color", "red"))
|
|
25
26
|
elif isinstance(agent, Sheep):
|
|
26
|
-
portrayal
|
|
27
|
-
portrayal["marker"] = "o"
|
|
28
|
-
portrayal["zorder"] = 2
|
|
27
|
+
portrayal.update(("color", "cyan"))
|
|
29
28
|
elif isinstance(agent, GrassPatch):
|
|
30
29
|
if agent.fully_grown:
|
|
31
|
-
portrayal
|
|
30
|
+
portrayal.update(("color", "tab:green"))
|
|
32
31
|
else:
|
|
33
|
-
portrayal
|
|
34
|
-
portrayal
|
|
35
|
-
portrayal["size"] = 75
|
|
32
|
+
portrayal.update(("color", "tab:brown"))
|
|
33
|
+
portrayal.update(("marker", "s"), ("size", 125), ("zorder", 1))
|
|
36
34
|
|
|
37
35
|
return portrayal
|
|
38
36
|
|
|
@@ -75,9 +73,6 @@ def post_process_lines(ax):
|
|
|
75
73
|
ax.legend(loc="center left", bbox_to_anchor=(1, 0.9))
|
|
76
74
|
|
|
77
75
|
|
|
78
|
-
space_component = make_space_component(
|
|
79
|
-
wolf_sheep_portrayal, draw_grid=False, post_process=post_process_space
|
|
80
|
-
)
|
|
81
76
|
lineplot_component = make_plot_component(
|
|
82
77
|
{"Wolves": "tab:orange", "Sheep": "tab:cyan", "Grass": "tab:green"},
|
|
83
78
|
post_process=post_process_lines,
|
|
@@ -86,9 +81,17 @@ lineplot_component = make_plot_component(
|
|
|
86
81
|
simulator = ABMSimulator()
|
|
87
82
|
model = WolfSheep(simulator=simulator, grass=True)
|
|
88
83
|
|
|
84
|
+
renderer = SpaceRenderer(
|
|
85
|
+
model,
|
|
86
|
+
backend="matplotlib",
|
|
87
|
+
)
|
|
88
|
+
renderer.draw_agents(wolf_sheep_portrayal)
|
|
89
|
+
renderer.post_process = post_process_space
|
|
90
|
+
|
|
89
91
|
page = SolaraViz(
|
|
90
92
|
model,
|
|
91
|
-
|
|
93
|
+
renderer,
|
|
94
|
+
components=[lineplot_component, CommandConsole],
|
|
92
95
|
model_params=model_params,
|
|
93
96
|
name="Wolf Sheep",
|
|
94
97
|
simulator=simulator,
|
|
@@ -8,7 +8,12 @@ This model tests Mesa's continuous space feature, and uses numpy arrays to repre
|
|
|
8
8
|
|
|
9
9
|
## How to Run
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
To run the model interactively, in this directory, run the following command
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
$ solara run app.py
|
|
15
|
+
```
|
|
16
|
+
|
|
12
17
|
|
|
13
18
|
## Files
|
|
14
19
|
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import sys
|
|
3
|
-
|
|
4
1
|
from matplotlib.markers import MarkerStyle
|
|
5
2
|
|
|
6
|
-
sys.path.insert(0, os.path.abspath("../../../.."))
|
|
7
|
-
|
|
8
3
|
from mesa.examples.basic.boid_flockers.model import BoidFlockers
|
|
9
|
-
from mesa.visualization import Slider, SolaraViz,
|
|
4
|
+
from mesa.visualization import Slider, SolaraViz, SpaceRenderer
|
|
5
|
+
from mesa.visualization.components import AgentPortrayalStyle
|
|
10
6
|
|
|
11
7
|
# Pre-compute markers for different angles (e.g., every 10 degrees)
|
|
12
8
|
MARKER_CACHE = {}
|
|
@@ -25,10 +21,12 @@ def boid_draw(agent):
|
|
|
25
21
|
rounded_deg = round(deg / 10) * 10 % 360
|
|
26
22
|
|
|
27
23
|
# using cached markers to speed things up
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
boid_style = AgentPortrayalStyle(
|
|
25
|
+
color="red", size=20, marker=MARKER_CACHE[rounded_deg]
|
|
26
|
+
)
|
|
27
|
+
if neighbors >= 2:
|
|
28
|
+
boid_style.update(("color", "green"), ("marker", MARKER_CACHE[rounded_deg]))
|
|
29
|
+
return boid_style
|
|
32
30
|
|
|
33
31
|
|
|
34
32
|
model_params = {
|
|
@@ -71,9 +69,15 @@ model_params = {
|
|
|
71
69
|
|
|
72
70
|
model = BoidFlockers()
|
|
73
71
|
|
|
72
|
+
# Quickest way to visualize grid along with agents or property layers.
|
|
73
|
+
renderer = SpaceRenderer(
|
|
74
|
+
model,
|
|
75
|
+
backend="matplotlib",
|
|
76
|
+
).render(agent_portrayal=boid_draw)
|
|
77
|
+
|
|
74
78
|
page = SolaraViz(
|
|
75
79
|
model,
|
|
76
|
-
|
|
80
|
+
renderer,
|
|
77
81
|
model_params=model_params,
|
|
78
82
|
name="Boid Flocking Model",
|
|
79
83
|
)
|
|
@@ -2,25 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## Summary
|
|
4
4
|
|
|
5
|
-
A simple model of agents exchanging wealth. All agents start with the same amount of money. Every step, each agent with one unit of money or more gives one unit of wealth to another random agent.
|
|
6
|
-
|
|
7
|
-
If you want to go over the step-by-step tutorial, please go and run the [Jupyter Notebook](https://github.com/projectmesa/mesa/blob/main/docs/tutorials/intro_tutorial.ipynb). The code here runs the finalized code in the last cells directly.
|
|
5
|
+
A simple model of agents exchanging wealth. All agents start with the same amount of money. Every step, each agent with one unit of money or more gives one unit of wealth to another random agent. Mesa's [Getting Started](https://mesa.readthedocs.io/latest/getting_started.html) section walks through the Boltzmann Wealth Model in a series of short introductory tutorials, starting with[Creating your First Model](https://mesa.readthedocs.io/latest/tutorials/0_first_model.html).
|
|
8
6
|
|
|
9
7
|
As the model runs, the distribution of wealth among agents goes from being perfectly uniform (all agents have the same starting wealth), to highly skewed -- a small number have high wealth, more have none at all.
|
|
10
8
|
|
|
11
9
|
## How to Run
|
|
12
10
|
|
|
13
|
-
To
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
To launch the interactive server, as described in the [last section of the tutorial](https://mesa.readthedocs.io/en/latest/tutorials/intro_tutorial.html#adding-visualization), run:
|
|
11
|
+
To run the model interactively, in this directory, run the following command
|
|
17
12
|
|
|
18
13
|
```
|
|
19
14
|
$ solara run app.py
|
|
20
15
|
```
|
|
21
16
|
|
|
22
|
-
If your browser doesn't open automatically, point it to [http://127.0.0.1:8765/](http://127.0.0.1:8765/). When the visualization loads, click on the Play button.
|
|
23
|
-
|
|
24
17
|
|
|
25
18
|
## Files
|
|
26
19
|
|
|
@@ -46,9 +39,6 @@ Then, you can run the Streamlit app using the following command:
|
|
|
46
39
|
|
|
47
40
|
## Further Reading
|
|
48
41
|
|
|
49
|
-
The full tutorial describing how the model is built can be found at:
|
|
50
|
-
https://mesa.readthedocs.io/en/latest/tutorials/intro_tutorial.html
|
|
51
|
-
|
|
52
42
|
This model is drawn from econophysics and presents a statistical mechanics approach to wealth distribution. Some examples of further reading on the topic can be found at:
|
|
53
43
|
|
|
54
44
|
[Milakovic, M. A Statistical Equilibrium Model of Wealth Distribution. February, 2001.](https://editorialexpress.com/cgi-bin/conference/download.cgi?db_name=SCE2001&paper_id=214)
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
+
import altair as alt
|
|
2
|
+
|
|
1
3
|
from mesa.examples.basic.boltzmann_wealth_model.model import BoltzmannWealth
|
|
2
4
|
from mesa.mesa_logging import INFO, log_to_stderr
|
|
3
5
|
from mesa.visualization import (
|
|
4
6
|
SolaraViz,
|
|
7
|
+
SpaceRenderer,
|
|
5
8
|
make_plot_component,
|
|
6
|
-
make_space_component,
|
|
7
9
|
)
|
|
10
|
+
from mesa.visualization.components import AgentPortrayalStyle
|
|
8
11
|
|
|
9
12
|
log_to_stderr(INFO)
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
def agent_portrayal(agent):
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
return AgentPortrayalStyle(
|
|
17
|
+
color=agent.wealth
|
|
18
|
+
) # we are using a colormap to translate wealth to color
|
|
15
19
|
|
|
16
20
|
|
|
17
21
|
model_params = {
|
|
@@ -33,45 +37,48 @@ model_params = {
|
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
|
|
36
|
-
def post_process(
|
|
37
|
-
|
|
40
|
+
def post_process(chart):
|
|
41
|
+
"""Post-process the Altair chart to add a colorbar legend."""
|
|
42
|
+
chart = chart.encode(
|
|
43
|
+
color=alt.Color(
|
|
44
|
+
"color:N",
|
|
45
|
+
scale=alt.Scale(scheme="viridis", domain=[0, 10]),
|
|
46
|
+
legend=alt.Legend(
|
|
47
|
+
title="Wealth",
|
|
48
|
+
orient="right",
|
|
49
|
+
type="gradient",
|
|
50
|
+
gradientLength=200,
|
|
51
|
+
),
|
|
52
|
+
),
|
|
53
|
+
)
|
|
54
|
+
return chart
|
|
38
55
|
|
|
39
56
|
|
|
40
|
-
# Create initial model instance
|
|
41
57
|
model = BoltzmannWealth(50, 10, 10)
|
|
42
58
|
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
|
|
59
|
+
# The SpaceRenderer is responsible for drawing the model's space and agents.
|
|
60
|
+
# It builds the visualization in layers, first drawing the grid structure,
|
|
61
|
+
# and then drawing the agents on top. It uses a specified backend
|
|
62
|
+
# (like "altair" or "matplotlib") for creating the plots.
|
|
63
|
+
renderer = SpaceRenderer(model, backend="altair")
|
|
64
|
+
# Can customize the grid appearance.
|
|
65
|
+
renderer.draw_structure(grid_color="black", grid_dash=[6, 2], grid_opacity=0.3)
|
|
66
|
+
renderer.draw_agents(agent_portrayal=agent_portrayal, cmap="viridis", vmin=0, vmax=10)
|
|
48
67
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
68
|
+
# The post_process function is used to modify the Altair chart after it has been created.
|
|
69
|
+
# It can be used to add legends, colorbars, or other visual elements.
|
|
70
|
+
renderer.post_process = post_process
|
|
71
|
+
|
|
72
|
+
# Creates a line plot component from the model's "Gini" datacollector.
|
|
52
73
|
GiniPlot = make_plot_component("Gini")
|
|
53
74
|
|
|
54
|
-
#
|
|
55
|
-
# visualization
|
|
56
|
-
# Display it using the following command in the example directory:
|
|
57
|
-
# solara run app.py
|
|
58
|
-
# It will automatically update and display any changes made to this file
|
|
75
|
+
# The SolaraViz page combines the model, renderer, and components into a web interface.
|
|
76
|
+
# To run the visualization, save this code as app.py and run `solara run app.py`
|
|
59
77
|
page = SolaraViz(
|
|
60
78
|
model,
|
|
61
|
-
|
|
79
|
+
renderer,
|
|
80
|
+
components=[GiniPlot],
|
|
62
81
|
model_params=model_params,
|
|
63
82
|
name="Boltzmann Wealth Model",
|
|
64
83
|
)
|
|
65
84
|
page # noqa
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
# In a notebook environment, we can also display the visualization elements directly
|
|
69
|
-
# SpaceGraph(model1)
|
|
70
|
-
# GiniPlot(model1)
|
|
71
|
-
|
|
72
|
-
# The plots will be static. If you want to pick up model steps,
|
|
73
|
-
# you have to make the model reactive first
|
|
74
|
-
# reactive_model = solara.reactive(model1)
|
|
75
|
-
# SpaceGraph(reactive_model)
|
|
76
|
-
# In a different notebook block:
|
|
77
|
-
# reactive_model.value.step()
|
|
@@ -9,20 +9,12 @@ The "game" is a zero-player game, meaning that its evolution is determined by it
|
|
|
9
9
|
|
|
10
10
|
## How to Run
|
|
11
11
|
|
|
12
|
-
To run the model interactively
|
|
12
|
+
To run the model interactively, in this directory, run the following command
|
|
13
13
|
|
|
14
14
|
```
|
|
15
15
|
$ solara run app.py
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
For streamlit, you need
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
$ streamlit run st_app.py
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
This will open your browser and show you the controls. You can start the model by hitting the run button.
|
|
25
|
-
|
|
26
18
|
## Files
|
|
27
19
|
|
|
28
20
|
* ``agents.py``: Defines the behavior of an individual cell, which can be in two states: DEAD or ALIVE.
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
from mesa.examples.basic.conways_game_of_life.model import ConwaysGameOfLife
|
|
2
2
|
from mesa.visualization import (
|
|
3
3
|
SolaraViz,
|
|
4
|
-
|
|
4
|
+
SpaceRenderer,
|
|
5
5
|
)
|
|
6
|
+
from mesa.visualization.components import AgentPortrayalStyle
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def agent_portrayal(agent):
|
|
9
|
-
return
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
return AgentPortrayalStyle(
|
|
11
|
+
color="white" if agent.state == 0 else "black",
|
|
12
|
+
marker="s",
|
|
13
|
+
size=30,
|
|
14
|
+
)
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
def post_process(ax):
|
|
@@ -54,15 +55,11 @@ model_params = {
|
|
|
54
55
|
# Create initial model instance
|
|
55
56
|
model1 = ConwaysGameOfLife()
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
#
|
|
59
|
-
#
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
SpaceGraph = make_space_component(
|
|
63
|
-
agent_portrayal, post_process=post_process, draw_grid=False
|
|
64
|
-
)
|
|
65
|
-
|
|
58
|
+
renderer = SpaceRenderer(model1, backend="matplotlib")
|
|
59
|
+
# In this case the renderer only draws the agents because we just want to observe
|
|
60
|
+
# the state of the agents, not the structure of the grid.
|
|
61
|
+
renderer.draw_agents(agent_portrayal=agent_portrayal)
|
|
62
|
+
renderer.post_process = post_process
|
|
66
63
|
|
|
67
64
|
# Create the SolaraViz page. This will automatically create a server and display the
|
|
68
65
|
# visualization elements in a web browser.
|
|
@@ -71,7 +68,7 @@ SpaceGraph = make_space_component(
|
|
|
71
68
|
# It will automatically update and display any changes made to this file
|
|
72
69
|
page = SolaraViz(
|
|
73
70
|
model1,
|
|
74
|
-
|
|
71
|
+
renderer,
|
|
75
72
|
model_params=model_params,
|
|
76
73
|
name="Game of Life",
|
|
77
74
|
)
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Summary
|
|
4
4
|
|
|
5
|
-
The Schelling segregation model is a classic agent-based model, demonstrating how even a mild preference for similar neighbors can lead to a much higher degree of segregation than we would intuitively expect. The model consists of agents on a square grid, where each grid cell can contain at most one agent. Agents come in two colors:
|
|
5
|
+
The Schelling segregation model is a classic agent-based model, demonstrating how even a mild preference for similar neighbors can lead to a much higher degree of segregation than we would intuitively expect. The model consists of agents on a square grid, where each grid cell can contain at most one agent. Agents come in two colors: orange and blue. They are happy if a certain number of their eight possible neighbors are of the same color, and unhappy otherwise. Unhappy agents will pick a random empty cell to move to each step, until they are happy. The model keeps running until there are no unhappy agents.
|
|
6
6
|
|
|
7
|
-
By default, the number of similar neighbors the agents need to be happy is set to 3. That means the agents would be perfectly happy with a majority of their neighbors being of a different color (e.g. a Blue agent would be happy with five
|
|
7
|
+
By default, the number of similar neighbors the agents need to be happy is set to 3. That means the agents would be perfectly happy with a majority of their neighbors being of a different color (e.g. a Blue agent would be happy with five Orange neighbors and three Blue ones). Despite this, the model consistently leads to a high degree of segregation, with most agents ending up with no neighbors of a different color.
|
|
8
8
|
|
|
9
9
|
## How to Run
|
|
10
10
|
|
|
@@ -14,14 +14,6 @@ To run the model interactively, in this directory, run the following command
|
|
|
14
14
|
$ solara run app.py
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Then open your browser to [http://127.0.0.1:8765/](http://127.0.0.1:8765/) and click the Play button.
|
|
18
|
-
|
|
19
|
-
To view and run some example model analyses, launch the IPython Notebook and open ``analysis.ipynb``. Visualizing the analysis also requires [matplotlib](http://matplotlib.org/).
|
|
20
|
-
|
|
21
|
-
## How to Run without the GUI
|
|
22
|
-
|
|
23
|
-
To run the model with the grid displayed as an ASCII text, run `python run_ascii.py` in this directory.
|
|
24
|
-
|
|
25
17
|
## Files
|
|
26
18
|
|
|
27
19
|
* ``model.py``: Contains the Schelling model class
|
|
@@ -19,8 +19,9 @@ class SchellingAgent(CellAgent):
|
|
|
19
19
|
self.type = agent_type
|
|
20
20
|
self.homophily = homophily
|
|
21
21
|
self.radius = radius
|
|
22
|
+
self.happy = False
|
|
22
23
|
|
|
23
|
-
def
|
|
24
|
+
def assign_state(self) -> None:
|
|
24
25
|
"""Determine if agent is happy and move if necessary."""
|
|
25
26
|
neighbors = list(self.cell.get_neighborhood(radius=self.radius).agents)
|
|
26
27
|
|
|
@@ -34,8 +35,13 @@ class SchellingAgent(CellAgent):
|
|
|
34
35
|
# If there are no neighbors, the similarity fraction is 0
|
|
35
36
|
similarity_fraction = 0.0
|
|
36
37
|
|
|
37
|
-
# Move if unhappy
|
|
38
38
|
if similarity_fraction < self.homophily:
|
|
39
|
-
self.
|
|
39
|
+
self.happy = False
|
|
40
40
|
else:
|
|
41
|
+
self.happy = True
|
|
41
42
|
self.model.happy += 1
|
|
43
|
+
|
|
44
|
+
def step(self) -> None:
|
|
45
|
+
# Move if unhappy
|
|
46
|
+
if not self.happy:
|
|
47
|
+
self.cell = self.model.grid.select_random_empty_cell()
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
1
3
|
import solara
|
|
2
4
|
|
|
3
5
|
from mesa.examples.basic.schelling.model import Schelling
|
|
4
6
|
from mesa.visualization import (
|
|
5
7
|
Slider,
|
|
6
8
|
SolaraViz,
|
|
9
|
+
SpaceRenderer,
|
|
7
10
|
make_plot_component,
|
|
8
|
-
make_space_component,
|
|
9
11
|
)
|
|
12
|
+
from mesa.visualization.components import AgentPortrayalStyle
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
def get_happy_agents(model):
|
|
@@ -14,8 +17,45 @@ def get_happy_agents(model):
|
|
|
14
17
|
return solara.Markdown(f"**Happy agents: {model.happy}**")
|
|
15
18
|
|
|
16
19
|
|
|
20
|
+
path = os.path.dirname(os.path.abspath(__file__))
|
|
21
|
+
|
|
22
|
+
|
|
17
23
|
def agent_portrayal(agent):
|
|
18
|
-
|
|
24
|
+
style = AgentPortrayalStyle(
|
|
25
|
+
x=agent.cell.coordinate[0],
|
|
26
|
+
y=agent.cell.coordinate[1],
|
|
27
|
+
marker=os.path.join(path, "resources", "orange_happy.png"),
|
|
28
|
+
size=75,
|
|
29
|
+
)
|
|
30
|
+
if agent.type == 0:
|
|
31
|
+
if agent.happy:
|
|
32
|
+
style.update(
|
|
33
|
+
(
|
|
34
|
+
"marker",
|
|
35
|
+
os.path.join(path, "resources", "blue_happy.png"),
|
|
36
|
+
),
|
|
37
|
+
)
|
|
38
|
+
else:
|
|
39
|
+
style.update(
|
|
40
|
+
(
|
|
41
|
+
"marker",
|
|
42
|
+
os.path.join(path, "resources", "blue_unhappy.png"),
|
|
43
|
+
),
|
|
44
|
+
("size", 50),
|
|
45
|
+
("zorder", 2),
|
|
46
|
+
)
|
|
47
|
+
else:
|
|
48
|
+
if not agent.happy:
|
|
49
|
+
style.update(
|
|
50
|
+
(
|
|
51
|
+
"marker",
|
|
52
|
+
os.path.join(path, "resources", "orange_unhappy.png"),
|
|
53
|
+
),
|
|
54
|
+
("size", 50),
|
|
55
|
+
("zorder", 2),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
return style
|
|
19
59
|
|
|
20
60
|
|
|
21
61
|
model_params = {
|
|
@@ -31,14 +71,21 @@ model_params = {
|
|
|
31
71
|
"height": 20,
|
|
32
72
|
}
|
|
33
73
|
|
|
74
|
+
# Note: Models with images as markers are very performance intensive.
|
|
34
75
|
model1 = Schelling()
|
|
76
|
+
renderer = SpaceRenderer(model1, backend="matplotlib")
|
|
77
|
+
# Here we use renderer.render() to render the agents and grid in one go.
|
|
78
|
+
# This function always renders the grid and then renders the agents or
|
|
79
|
+
# property layers on top of it if specified. It also supports passing the
|
|
80
|
+
# post_process function to fine-tune the plot after rendering in itself.
|
|
81
|
+
renderer.render(agent_portrayal=agent_portrayal)
|
|
35
82
|
|
|
36
83
|
HappyPlot = make_plot_component({"happy": "tab:green"})
|
|
37
84
|
|
|
38
85
|
page = SolaraViz(
|
|
39
86
|
model1,
|
|
87
|
+
renderer,
|
|
40
88
|
components=[
|
|
41
|
-
make_space_component(agent_portrayal),
|
|
42
89
|
HappyPlot,
|
|
43
90
|
get_happy_agents,
|
|
44
91
|
],
|
|
@@ -68,11 +68,13 @@ class Schelling(Model):
|
|
|
68
68
|
)
|
|
69
69
|
|
|
70
70
|
# Collect initial state
|
|
71
|
+
self.agents.do("assign_state")
|
|
71
72
|
self.datacollector.collect(self)
|
|
72
73
|
|
|
73
74
|
def step(self):
|
|
74
75
|
"""Run one step of the model."""
|
|
75
76
|
self.happy = 0 # Reset counter of happy agents
|
|
76
77
|
self.agents.shuffle_do("step") # Activate all agents in random order
|
|
78
|
+
self.agents.do("assign_state")
|
|
77
79
|
self.datacollector.collect(self) # Collect data
|
|
78
80
|
self.running = self.happy < len(self.agents) # Continue until everyone is happy
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -38,10 +38,6 @@ To run the model interactively, in this directory, run the following command
|
|
|
38
38
|
|
|
39
39
|
## Further Reading
|
|
40
40
|
|
|
41
|
-
The full tutorial describing how the model is built can be found at:
|
|
42
|
-
https://mesa.readthedocs.io/en/latest/tutorials/intro_tutorial.html
|
|
43
|
-
|
|
44
|
-
|
|
45
41
|
[Stonedahl, F. and Wilensky, U. (2008). NetLogo Virus on a Network model](http://ccl.northwestern.edu/netlogo/models/VirusonaNetwork).
|
|
46
42
|
Center for Connected Learning and Computer-Based Modeling, Northwestern University, Evanston, IL.
|
|
47
43
|
|
|
@@ -10,18 +10,19 @@ from mesa.examples.basic.virus_on_network.model import (
|
|
|
10
10
|
from mesa.visualization import (
|
|
11
11
|
Slider,
|
|
12
12
|
SolaraViz,
|
|
13
|
+
SpaceRenderer,
|
|
13
14
|
make_plot_component,
|
|
14
|
-
make_space_component,
|
|
15
15
|
)
|
|
16
|
+
from mesa.visualization.components import AgentPortrayalStyle
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
def agent_portrayal(agent):
|
|
19
20
|
node_color_dict = {
|
|
20
|
-
State.INFECTED: "
|
|
21
|
-
State.SUSCEPTIBLE: "
|
|
22
|
-
State.RESISTANT: "
|
|
21
|
+
State.INFECTED: "red",
|
|
22
|
+
State.SUSCEPTIBLE: "green",
|
|
23
|
+
State.RESISTANT: "gray",
|
|
23
24
|
}
|
|
24
|
-
return
|
|
25
|
+
return AgentPortrayalStyle(color=node_color_dict[agent.state], size=20)
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
def get_resistant_susceptible_ratio(model):
|
|
@@ -92,24 +93,40 @@ model_params = {
|
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
|
|
95
|
-
def post_process_lineplot(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
def post_process_lineplot(chart):
|
|
97
|
+
chart = chart.properties(
|
|
98
|
+
width=400,
|
|
99
|
+
height=400,
|
|
100
|
+
).configure_legend(
|
|
101
|
+
strokeColor="black",
|
|
102
|
+
fillColor="#ECE9E9",
|
|
103
|
+
orient="right",
|
|
104
|
+
cornerRadius=5,
|
|
105
|
+
padding=10,
|
|
106
|
+
strokeWidth=1,
|
|
107
|
+
)
|
|
108
|
+
return chart
|
|
109
|
+
|
|
99
110
|
|
|
111
|
+
model1 = VirusOnNetwork()
|
|
112
|
+
renderer = SpaceRenderer(model1, backend="altair")
|
|
113
|
+
renderer.draw_structure(
|
|
114
|
+
node_kwargs={"color": "black", "filled": False, "strokeWidth": 5},
|
|
115
|
+
edge_kwargs={"strokeDash": [6, 1]},
|
|
116
|
+
) # Do this to draw the underlying network and customize it
|
|
117
|
+
renderer.draw_agents(agent_portrayal)
|
|
100
118
|
|
|
101
|
-
|
|
119
|
+
# Plot components can also be in altair and support post_process
|
|
102
120
|
StatePlot = make_plot_component(
|
|
103
|
-
{"Infected": "
|
|
121
|
+
{"Infected": "red", "Susceptible": "green", "Resistant": "gray"},
|
|
122
|
+
backend="altair",
|
|
104
123
|
post_process=post_process_lineplot,
|
|
105
124
|
)
|
|
106
125
|
|
|
107
|
-
model1 = VirusOnNetwork()
|
|
108
|
-
|
|
109
126
|
page = SolaraViz(
|
|
110
127
|
model1,
|
|
128
|
+
renderer,
|
|
111
129
|
components=[
|
|
112
|
-
SpacePlot,
|
|
113
130
|
StatePlot,
|
|
114
131
|
get_resistant_susceptible_ratio,
|
|
115
132
|
],
|
mesa/experimental/__init__.py
CHANGED
|
@@ -15,6 +15,6 @@ Notes:
|
|
|
15
15
|
- Features graduate from experimental status once their APIs are stabilized
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
from mesa.experimental import continuous_space, devs, mesa_signals
|
|
18
|
+
from mesa.experimental import continuous_space, devs, mesa_signals, meta_agents
|
|
19
19
|
|
|
20
|
-
__all__ = ["continuous_space", "devs", "mesa_signals"]
|
|
20
|
+
__all__ = ["continuous_space", "devs", "mesa_signals", "meta_agents"]
|