Skip to content

Commit

Permalink
merge experimental boltzmann wealth into boltzmann wealth example
Browse files Browse the repository at this point in the history
  • Loading branch information
wang-boyu committed Oct 11, 2024
1 parent 6b99eaa commit f744179
Show file tree
Hide file tree
Showing 14 changed files with 178 additions and 346 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ This is based on Dorigo's Ant System "Swarm Intelligence" algorithm for generati

## Visualization Examples

### [Boltzmann Wealth Model (Experimental)](https://github.com/projectmesa/mesa-examples/tree/main/examples/boltzmann_wealth_model_experimental)
### [Boltzmann Wealth Model)](https://github.com/projectmesa/mesa-examples/tree/main/examples/boltzmann_wealth_model)

Boltzmann Wealth model with the experimental Juptyer notebook visualization feature.
Boltzmann Wealth model with an optional visualization using Streamlit.

### [Charts Example](https://github.com/projectmesa/mesa-examples/tree/main/examples/charts)

Expand Down
17 changes: 8 additions & 9 deletions examples/boltzmann_wealth_model/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,31 @@ As the model runs, the distribution of wealth among agents goes from being perfe

To follow the tutorial example, launch the Jupyter Notebook and run the code in ``Introduction to Mesa Tutorial Code.ipynb`` which you can find in the main mesa repo [here](https://github.com/projectmesa/mesa/blob/main/docs/tutorials/intro_tutorial.ipynb)

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:
Make sure to install the requirements first:

```
$ python server.py
pip install -r requirements.txt
```

Make sure to install the requirements first:
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:

```
pip install -r requirements.txt
$ solara run app.py
```

If your browser doesn't open automatically, point it to [http://127.0.0.1:8521/](http://127.0.0.1:8521/). When the visualization loads, press Reset, then Run.
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.


## Files

* ``boltzmann_wealth_model/model.py``: Final version of the model.
* ``boltzmann_wealth_model/server.py``: Code for the interactive visualization.
* ``run.py``: Launches the server.
* ``model.py``: Final version of the model.
* ``app.py``: Code for the interactive visualization.

## Optional

* ``boltzmann_wealth_model/app.py``: can be used to run the simulation via the streamlit interface.
* For this some additional packages like ``streamlit`` and ``altair`` needs to be installed.
* Once installed, the app can be opened in the browser using : ``streamlit run app.py``
* Once installed, the app can be opened in the browser using : ``streamlit run st_app.py``

## Further Reading

Expand Down
156 changes: 54 additions & 102 deletions examples/boltzmann_wealth_model/app.py
Original file line number Diff line number Diff line change
@@ -1,113 +1,65 @@
import time

import altair as alt
import pandas as pd
import streamlit as st
from boltzmann_wealth_model.model import BoltzmannWealthModel

model = st.title("Boltzman Wealth Model")
num_agents = st.slider(
"Choose how many agents to include in the model",
min_value=1,
max_value=100,
value=50,
from mesa.visualization import (
SolaraViz,
make_plot_measure,
make_space_matplotlib,
)
num_ticks = st.slider(
"Select number of Simulation Runs", min_value=1, max_value=100, value=50
)
height = st.slider("Select Grid Height", min_value=10, max_value=100, step=10, value=15)
width = st.slider("Select Grid Width", min_value=10, max_value=100, step=10, value=20)
model = BoltzmannWealthModel(num_agents, height, width)

from model import BoltzmannWealthModel

status_text = st.empty()
run = st.button("Run Simulation")

def agent_portrayal(agent):
size = 10
color = "tab:red"
if agent.wealth > 0:
size = 50
color = "tab:blue"
return {"size": size, "color": color}

if run:
tick = time.time()
step = 0
# init grid
df_grid = pd.DataFrame()
df_gini = pd.DataFrame({"step": [0], "gini": [-1]})
for x in range(width):
for y in range(height):
df_grid = pd.concat(
[df_grid, pd.DataFrame({"x": [x], "y": [y], "agent_count": 0})],
ignore_index=True,
)

heatmap = (
alt.Chart(df_grid)
.mark_point(size=100)
.encode(x="x", y="y", color=alt.Color("agent_count"))
.interactive()
.properties(width=800, height=600)
)
model_params = {
"N": {
"type": "SliderInt",
"value": 50,
"label": "Number of agents:",
"min": 10,
"max": 100,
"step": 1,
},
"width": 10,
"height": 10,
}

line = (
alt.Chart(df_gini)
.mark_line(point=True)
.encode(x="step", y="gini")
.properties(width=800, height=600)
)
# Create initial model instance
model1 = BoltzmannWealthModel(50, 10, 10)

# init progress bar
my_bar = st.progress(0, text="Simulation Progress") # progress
placeholder = st.empty()
st.subheader("Agent Grid")
chart = st.altair_chart(heatmap)
st.subheader("Gini Values")
line_chart = st.altair_chart(line)
# Create visualization elements. The visualization elements are solara components
# that receive the model instance as a "prop" and display it in a certain way.
# Under the hood these are just classes that receive the model instance.
# You can also author your own visualization elements, which can also be functions
# that receive the model instance and return a valid solara component.
SpaceGraph = make_space_matplotlib(agent_portrayal)
GiniPlot = make_plot_measure("Gini")

color_scale = alt.Scale(
domain=[0, 1, 2, 3, 4], range=["red", "cyan", "white", "white", "blue"]
)
for i in range(num_ticks):
model.step()
my_bar.progress((i / num_ticks), text="Simulation progress")
placeholder.text("Step = %d" % i)
for cell in model.grid.coord_iter():
cell_content, (x, y) = cell
agent_count = len(cell_content)
selected_row = df_grid[(df_grid["x"] == x) & (df_grid["y"] == y)]
df_grid.loc[selected_row.index, "agent_count"] = (
agent_count # random.choice([1,2])
)

df_gini = pd.concat(
[
df_gini,
pd.DataFrame(
{"step": [i], "gini": [model.datacollector.model_vars["Gini"][i]]}
),
]
)
# st.table(df_grid)
heatmap = (
alt.Chart(df_grid)
.mark_circle(size=100)
.encode(x="x", y="y", color=alt.Color("agent_count", scale=color_scale))
.interactive()
.properties(width=800, height=600)
)
chart.altair_chart(heatmap)

line = (
alt.Chart(df_gini)
.mark_line(point=True)
.encode(x="step", y="gini")
.properties(width=800, height=600)
)
line_chart.altair_chart(line)
# Create the SolaraViz page. This will automatically create a server and display the
# visualization elements in a web browser.
# Display it using the following command in the example directory:
# solara run app.py
# It will automatically update and display any changes made to this file
page = SolaraViz(
model1,
components=[SpaceGraph, GiniPlot],
model_params=model_params,
name="Boltzmann Wealth Model",
)
page # noqa

time.sleep(0.01)

tock = time.time()
st.success(f"Simulation completed in {tock - tick:.2f} secs")
# In a notebook environment, we can also display the visualization elements directly
# SpaceGraph(model1)
# GiniPlot(model1)

# st.subheader('Agent Grid')
# fig = px.imshow(agent_counts,labels={'color':'Agent Count'})
# st.plotly_chart(fig)
# st.subheader('Gini value over sim ticks (Plotly)')
# chart = st.line_chart(model.datacollector.model_vars['Gini'])
# The plots will be static. If you want to pick up model steps,
# you have to make the model reactive first
# reactive_model = solara.reactive(model1)
# SpaceGraph(reactive_model)
# In a different notebook block:
# reactive_model.value.step()
Empty file.
40 changes: 0 additions & 40 deletions examples/boltzmann_wealth_model/boltzmann_wealth_model/server.py

This file was deleted.

File renamed without changes.
2 changes: 1 addition & 1 deletion examples/boltzmann_wealth_model/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
mesa~=2.0
mesa[viz]~=3.0.0b0
3 changes: 0 additions & 3 deletions examples/boltzmann_wealth_model/run.py

This file was deleted.

113 changes: 113 additions & 0 deletions examples/boltzmann_wealth_model/st_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import time

import altair as alt
import pandas as pd
import streamlit as st
from model import BoltzmannWealthModel

model = st.title("Boltzman Wealth Model")
num_agents = st.slider(
"Choose how many agents to include in the model",
min_value=1,
max_value=100,
value=50,
)
num_ticks = st.slider(
"Select number of Simulation Runs", min_value=1, max_value=100, value=50
)
height = st.slider("Select Grid Height", min_value=10, max_value=100, step=10, value=15)
width = st.slider("Select Grid Width", min_value=10, max_value=100, step=10, value=20)
model = BoltzmannWealthModel(num_agents, height, width)


status_text = st.empty()
run = st.button("Run Simulation")


if run:
tick = time.time()
step = 0
# init grid
df_grid = pd.DataFrame()
df_gini = pd.DataFrame({"step": [0], "gini": [-1]})
for x in range(width):
for y in range(height):
df_grid = pd.concat(
[df_grid, pd.DataFrame({"x": [x], "y": [y], "agent_count": 0})],
ignore_index=True,
)

heatmap = (
alt.Chart(df_grid)
.mark_point(size=100)
.encode(x="x", y="y", color=alt.Color("agent_count"))
.interactive()
.properties(width=800, height=600)
)

line = (
alt.Chart(df_gini)
.mark_line(point=True)
.encode(x="step", y="gini")
.properties(width=800, height=600)
)

# init progress bar
my_bar = st.progress(0, text="Simulation Progress") # progress
placeholder = st.empty()
st.subheader("Agent Grid")
chart = st.altair_chart(heatmap)
st.subheader("Gini Values")
line_chart = st.altair_chart(line)

color_scale = alt.Scale(
domain=[0, 1, 2, 3, 4], range=["red", "cyan", "white", "white", "blue"]
)
for i in range(num_ticks):
model.step()
my_bar.progress((i / num_ticks), text="Simulation progress")
placeholder.text("Step = %d" % i)
for cell in model.grid.coord_iter():
cell_content, (x, y) = cell
agent_count = len(cell_content)
selected_row = df_grid[(df_grid["x"] == x) & (df_grid["y"] == y)]
df_grid.loc[selected_row.index, "agent_count"] = (
agent_count # random.choice([1,2])
)

df_gini = pd.concat(
[
df_gini,
pd.DataFrame(
{"step": [i], "gini": [model.datacollector.model_vars["Gini"][i]]}
),
]
)
# st.table(df_grid)
heatmap = (
alt.Chart(df_grid)
.mark_circle(size=100)
.encode(x="x", y="y", color=alt.Color("agent_count", scale=color_scale))
.interactive()
.properties(width=800, height=600)
)
chart.altair_chart(heatmap)

line = (
alt.Chart(df_gini)
.mark_line(point=True)
.encode(x="step", y="gini")
.properties(width=800, height=600)
)
line_chart.altair_chart(line)

time.sleep(0.01)

tock = time.time()
st.success(f"Simulation completed in {tock - tick:.2f} secs")

# st.subheader('Agent Grid')
# fig = px.imshow(agent_counts,labels={'color':'Agent Count'})
# st.plotly_chart(fig)
# st.subheader('Gini value over sim ticks (Plotly)')
# chart = st.line_chart(model.datacollector.model_vars['Gini'])
Loading

0 comments on commit f744179

Please sign in to comment.