|
1 | | -import time |
2 | | - |
3 | | -import altair as alt |
4 | | -import pandas as pd |
5 | | -import streamlit as st |
6 | | -from boltzmann_wealth_model.model import BoltzmannWealthModel |
7 | | - |
8 | | -model = st.title("Boltzman Wealth Model") |
9 | | -num_agents = st.slider( |
10 | | - "Choose how many agents to include in the model", |
11 | | - min_value=1, |
12 | | - max_value=100, |
13 | | - value=50, |
| 1 | +from mesa.visualization import ( |
| 2 | + SolaraViz, |
| 3 | + make_plot_measure, |
| 4 | + make_space_matplotlib, |
14 | 5 | ) |
15 | | -num_ticks = st.slider( |
16 | | - "Select number of Simulation Runs", min_value=1, max_value=100, value=50 |
17 | | -) |
18 | | -height = st.slider("Select Grid Height", min_value=10, max_value=100, step=10, value=15) |
19 | | -width = st.slider("Select Grid Width", min_value=10, max_value=100, step=10, value=20) |
20 | | -model = BoltzmannWealthModel(num_agents, height, width) |
21 | | - |
| 6 | +from model import BoltzmannWealthModel |
22 | 7 |
|
23 | | -status_text = st.empty() |
24 | | -run = st.button("Run Simulation") |
25 | 8 |
|
| 9 | +def agent_portrayal(agent): |
| 10 | + size = 10 |
| 11 | + color = "tab:red" |
| 12 | + if agent.wealth > 0: |
| 13 | + size = 50 |
| 14 | + color = "tab:blue" |
| 15 | + return {"size": size, "color": color} |
26 | 16 |
|
27 | | -if run: |
28 | | - tick = time.time() |
29 | | - step = 0 |
30 | | - # init grid |
31 | | - df_grid = pd.DataFrame() |
32 | | - df_gini = pd.DataFrame({"step": [0], "gini": [-1]}) |
33 | | - for x in range(width): |
34 | | - for y in range(height): |
35 | | - df_grid = pd.concat( |
36 | | - [df_grid, pd.DataFrame({"x": [x], "y": [y], "agent_count": 0})], |
37 | | - ignore_index=True, |
38 | | - ) |
39 | 17 |
|
40 | | - heatmap = ( |
41 | | - alt.Chart(df_grid) |
42 | | - .mark_point(size=100) |
43 | | - .encode(x="x", y="y", color=alt.Color("agent_count")) |
44 | | - .interactive() |
45 | | - .properties(width=800, height=600) |
46 | | - ) |
| 18 | +model_params = { |
| 19 | + "N": { |
| 20 | + "type": "SliderInt", |
| 21 | + "value": 50, |
| 22 | + "label": "Number of agents:", |
| 23 | + "min": 10, |
| 24 | + "max": 100, |
| 25 | + "step": 1, |
| 26 | + }, |
| 27 | + "width": 10, |
| 28 | + "height": 10, |
| 29 | +} |
47 | 30 |
|
48 | | - line = ( |
49 | | - alt.Chart(df_gini) |
50 | | - .mark_line(point=True) |
51 | | - .encode(x="step", y="gini") |
52 | | - .properties(width=800, height=600) |
53 | | - ) |
| 31 | +# Create initial model instance |
| 32 | +model1 = BoltzmannWealthModel(50, 10, 10) |
54 | 33 |
|
55 | | - # init progress bar |
56 | | - my_bar = st.progress(0, text="Simulation Progress") # progress |
57 | | - placeholder = st.empty() |
58 | | - st.subheader("Agent Grid") |
59 | | - chart = st.altair_chart(heatmap) |
60 | | - st.subheader("Gini Values") |
61 | | - line_chart = st.altair_chart(line) |
| 34 | +# Create visualization elements. The visualization elements are solara components |
| 35 | +# that receive the model instance as a "prop" and display it in a certain way. |
| 36 | +# Under the hood these are just classes that receive the model instance. |
| 37 | +# You can also author your own visualization elements, which can also be functions |
| 38 | +# that receive the model instance and return a valid solara component. |
| 39 | +SpaceGraph = make_space_matplotlib(agent_portrayal) |
| 40 | +GiniPlot = make_plot_measure("Gini") |
62 | 41 |
|
63 | | - color_scale = alt.Scale( |
64 | | - domain=[0, 1, 2, 3, 4], range=["red", "cyan", "white", "white", "blue"] |
65 | | - ) |
66 | | - for i in range(num_ticks): |
67 | | - model.step() |
68 | | - my_bar.progress((i / num_ticks), text="Simulation progress") |
69 | | - placeholder.text("Step = %d" % i) |
70 | | - for cell in model.grid.coord_iter(): |
71 | | - cell_content, (x, y) = cell |
72 | | - agent_count = len(cell_content) |
73 | | - selected_row = df_grid[(df_grid["x"] == x) & (df_grid["y"] == y)] |
74 | | - df_grid.loc[selected_row.index, "agent_count"] = ( |
75 | | - agent_count # random.choice([1,2]) |
76 | | - ) |
77 | | - |
78 | | - df_gini = pd.concat( |
79 | | - [ |
80 | | - df_gini, |
81 | | - pd.DataFrame( |
82 | | - {"step": [i], "gini": [model.datacollector.model_vars["Gini"][i]]} |
83 | | - ), |
84 | | - ] |
85 | | - ) |
86 | | - # st.table(df_grid) |
87 | | - heatmap = ( |
88 | | - alt.Chart(df_grid) |
89 | | - .mark_circle(size=100) |
90 | | - .encode(x="x", y="y", color=alt.Color("agent_count", scale=color_scale)) |
91 | | - .interactive() |
92 | | - .properties(width=800, height=600) |
93 | | - ) |
94 | | - chart.altair_chart(heatmap) |
95 | | - |
96 | | - line = ( |
97 | | - alt.Chart(df_gini) |
98 | | - .mark_line(point=True) |
99 | | - .encode(x="step", y="gini") |
100 | | - .properties(width=800, height=600) |
101 | | - ) |
102 | | - line_chart.altair_chart(line) |
| 42 | +# Create the SolaraViz page. This will automatically create a server and display the |
| 43 | +# visualization elements in a web browser. |
| 44 | +# Display it using the following command in the example directory: |
| 45 | +# solara run app.py |
| 46 | +# It will automatically update and display any changes made to this file |
| 47 | +page = SolaraViz( |
| 48 | + model1, |
| 49 | + components=[SpaceGraph, GiniPlot], |
| 50 | + model_params=model_params, |
| 51 | + name="Boltzmann Wealth Model", |
| 52 | +) |
| 53 | +page # noqa |
103 | 54 |
|
104 | | - time.sleep(0.01) |
105 | 55 |
|
106 | | - tock = time.time() |
107 | | - st.success(f"Simulation completed in {tock - tick:.2f} secs") |
| 56 | +# In a notebook environment, we can also display the visualization elements directly |
| 57 | +# SpaceGraph(model1) |
| 58 | +# GiniPlot(model1) |
108 | 59 |
|
109 | | - # st.subheader('Agent Grid') |
110 | | - # fig = px.imshow(agent_counts,labels={'color':'Agent Count'}) |
111 | | - # st.plotly_chart(fig) |
112 | | - # st.subheader('Gini value over sim ticks (Plotly)') |
113 | | - # chart = st.line_chart(model.datacollector.model_vars['Gini']) |
| 60 | +# The plots will be static. If you want to pick up model steps, |
| 61 | +# you have to make the model reactive first |
| 62 | +# reactive_model = solara.reactive(model1) |
| 63 | +# SpaceGraph(reactive_model) |
| 64 | +# In a different notebook block: |
| 65 | +# reactive_model.value.step() |
0 commit comments