Mesa 3.0.0b1__py3-none-any.whl → 3.0.0b2__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 -3
- mesa/agent.py +23 -8
- mesa/examples/__init__.py +21 -0
- {examples → mesa/examples}/advanced/epstein_civil_violence/Readme.md +3 -2
- mesa/examples/advanced/epstein_civil_violence/app.py +72 -0
- {examples/advanced/epstein_civil_violence → mesa/examples/advanced}/epstein_civil_violence/model.py +4 -4
- examples/advanced/pd_grid/readme.md → mesa/examples/advanced/pd_grid/Readme.md +4 -3
- mesa/examples/advanced/pd_grid/app.py +50 -0
- {examples/advanced/pd_grid → mesa/examples/advanced}/pd_grid/model.py +1 -2
- {examples → mesa/examples}/advanced/sugarscape_g1mt/Readme.md +6 -29
- examples/advanced/sugarscape_g1mt/sugarscape_g1mt/trader_agents.py → mesa/examples/advanced/sugarscape_g1mt/agents.py +26 -3
- {examples → mesa/examples}/advanced/sugarscape_g1mt/app.py +23 -14
- {examples/advanced/sugarscape_g1mt → mesa/examples/advanced}/sugarscape_g1mt/model.py +6 -6
- {examples → mesa/examples}/advanced/sugarscape_g1mt/tests.py +3 -6
- mesa/examples/advanced/wolf_sheep/app.py +77 -0
- {examples/advanced/wolf_sheep → mesa/examples/advanced}/wolf_sheep/model.py +9 -8
- mesa/examples/basic/boid_flockers/Readme.md +22 -0
- {examples → mesa/examples}/basic/boid_flockers/app.py +1 -2
- {examples → mesa/examples}/basic/boid_flockers/model.py +1 -2
- {examples → mesa/examples}/basic/boltzmann_wealth_model/Readme.md +1 -5
- mesa/examples/basic/boltzmann_wealth_model/__init__.py +0 -0
- {examples → mesa/examples}/basic/boltzmann_wealth_model/app.py +1 -2
- {examples → mesa/examples}/basic/boltzmann_wealth_model/model.py +3 -4
- {examples → mesa/examples}/basic/conways_game_of_life/Readme.md +11 -7
- mesa/examples/basic/conways_game_of_life/__init__.py +0 -0
- {examples → mesa/examples}/basic/conways_game_of_life/agents.py +8 -8
- mesa/examples/basic/conways_game_of_life/app.py +39 -0
- {examples → mesa/examples}/basic/conways_game_of_life/model.py +3 -4
- {examples → mesa/examples}/basic/conways_game_of_life/st_app.py +2 -1
- examples/basic/schelling/README.md → mesa/examples/basic/schelling/Readme.md +2 -9
- mesa/examples/basic/schelling/__init__.py +0 -0
- {examples → mesa/examples}/basic/schelling/app.py +1 -2
- {examples → mesa/examples}/basic/schelling/model.py +1 -2
- mesa/examples/basic/virus_on_network/__init__.py +0 -0
- {examples → mesa/examples}/basic/virus_on_network/app.py +5 -2
- {examples → mesa/examples}/basic/virus_on_network/model.py +4 -7
- mesa/experimental/cell_space/discrete_space.py +6 -0
- mesa/experimental/devs/eventlist.py +6 -0
- mesa/model.py +13 -0
- mesa/space.py +70 -5
- mesa/visualization/components/altair.py +87 -19
- mesa/visualization/components/matplotlib.py +55 -11
- {mesa-3.0.0b1.dist-info → mesa-3.0.0b2.dist-info}/METADATA +1 -3
- mesa-3.0.0b2.dist-info/RECORD +93 -0
- examples/advanced/epstein_civil_violence/epstein_civil_violence/portrayal.py +0 -33
- examples/advanced/epstein_civil_violence/epstein_civil_violence/server.py +0 -81
- examples/advanced/epstein_civil_violence/requirements.txt +0 -3
- examples/advanced/epstein_civil_violence/run.py +0 -3
- examples/advanced/pd_grid/pd_grid/portrayal.py +0 -19
- examples/advanced/pd_grid/pd_grid/server.py +0 -21
- examples/advanced/pd_grid/requirements.txt +0 -3
- examples/advanced/pd_grid/run.py +0 -3
- examples/advanced/sugarscape_g1mt/requirements.txt +0 -6
- examples/advanced/sugarscape_g1mt/run.py +0 -105
- examples/advanced/sugarscape_g1mt/sugarscape_g1mt/resource_agents.py +0 -26
- examples/advanced/sugarscape_g1mt/sugarscape_g1mt/server.py +0 -61
- examples/advanced/wolf_sheep/requirements.txt +0 -1
- examples/advanced/wolf_sheep/run.py +0 -3
- examples/advanced/wolf_sheep/wolf_sheep/resources/sheep.png +0 -0
- examples/advanced/wolf_sheep/wolf_sheep/resources/wolf.png +0 -0
- examples/advanced/wolf_sheep/wolf_sheep/server.py +0 -78
- examples/basic/__init__.py +0 -13
- examples/basic/boid_flockers/Readme.md +0 -43
- examples/basic/conways_game_of_life/portrayal.py +0 -18
- examples/basic/conways_game_of_life/requirements.txt +0 -1
- examples/basic/conways_game_of_life/server.py +0 -11
- mesa/cookiecutter-mesa/cookiecutter.json +0 -8
- mesa/cookiecutter-mesa/hooks/post_gen_project.py +0 -13
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/README.md +0 -4
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/app.pytemplate +0 -27
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/setup.pytemplate +0 -11
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/__init__.py +0 -1
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/model.pytemplate +0 -60
- mesa/examples.py +0 -3
- mesa/main.py +0 -65
- mesa-3.0.0b1.dist-info/RECORD +0 -114
- {examples → mesa/examples}/README.md +0 -0
- {examples → mesa/examples/advanced}/__init__.py +0 -0
- {examples → mesa/examples}/advanced/epstein_civil_violence/Epstein Civil Violence.ipynb +0 -0
- {examples/advanced → mesa/examples/advanced/epstein_civil_violence}/__init__.py +0 -0
- /examples/advanced/epstein_civil_violence/epstein_civil_violence/agent.py → /mesa/examples/advanced/epstein_civil_violence/agents.py +0 -0
- {examples/advanced/epstein_civil_violence/epstein_civil_violence → mesa/examples/advanced/pd_grid}/__init__.py +0 -0
- /examples/advanced/pd_grid/pd_grid/agent.py → /mesa/examples/advanced/pd_grid/agents.py +0 -0
- {examples → mesa/examples}/advanced/pd_grid/analysis.ipynb +0 -0
- {examples/advanced/pd_grid/pd_grid → mesa/examples/advanced/sugarscape_g1mt}/__init__.py +0 -0
- {examples/advanced/sugarscape_g1mt → mesa/examples/advanced}/sugarscape_g1mt/sugar-map.txt +0 -0
- {examples → mesa/examples}/advanced/wolf_sheep/Readme.md +0 -0
- {examples/advanced/sugarscape_g1mt/sugarscape_g1mt → mesa/examples/advanced/wolf_sheep}/__init__.py +0 -0
- {examples/advanced/wolf_sheep → mesa/examples/advanced}/wolf_sheep/agents.py +0 -0
- {examples/advanced/wolf_sheep → mesa/examples/basic}/__init__.py +0 -0
- {examples/advanced/wolf_sheep/wolf_sheep → mesa/examples/basic/boid_flockers}/__init__.py +0 -0
- {examples → mesa/examples}/basic/boid_flockers/agents.py +0 -0
- {examples → mesa/examples}/basic/boltzmann_wealth_model/agents.py +0 -0
- {examples → mesa/examples}/basic/boltzmann_wealth_model/st_app.py +0 -0
- {examples → mesa/examples}/basic/schelling/agents.py +0 -0
- {examples → mesa/examples}/basic/schelling/analysis.ipynb +0 -0
- /examples/basic/virus_on_network/README.md → /mesa/examples/basic/virus_on_network/Readme.md +0 -0
- {examples → mesa/examples}/basic/virus_on_network/agents.py +0 -0
- {mesa-3.0.0b1.dist-info → mesa-3.0.0b2.dist-info}/WHEEL +0 -0
- {mesa-3.0.0b1.dist-info → mesa-3.0.0b2.dist-info}/entry_points.txt +0 -0
- {mesa-3.0.0b1.dist-info → mesa-3.0.0b2.dist-info}/licenses/LICENSE +0 -0
- {mesa-3.0.0b1.dist-info → mesa-3.0.0b2.dist-info}/licenses/NOTICE +0 -0
mesa/__init__.py
CHANGED
|
@@ -5,7 +5,6 @@ Core Objects: Model, and Agent.
|
|
|
5
5
|
|
|
6
6
|
import datetime
|
|
7
7
|
|
|
8
|
-
import mesa.examples as examples
|
|
9
8
|
import mesa.experimental as experimental
|
|
10
9
|
import mesa.space as space
|
|
11
10
|
import mesa.time as time
|
|
@@ -22,11 +21,10 @@ __all__ = [
|
|
|
22
21
|
"DataCollector",
|
|
23
22
|
"batch_run",
|
|
24
23
|
"experimental",
|
|
25
|
-
"examples",
|
|
26
24
|
]
|
|
27
25
|
|
|
28
26
|
__title__ = "mesa"
|
|
29
|
-
__version__ = "3.0.
|
|
27
|
+
__version__ = "3.0.0b2"
|
|
30
28
|
__license__ = "Apache 2.0"
|
|
31
29
|
_this_year = datetime.datetime.now(tz=datetime.timezone.utc).date().year
|
|
32
30
|
__copyright__ = f"Copyright {_this_year} Project Mesa Team"
|
mesa/agent.py
CHANGED
|
@@ -21,6 +21,8 @@ from random import Random
|
|
|
21
21
|
# mypy
|
|
22
22
|
from typing import TYPE_CHECKING, Any, Literal, overload
|
|
23
23
|
|
|
24
|
+
import numpy as np
|
|
25
|
+
|
|
24
26
|
if TYPE_CHECKING:
|
|
25
27
|
# We ensure that these are not imported during runtime to prevent cyclic
|
|
26
28
|
# dependency.
|
|
@@ -67,7 +69,13 @@ class Agent:
|
|
|
67
69
|
self.model.register_agent(self)
|
|
68
70
|
|
|
69
71
|
def remove(self) -> None:
|
|
70
|
-
"""Remove and delete the agent from the model.
|
|
72
|
+
"""Remove and delete the agent from the model.
|
|
73
|
+
|
|
74
|
+
Notes:
|
|
75
|
+
If you need to do additional cleanup when removing an agent by for example removing
|
|
76
|
+
it from a space, consider extending this method in your own agent class.
|
|
77
|
+
|
|
78
|
+
"""
|
|
71
79
|
with contextlib.suppress(KeyError):
|
|
72
80
|
self.model.deregister_agent(self)
|
|
73
81
|
|
|
@@ -79,9 +87,14 @@ class Agent:
|
|
|
79
87
|
|
|
80
88
|
@property
|
|
81
89
|
def random(self) -> Random:
|
|
82
|
-
"""Return a seeded rng."""
|
|
90
|
+
"""Return a seeded stdlib rng."""
|
|
83
91
|
return self.model.random
|
|
84
92
|
|
|
93
|
+
@property
|
|
94
|
+
def rng(self) -> np.random.Generator:
|
|
95
|
+
"""Return a seeded np.random rng."""
|
|
96
|
+
return self.model.rng
|
|
97
|
+
|
|
85
98
|
|
|
86
99
|
class AgentSet(MutableSet, Sequence):
|
|
87
100
|
"""A collection class that represents an ordered set of agents within an agent-based model (ABM).
|
|
@@ -288,15 +301,17 @@ class AgentSet(MutableSet, Sequence):
|
|
|
288
301
|
|
|
289
302
|
It's a fast, optimized version of calling shuffle() followed by do().
|
|
290
303
|
"""
|
|
291
|
-
|
|
292
|
-
self.random.shuffle(
|
|
304
|
+
weakrefs = list(self._agents.keyrefs())
|
|
305
|
+
self.random.shuffle(weakrefs)
|
|
293
306
|
|
|
294
307
|
if isinstance(method, str):
|
|
295
|
-
for
|
|
296
|
-
|
|
308
|
+
for ref in weakrefs:
|
|
309
|
+
if (agent := ref()) is not None:
|
|
310
|
+
getattr(agent, method)(*args, **kwargs)
|
|
297
311
|
else:
|
|
298
|
-
for
|
|
299
|
-
|
|
312
|
+
for ref in weakrefs:
|
|
313
|
+
if (agent := ref()) is not None:
|
|
314
|
+
method(agent, *args, **kwargs)
|
|
300
315
|
|
|
301
316
|
return self
|
|
302
317
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from mesa.examples.advanced.epstein_civil_violence.model import EpsteinCivilViolence
|
|
2
|
+
from mesa.examples.advanced.pd_grid.model import PdGrid
|
|
3
|
+
from mesa.examples.advanced.sugarscape_g1mt.model import SugarscapeG1mt
|
|
4
|
+
from mesa.examples.advanced.wolf_sheep.model import WolfSheep
|
|
5
|
+
from mesa.examples.basic.boid_flockers.model import BoidFlockers
|
|
6
|
+
from mesa.examples.basic.boltzmann_wealth_model.model import BoltzmannWealthModel
|
|
7
|
+
from mesa.examples.basic.conways_game_of_life.model import ConwaysGameOfLife
|
|
8
|
+
from mesa.examples.basic.schelling.model import Schelling
|
|
9
|
+
from mesa.examples.basic.virus_on_network.model import VirusOnNetwork
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"BoidFlockers",
|
|
13
|
+
"BoltzmannWealthModel",
|
|
14
|
+
"ConwaysGameOfLife",
|
|
15
|
+
"Schelling",
|
|
16
|
+
"VirusOnNetwork",
|
|
17
|
+
"EpsteinCivilViolence",
|
|
18
|
+
"PdGrid",
|
|
19
|
+
"SugarscapeG1mt",
|
|
20
|
+
"WolfSheep",
|
|
21
|
+
]
|
|
@@ -18,8 +18,9 @@ Then open your browser to [http://127.0.0.1:8521/](http://127.0.0.1:8521/) and p
|
|
|
18
18
|
|
|
19
19
|
## Files
|
|
20
20
|
|
|
21
|
-
* ``
|
|
22
|
-
* ``
|
|
21
|
+
* ``model.py``: Core model code.
|
|
22
|
+
* ``agent.py``: Agent classes.
|
|
23
|
+
* ``app.py``: Sets up the interactive visualization.
|
|
23
24
|
* ``Epstein Civil Violence.ipynb``: Jupyter notebook conducting some preliminary analysis of the model.
|
|
24
25
|
|
|
25
26
|
## Further Reading
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from mesa.examples.advanced.epstein_civil_violence.agents import Citizen, Cop
|
|
2
|
+
from mesa.examples.advanced.epstein_civil_violence.model import EpsteinCivilViolence
|
|
3
|
+
from mesa.visualization import (
|
|
4
|
+
Slider,
|
|
5
|
+
SolaraViz,
|
|
6
|
+
make_plot_measure,
|
|
7
|
+
make_space_matplotlib,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
COP_COLOR = "#000000"
|
|
11
|
+
AGENT_QUIET_COLOR = "#648FFF"
|
|
12
|
+
AGENT_REBEL_COLOR = "#FE6100"
|
|
13
|
+
JAIL_COLOR = "#808080"
|
|
14
|
+
JAIL_SHAPE = "rect"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def citizen_cop_portrayal(agent):
|
|
18
|
+
if agent is None:
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
portrayal = {
|
|
22
|
+
"size": 25,
|
|
23
|
+
"shape": "s", # square marker
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if isinstance(agent, Citizen):
|
|
27
|
+
color = (
|
|
28
|
+
AGENT_QUIET_COLOR if agent.condition == "Quiescent" else AGENT_REBEL_COLOR
|
|
29
|
+
)
|
|
30
|
+
color = JAIL_COLOR if agent.jail_sentence else color
|
|
31
|
+
shape = JAIL_SHAPE if agent.jail_sentence else "circle"
|
|
32
|
+
portrayal["color"] = color
|
|
33
|
+
portrayal["shape"] = shape
|
|
34
|
+
if shape == "s":
|
|
35
|
+
portrayal["w"] = 0.9
|
|
36
|
+
portrayal["h"] = 0.9
|
|
37
|
+
else:
|
|
38
|
+
portrayal["r"] = 0.5
|
|
39
|
+
portrayal["filled"] = False
|
|
40
|
+
portrayal["layer"] = 0
|
|
41
|
+
|
|
42
|
+
elif isinstance(agent, Cop):
|
|
43
|
+
portrayal["color"] = COP_COLOR
|
|
44
|
+
portrayal["r"] = 0.9
|
|
45
|
+
portrayal["layer"] = 1
|
|
46
|
+
|
|
47
|
+
return portrayal
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
model_params = {
|
|
51
|
+
"height": 40,
|
|
52
|
+
"width": 40,
|
|
53
|
+
"citizen_density": Slider("Initial Agent Density", 0.7, 0.0, 0.9, 0.1),
|
|
54
|
+
"cop_density": Slider("Initial Cop Density", 0.04, 0.0, 0.1, 0.01),
|
|
55
|
+
"citizen_vision": Slider("Citizen Vision", 7, 1, 10, 1),
|
|
56
|
+
"cop_vision": Slider("Cop Vision", 7, 1, 10, 1),
|
|
57
|
+
"legitimacy": Slider("Government Legitimacy", 0.82, 0.0, 1, 0.01),
|
|
58
|
+
"max_jail_term": Slider("Max Jail Term", 30, 0, 50, 1),
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
space_component = make_space_matplotlib(citizen_cop_portrayal)
|
|
62
|
+
chart_component = make_plot_measure(["Quiescent", "Active", "Jailed"])
|
|
63
|
+
|
|
64
|
+
epstein_model = EpsteinCivilViolence()
|
|
65
|
+
|
|
66
|
+
page = SolaraViz(
|
|
67
|
+
epstein_model,
|
|
68
|
+
components=[space_component, chart_component],
|
|
69
|
+
model_params=model_params,
|
|
70
|
+
name="Epstein Civil Violence",
|
|
71
|
+
)
|
|
72
|
+
page # noqa
|
{examples/advanced/epstein_civil_violence → mesa/examples/advanced}/epstein_civil_violence/model.py
RENAMED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import mesa
|
|
2
|
-
|
|
3
|
-
from .agent import Citizen, Cop
|
|
2
|
+
from mesa.examples.advanced.epstein_civil_violence.agents import Citizen, Cop
|
|
4
3
|
|
|
5
4
|
|
|
6
5
|
class EpsteinCivilViolence(mesa.Model):
|
|
@@ -43,8 +42,9 @@ class EpsteinCivilViolence(mesa.Model):
|
|
|
43
42
|
arrest_prob_constant=2.3,
|
|
44
43
|
movement=True,
|
|
45
44
|
max_iters=1000,
|
|
45
|
+
seed=None,
|
|
46
46
|
):
|
|
47
|
-
super().__init__()
|
|
47
|
+
super().__init__(seed=seed)
|
|
48
48
|
self.width = width
|
|
49
49
|
self.height = height
|
|
50
50
|
self.citizen_density = citizen_density
|
|
@@ -60,7 +60,7 @@ class EpsteinCivilViolence(mesa.Model):
|
|
|
60
60
|
self.iteration = 0
|
|
61
61
|
|
|
62
62
|
self.grid = mesa.experimental.cell_space.OrthogonalMooreGrid(
|
|
63
|
-
(width, height), capacity=1, torus=True
|
|
63
|
+
(width, height), capacity=1, torus=True, random=self.random
|
|
64
64
|
)
|
|
65
65
|
|
|
66
66
|
model_reporters = {
|
|
@@ -19,7 +19,7 @@ The Demographic Prisoner's Dilemma demonstrates how simple rules can lead to the
|
|
|
19
19
|
|
|
20
20
|
##### Web based model simulation
|
|
21
21
|
|
|
22
|
-
To run the model interactively, run ``
|
|
22
|
+
To run the model interactively, run ``solara run app.py`` in this directory.
|
|
23
23
|
|
|
24
24
|
##### Jupyter Notebook
|
|
25
25
|
|
|
@@ -27,8 +27,9 @@ Launch the ``Demographic Prisoner's Dilemma Activation Schedule.ipynb`` notebook
|
|
|
27
27
|
|
|
28
28
|
## Files
|
|
29
29
|
|
|
30
|
-
* ``
|
|
31
|
-
* ``
|
|
30
|
+
* ``agents.py``: contains the agent class.
|
|
31
|
+
* ``model.py``: contains the model class; the model takes a ``activation_order`` string as an argument, which determines in which order agents are activated: Sequential, Random or Simultaneous.
|
|
32
|
+
* ``app.py``: contains the interactive visualization server.
|
|
32
33
|
* ``Demographic Prisoner's Dilemma Activation Schedule.ipynb``: Jupyter Notebook for running the scheduling experiment. This runs the model three times, one for each activation type, and demonstrates how the activation regime drives the model to different outcomes.
|
|
33
34
|
|
|
34
35
|
## Further Reading
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Solara-based visualization for the Spatial Prisoner's Dilemma Model.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from mesa.examples.advanced.pd_grid.model import PdGrid
|
|
6
|
+
from mesa.visualization import SolaraViz, make_plot_measure, make_space_matplotlib
|
|
7
|
+
from mesa.visualization.UserParam import Slider
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def pd_agent_portrayal(agent):
|
|
11
|
+
"""
|
|
12
|
+
Portrayal function for rendering PD agents in the visualization.
|
|
13
|
+
"""
|
|
14
|
+
return {
|
|
15
|
+
"color": "blue" if agent.move == "C" else "red",
|
|
16
|
+
"shape": "s", # square marker
|
|
17
|
+
"size": 25,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# Model parameters
|
|
22
|
+
model_params = {
|
|
23
|
+
"width": Slider("Grid Width", value=50, min=10, max=100, step=1),
|
|
24
|
+
"height": Slider("Grid Height", value=50, min=10, max=100, step=1),
|
|
25
|
+
"activation_order": {
|
|
26
|
+
"type": "Select",
|
|
27
|
+
"value": "Random",
|
|
28
|
+
"values": PdGrid.activation_regimes,
|
|
29
|
+
"label": "Activation Regime",
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# Create grid visualization component using Altair
|
|
35
|
+
grid_viz = make_space_matplotlib(agent_portrayal=pd_agent_portrayal)
|
|
36
|
+
|
|
37
|
+
# Create plot for tracking cooperating agents over time
|
|
38
|
+
plot_component = make_plot_measure("Cooperating_Agents")
|
|
39
|
+
|
|
40
|
+
# Initialize model
|
|
41
|
+
initial_model = PdGrid()
|
|
42
|
+
|
|
43
|
+
# Create visualization with all components
|
|
44
|
+
page = SolaraViz(
|
|
45
|
+
model=initial_model,
|
|
46
|
+
components=[grid_viz, plot_component],
|
|
47
|
+
model_params=model_params,
|
|
48
|
+
name="Spatial Prisoner's Dilemma",
|
|
49
|
+
)
|
|
50
|
+
page # noqa B018
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import mesa
|
|
2
|
+
from mesa.examples.advanced.pd_grid.agents import PDAgent
|
|
2
3
|
from mesa.experimental.cell_space import OrthogonalMooreGrid
|
|
3
4
|
|
|
4
|
-
from .agent import PDAgent
|
|
5
|
-
|
|
6
5
|
|
|
7
6
|
class PdGrid(mesa.Model):
|
|
8
7
|
"""Model class for iterated, spatial prisoner's dilemma model."""
|
|
@@ -34,51 +34,28 @@ cross over one another otherwise *end*.
|
|
|
34
34
|
(Epstein and Axtell, 1996, p. 105)
|
|
35
35
|
|
|
36
36
|
The model demonstrates several Mesa concepts and features:
|
|
37
|
-
-
|
|
37
|
+
- OrthogonalMooreGrid
|
|
38
38
|
- Multiple agent types (traders, sugar, spice)
|
|
39
39
|
- Dynamically removing agents from the grid and schedule when they die
|
|
40
40
|
- Data Collection at the model and agent level
|
|
41
|
-
-
|
|
41
|
+
- custom solara matplotlib space visualization
|
|
42
42
|
|
|
43
|
-
## Installation
|
|
44
|
-
|
|
45
|
-
To install the dependencies use pip and the requirements.txt in this directory. e.g.
|
|
46
|
-
|
|
47
|
-
```
|
|
48
|
-
$ pip install -r requirements.txt
|
|
49
|
-
```
|
|
50
43
|
|
|
51
44
|
## How to Run
|
|
52
|
-
|
|
53
|
-
To run the model a single instance of the model:
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
$ python run.py -s
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
To run the model with BatchRunner:
|
|
60
|
-
|
|
61
|
-
```
|
|
62
|
-
$ python run.py -b
|
|
63
|
-
```
|
|
64
|
-
|
|
65
45
|
To run the model interactively:
|
|
66
46
|
|
|
67
47
|
```
|
|
68
|
-
$
|
|
48
|
+
$ solara run app.py
|
|
69
49
|
```
|
|
70
50
|
|
|
71
51
|
Then open your browser to [http://127.0.0.1:8521/](http://127.0.0.1:8521/) and press Reset, then Run.
|
|
72
52
|
|
|
73
53
|
## Files
|
|
74
54
|
|
|
75
|
-
* `
|
|
76
|
-
* `
|
|
77
|
-
* `sugarscape_g1mt/model.py`: Manages the Sugarscape Constant Growback with Traders model.
|
|
78
|
-
* `sugarscape_g1mt/sugar_map.txt`: Provides sugar and spice landscape in raster type format.
|
|
79
|
-
* `server.py`: Sets up an interactive visualization server.
|
|
80
|
-
* `run.py`: Runs Server, Single Run or Batch Run with data collection and basic analysis.
|
|
55
|
+
* `model.py`: The Sugarscape Constant Growback with Traders model.
|
|
56
|
+
* `agents.py`: Defines the Trader agent class and the Resource agent class which contains an amount of sugar and spice.
|
|
81
57
|
* `app.py`: Runs a visualization server via Solara (`solara run app.py`).
|
|
58
|
+
* `sugar_map.txt`: Provides sugar and spice landscape in raster type format.
|
|
82
59
|
* `tests.py`: Has tests to ensure that the model reproduces the results in shown in Growing Artificial Societies.
|
|
83
60
|
|
|
84
61
|
## Additional Resources
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import math
|
|
2
2
|
|
|
3
|
-
from mesa.experimental.cell_space import CellAgent
|
|
4
|
-
|
|
5
|
-
from .resource_agents import Resource
|
|
3
|
+
from mesa.experimental.cell_space import CellAgent, FixedAgent
|
|
6
4
|
|
|
7
5
|
|
|
8
6
|
# Helper function
|
|
@@ -20,6 +18,31 @@ def get_distance(cell_1, cell_2):
|
|
|
20
18
|
return math.sqrt(dx**2 + dy**2)
|
|
21
19
|
|
|
22
20
|
|
|
21
|
+
class Resource(FixedAgent):
|
|
22
|
+
"""
|
|
23
|
+
Resource:
|
|
24
|
+
- contains an amount of sugar and spice
|
|
25
|
+
- grows 1 amount of sugar at each turn
|
|
26
|
+
- grows 1 amount of spice at each turn
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(self, model, max_sugar, max_spice, cell):
|
|
30
|
+
super().__init__(model)
|
|
31
|
+
self.sugar_amount = max_sugar
|
|
32
|
+
self.max_sugar = max_sugar
|
|
33
|
+
self.spice_amount = max_spice
|
|
34
|
+
self.max_spice = max_spice
|
|
35
|
+
self.cell = cell
|
|
36
|
+
|
|
37
|
+
def step(self):
|
|
38
|
+
"""
|
|
39
|
+
Growth function, adds one unit of sugar and spice each step up to
|
|
40
|
+
max amount
|
|
41
|
+
"""
|
|
42
|
+
self.sugar_amount = min([self.max_sugar, self.sugar_amount + 1])
|
|
43
|
+
self.spice_amount = min([self.max_spice, self.spice_amount + 1])
|
|
44
|
+
|
|
45
|
+
|
|
23
46
|
class Trader(CellAgent):
|
|
24
47
|
"""
|
|
25
48
|
Trader:
|
|
@@ -1,10 +1,19 @@
|
|
|
1
|
+
import os.path
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
sys.path.insert(
|
|
5
|
+
0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../../"))
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
|
|
1
9
|
import numpy as np
|
|
2
10
|
import solara
|
|
3
11
|
from matplotlib.figure import Figure
|
|
4
|
-
from mesa.visualization import SolaraViz, make_plot_measure
|
|
5
12
|
from sugarscape_g1mt.model import SugarscapeG1mt
|
|
6
13
|
from sugarscape_g1mt.trader_agents import Trader
|
|
7
14
|
|
|
15
|
+
from mesa.visualization import SolaraViz, make_plot_measure
|
|
16
|
+
|
|
8
17
|
|
|
9
18
|
def SpaceDrawer(model):
|
|
10
19
|
def portray(g):
|
|
@@ -14,19 +23,19 @@ def SpaceDrawer(model):
|
|
|
14
23
|
"trader": {"x": [], "y": [], "c": "tab:red", "marker": "o", "s": 10},
|
|
15
24
|
}
|
|
16
25
|
|
|
17
|
-
for
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
for agent in g.all_cells.agents:
|
|
27
|
+
i, j = agent.cell.coordinate
|
|
28
|
+
if isinstance(agent, Trader):
|
|
29
|
+
layers["trader"]["x"].append(i)
|
|
30
|
+
layers["trader"]["y"].append(j)
|
|
31
|
+
else:
|
|
32
|
+
# Don't visualize resource with value <= 1.
|
|
33
|
+
layers["sugar"][i][j] = (
|
|
34
|
+
agent.sugar_amount if agent.sugar_amount > 1 else np.nan
|
|
35
|
+
)
|
|
36
|
+
layers["spice"][i][j] = (
|
|
37
|
+
agent.spice_amount if agent.spice_amount > 1 else np.nan
|
|
38
|
+
)
|
|
30
39
|
return layers
|
|
31
40
|
|
|
32
41
|
fig = Figure()
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
|
-
import mesa
|
|
4
3
|
import numpy as np
|
|
5
|
-
from mesa.experimental.cell_space import OrthogonalVonNeumannGrid
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
from .
|
|
5
|
+
import mesa
|
|
6
|
+
from mesa.examples.advanced.sugarscape_g1mt.agents import Resource, Trader
|
|
7
|
+
from mesa.experimental.cell_space import OrthogonalVonNeumannGrid
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
# Helper Functions
|
|
@@ -53,8 +52,9 @@ class SugarscapeG1mt(mesa.Model):
|
|
|
53
52
|
vision_min=1,
|
|
54
53
|
vision_max=5,
|
|
55
54
|
enable_trade=True,
|
|
55
|
+
seed=None,
|
|
56
56
|
):
|
|
57
|
-
super().__init__()
|
|
57
|
+
super().__init__(seed=seed)
|
|
58
58
|
# Initiate width and height of sugarscape
|
|
59
59
|
self.width = width
|
|
60
60
|
self.height = height
|
|
@@ -176,5 +176,5 @@ class SugarscapeG1mt(mesa.Model):
|
|
|
176
176
|
self.datacollector._agent_records[self.steps] = agent_trades
|
|
177
177
|
|
|
178
178
|
def run_model(self, step_count=1000):
|
|
179
|
-
for
|
|
179
|
+
for _ in range(step_count):
|
|
180
180
|
self.step()
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import random
|
|
2
|
-
|
|
3
1
|
import numpy as np
|
|
4
2
|
from scipy import stats
|
|
5
|
-
from sugarscape_g1mt.model import SugarscapeG1mt, flatten
|
|
6
|
-
from sugarscape_g1mt.trader_agents import Trader
|
|
7
3
|
|
|
8
|
-
|
|
4
|
+
from .agents import Trader
|
|
5
|
+
from .model import SugarscapeG1mt, flatten
|
|
9
6
|
|
|
10
7
|
|
|
11
8
|
def check_slope(y, increasing):
|
|
@@ -19,7 +16,7 @@ def check_slope(y, increasing):
|
|
|
19
16
|
def test_decreasing_price_variance():
|
|
20
17
|
# The variance of the average trade price should decrease over time (figure IV-3)
|
|
21
18
|
# See Growing Artificial Societies p. 109.
|
|
22
|
-
model = SugarscapeG1mt()
|
|
19
|
+
model = SugarscapeG1mt(42)
|
|
23
20
|
model.datacollector._new_model_reporter(
|
|
24
21
|
"price_variance",
|
|
25
22
|
lambda m: np.var(
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from mesa.examples.advanced.wolf_sheep.agents import GrassPatch, Sheep, Wolf
|
|
2
|
+
from mesa.examples.advanced.wolf_sheep.model import WolfSheep
|
|
3
|
+
from mesa.visualization import (
|
|
4
|
+
Slider,
|
|
5
|
+
SolaraViz,
|
|
6
|
+
make_plot_measure,
|
|
7
|
+
make_space_matplotlib,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
WOLF_COLOR = "#000000"
|
|
11
|
+
SHEEP_COLOR = "#648FFF"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def wolf_sheep_portrayal(agent):
|
|
15
|
+
if agent is None:
|
|
16
|
+
return
|
|
17
|
+
|
|
18
|
+
portrayal = {
|
|
19
|
+
"size": 25,
|
|
20
|
+
"shape": "s", # square marker
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if isinstance(agent, Wolf):
|
|
24
|
+
portrayal["color"] = WOLF_COLOR
|
|
25
|
+
portrayal["Layer"] = 3
|
|
26
|
+
elif isinstance(agent, Sheep):
|
|
27
|
+
portrayal["color"] = SHEEP_COLOR
|
|
28
|
+
portrayal["Layer"] = 2
|
|
29
|
+
elif isinstance(agent, GrassPatch):
|
|
30
|
+
if agent.fully_grown:
|
|
31
|
+
portrayal["color"] = "#00FF00"
|
|
32
|
+
else:
|
|
33
|
+
portrayal["color"] = "#84e184"
|
|
34
|
+
# portrayal["shape"] = "rect"
|
|
35
|
+
# portrayal["Filled"] = "true"
|
|
36
|
+
portrayal["Layer"] = 1
|
|
37
|
+
|
|
38
|
+
return portrayal
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
model_params = {
|
|
42
|
+
# The following line is an example to showcase StaticText.
|
|
43
|
+
"grass": {
|
|
44
|
+
"type": "Select",
|
|
45
|
+
"value": True,
|
|
46
|
+
"values": [True, False],
|
|
47
|
+
"label": "grass regrowth enabled?",
|
|
48
|
+
},
|
|
49
|
+
"grass_regrowth_time": Slider("Grass Regrowth Time", 20, 1, 50),
|
|
50
|
+
"initial_sheep": Slider("Initial Sheep Population", 100, 10, 300),
|
|
51
|
+
"sheep_reproduce": Slider("Sheep Reproduction Rate", 0.04, 0.01, 1.0, 0.01),
|
|
52
|
+
"initial_wolves": Slider("Initial Wolf Population", 10, 5, 100),
|
|
53
|
+
"wolf_reproduce": Slider(
|
|
54
|
+
"Wolf Reproduction Rate",
|
|
55
|
+
0.05,
|
|
56
|
+
0.01,
|
|
57
|
+
1.0,
|
|
58
|
+
0.01,
|
|
59
|
+
),
|
|
60
|
+
"wolf_gain_from_food": Slider("Wolf Gain From Food Rate", 20, 1, 50),
|
|
61
|
+
"sheep_gain_from_food": Slider("Sheep Gain From Food", 4, 1, 10),
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
space_component = make_space_matplotlib(wolf_sheep_portrayal)
|
|
66
|
+
lineplot_component = make_plot_measure(["Wolves", "Sheep", "Grass"])
|
|
67
|
+
|
|
68
|
+
model = WolfSheep()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
page = SolaraViz(
|
|
72
|
+
model,
|
|
73
|
+
components=[space_component, lineplot_component],
|
|
74
|
+
model_params=model_params,
|
|
75
|
+
name="Wolf Sheep",
|
|
76
|
+
)
|
|
77
|
+
page # noqa
|
|
@@ -10,10 +10,9 @@ Replication of the model found in NetLogo:
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
import mesa
|
|
13
|
+
from mesa.examples.advanced.wolf_sheep.agents import GrassPatch, Sheep, Wolf
|
|
13
14
|
from mesa.experimental.cell_space import OrthogonalMooreGrid
|
|
14
15
|
|
|
15
|
-
from .agents import GrassPatch, Sheep, Wolf
|
|
16
|
-
|
|
17
16
|
|
|
18
17
|
class WolfSheep(mesa.Model):
|
|
19
18
|
"""
|
|
@@ -67,7 +66,7 @@ class WolfSheep(mesa.Model):
|
|
|
67
66
|
once it is eaten
|
|
68
67
|
sheep_gain_from_food: Energy sheep gain from grass, if enabled.
|
|
69
68
|
"""
|
|
70
|
-
super().__init__(seed=
|
|
69
|
+
super().__init__(seed=seed)
|
|
71
70
|
# Set parameters
|
|
72
71
|
self.width = width
|
|
73
72
|
self.height = height
|
|
@@ -81,15 +80,17 @@ class WolfSheep(mesa.Model):
|
|
|
81
80
|
collectors = {
|
|
82
81
|
"Wolves": lambda m: len(m.agents_by_type[Wolf]),
|
|
83
82
|
"Sheep": lambda m: len(m.agents_by_type[Sheep]),
|
|
83
|
+
"Grass": lambda m: len(
|
|
84
|
+
m.agents_by_type[GrassPatch].select(lambda a: a.fully_grown)
|
|
85
|
+
)
|
|
86
|
+
if m.grass
|
|
87
|
+
else -1,
|
|
84
88
|
}
|
|
85
89
|
|
|
86
|
-
if grass:
|
|
87
|
-
collectors["Grass"] = lambda m: len(m.agents_by_type[GrassPatch])
|
|
88
|
-
|
|
89
90
|
self.datacollector = mesa.DataCollector(collectors)
|
|
90
91
|
|
|
91
92
|
# Create sheep:
|
|
92
|
-
for
|
|
93
|
+
for _ in range(self.initial_sheep):
|
|
93
94
|
x = self.random.randrange(self.width)
|
|
94
95
|
y = self.random.randrange(self.height)
|
|
95
96
|
energy = self.random.randrange(2 * self.sheep_gain_from_food)
|
|
@@ -132,5 +133,5 @@ class WolfSheep(mesa.Model):
|
|
|
132
133
|
self.datacollector.collect(self)
|
|
133
134
|
|
|
134
135
|
def run_model(self, step_count=200):
|
|
135
|
-
for
|
|
136
|
+
for _ in range(step_count):
|
|
136
137
|
self.step()
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Boids Flockers
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
An implementation of Craig Reynolds's Boids flocker model. Agents (simulated birds) try to fly towards the average position of their neighbors and in the same direction as them, while maintaining a minimum distance. This produces flocking behavior.
|
|
6
|
+
|
|
7
|
+
This model tests Mesa's continuous space feature, and uses numpy arrays to represent vectors.
|
|
8
|
+
|
|
9
|
+
## How to Run
|
|
10
|
+
|
|
11
|
+
* To launch the visualization interactively, run ``solara run app.py`` in this directory.It will automatically open a browser page.
|
|
12
|
+
|
|
13
|
+
## Files
|
|
14
|
+
|
|
15
|
+
* [model.py](model.py): Ccntains the Boid Model
|
|
16
|
+
* [agents.py](agents.py): Contains the Boid agent
|
|
17
|
+
* [app.py](app.py): Solara based Visualization code.
|
|
18
|
+
|
|
19
|
+
## Further Reading
|
|
20
|
+
|
|
21
|
+
The following link can be visited for more information on the boid flockers model:
|
|
22
|
+
https://cs.stanford.edu/people/eroberts/courses/soco/projects/2008-09/modeling-natural-systems/boids.html
|