Mesa 2.4.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 +1 -3
- mesa/agent.py +53 -332
- mesa/batchrunner.py +8 -11
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/app.pytemplate +27 -0
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/model.pytemplate +1 -1
- mesa/datacollection.py +21 -136
- mesa/experimental/__init__.py +1 -3
- mesa/experimental/cell_space/cell_collection.py +2 -2
- mesa/experimental/cell_space/grid.py +1 -1
- mesa/experimental/cell_space/network.py +3 -3
- mesa/experimental/devs/eventlist.py +2 -1
- mesa/experimental/devs/examples/epstein_civil_violence.py +1 -2
- mesa/experimental/devs/examples/wolf_sheep.py +2 -3
- mesa/experimental/devs/simulator.py +2 -1
- mesa/model.py +23 -93
- mesa/space.py +11 -17
- mesa/time.py +1 -3
- mesa/visualization/UserParam.py +56 -1
- mesa/visualization/__init__.py +2 -6
- mesa/{experimental → visualization}/components/altair.py +1 -2
- mesa/{experimental → visualization}/components/matplotlib.py +4 -6
- mesa/{experimental → visualization}/jupyter_viz.py +117 -20
- {mesa-2.4.0.dist-info → mesa-3.0.0a0.dist-info}/METADATA +4 -11
- mesa-3.0.0a0.dist-info/RECORD +38 -0
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/run.pytemplate +0 -3
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/server.pytemplate +0 -36
- mesa/experimental/UserParam.py +0 -56
- mesa/flat/__init__.py +0 -6
- mesa/flat/visualization.py +0 -5
- mesa/visualization/ModularVisualization.py +0 -1
- mesa/visualization/TextVisualization.py +0 -1
- mesa/visualization/modules.py +0 -1
- mesa-2.4.0.dist-info/RECORD +0 -45
- {mesa-2.4.0.dist-info → mesa-3.0.0a0.dist-info}/WHEEL +0 -0
- {mesa-2.4.0.dist-info → mesa-3.0.0a0.dist-info}/entry_points.txt +0 -0
- {mesa-2.4.0.dist-info → mesa-3.0.0a0.dist-info}/licenses/LICENSE +0 -0
mesa/visualization/UserParam.py
CHANGED
|
@@ -1 +1,56 @@
|
|
|
1
|
-
|
|
1
|
+
class UserParam:
|
|
2
|
+
_ERROR_MESSAGE = "Missing or malformed inputs for '{}' Option '{}'"
|
|
3
|
+
|
|
4
|
+
def maybe_raise_error(self, param_type, valid):
|
|
5
|
+
if valid:
|
|
6
|
+
return
|
|
7
|
+
msg = self._ERROR_MESSAGE.format(param_type, self.label)
|
|
8
|
+
raise ValueError(msg)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Slider(UserParam):
|
|
12
|
+
"""
|
|
13
|
+
A number-based slider input with settable increment.
|
|
14
|
+
|
|
15
|
+
Example:
|
|
16
|
+
|
|
17
|
+
slider_option = Slider("My Slider", value=123, min=10, max=200, step=0.1)
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
label: The displayed label in the UI
|
|
21
|
+
value: The initial value of the slider
|
|
22
|
+
min: The minimum possible value of the slider
|
|
23
|
+
max: The maximum possible value of the slider
|
|
24
|
+
step: The step between min and max for a range of possible values
|
|
25
|
+
dtype: either int or float
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
label="",
|
|
31
|
+
value=None,
|
|
32
|
+
min=None,
|
|
33
|
+
max=None,
|
|
34
|
+
step=1,
|
|
35
|
+
dtype=None,
|
|
36
|
+
):
|
|
37
|
+
self.label = label
|
|
38
|
+
self.value = value
|
|
39
|
+
self.min = min
|
|
40
|
+
self.max = max
|
|
41
|
+
self.step = step
|
|
42
|
+
|
|
43
|
+
# Validate option type to make sure values are supplied properly
|
|
44
|
+
valid = not (self.value is None or self.min is None or self.max is None)
|
|
45
|
+
self.maybe_raise_error("slider", valid)
|
|
46
|
+
|
|
47
|
+
if dtype is None:
|
|
48
|
+
self.is_float_slider = self._check_values_are_float(value, min, max, step)
|
|
49
|
+
else:
|
|
50
|
+
self.is_float_slider = dtype is float
|
|
51
|
+
|
|
52
|
+
def _check_values_are_float(self, value, min, max, step):
|
|
53
|
+
return any(isinstance(n, float) for n in (value, min, max, step))
|
|
54
|
+
|
|
55
|
+
def get(self, attr):
|
|
56
|
+
return getattr(self, attr)
|
mesa/visualization/__init__.py
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import
|
|
1
|
+
from .jupyter_viz import JupyterViz, Slider, make_text
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
from mesa_viz_tornado.ModularVisualization import * # noqa
|
|
5
|
-
from mesa_viz_tornado.modules import * # noqa
|
|
6
|
-
from mesa_viz_tornado.UserParam import * # noqa
|
|
7
|
-
from mesa_viz_tornado.TextVisualization import * # noqa
|
|
3
|
+
__all__ = ["JupyterViz", "make_text", "Slider"]
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import contextlib
|
|
2
|
-
from typing import Optional
|
|
3
2
|
|
|
4
3
|
import solara
|
|
5
4
|
|
|
@@ -8,7 +7,7 @@ with contextlib.suppress(ImportError):
|
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
@solara.component
|
|
11
|
-
def SpaceAltair(model, agent_portrayal, dependencies:
|
|
10
|
+
def SpaceAltair(model, agent_portrayal, dependencies: list[any] | None = None):
|
|
12
11
|
space = getattr(model, "grid", None)
|
|
13
12
|
if space is None:
|
|
14
13
|
# Sometimes the space is defined as model.space instead of model.grid
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Optional
|
|
2
|
-
|
|
3
1
|
import networkx as nx
|
|
4
2
|
import solara
|
|
5
3
|
from matplotlib.figure import Figure
|
|
@@ -9,7 +7,7 @@ import mesa
|
|
|
9
7
|
|
|
10
8
|
|
|
11
9
|
@solara.component
|
|
12
|
-
def SpaceMatplotlib(model, agent_portrayal, dependencies:
|
|
10
|
+
def SpaceMatplotlib(model, agent_portrayal, dependencies: list[any] | None = None):
|
|
13
11
|
space_fig = Figure()
|
|
14
12
|
space_ax = space_fig.subplots()
|
|
15
13
|
space = getattr(model, "grid", None)
|
|
@@ -50,7 +48,7 @@ def _draw_grid(space, space_ax, agent_portrayal):
|
|
|
50
48
|
out = {"x": x, "y": y}
|
|
51
49
|
# This is the default value for the marker size, which auto-scales
|
|
52
50
|
# according to the grid area.
|
|
53
|
-
out["s"] = (180 /
|
|
51
|
+
out["s"] = (180 / min(g.width, g.height)) ** 2
|
|
54
52
|
if len(s) > 0:
|
|
55
53
|
out["s"] = s
|
|
56
54
|
if len(c) > 0:
|
|
@@ -116,7 +114,7 @@ def _draw_continuous_space(space, space_ax, agent_portrayal):
|
|
|
116
114
|
|
|
117
115
|
|
|
118
116
|
@solara.component
|
|
119
|
-
def PlotMatplotlib(model, measure, dependencies:
|
|
117
|
+
def PlotMatplotlib(model, measure, dependencies: list[any] | None = None):
|
|
120
118
|
fig = Figure()
|
|
121
119
|
ax = fig.subplots()
|
|
122
120
|
df = model.datacollector.get_model_vars_dataframe()
|
|
@@ -127,7 +125,7 @@ def PlotMatplotlib(model, measure, dependencies: Optional[list[any]] = None):
|
|
|
127
125
|
for m, color in measure.items():
|
|
128
126
|
ax.plot(df.loc[:, m], label=m, color=color)
|
|
129
127
|
fig.legend()
|
|
130
|
-
elif isinstance(measure,
|
|
128
|
+
elif isinstance(measure, list | tuple):
|
|
131
129
|
for m in measure:
|
|
132
130
|
ax.plot(df.loc[:, m], label=m)
|
|
133
131
|
fig.legend()
|
|
@@ -1,17 +1,38 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Mesa visualization module for creating interactive model visualizations.
|
|
3
|
+
|
|
4
|
+
This module provides components to create browser- and Jupyter notebook-based visualizations of
|
|
5
|
+
Mesa models, allowing users to watch models run step-by-step and interact with model parameters.
|
|
6
|
+
|
|
7
|
+
Key features:
|
|
8
|
+
- JupyterViz: Main component for creating visualizations, supporting grid displays and plots
|
|
9
|
+
- ModelController: Handles model execution controls (step, play, pause, reset)
|
|
10
|
+
- UserInputs: Generates UI elements for adjusting model parameters
|
|
11
|
+
- Card: Renders individual visualization elements (space, measures)
|
|
12
|
+
|
|
13
|
+
The module uses Solara for rendering in Jupyter notebooks or as standalone web applications.
|
|
14
|
+
It supports various types of visualizations including matplotlib plots, agent grids, and
|
|
15
|
+
custom visualization components.
|
|
16
|
+
|
|
17
|
+
Usage:
|
|
18
|
+
1. Define an agent_portrayal function to specify how agents should be displayed
|
|
19
|
+
2. Set up model_params to define adjustable parameters
|
|
20
|
+
3. Create a JupyterViz instance with your model, parameters, and desired measures
|
|
21
|
+
4. Display the visualization in a Jupyter notebook or run as a Solara app
|
|
22
|
+
|
|
23
|
+
See the Visualization Tutorial and example models for more details.
|
|
24
|
+
"""
|
|
25
|
+
|
|
1
26
|
import sys
|
|
2
27
|
import threading
|
|
3
28
|
|
|
4
|
-
import matplotlib.pyplot as plt
|
|
5
29
|
import reacton.ipywidgets as widgets
|
|
6
30
|
import solara
|
|
7
31
|
from solara.alias import rv
|
|
8
32
|
|
|
9
|
-
import mesa.
|
|
10
|
-
import mesa.
|
|
11
|
-
from mesa.
|
|
12
|
-
|
|
13
|
-
# Avoid interactive backend
|
|
14
|
-
plt.switch_backend("agg")
|
|
33
|
+
import mesa.visualization.components.altair as components_altair
|
|
34
|
+
import mesa.visualization.components.matplotlib as components_matplotlib
|
|
35
|
+
from mesa.visualization.UserParam import Slider
|
|
15
36
|
|
|
16
37
|
|
|
17
38
|
# TODO: Turn this function into a Solara component once the current_step.value
|
|
@@ -19,6 +40,21 @@ plt.switch_backend("agg")
|
|
|
19
40
|
def Card(
|
|
20
41
|
model, measures, agent_portrayal, space_drawer, dependencies, color, layout_type
|
|
21
42
|
):
|
|
43
|
+
"""
|
|
44
|
+
Create a card component for visualizing model space or measures.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
model: The Mesa model instance
|
|
48
|
+
measures: List of measures to be plotted
|
|
49
|
+
agent_portrayal: Function to define agent appearance
|
|
50
|
+
space_drawer: Method to render agent space
|
|
51
|
+
dependencies: List of dependencies for updating the visualization
|
|
52
|
+
color: Background color of the card
|
|
53
|
+
layout_type: Type of layout (Space or Measure)
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
rv.Card: A card component containing the visualization
|
|
57
|
+
"""
|
|
22
58
|
with rv.Card(
|
|
23
59
|
style_=f"background-color: {color}; width: 100%; height: 100%"
|
|
24
60
|
) as main:
|
|
@@ -60,19 +96,21 @@ def JupyterViz(
|
|
|
60
96
|
play_interval=150,
|
|
61
97
|
seed=None,
|
|
62
98
|
):
|
|
63
|
-
"""
|
|
99
|
+
"""
|
|
100
|
+
Initialize a component to visualize a model.
|
|
101
|
+
|
|
64
102
|
Args:
|
|
65
|
-
model_class:
|
|
66
|
-
model_params:
|
|
67
|
-
measures:
|
|
68
|
-
name:
|
|
69
|
-
agent_portrayal:
|
|
70
|
-
space_drawer:
|
|
103
|
+
model_class: Class of the model to instantiate
|
|
104
|
+
model_params: Parameters for initializing the model
|
|
105
|
+
measures: List of callables or data attributes to plot
|
|
106
|
+
name: Name for display
|
|
107
|
+
agent_portrayal: Options for rendering agents (dictionary)
|
|
108
|
+
space_drawer: Method to render the agent space for
|
|
71
109
|
the model; default implementation is the `SpaceMatplotlib` component;
|
|
72
110
|
simulations with no space to visualize should
|
|
73
111
|
specify `space_drawer=False`
|
|
74
|
-
play_interval:
|
|
75
|
-
seed:
|
|
112
|
+
play_interval: Play interval (default: 150)
|
|
113
|
+
seed: The random seed used to initialize the model
|
|
76
114
|
"""
|
|
77
115
|
if name is None:
|
|
78
116
|
name = model_class.__name__
|
|
@@ -88,6 +126,7 @@ def JupyterViz(
|
|
|
88
126
|
|
|
89
127
|
# 2. Set up Model
|
|
90
128
|
def make_model():
|
|
129
|
+
"""Create a new model instance with current parameters and seed."""
|
|
91
130
|
model = model_class.__new__(
|
|
92
131
|
model_class, **model_parameters, seed=reactive_seed.value
|
|
93
132
|
)
|
|
@@ -106,6 +145,7 @@ def JupyterViz(
|
|
|
106
145
|
)
|
|
107
146
|
|
|
108
147
|
def handle_change_model_params(name: str, value: any):
|
|
148
|
+
"""Update model parameters when user input changes."""
|
|
109
149
|
set_model_parameters({**model_parameters, name: value})
|
|
110
150
|
|
|
111
151
|
# 3. Set up UI
|
|
@@ -115,12 +155,14 @@ def JupyterViz(
|
|
|
115
155
|
|
|
116
156
|
# render layout and plot
|
|
117
157
|
def do_reseed():
|
|
158
|
+
"""Update the random seed for the model."""
|
|
118
159
|
reactive_seed.value = model.random.random()
|
|
119
160
|
|
|
120
161
|
# jupyter
|
|
121
162
|
dependencies = [current_step.value, reactive_seed.value]
|
|
122
163
|
|
|
123
164
|
def render_in_jupyter():
|
|
165
|
+
"""Render the visualization components in Jupyter notebook."""
|
|
124
166
|
with solara.GridFixed(columns=2):
|
|
125
167
|
UserInputs(user_params, on_change=handle_change_model_params)
|
|
126
168
|
ModelController(model, play_interval, current_step, reset_counter)
|
|
@@ -154,6 +196,7 @@ def JupyterViz(
|
|
|
154
196
|
)
|
|
155
197
|
|
|
156
198
|
def render_in_browser():
|
|
199
|
+
"""Render the visualization components in a web browser."""
|
|
157
200
|
# if space drawer is disabled, do not include it
|
|
158
201
|
layout_types = [{"Space": "default"}] if space_drawer else []
|
|
159
202
|
|
|
@@ -205,6 +248,15 @@ def JupyterViz(
|
|
|
205
248
|
|
|
206
249
|
@solara.component
|
|
207
250
|
def ModelController(model, play_interval, current_step, reset_counter):
|
|
251
|
+
"""
|
|
252
|
+
Create controls for model execution (step, play, pause, reset).
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
model: The model being visualized
|
|
256
|
+
play_interval: Interval between steps during play
|
|
257
|
+
current_step: Reactive value for the current step
|
|
258
|
+
reset_counter: Counter to trigger model reset
|
|
259
|
+
"""
|
|
208
260
|
playing = solara.use_reactive(False)
|
|
209
261
|
thread = solara.use_reactive(None)
|
|
210
262
|
# We track the previous step to detect if user resets the model via
|
|
@@ -214,6 +266,7 @@ def ModelController(model, play_interval, current_step, reset_counter):
|
|
|
214
266
|
previous_step = solara.use_reactive(0)
|
|
215
267
|
|
|
216
268
|
def on_value_play(change):
|
|
269
|
+
"""Handle play/pause state changes."""
|
|
217
270
|
if previous_step.value > current_step.value and current_step.value == 0:
|
|
218
271
|
# We add extra checks for current_step.value == 0, just to be sure.
|
|
219
272
|
# We automatically stop the playing if a model is reset.
|
|
@@ -224,31 +277,37 @@ def ModelController(model, play_interval, current_step, reset_counter):
|
|
|
224
277
|
playing.value = False
|
|
225
278
|
|
|
226
279
|
def do_step():
|
|
280
|
+
"""Advance the model by one step."""
|
|
227
281
|
model.step()
|
|
228
282
|
previous_step.value = current_step.value
|
|
229
283
|
current_step.value = model._steps
|
|
230
284
|
|
|
231
285
|
def do_play():
|
|
286
|
+
"""Run the model continuously."""
|
|
232
287
|
model.running = True
|
|
233
288
|
while model.running:
|
|
234
289
|
do_step()
|
|
235
290
|
|
|
236
291
|
def threaded_do_play():
|
|
292
|
+
"""Start a new thread for continuous model execution."""
|
|
237
293
|
if thread is not None and thread.is_alive():
|
|
238
294
|
return
|
|
239
295
|
thread.value = threading.Thread(target=do_play)
|
|
240
296
|
thread.start()
|
|
241
297
|
|
|
242
298
|
def do_pause():
|
|
299
|
+
"""Pause the model execution."""
|
|
243
300
|
if (thread is None) or (not thread.is_alive()):
|
|
244
301
|
return
|
|
245
302
|
model.running = False
|
|
246
303
|
thread.join()
|
|
247
304
|
|
|
248
305
|
def do_reset():
|
|
306
|
+
"""Reset the model."""
|
|
249
307
|
reset_counter.value += 1
|
|
250
308
|
|
|
251
309
|
def do_set_playing(value):
|
|
310
|
+
"""Set the playing state."""
|
|
252
311
|
if current_step.value == 0:
|
|
253
312
|
# This means the model has been recreated, and the step resets to
|
|
254
313
|
# 0. We want to avoid triggering the playing.value = False in the
|
|
@@ -292,6 +351,15 @@ def ModelController(model, play_interval, current_step, reset_counter):
|
|
|
292
351
|
|
|
293
352
|
|
|
294
353
|
def split_model_params(model_params):
|
|
354
|
+
"""
|
|
355
|
+
Split model parameters into user-adjustable and fixed parameters.
|
|
356
|
+
|
|
357
|
+
Args:
|
|
358
|
+
model_params: Dictionary of all model parameters
|
|
359
|
+
|
|
360
|
+
Returns:
|
|
361
|
+
tuple: (user_adjustable_params, fixed_params)
|
|
362
|
+
"""
|
|
295
363
|
model_params_input = {}
|
|
296
364
|
model_params_fixed = {}
|
|
297
365
|
for k, v in model_params.items():
|
|
@@ -303,6 +371,15 @@ def split_model_params(model_params):
|
|
|
303
371
|
|
|
304
372
|
|
|
305
373
|
def check_param_is_fixed(param):
|
|
374
|
+
"""
|
|
375
|
+
Check if a parameter is fixed (not user-adjustable).
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
param: Parameter to check
|
|
379
|
+
|
|
380
|
+
Returns:
|
|
381
|
+
bool: True if parameter is fixed, False otherwise
|
|
382
|
+
"""
|
|
306
383
|
if isinstance(param, Slider):
|
|
307
384
|
return False
|
|
308
385
|
if not isinstance(param, dict):
|
|
@@ -313,14 +390,15 @@ def check_param_is_fixed(param):
|
|
|
313
390
|
|
|
314
391
|
@solara.component
|
|
315
392
|
def UserInputs(user_params, on_change=None):
|
|
316
|
-
"""
|
|
393
|
+
"""
|
|
394
|
+
Initialize user inputs for configurable model parameters.
|
|
317
395
|
Currently supports :class:`solara.SliderInt`, :class:`solara.SliderFloat`,
|
|
318
396
|
:class:`solara.Select`, and :class:`solara.Checkbox`.
|
|
319
397
|
|
|
320
|
-
|
|
321
|
-
user_params:
|
|
398
|
+
Args:
|
|
399
|
+
user_params: Dictionary with options for the input, including label,
|
|
322
400
|
min and max values, and other fields specific to the input type.
|
|
323
|
-
on_change:
|
|
401
|
+
on_change: Function to be called with (name, value) when the value of an input changes.
|
|
324
402
|
"""
|
|
325
403
|
|
|
326
404
|
for name, options in user_params.items():
|
|
@@ -381,6 +459,16 @@ def UserInputs(user_params, on_change=None):
|
|
|
381
459
|
|
|
382
460
|
|
|
383
461
|
def make_text(renderer):
|
|
462
|
+
"""
|
|
463
|
+
Create a function that renders text using Markdown.
|
|
464
|
+
|
|
465
|
+
Args:
|
|
466
|
+
renderer: Function that takes a model and returns a string
|
|
467
|
+
|
|
468
|
+
Returns:
|
|
469
|
+
function: A function that renders the text as Markdown
|
|
470
|
+
"""
|
|
471
|
+
|
|
384
472
|
def function(model):
|
|
385
473
|
solara.Markdown(renderer(model))
|
|
386
474
|
|
|
@@ -388,6 +476,15 @@ def make_text(renderer):
|
|
|
388
476
|
|
|
389
477
|
|
|
390
478
|
def make_initial_grid_layout(layout_types):
|
|
479
|
+
"""
|
|
480
|
+
Create an initial grid layout for visualization components.
|
|
481
|
+
|
|
482
|
+
Args:
|
|
483
|
+
layout_types: List of layout types (Space or Measure)
|
|
484
|
+
|
|
485
|
+
Returns:
|
|
486
|
+
list: Initial grid layout configuration
|
|
487
|
+
"""
|
|
391
488
|
return [
|
|
392
489
|
{
|
|
393
490
|
"i": i,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: Mesa
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0a0
|
|
4
4
|
Summary: Agent-based modeling (ABM) in Python
|
|
5
5
|
Project-URL: homepage, https://github.com/projectmesa/mesa
|
|
6
6
|
Project-URL: repository, https://github.com/projectmesa/mesa
|
|
@@ -14,25 +14,23 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
14
14
|
Classifier: Natural Language :: English
|
|
15
15
|
Classifier: Operating System :: OS Independent
|
|
16
16
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.10
|
|
19
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
20
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
22
20
|
Classifier: Topic :: Scientific/Engineering
|
|
23
21
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
24
22
|
Classifier: Topic :: Scientific/Engineering :: Artificial Life
|
|
25
|
-
Requires-Python: >=3.
|
|
23
|
+
Requires-Python: >=3.10
|
|
26
24
|
Requires-Dist: click
|
|
27
25
|
Requires-Dist: cookiecutter
|
|
28
26
|
Requires-Dist: matplotlib
|
|
29
|
-
Requires-Dist: mesa-viz-tornado>=0.1.3,~=0.1.0
|
|
30
27
|
Requires-Dist: networkx
|
|
31
28
|
Requires-Dist: numpy
|
|
32
29
|
Requires-Dist: pandas
|
|
33
30
|
Requires-Dist: solara
|
|
34
31
|
Requires-Dist: tqdm
|
|
35
32
|
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: coverage; extra == 'dev'
|
|
36
34
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
37
35
|
Requires-Dist: pytest-mock; extra == 'dev'
|
|
38
36
|
Requires-Dist: pytest>=4.6; extra == 'dev'
|
|
@@ -56,8 +54,6 @@ Description-Content-Type: text/markdown
|
|
|
56
54
|
| Meta | [](https://github.com/astral-sh/ruff) [](https://github.com/psf/black) [](https://github.com/pypa/hatch) |
|
|
57
55
|
| Chat | [](https://matrix.to/#/#project-mesa:matrix.org) |
|
|
58
56
|
|
|
59
|
-
*This is the `2.4.x-maintenance` branch. Example models for Mesa 2.x can be found [here](https://github.com/projectmesa/mesa-examples/tree/mesa-2.x/examples).*
|
|
60
|
-
|
|
61
57
|
Mesa allows users to quickly create agent-based models using built-in
|
|
62
58
|
core components (such as spatial grids and agent schedulers) or
|
|
63
59
|
customized implementations; visualize them using a browser-based
|
|
@@ -97,18 +93,15 @@ Or any other (development) branch on this repo or your own fork:
|
|
|
97
93
|
pip install -U -e git+https://github.com/YOUR_FORK/mesa@YOUR_BRANCH#egg=mesa
|
|
98
94
|
```
|
|
99
95
|
|
|
100
|
-
## Resources
|
|
101
96
|
For resources or help on using Mesa, check out the following:
|
|
102
97
|
|
|
103
98
|
- [Intro to Mesa Tutorial](http://mesa.readthedocs.org/en/stable/tutorials/intro_tutorial.html) (An introductory model, the Boltzmann
|
|
104
99
|
Wealth Model, for beginners or those new to Mesa.)
|
|
105
|
-
- [Visualization Tutorial](https://mesa.readthedocs.io/stable/tutorials/visualization_tutorial.html) (An introduction into our Solara visualization)
|
|
106
100
|
- [Complexity Explorer Tutorial](https://www.complexityexplorer.org/courses/172-agent-based-models-with-python-an-introduction-to-mesa) (An advanced-beginner model,
|
|
107
101
|
SugarScape with Traders, with instructional videos)
|
|
108
|
-
- [Mesa Examples](https://github.com/projectmesa/mesa-examples/tree/
|
|
102
|
+
- [Mesa Examples](https://github.com/projectmesa/mesa-examples/tree/main/examples) (A repository of seminal ABMs using Mesa and
|
|
109
103
|
examples of employing specific Mesa Features)
|
|
110
104
|
- [Docs](http://mesa.readthedocs.org/) (Mesa's documentation, API and useful snippets)
|
|
111
|
-
- [Development version docs](https://mesa.readthedocs.io/latest/) (the latest version docs if you're using a pre-release Mesa version)
|
|
112
105
|
- [Discussions](https://github.com/projectmesa/mesa/discussions) (GitHub threaded discussions about Mesa)
|
|
113
106
|
- [Matrix Chat](https://matrix.to/#/#project-mesa:matrix.org) (Chat Forum via Matrix to talk about Mesa)
|
|
114
107
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
mesa/__init__.py,sha256=HulQ0a6D9eQCogbsJEKTSLOt9SGOlPwMq7-DDlbmtaU,618
|
|
2
|
+
mesa/agent.py,sha256=fx_h8RnX5DJCmfJtloIb_fprXXp8bFzC3_RnLOLlOvY,12902
|
|
3
|
+
mesa/batchrunner.py,sha256=Kxi0pe2Zeg40R-J07JhEllkpBmREWb7RHuoTenLYEw0,6055
|
|
4
|
+
mesa/datacollection.py,sha256=CQ2QsW-mkEVbDVTsOkLy8NAQEKeoILdLB0zWS2sxnyk,11444
|
|
5
|
+
mesa/main.py,sha256=7MovfNz88VWNnfXP0kcERB6C3GfkVOh0hb0o32hM9LU,1602
|
|
6
|
+
mesa/model.py,sha256=GqayRWhohSS96kMwHCNGI7XvEkwI8GHS2SRL6SZ9N5E,5810
|
|
7
|
+
mesa/space.py,sha256=9eDEUQBcck8QYWvRn3fDw2zS2bO1Yjc7VjvvrMikzPE,62447
|
|
8
|
+
mesa/time.py,sha256=9gNoyUqYkt_gUPFBMhm38pK87mcntwAZ1lJzxqW3BSA,15211
|
|
9
|
+
mesa/cookiecutter-mesa/cookiecutter.json,sha256=tBSWli39fOWUXGfiDCTKd92M7uKaBIswXbkOdbUufYY,337
|
|
10
|
+
mesa/cookiecutter-mesa/hooks/post_gen_project.py,sha256=8JoXZKIioRYEWJURC0udj8WS3rg0c4So62sOZSGbrMY,294
|
|
11
|
+
mesa/cookiecutter-mesa/{{cookiecutter.snake}}/README.md,sha256=Yji4lGY-NtQSnW-oBj0_Jhs-XhCfZA8R1mBBM_IllGs,80
|
|
12
|
+
mesa/cookiecutter-mesa/{{cookiecutter.snake}}/app.pytemplate,sha256=g0a-i2ihi4RJFGqVQSPqJ0Rbn3WXSh9s8dVwAfPIkCE,586
|
|
13
|
+
mesa/cookiecutter-mesa/{{cookiecutter.snake}}/setup.pytemplate,sha256=UtRpLM_CkeUZRec-Ef_LiO_x7SKaWN11fOiH9T1UmTw,214
|
|
14
|
+
mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/model.pytemplate,sha256=Aml4Z6E1yj7E7DtHNSUqnKNRUdkxG9WWtJyW8fkxCng,1870
|
|
16
|
+
mesa/experimental/__init__.py,sha256=MaSRE9cTFIWwMZsbRKfnCiCBkhvtzJdgWlg3Dls7Unw,67
|
|
17
|
+
mesa/experimental/cell_space/__init__.py,sha256=trFVKf2l5RbkCUyxP09Kox_J3ak2YdM4o3t40Tsjjm4,628
|
|
18
|
+
mesa/experimental/cell_space/cell.py,sha256=AUnvVnXWhdgzr0bLKDRDO9c93v22Zkw6W-tWxhEhGdQ,4578
|
|
19
|
+
mesa/experimental/cell_space/cell_agent.py,sha256=G4u9ht4gW9ns1y2L7pFumF3K4HiP6ROuxwrxHZ-mL1M,1107
|
|
20
|
+
mesa/experimental/cell_space/cell_collection.py,sha256=4FmfDEg9LoFiJ0mF_nC8KUt9fCJ7Q21erjWPeBTQ_lw,2293
|
|
21
|
+
mesa/experimental/cell_space/discrete_space.py,sha256=ta__YojsrrhWL4DgMzUqZpSgbeexKMrA6bxlYPJGfK0,1921
|
|
22
|
+
mesa/experimental/cell_space/grid.py,sha256=gYDExuFBMF3OThUkhbXmolQFKBOqTukcibjfgXicP00,6948
|
|
23
|
+
mesa/experimental/cell_space/network.py,sha256=mAaFHBdd4s9kxUWHbViovLW2-pU2yXH0dtY_vF8sCJg,1179
|
|
24
|
+
mesa/experimental/devs/__init__.py,sha256=CWam15vCj-RD_biMyqv4sJfos1fsL823P7MDEGrbwW8,174
|
|
25
|
+
mesa/experimental/devs/eventlist.py,sha256=AM-gpivXQ889Ewt66T_ai6Yy6ldx0G69Unu1lasSNxI,4907
|
|
26
|
+
mesa/experimental/devs/simulator.py,sha256=0SMC7daIOyL2rYfoQOOTaTOYDos0gLeBUbU1Krd42HA,9557
|
|
27
|
+
mesa/experimental/devs/examples/epstein_civil_violence.py,sha256=KqH9KI-A_BYt7oWi9kaOhTzjrf2pETqzSpAQG8ewud0,9667
|
|
28
|
+
mesa/experimental/devs/examples/wolf_sheep.py,sha256=h5z-eDqMpYeOjrq293N2BcQbs_LDVsgtg9vblXJM7XQ,7697
|
|
29
|
+
mesa/visualization/UserParam.py,sha256=WgnY3Q0padtGqUCaezgYzd6cZ7LziuIQnGKP3DBuHZY,1641
|
|
30
|
+
mesa/visualization/__init__.py,sha256=0utc6SZqru1rhxhBxoFGeQNawLHen5RnILvon12Bd_8,104
|
|
31
|
+
mesa/visualization/jupyter_viz.py,sha256=GKlLADaloVwdl5OQr0bxoXLUHBEozr5tUtZHQLg_Z9c,16987
|
|
32
|
+
mesa/visualization/components/altair.py,sha256=V2CQ-Zr7PeijgWtYBNH3VklGVfrf1ee70XVh0DBBONQ,2366
|
|
33
|
+
mesa/visualization/components/matplotlib.py,sha256=cmW3D2ebDcOd6TiBr_kHcBjhh8NeNEMNsz8eJP8N9sU,4289
|
|
34
|
+
mesa-3.0.0a0.dist-info/METADATA,sha256=kyMeHZK6f-_eUgcMSoWoB-IGV6rWiShgrEvxkd9jCM8,7771
|
|
35
|
+
mesa-3.0.0a0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
36
|
+
mesa-3.0.0a0.dist-info/entry_points.txt,sha256=IOcQtetGF8l4wHpOs_hGb19Rz-FS__BMXOJR10IBPsA,39
|
|
37
|
+
mesa-3.0.0a0.dist-info/licenses/LICENSE,sha256=OGUgret9fRrm8J3pdsPXETIjf0H8puK_Nmy970ZzT78,572
|
|
38
|
+
mesa-3.0.0a0.dist-info/RECORD,,
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Configure visualization elements and instantiate a server
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
from .model import {{ cookiecutter.model }}, {{ cookiecutter.agent }} # noqa
|
|
6
|
-
|
|
7
|
-
import mesa
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def circle_portrayal_example(agent):
|
|
11
|
-
if agent is None:
|
|
12
|
-
return
|
|
13
|
-
|
|
14
|
-
portrayal = {
|
|
15
|
-
"Shape": "circle",
|
|
16
|
-
"Filled": "true",
|
|
17
|
-
"Layer": 0,
|
|
18
|
-
"r": 0.5,
|
|
19
|
-
"Color": "Pink",
|
|
20
|
-
}
|
|
21
|
-
return portrayal
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
canvas_element = mesa.visualization.CanvasGrid(
|
|
25
|
-
circle_portrayal_example, 20, 20, 500, 500
|
|
26
|
-
)
|
|
27
|
-
chart_element = mesa.visualization.ChartModule([{"Label": "{{ cookiecutter.camel }}", "Color": "Pink"}])
|
|
28
|
-
|
|
29
|
-
model_kwargs = {"num_agents": 10, "width": 10, "height": 10}
|
|
30
|
-
|
|
31
|
-
server = mesa.visualization.ModularServer(
|
|
32
|
-
{{cookiecutter.model}},
|
|
33
|
-
[canvas_element, chart_element],
|
|
34
|
-
"{{ cookiecutter.camel }}",
|
|
35
|
-
model_kwargs,
|
|
36
|
-
)
|
mesa/experimental/UserParam.py
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
class UserParam:
|
|
2
|
-
_ERROR_MESSAGE = "Missing or malformed inputs for '{}' Option '{}'"
|
|
3
|
-
|
|
4
|
-
def maybe_raise_error(self, param_type, valid):
|
|
5
|
-
if valid:
|
|
6
|
-
return
|
|
7
|
-
msg = self._ERROR_MESSAGE.format(param_type, self.label)
|
|
8
|
-
raise ValueError(msg)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class Slider(UserParam):
|
|
12
|
-
"""
|
|
13
|
-
A number-based slider input with settable increment.
|
|
14
|
-
|
|
15
|
-
Example:
|
|
16
|
-
|
|
17
|
-
slider_option = Slider("My Slider", value=123, min=10, max=200, step=0.1)
|
|
18
|
-
|
|
19
|
-
Args:
|
|
20
|
-
label: The displayed label in the UI
|
|
21
|
-
value: The initial value of the slider
|
|
22
|
-
min: The minimum possible value of the slider
|
|
23
|
-
max: The maximum possible value of the slider
|
|
24
|
-
step: The step between min and max for a range of possible values
|
|
25
|
-
dtype: either int or float
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
def __init__(
|
|
29
|
-
self,
|
|
30
|
-
label="",
|
|
31
|
-
value=None,
|
|
32
|
-
min=None,
|
|
33
|
-
max=None,
|
|
34
|
-
step=1,
|
|
35
|
-
dtype=None,
|
|
36
|
-
):
|
|
37
|
-
self.label = label
|
|
38
|
-
self.value = value
|
|
39
|
-
self.min = min
|
|
40
|
-
self.max = max
|
|
41
|
-
self.step = step
|
|
42
|
-
|
|
43
|
-
# Validate option type to make sure values are supplied properly
|
|
44
|
-
valid = not (self.value is None or self.min is None or self.max is None)
|
|
45
|
-
self.maybe_raise_error("slider", valid)
|
|
46
|
-
|
|
47
|
-
if dtype is None:
|
|
48
|
-
self.is_float_slider = self._check_values_are_float(value, min, max, step)
|
|
49
|
-
else:
|
|
50
|
-
self.is_float_slider = dtype == float
|
|
51
|
-
|
|
52
|
-
def _check_values_are_float(self, value, min, max, step):
|
|
53
|
-
return any(isinstance(n, float) for n in (value, min, max, step))
|
|
54
|
-
|
|
55
|
-
def get(self, attr):
|
|
56
|
-
return getattr(self, attr)
|
mesa/flat/__init__.py
DELETED
mesa/flat/visualization.py
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
# This collects all of Mesa visualization components under a flat namespace.
|
|
2
|
-
from mesa_viz_tornado.ModularVisualization import * # noqa
|
|
3
|
-
from mesa_viz_tornado.modules import * # noqa
|
|
4
|
-
from mesa_viz_tornado.UserParam import * # noqa
|
|
5
|
-
from mesa_viz_tornado.TextVisualization import * # noqa
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from mesa_viz_tornado.ModularVisualization import * # noqa
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from mesa_viz_tornado.TextVisualization import * # noqa
|
mesa/visualization/modules.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from mesa_viz_tornado.modules import * # noqa
|