Mesa 3.0.0__py3-none-any.whl → 3.0.0a0__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 +3 -3
- mesa/agent.py +114 -406
- mesa/batchrunner.py +27 -54
- mesa/cookiecutter-mesa/cookiecutter.json +8 -0
- mesa/cookiecutter-mesa/hooks/post_gen_project.py +11 -0
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/README.md +4 -0
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/app.pytemplate +27 -0
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/setup.pytemplate +11 -0
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/model.pytemplate +60 -0
- mesa/datacollection.py +29 -140
- mesa/experimental/__init__.py +1 -11
- mesa/experimental/cell_space/__init__.py +1 -16
- mesa/experimental/cell_space/cell.py +23 -93
- mesa/experimental/cell_space/cell_agent.py +21 -117
- mesa/experimental/cell_space/cell_collection.py +17 -54
- mesa/experimental/cell_space/discrete_space.py +8 -92
- mesa/experimental/cell_space/grid.py +8 -32
- mesa/experimental/cell_space/network.py +7 -12
- mesa/experimental/devs/__init__.py +0 -2
- mesa/experimental/devs/eventlist.py +14 -52
- mesa/experimental/devs/examples/epstein_civil_violence.py +39 -71
- mesa/experimental/devs/examples/wolf_sheep.py +45 -45
- mesa/experimental/devs/simulator.py +15 -55
- mesa/main.py +63 -0
- mesa/model.py +83 -211
- mesa/space.py +149 -215
- mesa/time.py +77 -62
- mesa/{experimental → visualization}/UserParam.py +6 -17
- mesa/visualization/__init__.py +2 -25
- mesa/{experimental → visualization}/components/altair.py +0 -10
- mesa/visualization/components/matplotlib.py +134 -0
- mesa/{experimental/solara_viz.py → visualization/jupyter_viz.py} +110 -65
- {mesa-3.0.0.dist-info → mesa-3.0.0a0.dist-info}/METADATA +13 -65
- mesa-3.0.0a0.dist-info/RECORD +38 -0
- mesa-3.0.0.dist-info/licenses/NOTICE → mesa-3.0.0a0.dist-info/licenses/LICENSE +2 -2
- mesa/examples/README.md +0 -37
- mesa/examples/__init__.py +0 -21
- mesa/examples/advanced/epstein_civil_violence/Epstein Civil Violence.ipynb +0 -116
- mesa/examples/advanced/epstein_civil_violence/Readme.md +0 -34
- mesa/examples/advanced/epstein_civil_violence/__init__.py +0 -0
- mesa/examples/advanced/epstein_civil_violence/agents.py +0 -164
- mesa/examples/advanced/epstein_civil_violence/app.py +0 -73
- mesa/examples/advanced/epstein_civil_violence/model.py +0 -114
- mesa/examples/advanced/pd_grid/Readme.md +0 -43
- mesa/examples/advanced/pd_grid/__init__.py +0 -0
- mesa/examples/advanced/pd_grid/agents.py +0 -50
- mesa/examples/advanced/pd_grid/analysis.ipynb +0 -228
- mesa/examples/advanced/pd_grid/app.py +0 -54
- mesa/examples/advanced/pd_grid/model.py +0 -71
- mesa/examples/advanced/sugarscape_g1mt/Readme.md +0 -64
- mesa/examples/advanced/sugarscape_g1mt/__init__.py +0 -0
- mesa/examples/advanced/sugarscape_g1mt/agents.py +0 -344
- mesa/examples/advanced/sugarscape_g1mt/app.py +0 -62
- mesa/examples/advanced/sugarscape_g1mt/model.py +0 -180
- mesa/examples/advanced/sugarscape_g1mt/sugar-map.txt +0 -50
- mesa/examples/advanced/sugarscape_g1mt/tests.py +0 -69
- mesa/examples/advanced/wolf_sheep/Readme.md +0 -57
- mesa/examples/advanced/wolf_sheep/__init__.py +0 -0
- mesa/examples/advanced/wolf_sheep/agents.py +0 -102
- mesa/examples/advanced/wolf_sheep/app.py +0 -84
- mesa/examples/advanced/wolf_sheep/model.py +0 -137
- mesa/examples/basic/__init__.py +0 -0
- mesa/examples/basic/boid_flockers/Readme.md +0 -22
- mesa/examples/basic/boid_flockers/__init__.py +0 -0
- mesa/examples/basic/boid_flockers/agents.py +0 -71
- mesa/examples/basic/boid_flockers/app.py +0 -58
- mesa/examples/basic/boid_flockers/model.py +0 -69
- mesa/examples/basic/boltzmann_wealth_model/Readme.md +0 -56
- mesa/examples/basic/boltzmann_wealth_model/__init__.py +0 -0
- mesa/examples/basic/boltzmann_wealth_model/agents.py +0 -31
- mesa/examples/basic/boltzmann_wealth_model/app.py +0 -74
- mesa/examples/basic/boltzmann_wealth_model/model.py +0 -43
- mesa/examples/basic/boltzmann_wealth_model/st_app.py +0 -115
- mesa/examples/basic/conways_game_of_life/Readme.md +0 -39
- mesa/examples/basic/conways_game_of_life/__init__.py +0 -0
- mesa/examples/basic/conways_game_of_life/agents.py +0 -47
- mesa/examples/basic/conways_game_of_life/app.py +0 -51
- mesa/examples/basic/conways_game_of_life/model.py +0 -31
- mesa/examples/basic/conways_game_of_life/st_app.py +0 -72
- mesa/examples/basic/schelling/Readme.md +0 -40
- mesa/examples/basic/schelling/__init__.py +0 -0
- mesa/examples/basic/schelling/agents.py +0 -26
- mesa/examples/basic/schelling/analysis.ipynb +0 -205
- mesa/examples/basic/schelling/app.py +0 -42
- mesa/examples/basic/schelling/model.py +0 -59
- mesa/examples/basic/virus_on_network/Readme.md +0 -61
- mesa/examples/basic/virus_on_network/__init__.py +0 -0
- mesa/examples/basic/virus_on_network/agents.py +0 -69
- mesa/examples/basic/virus_on_network/app.py +0 -114
- mesa/examples/basic/virus_on_network/model.py +0 -96
- mesa/experimental/cell_space/voronoi.py +0 -257
- mesa/experimental/components/matplotlib.py +0 -242
- mesa/visualization/components/__init__.py +0 -83
- mesa/visualization/components/altair_components.py +0 -188
- mesa/visualization/components/matplotlib_components.py +0 -175
- mesa/visualization/mpl_space_drawing.py +0 -593
- mesa/visualization/solara_viz.py +0 -458
- mesa/visualization/user_param.py +0 -69
- mesa/visualization/utils.py +0 -9
- mesa-3.0.0.dist-info/RECORD +0 -95
- mesa-3.0.0.dist-info/licenses/LICENSE +0 -202
- /mesa/{examples/advanced → cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}}/__init__.py +0 -0
- {mesa-3.0.0.dist-info → mesa-3.0.0a0.dist-info}/WHEEL +0 -0
- {mesa-3.0.0.dist-info → mesa-3.0.0a0.dist-info}/entry_points.txt +0 -0
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
from scipy import stats
|
|
3
|
-
|
|
4
|
-
from .agents import Trader
|
|
5
|
-
from .model import SugarscapeG1mt, flatten
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def check_slope(y, increasing):
|
|
9
|
-
x = range(len(y))
|
|
10
|
-
slope, intercept, _, p_value, _ = stats.linregress(x, y)
|
|
11
|
-
result = (slope > 0) if increasing else (slope < 0)
|
|
12
|
-
# p_value for significance.
|
|
13
|
-
assert result and p_value < 0.05, (slope, p_value)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def test_decreasing_price_variance():
|
|
17
|
-
# The variance of the average trade price should decrease over time (figure IV-3)
|
|
18
|
-
# See Growing Artificial Societies p. 109.
|
|
19
|
-
model = SugarscapeG1mt(42)
|
|
20
|
-
model.datacollector._new_model_reporter(
|
|
21
|
-
"price_variance",
|
|
22
|
-
lambda m: np.var(
|
|
23
|
-
flatten([a.prices for a in m.agents_by_type[Trader].values()])
|
|
24
|
-
),
|
|
25
|
-
)
|
|
26
|
-
model.run_model(step_count=50)
|
|
27
|
-
|
|
28
|
-
df_model = model.datacollector.get_model_vars_dataframe()
|
|
29
|
-
|
|
30
|
-
check_slope(df_model.price_variance, increasing=False)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def test_carrying_capacity():
|
|
34
|
-
def calculate_carrying_capacities(enable_trade):
|
|
35
|
-
carrying_capacities = []
|
|
36
|
-
visions = range(1, 10)
|
|
37
|
-
for vision_max in visions:
|
|
38
|
-
model = SugarscapeG1mt(vision_max=vision_max, enable_trade=enable_trade)
|
|
39
|
-
model.run_model(step_count=50)
|
|
40
|
-
carrying_capacities.append(len(model.agents_by_type[Trader]))
|
|
41
|
-
return carrying_capacities
|
|
42
|
-
|
|
43
|
-
# Carrying capacity should increase over mean vision (figure IV-6).
|
|
44
|
-
# See Growing Artificial Societies p. 112.
|
|
45
|
-
carrying_capacities_with_trade = calculate_carrying_capacities(True)
|
|
46
|
-
check_slope(
|
|
47
|
-
carrying_capacities_with_trade,
|
|
48
|
-
increasing=True,
|
|
49
|
-
)
|
|
50
|
-
# Carrying capacity should be higher when trade is enabled (figure IV-6).
|
|
51
|
-
carrying_capacities_no_trade = calculate_carrying_capacities(False)
|
|
52
|
-
check_slope(
|
|
53
|
-
carrying_capacities_no_trade,
|
|
54
|
-
increasing=True,
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
t_statistic, p_value = stats.ttest_rel(
|
|
58
|
-
carrying_capacities_with_trade, carrying_capacities_no_trade
|
|
59
|
-
)
|
|
60
|
-
# t_statistic > 0 means carrying_capacities_with_trade has larger values
|
|
61
|
-
# than carrying_capacities_no_trade.
|
|
62
|
-
# p_value for significance.
|
|
63
|
-
assert t_statistic > 0 and p_value < 0.05
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
# TODO:
|
|
67
|
-
# 1. Reproduce figure IV-12 that the log of average price should decrease over average agent age
|
|
68
|
-
# 2. Reproduce figure IV-13 that the gini coefficient on trade should decrease over mean vision, and should be higher with trade
|
|
69
|
-
# 3. a stricter test would be to ensure the amount of variance of the trade price matches figure IV-3
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# Wolf-Sheep Predation Model
|
|
2
|
-
|
|
3
|
-
## Summary
|
|
4
|
-
|
|
5
|
-
A simple ecological model, consisting of three agent types: wolves, sheep, and grass. The wolves and the sheep wander around the grid at random. Wolves and sheep both expend energy moving around, and replenish it by eating. Sheep eat grass, and wolves eat sheep if they end up on the same grid cell.
|
|
6
|
-
|
|
7
|
-
If wolves and sheep have enough energy, they reproduce, creating a new wolf or sheep (in this simplified model, only one parent is needed for reproduction). The grass on each cell regrows at a constant rate. If any wolves and sheep run out of energy, they die.
|
|
8
|
-
|
|
9
|
-
The model is tests and demonstrates several Mesa concepts and features:
|
|
10
|
-
- MultiGrid
|
|
11
|
-
- Multiple agent types (wolves, sheep, grass)
|
|
12
|
-
- Overlay arbitrary text (wolf's energy) on agent's shapes while drawing on CanvasGrid
|
|
13
|
-
- Agents inheriting a behavior (random movement) from an abstract parent
|
|
14
|
-
- Writing a model composed of multiple files.
|
|
15
|
-
- Dynamically adding and removing agents from the schedule
|
|
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
|
-
## How to Run
|
|
31
|
-
|
|
32
|
-
To run the model interactively, run ``mesa runserver`` in this directory. e.g.
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
$ mesa runserver
|
|
36
|
-
```
|
|
37
|
-
|
|
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
|
-
## Files
|
|
41
|
-
|
|
42
|
-
* ``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.
|
|
43
|
-
* ``wolf_sheep/test_random_walk.py``: Defines a simple model and a text-only visualization intended to make sure the RandomWalk class was working as expected. This doesn't actually model anything, but serves as an ad-hoc unit test. To run it, ``cd`` into the ``wolf_sheep`` directory and run ``python test_random_walk.py``. You'll see a series of ASCII grids, one per model step, with each cell showing a count of the number of agents in it.
|
|
44
|
-
* ``wolf_sheep/agents.py``: Defines the Wolf, Sheep, and GrassPatch agent classes.
|
|
45
|
-
* ``wolf_sheep/scheduler.py``: Defines a custom variant on the RandomActivationByType scheduler, where we can define filters for the `get_type_count` function.
|
|
46
|
-
* ``wolf_sheep/model.py``: Defines the Wolf-Sheep Predation model itself
|
|
47
|
-
* ``wolf_sheep/server.py``: Sets up the interactive visualization server
|
|
48
|
-
* ``run.py``: Launches a model visualization server.
|
|
49
|
-
|
|
50
|
-
## Further Reading
|
|
51
|
-
|
|
52
|
-
This model is closely based on the NetLogo Wolf-Sheep Predation Model:
|
|
53
|
-
|
|
54
|
-
Wilensky, U. (1997). NetLogo Wolf Sheep Predation model. http://ccl.northwestern.edu/netlogo/models/WolfSheepPredation. Center for Connected Learning and Computer-Based Modeling, Northwestern University, Evanston, IL.
|
|
55
|
-
|
|
56
|
-
See also the [Lotka–Volterra equations
|
|
57
|
-
](https://en.wikipedia.org/wiki/Lotka%E2%80%93Volterra_equations) for an example of a classic differential-equation model with similar dynamics.
|
|
File without changes
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
from mesa.experimental.cell_space import CellAgent, FixedAgent
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class Animal(CellAgent):
|
|
5
|
-
"""The base animal class."""
|
|
6
|
-
|
|
7
|
-
def __init__(self, model, energy, p_reproduce, energy_from_food, cell):
|
|
8
|
-
"""Initializes an animal.
|
|
9
|
-
|
|
10
|
-
Args:
|
|
11
|
-
model: a model instance
|
|
12
|
-
energy: starting amount of energy
|
|
13
|
-
p_reproduce: probability of sexless reproduction
|
|
14
|
-
energy_from_food: energy obtained from 1 unit of food
|
|
15
|
-
cell: the cell in which the animal starts
|
|
16
|
-
"""
|
|
17
|
-
super().__init__(model)
|
|
18
|
-
self.energy = energy
|
|
19
|
-
self.p_reproduce = p_reproduce
|
|
20
|
-
self.energy_from_food = energy_from_food
|
|
21
|
-
self.cell = cell
|
|
22
|
-
|
|
23
|
-
def spawn_offspring(self):
|
|
24
|
-
"""Create offspring."""
|
|
25
|
-
self.energy /= 2
|
|
26
|
-
self.__class__(
|
|
27
|
-
self.model,
|
|
28
|
-
self.energy,
|
|
29
|
-
self.p_reproduce,
|
|
30
|
-
self.energy_from_food,
|
|
31
|
-
self.cell,
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
def feed(self): ...
|
|
35
|
-
|
|
36
|
-
def step(self):
|
|
37
|
-
"""One step of the agent."""
|
|
38
|
-
self.cell = self.cell.neighborhood.select_random_cell()
|
|
39
|
-
self.energy -= 1
|
|
40
|
-
|
|
41
|
-
self.feed()
|
|
42
|
-
|
|
43
|
-
if self.energy < 0:
|
|
44
|
-
self.remove()
|
|
45
|
-
elif self.random.random() < self.p_reproduce:
|
|
46
|
-
self.spawn_offspring()
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class Sheep(Animal):
|
|
50
|
-
"""A sheep that walks around, reproduces (asexually) and gets eaten."""
|
|
51
|
-
|
|
52
|
-
def feed(self):
|
|
53
|
-
"""If possible eat the food in the current location."""
|
|
54
|
-
# If there is grass available, eat it
|
|
55
|
-
if self.model.grass:
|
|
56
|
-
grass_patch = next(
|
|
57
|
-
obj for obj in self.cell.agents if isinstance(obj, GrassPatch)
|
|
58
|
-
)
|
|
59
|
-
if grass_patch.fully_grown:
|
|
60
|
-
self.energy += self.energy_from_food
|
|
61
|
-
grass_patch.fully_grown = False
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
class Wolf(Animal):
|
|
65
|
-
"""A wolf that walks around, reproduces (asexually) and eats sheep."""
|
|
66
|
-
|
|
67
|
-
def feed(self):
|
|
68
|
-
"""If possible eat the food in the current location."""
|
|
69
|
-
sheep = [obj for obj in self.cell.agents if isinstance(obj, Sheep)]
|
|
70
|
-
if len(sheep) > 0:
|
|
71
|
-
sheep_to_eat = self.random.choice(sheep)
|
|
72
|
-
self.energy += self.energy_from_food
|
|
73
|
-
|
|
74
|
-
# Kill the sheep
|
|
75
|
-
sheep_to_eat.remove()
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
class GrassPatch(FixedAgent):
|
|
79
|
-
"""
|
|
80
|
-
A patch of grass that grows at a fixed rate and it is eaten by sheep
|
|
81
|
-
"""
|
|
82
|
-
|
|
83
|
-
def __init__(self, model, fully_grown, countdown):
|
|
84
|
-
"""
|
|
85
|
-
Creates a new patch of grass
|
|
86
|
-
|
|
87
|
-
Args:
|
|
88
|
-
grown: (boolean) Whether the patch of grass is fully grown or not
|
|
89
|
-
countdown: Time for the patch of grass to be fully grown again
|
|
90
|
-
"""
|
|
91
|
-
super().__init__(model)
|
|
92
|
-
self.fully_grown = fully_grown
|
|
93
|
-
self.countdown = countdown
|
|
94
|
-
|
|
95
|
-
def step(self):
|
|
96
|
-
if not self.fully_grown:
|
|
97
|
-
if self.countdown <= 0:
|
|
98
|
-
# Set as fully grown
|
|
99
|
-
self.fully_grown = True
|
|
100
|
-
self.countdown = self.model.grass_regrowth_time
|
|
101
|
-
else:
|
|
102
|
-
self.countdown -= 1
|
|
@@ -1,84 +0,0 @@
|
|
|
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_component,
|
|
7
|
-
make_space_component,
|
|
8
|
-
)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def wolf_sheep_portrayal(agent):
|
|
12
|
-
if agent is None:
|
|
13
|
-
return
|
|
14
|
-
|
|
15
|
-
portrayal = {
|
|
16
|
-
"size": 25,
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if isinstance(agent, Wolf):
|
|
20
|
-
portrayal["color"] = "tab:red"
|
|
21
|
-
portrayal["marker"] = "o"
|
|
22
|
-
portrayal["zorder"] = 2
|
|
23
|
-
elif isinstance(agent, Sheep):
|
|
24
|
-
portrayal["color"] = "tab:cyan"
|
|
25
|
-
portrayal["marker"] = "o"
|
|
26
|
-
portrayal["zorder"] = 2
|
|
27
|
-
elif isinstance(agent, GrassPatch):
|
|
28
|
-
if agent.fully_grown:
|
|
29
|
-
portrayal["color"] = "tab:green"
|
|
30
|
-
else:
|
|
31
|
-
portrayal["color"] = "tab:brown"
|
|
32
|
-
portrayal["marker"] = "s"
|
|
33
|
-
portrayal["size"] = 75
|
|
34
|
-
|
|
35
|
-
return portrayal
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
model_params = {
|
|
39
|
-
# The following line is an example to showcase StaticText.
|
|
40
|
-
"grass": {
|
|
41
|
-
"type": "Select",
|
|
42
|
-
"value": True,
|
|
43
|
-
"values": [True, False],
|
|
44
|
-
"label": "grass regrowth enabled?",
|
|
45
|
-
},
|
|
46
|
-
"grass_regrowth_time": Slider("Grass Regrowth Time", 20, 1, 50),
|
|
47
|
-
"initial_sheep": Slider("Initial Sheep Population", 100, 10, 300),
|
|
48
|
-
"sheep_reproduce": Slider("Sheep Reproduction Rate", 0.04, 0.01, 1.0, 0.01),
|
|
49
|
-
"initial_wolves": Slider("Initial Wolf Population", 10, 5, 100),
|
|
50
|
-
"wolf_reproduce": Slider(
|
|
51
|
-
"Wolf Reproduction Rate",
|
|
52
|
-
0.05,
|
|
53
|
-
0.01,
|
|
54
|
-
1.0,
|
|
55
|
-
0.01,
|
|
56
|
-
),
|
|
57
|
-
"wolf_gain_from_food": Slider("Wolf Gain From Food Rate", 20, 1, 50),
|
|
58
|
-
"sheep_gain_from_food": Slider("Sheep Gain From Food", 4, 1, 10),
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def post_process(ax):
|
|
63
|
-
ax.set_aspect("equal")
|
|
64
|
-
ax.set_xticks([])
|
|
65
|
-
ax.set_yticks([])
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
space_component = make_space_component(
|
|
69
|
-
wolf_sheep_portrayal, draw_grid=False, post_process=post_process
|
|
70
|
-
)
|
|
71
|
-
lineplot_component = make_plot_component(
|
|
72
|
-
{"Wolves": "tab:orange", "Sheep": "tab:cyan", "Grass": "tab:green"}
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
model = WolfSheep(grass=True)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
page = SolaraViz(
|
|
79
|
-
model,
|
|
80
|
-
components=[space_component, lineplot_component],
|
|
81
|
-
model_params=model_params,
|
|
82
|
-
name="Wolf Sheep",
|
|
83
|
-
)
|
|
84
|
-
page # noqa
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Wolf-Sheep Predation Model
|
|
3
|
-
================================
|
|
4
|
-
|
|
5
|
-
Replication of the model found in NetLogo:
|
|
6
|
-
Wilensky, U. (1997). NetLogo Wolf Sheep Predation model.
|
|
7
|
-
http://ccl.northwestern.edu/netlogo/models/WolfSheepPredation.
|
|
8
|
-
Center for Connected Learning and Computer-Based Modeling,
|
|
9
|
-
Northwestern University, Evanston, IL.
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
import mesa
|
|
13
|
-
from mesa.examples.advanced.wolf_sheep.agents import GrassPatch, Sheep, Wolf
|
|
14
|
-
from mesa.experimental.cell_space import OrthogonalMooreGrid
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class WolfSheep(mesa.Model):
|
|
18
|
-
"""
|
|
19
|
-
Wolf-Sheep Predation Model
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
height = 20
|
|
23
|
-
width = 20
|
|
24
|
-
|
|
25
|
-
initial_sheep = 100
|
|
26
|
-
initial_wolves = 50
|
|
27
|
-
|
|
28
|
-
sheep_reproduce = 0.04
|
|
29
|
-
wolf_reproduce = 0.05
|
|
30
|
-
|
|
31
|
-
wolf_gain_from_food = 20
|
|
32
|
-
|
|
33
|
-
grass = False
|
|
34
|
-
grass_regrowth_time = 30
|
|
35
|
-
sheep_gain_from_food = 4
|
|
36
|
-
|
|
37
|
-
description = (
|
|
38
|
-
"A model for simulating wolf and sheep (predator-prey) ecosystem modelling."
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
def __init__(
|
|
42
|
-
self,
|
|
43
|
-
width=20,
|
|
44
|
-
height=20,
|
|
45
|
-
initial_sheep=100,
|
|
46
|
-
initial_wolves=50,
|
|
47
|
-
sheep_reproduce=0.04,
|
|
48
|
-
wolf_reproduce=0.05,
|
|
49
|
-
wolf_gain_from_food=20,
|
|
50
|
-
grass=False,
|
|
51
|
-
grass_regrowth_time=30,
|
|
52
|
-
sheep_gain_from_food=4,
|
|
53
|
-
seed=None,
|
|
54
|
-
):
|
|
55
|
-
"""
|
|
56
|
-
Create a new Wolf-Sheep model with the given parameters.
|
|
57
|
-
|
|
58
|
-
Args:
|
|
59
|
-
initial_sheep: Number of sheep to start with
|
|
60
|
-
initial_wolves: Number of wolves to start with
|
|
61
|
-
sheep_reproduce: Probability of each sheep reproducing each step
|
|
62
|
-
wolf_reproduce: Probability of each wolf reproducing each step
|
|
63
|
-
wolf_gain_from_food: Energy a wolf gains from eating a sheep
|
|
64
|
-
grass: Whether to have the sheep eat grass for energy
|
|
65
|
-
grass_regrowth_time: How long it takes for a grass patch to regrow
|
|
66
|
-
once it is eaten
|
|
67
|
-
sheep_gain_from_food: Energy sheep gain from grass, if enabled.
|
|
68
|
-
"""
|
|
69
|
-
super().__init__(seed=seed)
|
|
70
|
-
# Set parameters
|
|
71
|
-
self.width = width
|
|
72
|
-
self.height = height
|
|
73
|
-
self.initial_sheep = initial_sheep
|
|
74
|
-
self.initial_wolves = initial_wolves
|
|
75
|
-
self.grass = grass
|
|
76
|
-
self.grass_regrowth_time = grass_regrowth_time
|
|
77
|
-
|
|
78
|
-
self.grid = OrthogonalMooreGrid((self.width, self.height), torus=True)
|
|
79
|
-
|
|
80
|
-
collectors = {
|
|
81
|
-
"Wolves": lambda m: len(m.agents_by_type[Wolf]),
|
|
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,
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
self.datacollector = mesa.DataCollector(collectors)
|
|
91
|
-
|
|
92
|
-
# Create sheep:
|
|
93
|
-
for _ in range(self.initial_sheep):
|
|
94
|
-
x = self.random.randrange(self.width)
|
|
95
|
-
y = self.random.randrange(self.height)
|
|
96
|
-
energy = self.random.randrange(2 * self.sheep_gain_from_food)
|
|
97
|
-
Sheep(
|
|
98
|
-
self, energy, sheep_reproduce, sheep_gain_from_food, self.grid[(x, y)]
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
# Create wolves
|
|
102
|
-
for _ in range(self.initial_wolves):
|
|
103
|
-
x = self.random.randrange(self.width)
|
|
104
|
-
y = self.random.randrange(self.height)
|
|
105
|
-
energy = self.random.randrange(2 * self.wolf_gain_from_food)
|
|
106
|
-
Wolf(self, energy, wolf_reproduce, wolf_gain_from_food, self.grid[(x, y)])
|
|
107
|
-
|
|
108
|
-
# Create grass patches
|
|
109
|
-
if self.grass:
|
|
110
|
-
for cell in self.grid.all_cells:
|
|
111
|
-
fully_grown = self.random.choice([True, False])
|
|
112
|
-
|
|
113
|
-
if fully_grown:
|
|
114
|
-
countdown = self.grass_regrowth_time
|
|
115
|
-
else:
|
|
116
|
-
countdown = self.random.randrange(self.grass_regrowth_time)
|
|
117
|
-
|
|
118
|
-
patch = GrassPatch(self, fully_grown, countdown)
|
|
119
|
-
patch.cell = cell
|
|
120
|
-
|
|
121
|
-
self.running = True
|
|
122
|
-
self.datacollector.collect(self)
|
|
123
|
-
|
|
124
|
-
def step(self):
|
|
125
|
-
# This replicated the behavior of the old RandomActivationByType scheduler
|
|
126
|
-
# when using step(shuffle_types=True, shuffle_agents=True).
|
|
127
|
-
# Conceptually, it can be argued that this should be modelled differently.
|
|
128
|
-
self.random.shuffle(self.agent_types)
|
|
129
|
-
for agent_type in self.agent_types:
|
|
130
|
-
self.agents_by_type[agent_type].shuffle_do("step")
|
|
131
|
-
|
|
132
|
-
# collect data
|
|
133
|
-
self.datacollector.collect(self)
|
|
134
|
-
|
|
135
|
-
def run_model(self, step_count=200):
|
|
136
|
-
for _ in range(step_count):
|
|
137
|
-
self.step()
|
mesa/examples/basic/__init__.py
DELETED
|
File without changes
|
|
@@ -1,22 +0,0 @@
|
|
|
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
|
|
File without changes
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
|
|
3
|
-
from mesa import Agent
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class Boid(Agent):
|
|
7
|
-
"""A Boid-style flocker agent.
|
|
8
|
-
|
|
9
|
-
The agent follows three behaviors to flock:
|
|
10
|
-
- Cohesion: steering towards neighboring agents.
|
|
11
|
-
- Separation: avoiding getting too close to any other agent.
|
|
12
|
-
- Alignment: try to fly in the same direction as the neighbors.
|
|
13
|
-
|
|
14
|
-
Boids have a vision that defines the radius in which they look for their
|
|
15
|
-
neighbors to flock with. Their speed (a scalar) and direction (a vector)
|
|
16
|
-
define their movement. Separation is their desired minimum distance from
|
|
17
|
-
any other Boid.
|
|
18
|
-
"""
|
|
19
|
-
|
|
20
|
-
def __init__(
|
|
21
|
-
self,
|
|
22
|
-
model,
|
|
23
|
-
speed,
|
|
24
|
-
direction,
|
|
25
|
-
vision,
|
|
26
|
-
separation,
|
|
27
|
-
cohere=0.03,
|
|
28
|
-
separate=0.015,
|
|
29
|
-
match=0.05,
|
|
30
|
-
):
|
|
31
|
-
"""Create a new Boid flocker agent.
|
|
32
|
-
|
|
33
|
-
Args:
|
|
34
|
-
speed: Distance to move per step.
|
|
35
|
-
direction: numpy vector for the Boid's direction of movement.
|
|
36
|
-
vision: Radius to look around for nearby Boids.
|
|
37
|
-
separation: Minimum distance to maintain from other Boids.
|
|
38
|
-
cohere: the relative importance of matching neighbors' positions
|
|
39
|
-
separate: the relative importance of avoiding close neighbors
|
|
40
|
-
match: the relative importance of matching neighbors' headings
|
|
41
|
-
"""
|
|
42
|
-
super().__init__(model)
|
|
43
|
-
self.speed = speed
|
|
44
|
-
self.direction = direction
|
|
45
|
-
self.vision = vision
|
|
46
|
-
self.separation = separation
|
|
47
|
-
self.cohere_factor = cohere
|
|
48
|
-
self.separate_factor = separate
|
|
49
|
-
self.match_factor = match
|
|
50
|
-
self.neighbors = None
|
|
51
|
-
|
|
52
|
-
def step(self):
|
|
53
|
-
"""Get the Boid's neighbors, compute the new vector, and move accordingly."""
|
|
54
|
-
self.neighbors = self.model.space.get_neighbors(self.pos, self.vision, False)
|
|
55
|
-
n = 0
|
|
56
|
-
match_vector, separation_vector, cohere = np.zeros((3, 2))
|
|
57
|
-
for neighbor in self.neighbors:
|
|
58
|
-
n += 1
|
|
59
|
-
heading = self.model.space.get_heading(self.pos, neighbor.pos)
|
|
60
|
-
cohere += heading
|
|
61
|
-
if self.model.space.get_distance(self.pos, neighbor.pos) < self.separation:
|
|
62
|
-
separation_vector -= heading
|
|
63
|
-
match_vector += neighbor.direction
|
|
64
|
-
n = max(n, 1)
|
|
65
|
-
cohere = cohere * self.cohere_factor
|
|
66
|
-
separation_vector = separation_vector * self.separate_factor
|
|
67
|
-
match_vector = match_vector * self.match_factor
|
|
68
|
-
self.direction += (cohere + separation_vector + match_vector) / n
|
|
69
|
-
self.direction /= np.linalg.norm(self.direction)
|
|
70
|
-
new_pos = self.pos + self.direction * self.speed
|
|
71
|
-
self.model.space.move_agent(self, new_pos)
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
from mesa.examples.basic.boid_flockers.model import BoidFlockers
|
|
2
|
-
from mesa.visualization import Slider, SolaraViz, make_space_component
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def boid_draw(agent):
|
|
6
|
-
if not agent.neighbors: # Only for the first Frame
|
|
7
|
-
neighbors = len(agent.model.space.get_neighbors(agent.pos, agent.vision, False))
|
|
8
|
-
else:
|
|
9
|
-
neighbors = len(agent.neighbors)
|
|
10
|
-
|
|
11
|
-
if neighbors <= 1:
|
|
12
|
-
return {"color": "red", "size": 20}
|
|
13
|
-
elif neighbors >= 2:
|
|
14
|
-
return {"color": "green", "size": 20}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
model_params = {
|
|
18
|
-
"population": Slider(
|
|
19
|
-
label="Number of boids",
|
|
20
|
-
value=100,
|
|
21
|
-
min=10,
|
|
22
|
-
max=200,
|
|
23
|
-
step=10,
|
|
24
|
-
),
|
|
25
|
-
"width": 100,
|
|
26
|
-
"height": 100,
|
|
27
|
-
"speed": Slider(
|
|
28
|
-
label="Speed of Boids",
|
|
29
|
-
value=5,
|
|
30
|
-
min=1,
|
|
31
|
-
max=20,
|
|
32
|
-
step=1,
|
|
33
|
-
),
|
|
34
|
-
"vision": Slider(
|
|
35
|
-
label="Vision of Bird (radius)",
|
|
36
|
-
value=10,
|
|
37
|
-
min=1,
|
|
38
|
-
max=50,
|
|
39
|
-
step=1,
|
|
40
|
-
),
|
|
41
|
-
"separation": Slider(
|
|
42
|
-
label="Minimum Separation",
|
|
43
|
-
value=2,
|
|
44
|
-
min=1,
|
|
45
|
-
max=20,
|
|
46
|
-
step=1,
|
|
47
|
-
),
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
model = BoidFlockers()
|
|
51
|
-
|
|
52
|
-
page = SolaraViz(
|
|
53
|
-
model,
|
|
54
|
-
[make_space_component(agent_portrayal=boid_draw, backend="matplotlib")],
|
|
55
|
-
model_params=model_params,
|
|
56
|
-
name="Boid Flocking Model",
|
|
57
|
-
)
|
|
58
|
-
page # noqa
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"""Flockers.
|
|
2
|
-
=============================================================
|
|
3
|
-
A Mesa implementation of Craig Reynolds's Boids flocker model.
|
|
4
|
-
Uses numpy arrays to represent vectors.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import numpy as np
|
|
8
|
-
|
|
9
|
-
import mesa
|
|
10
|
-
from mesa.examples.basic.boid_flockers.agents import Boid
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class BoidFlockers(mesa.Model):
|
|
14
|
-
"""Flocker model class. Handles agent creation, placement and scheduling."""
|
|
15
|
-
|
|
16
|
-
def __init__(
|
|
17
|
-
self,
|
|
18
|
-
seed=None,
|
|
19
|
-
population=100,
|
|
20
|
-
width=100,
|
|
21
|
-
height=100,
|
|
22
|
-
vision=10,
|
|
23
|
-
speed=1,
|
|
24
|
-
separation=1,
|
|
25
|
-
cohere=0.03,
|
|
26
|
-
separate=0.015,
|
|
27
|
-
match=0.05,
|
|
28
|
-
):
|
|
29
|
-
"""Create a new Flockers model.
|
|
30
|
-
|
|
31
|
-
Args:
|
|
32
|
-
population: Number of Boids
|
|
33
|
-
width, height: Size of the space.
|
|
34
|
-
speed: How fast should the Boids move.
|
|
35
|
-
vision: How far around should each Boid look for its neighbors
|
|
36
|
-
separation: What's the minimum distance each Boid will attempt to
|
|
37
|
-
keep from any other
|
|
38
|
-
cohere, separate, match: factors for the relative importance of
|
|
39
|
-
the three drives.
|
|
40
|
-
"""
|
|
41
|
-
super().__init__(seed=seed)
|
|
42
|
-
self.population = population
|
|
43
|
-
self.vision = vision
|
|
44
|
-
self.speed = speed
|
|
45
|
-
self.separation = separation
|
|
46
|
-
|
|
47
|
-
self.space = mesa.space.ContinuousSpace(width, height, True)
|
|
48
|
-
self.factors = {"cohere": cohere, "separate": separate, "match": match}
|
|
49
|
-
self.make_agents()
|
|
50
|
-
|
|
51
|
-
def make_agents(self):
|
|
52
|
-
"""Create self.population agents, with random positions and starting headings."""
|
|
53
|
-
for _ in range(self.population):
|
|
54
|
-
x = self.random.random() * self.space.x_max
|
|
55
|
-
y = self.random.random() * self.space.y_max
|
|
56
|
-
pos = np.array((x, y))
|
|
57
|
-
direction = np.random.random(2) * 2 - 1
|
|
58
|
-
boid = Boid(
|
|
59
|
-
model=self,
|
|
60
|
-
speed=self.speed,
|
|
61
|
-
direction=direction,
|
|
62
|
-
vision=self.vision,
|
|
63
|
-
separation=self.separation,
|
|
64
|
-
**self.factors,
|
|
65
|
-
)
|
|
66
|
-
self.space.place_agent(boid, pos)
|
|
67
|
-
|
|
68
|
-
def step(self):
|
|
69
|
-
self.agents.shuffle_do("step")
|