Skip to content

Commit 501ff15

Browse files
committed
Merge branch 'main' into sync-pyproject-with-mesa
# Conflicts: # examples/boltzmann_wealth_model_network/boltzmann_wealth_model_network/model.py # examples/boltzmann_wealth_model_network/boltzmann_wealth_model_network/server.py # examples/color_patches/color_patches/model.py
2 parents f16a8b2 + 7eac2eb commit 501ff15

File tree

26 files changed

+383
-301
lines changed

26 files changed

+383
-301
lines changed

examples/bank_reserves/app.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
from bank_reserves.agents import Person
2+
from bank_reserves.model import BankReservesModel
3+
from mesa.visualization import (
4+
SolaraViz,
5+
make_plot_component,
6+
make_space_component,
7+
)
8+
from mesa.visualization.user_param import (
9+
Slider,
10+
)
11+
12+
# The colors here are taken from Matplotlib's tab10 palette
13+
# Green
14+
RICH_COLOR = "#2ca02c"
15+
# Red
16+
POOR_COLOR = "#d62728"
17+
# Blue
18+
MID_COLOR = "#1f77b4"
19+
20+
21+
def person_portrayal(agent):
22+
if agent is None:
23+
return
24+
25+
portrayal = {}
26+
27+
# update portrayal characteristics for each Person object
28+
if isinstance(agent, Person):
29+
portrayal["Shape"] = "circle"
30+
portrayal["r"] = 0.5
31+
portrayal["Layer"] = 0
32+
portrayal["Filled"] = "true"
33+
34+
color = MID_COLOR
35+
36+
# set agent color based on savings and loans
37+
if agent.savings > agent.model.rich_threshold:
38+
color = RICH_COLOR
39+
if agent.savings < 10 and agent.loans < 10:
40+
color = MID_COLOR
41+
if agent.loans > 10:
42+
color = POOR_COLOR
43+
44+
portrayal["color"] = color
45+
46+
return portrayal
47+
48+
49+
def post_process_space(ax):
50+
ax.set_aspect("equal")
51+
ax.set_xticks([])
52+
ax.set_yticks([])
53+
54+
55+
def post_process_lines(ax):
56+
ax.legend(loc="center left", bbox_to_anchor=(1, 0.9))
57+
58+
59+
# dictionary of user settable parameters - these map to the model __init__ parameters
60+
model_params = {
61+
"init_people": Slider(
62+
"People",
63+
25,
64+
1,
65+
200,
66+
# description="Initial Number of People"
67+
),
68+
"rich_threshold": Slider(
69+
"Rich Threshold",
70+
10,
71+
1,
72+
20,
73+
# description="Upper End of Random Initial Wallet Amount",
74+
),
75+
"reserve_percent": Slider(
76+
"Reserves",
77+
50,
78+
1,
79+
100,
80+
# description="Percent of deposits the bank has to hold in reserve",
81+
),
82+
}
83+
84+
space_component = make_space_component(
85+
person_portrayal,
86+
draw_grid=False,
87+
post_process=post_process_space,
88+
)
89+
lineplot_component = make_plot_component(
90+
{"Rich": RICH_COLOR, "Poor": POOR_COLOR, "Middle Class": MID_COLOR},
91+
post_process=post_process_lines,
92+
)
93+
model = BankReservesModel()
94+
95+
page = SolaraViz(
96+
model,
97+
components=[space_component, lineplot_component],
98+
model_params=model_params,
99+
name="Bank Reserves Model",
100+
)
101+
page # noqa

examples/bank_reserves/bank_reserves/server.py

Lines changed: 0 additions & 90 deletions
This file was deleted.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
itertools
2-
mesa~=2.0
1+
mesa[viz]>=3.1.4
2+
networkx
33
numpy
44
pandas

examples/bank_reserves/run.py

Lines changed: 0 additions & 3 deletions
This file was deleted.

examples/boltzmann_wealth_model_network/README.md

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,29 @@ In this network implementation, agents must be located on a node, with a limit o
1010

1111
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.
1212

13-
JavaScript library used in this example to render the network: [sigma.js](http://sigmajs.org/).
14-
1513
## Installation
1614

17-
To install the dependencies use pip and the requirements.txt in this directory. e.g.
15+
To install the dependencies use `pip` to install `mesa[rec]`
1816

19-
```
20-
$ pip install -r requirements.txt
17+
```bash
18+
$ pip install mesa[rec]
2119
```
2220

2321
## How to Run
2422

25-
To run the model interactively, run ``mesa runserver`` in this directory. e.g.
23+
To run the model interactively, run ``solara run`` in this directory. e.g.
2624

27-
```
28-
$ mesa runserver
25+
```bash
26+
$ solara run app.py
2927
```
3028

31-
Then open your browser to [http://127.0.0.1:8521/](http://127.0.0.1:8521/) and press Reset, then Run.
29+
Then open your browser to [http://localhost:8765/](http://localhost:8765/) and press Reset, then Run.
3230

3331
## Files
3432

35-
* ``run.py``: Launches a model visualization server.
36-
* ``model.py``: Contains the agent class, and the overall model class.
37-
* ``server.py``: Defines classes for visualizing the model (network layout) in the browser via Mesa's modular server, and instantiates a visualization server.
33+
* ``model.py``: Contains creation of agents, the network, and management of agent execution.
34+
* ``agents.py``: Contains logic for giving money, and moving on the network.
35+
* ``app.py``: Contains the code for the interactive Solara visualization.
3836

3937
## Further Reading
4038

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
from boltzmann_wealth_model_network.model import BoltzmannWealthModelNetwork
2+
from mesa.mesa_logging import INFO, log_to_stderr
3+
from mesa.visualization import (
4+
SolaraViz,
5+
make_plot_component,
6+
make_space_component,
7+
)
8+
9+
log_to_stderr(INFO)
10+
11+
12+
# Tells Solara how to draw each agent.
13+
def agent_portrayal(agent):
14+
return {
15+
"color": agent.wealth, # using a colormap to convert wealth to color
16+
"size": 50,
17+
}
18+
19+
20+
model_params = {
21+
"seed": {
22+
"type": "InputText",
23+
"value": 42,
24+
"label": "Random seed",
25+
},
26+
"n": {
27+
"type": "SliderInt",
28+
"value": 7,
29+
"label": "Number of agents",
30+
"min": 2,
31+
"max": 10,
32+
"step": 1,
33+
# "description": "Choose how many agents to include in the model",
34+
},
35+
"num_nodes": {
36+
"type": "SliderInt",
37+
"value": 10,
38+
"label": "Number of nodes",
39+
"min": 3,
40+
"max": 12,
41+
"step": 1,
42+
# "description": "Choose how many nodes to include in the model, with at least the same number of agents",
43+
},
44+
}
45+
46+
47+
def post_process(ax):
48+
ax.get_figure().colorbar(ax.collections[0], label="wealth", ax=ax)
49+
50+
51+
# Create initial model instance
52+
money_model = BoltzmannWealthModelNetwork(n=7, num_nodes=10, seed=42)
53+
54+
# Create visualization elements. The visualization elements are Solara
55+
# components that receive the model instance as a "prop" and display it in a
56+
# certain way. Under the hood these are just classes that receive the model
57+
# instance. You can also author your own visualization elements, which can also
58+
# be functions that receive the model instance and return a valid Solara
59+
# component.
60+
61+
SpaceGraph = make_space_component(
62+
agent_portrayal, cmap="viridis", vmin=0, vmax=10, post_process=post_process
63+
)
64+
GiniPlot = make_plot_component("Gini")
65+
66+
# Create the SolaraViz page. This will automatically create a server and display
67+
# the visualization elements in a web browser.
68+
#
69+
# Display it using the following command in the example directory:
70+
# solara run app.py
71+
# It will automatically update and display any changes made to this file.
72+
73+
page = SolaraViz(
74+
money_model,
75+
components=[SpaceGraph, GiniPlot],
76+
model_params=model_params,
77+
name="Boltzmann Wealth Model: Network",
78+
)
79+
page # noqa
80+
81+
82+
# In a notebook environment, we can also display the visualization elements
83+
# directly.
84+
#
85+
# SpaceGraph(model1)
86+
# GiniPlot(model1)
87+
88+
# The plots will be static. If you want to pick up model steps,
89+
# you have to make the model reactive first
90+
#
91+
# reactive_model = solara.reactive(model1)
92+
# SpaceGraph(reactive_model)
93+
94+
# In a different notebook block:
95+
#
96+
# reactive_model.value.step()
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from mesa.discrete_space import CellAgent
2+
3+
4+
class MoneyAgent(CellAgent):
5+
"""An agent with fixed initial wealth.
6+
7+
Each agent starts with 1 unit of wealth and can give 1 unit to other agents
8+
if they occupy the same cell.
9+
10+
Attributes:
11+
wealth (int): The agent's current wealth (starts at 1)
12+
"""
13+
14+
def __init__(self, model):
15+
"""Create a new agent.
16+
17+
Args:
18+
model (Model): The model instance that contains the agent
19+
"""
20+
super().__init__(model)
21+
self.wealth = 1
22+
23+
def give_money(self):
24+
neighbors = [agent for agent in self.cell.neighborhood.agents if agent != self]
25+
if len(neighbors) > 0:
26+
other = self.random.choice(neighbors)
27+
other.wealth += 1
28+
self.wealth -= 1
29+
30+
def step(self):
31+
empty_neighbors = [cell for cell in self.cell.neighborhood if cell.is_empty]
32+
if empty_neighbors:
33+
self.cell = self.random.choice(empty_neighbors)
34+
35+
if self.wealth > 0:
36+
self.give_money()

0 commit comments

Comments
 (0)