Mesa 3.2.0__py3-none-any.whl → 3.3.0__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.

Files changed (40) hide show
  1. mesa/__init__.py +1 -1
  2. mesa/agent.py +3 -3
  3. mesa/datacollection.py +1 -1
  4. mesa/examples/advanced/epstein_civil_violence/app.py +11 -11
  5. mesa/examples/advanced/pd_grid/app.py +10 -11
  6. mesa/examples/advanced/sugarscape_g1mt/app.py +34 -16
  7. mesa/examples/advanced/wolf_sheep/app.py +21 -18
  8. mesa/examples/basic/boid_flockers/app.py +15 -11
  9. mesa/examples/basic/boltzmann_wealth_model/app.py +39 -32
  10. mesa/examples/basic/conways_game_of_life/app.py +13 -16
  11. mesa/examples/basic/schelling/Readme.md +2 -2
  12. mesa/examples/basic/schelling/agents.py +9 -3
  13. mesa/examples/basic/schelling/app.py +50 -3
  14. mesa/examples/basic/schelling/model.py +2 -0
  15. mesa/examples/basic/schelling/resources/blue_happy.png +0 -0
  16. mesa/examples/basic/schelling/resources/blue_unhappy.png +0 -0
  17. mesa/examples/basic/schelling/resources/orange_happy.png +0 -0
  18. mesa/examples/basic/schelling/resources/orange_unhappy.png +0 -0
  19. mesa/examples/basic/virus_on_network/app.py +31 -14
  20. mesa/experimental/continuous_space/continuous_space.py +1 -1
  21. mesa/space.py +4 -1
  22. mesa/visualization/__init__.py +2 -0
  23. mesa/visualization/backends/__init__.py +23 -0
  24. mesa/visualization/backends/abstract_renderer.py +97 -0
  25. mesa/visualization/backends/altair_backend.py +440 -0
  26. mesa/visualization/backends/matplotlib_backend.py +419 -0
  27. mesa/visualization/components/__init__.py +28 -8
  28. mesa/visualization/components/altair_components.py +86 -0
  29. mesa/visualization/components/matplotlib_components.py +4 -2
  30. mesa/visualization/components/portrayal_components.py +120 -0
  31. mesa/visualization/mpl_space_drawing.py +292 -129
  32. mesa/visualization/solara_viz.py +274 -32
  33. mesa/visualization/space_drawers.py +797 -0
  34. mesa/visualization/space_renderer.py +399 -0
  35. {mesa-3.2.0.dist-info → mesa-3.3.0.dist-info}/METADATA +13 -4
  36. {mesa-3.2.0.dist-info → mesa-3.3.0.dist-info}/RECORD +39 -29
  37. mesa/examples/advanced/sugarscape_g1mt/tests.py +0 -69
  38. {mesa-3.2.0.dist-info → mesa-3.3.0.dist-info}/WHEEL +0 -0
  39. {mesa-3.2.0.dist-info → mesa-3.3.0.dist-info}/licenses/LICENSE +0 -0
  40. {mesa-3.2.0.dist-info → mesa-3.3.0.dist-info}/licenses/NOTICE +0 -0
@@ -0,0 +1,399 @@
1
+ """Space rendering module for Mesa visualizations.
2
+
3
+ This module provides functionality to render Mesa model spaces with different
4
+ backends, supporting various space types and visualization components.
5
+ """
6
+
7
+ import contextlib
8
+ import warnings
9
+ from collections.abc import Callable
10
+ from typing import Literal
11
+
12
+ import altair as alt
13
+ import numpy as np
14
+ import pandas as pd
15
+
16
+ import mesa
17
+ from mesa.discrete_space import (
18
+ OrthogonalMooreGrid,
19
+ OrthogonalVonNeumannGrid,
20
+ VoronoiGrid,
21
+ )
22
+ from mesa.space import (
23
+ ContinuousSpace,
24
+ HexMultiGrid,
25
+ HexSingleGrid,
26
+ MultiGrid,
27
+ NetworkGrid,
28
+ SingleGrid,
29
+ _HexGrid,
30
+ )
31
+ from mesa.visualization.backends import AltairBackend, MatplotlibBackend
32
+ from mesa.visualization.space_drawers import (
33
+ ContinuousSpaceDrawer,
34
+ HexSpaceDrawer,
35
+ NetworkSpaceDrawer,
36
+ OrthogonalSpaceDrawer,
37
+ VoronoiSpaceDrawer,
38
+ )
39
+
40
+ OrthogonalGrid = SingleGrid | MultiGrid | OrthogonalMooreGrid | OrthogonalVonNeumannGrid
41
+ HexGrid = HexSingleGrid | HexMultiGrid | mesa.discrete_space.HexGrid
42
+ Network = NetworkGrid | mesa.discrete_space.Network
43
+
44
+
45
+ class SpaceRenderer:
46
+ """Renders Mesa spaces using different visualization backends.
47
+
48
+ Supports multiple space types and backends for flexible visualization
49
+ of agent-based models.
50
+ """
51
+
52
+ def __init__(
53
+ self,
54
+ model: mesa.Model,
55
+ backend: Literal["matplotlib", "altair"] | None = "matplotlib",
56
+ ):
57
+ """Initialize the space renderer.
58
+
59
+ Args:
60
+ model (mesa.Model): The Mesa model to render.
61
+ backend (Literal["matplotlib", "altair"] | None): The visualization backend to use.
62
+ """
63
+ self.space = getattr(model, "grid", getattr(model, "space", None))
64
+
65
+ self.space_drawer = self._get_space_drawer()
66
+ self.space_mesh = None
67
+ self.agent_mesh = None
68
+ self.propertylayer_mesh = None
69
+
70
+ self.post_process_func = None
71
+ # Keep track of whether post-processing has been applied
72
+ # to avoid multiple applications on the same axis.
73
+ self._post_process_applied = False
74
+
75
+ self.backend = backend
76
+
77
+ if backend == "matplotlib":
78
+ self.backend_renderer = MatplotlibBackend(
79
+ self.space_drawer,
80
+ )
81
+ elif backend == "altair":
82
+ self.backend_renderer = AltairBackend(
83
+ self.space_drawer,
84
+ )
85
+ else:
86
+ raise ValueError(f"Unsupported backend: {backend}")
87
+
88
+ self.backend_renderer.initialize_canvas()
89
+
90
+ def _get_space_drawer(self):
91
+ """Get appropriate space drawer based on space type.
92
+
93
+ Returns:
94
+ Space drawer instance for the model's space type.
95
+
96
+ Raises:
97
+ ValueError: If the space type is not supported.
98
+ """
99
+ if isinstance(self.space, HexGrid | _HexGrid):
100
+ return HexSpaceDrawer(self.space)
101
+ elif isinstance(self.space, OrthogonalGrid):
102
+ return OrthogonalSpaceDrawer(self.space)
103
+ elif isinstance(
104
+ self.space,
105
+ ContinuousSpace | mesa.experimental.continuous_space.ContinuousSpace,
106
+ ):
107
+ return ContinuousSpaceDrawer(self.space)
108
+ elif isinstance(self.space, VoronoiGrid):
109
+ return VoronoiSpaceDrawer(self.space)
110
+ elif isinstance(self.space, Network):
111
+ return NetworkSpaceDrawer(self.space)
112
+ raise ValueError(
113
+ f"Unsupported space type: {type(self.space).__name__}. "
114
+ "Supported types are OrthogonalGrid, HexGrid, ContinuousSpace, VoronoiGrid, and Network."
115
+ )
116
+
117
+ def _map_coordinates(self, arguments):
118
+ """Map agent coordinates to appropriate space coordinates.
119
+
120
+ Args:
121
+ arguments (dict): Dictionary containing agent data with coordinates.
122
+
123
+ Returns:
124
+ dict: Dictionary with mapped coordinates appropriate for the space type.
125
+ """
126
+ mapped_arguments = arguments.copy()
127
+
128
+ if isinstance(self.space, OrthogonalGrid | VoronoiGrid | ContinuousSpace):
129
+ # Use the coordinates directly for Orthogonal grids, Voronoi grids and Continuous spaces
130
+ mapped_arguments["loc"] = arguments["loc"].astype(float)
131
+
132
+ elif isinstance(self.space, HexGrid):
133
+ # Map rectangular coordinates to hexagonal grid coordinates
134
+ loc = arguments["loc"].astype(float)
135
+ if loc.size > 0:
136
+ # Calculate hexagon centers
137
+ loc[:, 0] = loc[:, 0] * self.space_drawer.x_spacing + (
138
+ (loc[:, 1] - 1) % 2
139
+ ) * (self.space_drawer.x_spacing / 2)
140
+ loc[:, 1] = loc[:, 1] * self.space_drawer.y_spacing
141
+ mapped_arguments["loc"] = loc
142
+
143
+ elif isinstance(self.space, Network):
144
+ # Map coordinates for Network spaces
145
+ loc = arguments["loc"].astype(float)
146
+ pos = np.asarray(list(self.space_drawer.pos.values()))
147
+ # For network only both x and y contains the correct coordinates
148
+ # use one of them
149
+ x = loc[:, 0]
150
+ if x is None:
151
+ x = loc[:, 1]
152
+
153
+ # Ensure x is an integer index for the position mapping
154
+ x = x.astype(int)
155
+
156
+ # FIXME: Find better way to handle this case
157
+ # x updates before pos can, therefore gives us index error that
158
+ # needs to be ignored.
159
+ with contextlib.suppress(IndexError):
160
+ mapped_arguments["loc"] = pos[x]
161
+
162
+ return mapped_arguments
163
+
164
+ def draw_structure(self, **kwargs):
165
+ """Draw the space structure.
166
+
167
+ Args:
168
+ **kwargs: Additional keyword arguments for the drawing function.
169
+ Checkout respective `SpaceDrawer` class on details how to pass **kwargs.
170
+
171
+ Returns:
172
+ The visual representation of the space structure.
173
+ """
174
+ # Store space_kwargs for internal use
175
+ self.space_kwargs = kwargs
176
+
177
+ self.space_mesh = self.backend_renderer.draw_structure(**self.space_kwargs)
178
+ return self.space_mesh
179
+
180
+ def draw_agents(self, agent_portrayal: Callable, **kwargs):
181
+ """Draw agents on the space.
182
+
183
+ Args:
184
+ agent_portrayal (Callable): Function that takes an agent and returns AgentPortrayalStyle.
185
+ **kwargs: Additional keyword arguments for the drawing function.
186
+ Checkout respective `SpaceDrawer` class on details how to pass **kwargs.
187
+
188
+ Returns:
189
+ The visual representation of the agents.
190
+ """
191
+ # Store data for internal use
192
+ self.agent_portrayal = agent_portrayal
193
+ self.agent_kwargs = kwargs
194
+
195
+ # Prepare data for agent plotting
196
+ arguments = self.backend_renderer.collect_agent_data(
197
+ self.space, agent_portrayal, default_size=self.space_drawer.s_default
198
+ )
199
+ arguments = self._map_coordinates(arguments)
200
+
201
+ self.agent_mesh = self.backend_renderer.draw_agents(
202
+ arguments, **self.agent_kwargs
203
+ )
204
+ return self.agent_mesh
205
+
206
+ def draw_propertylayer(self, propertylayer_portrayal: Callable | dict):
207
+ """Draw property layers on the space.
208
+
209
+ Args:
210
+ propertylayer_portrayal (Callable | dict): Function that returns PropertyLayerStyle
211
+ or dict with portrayal parameters.
212
+
213
+ Returns:
214
+ The visual representation of the property layers.
215
+
216
+ Raises:
217
+ Exception: If no property layers are found on the space.
218
+ """
219
+ # Import here to avoid circular imports
220
+ from mesa.visualization.components import PropertyLayerStyle # noqa: PLC0415
221
+
222
+ def _dict_to_callable(portrayal_dict):
223
+ """Convert legacy dict portrayal to callable.
224
+
225
+ Args:
226
+ portrayal_dict (dict): Dictionary with portrayal parameters.
227
+
228
+ Returns:
229
+ Callable: Function that returns PropertyLayerStyle.
230
+ """
231
+
232
+ def style_callable(layer_object):
233
+ layer_name = layer_object.name
234
+ params = portrayal_dict.get(layer_name)
235
+
236
+ warnings.warn(
237
+ "Dict propertylayer_portrayal is deprecated. "
238
+ "Use a callable returning PropertyLayerStyle instead.",
239
+ PendingDeprecationWarning,
240
+ stacklevel=2,
241
+ )
242
+
243
+ if params is None:
244
+ return None
245
+
246
+ return PropertyLayerStyle(
247
+ color=params.get("color"),
248
+ colormap=params.get("colormap"),
249
+ alpha=params.get("alpha", PropertyLayerStyle.alpha),
250
+ vmin=params.get("vmin"),
251
+ vmax=params.get("vmax"),
252
+ colorbar=params.get("colorbar", PropertyLayerStyle.colorbar),
253
+ )
254
+
255
+ return style_callable
256
+
257
+ # Get property layers
258
+ try:
259
+ # old style spaces
260
+ property_layers = self.space.properties
261
+ except AttributeError:
262
+ # new style spaces
263
+ property_layers = self.space._mesa_property_layers
264
+
265
+ # Convert portrayal to callable if needed
266
+ if isinstance(propertylayer_portrayal, dict):
267
+ self.propertylayer_portrayal = _dict_to_callable(propertylayer_portrayal)
268
+ else:
269
+ self.propertylayer_portrayal = propertylayer_portrayal
270
+
271
+ number_of_propertylayers = sum(
272
+ [1 for layer in property_layers if layer != "empty"]
273
+ )
274
+ if number_of_propertylayers < 1:
275
+ raise Exception("No property layers were found on the space.")
276
+
277
+ self.propertylayer_mesh = self.backend_renderer.draw_propertylayer(
278
+ self.space, property_layers, self.propertylayer_portrayal
279
+ )
280
+ return self.propertylayer_mesh
281
+
282
+ def render(
283
+ self,
284
+ agent_portrayal: Callable | None = None,
285
+ propertylayer_portrayal: Callable | dict | None = None,
286
+ post_process: Callable | None = None,
287
+ **kwargs,
288
+ ):
289
+ """Render the complete space with structure, agents, and property layers.
290
+
291
+ It is an all-in-one method that draws everything required therefore eliminates
292
+ the need of calling each method separately, but has a drawback, if want to pass
293
+ kwargs to customize the drawing, they have to be broken into
294
+ space_kwargs and agent_kwargs.
295
+
296
+ Args:
297
+ agent_portrayal (Callable | None): Function that returns AgentPortrayalStyle.
298
+ If None, agents won't be drawn.
299
+ propertylayer_portrayal (Callable | dict | None): Function that returns
300
+ PropertyLayerStyle or dict with portrayal parameters. If None,
301
+ property layers won't be drawn.
302
+ post_process (Callable | None): Function to apply post-processing to the canvas.
303
+ **kwargs: Additional keyword arguments for drawing functions.
304
+ * ``space_kwargs`` (dict): Arguments for ``draw_structure()``.
305
+ * ``agent_kwargs`` (dict): Arguments for ``draw_agents()``.
306
+ """
307
+ space_kwargs = kwargs.pop("space_kwargs", {})
308
+ agent_kwargs = kwargs.pop("agent_kwargs", {})
309
+ if self.space_mesh is None:
310
+ self.draw_structure(**space_kwargs)
311
+ if self.agent_mesh is None and agent_portrayal is not None:
312
+ self.draw_agents(agent_portrayal, **agent_kwargs)
313
+ if self.propertylayer_mesh is None and propertylayer_portrayal is not None:
314
+ self.draw_propertylayer(propertylayer_portrayal)
315
+
316
+ self.post_process_func = post_process
317
+ return self
318
+
319
+ @property
320
+ def canvas(self):
321
+ """Get the current canvas object.
322
+
323
+ Returns:
324
+ The backend-specific canvas object.
325
+ """
326
+ if self.backend == "matplotlib":
327
+ ax = self.backend_renderer.ax
328
+ if ax is None:
329
+ self.backend_renderer.initialize_canvas()
330
+ return ax
331
+
332
+ elif self.backend == "altair":
333
+ structure = self.space_mesh if self.space_mesh else None
334
+ agents = self.agent_mesh if self.agent_mesh else None
335
+ prop_base, prop_cbar = self.propertylayer_mesh or (None, None)
336
+
337
+ if self.space_mesh:
338
+ structure = self.draw_structure(**self.space_kwargs)
339
+ if self.agent_mesh:
340
+ agents = self.draw_agents(self.agent_portrayal, **self.agent_kwargs)
341
+ if self.propertylayer_mesh:
342
+ prop_base, prop_cbar = self.draw_propertylayer(
343
+ self.propertylayer_portrayal
344
+ )
345
+
346
+ spatial_charts_list = [
347
+ chart for chart in [structure, prop_base, agents] if chart
348
+ ]
349
+
350
+ main_spatial = None
351
+ if spatial_charts_list:
352
+ main_spatial = (
353
+ spatial_charts_list[0]
354
+ if len(spatial_charts_list) == 1
355
+ else alt.layer(*spatial_charts_list)
356
+ )
357
+
358
+ # Determine final chart by combining with color bar if present
359
+ final_chart = None
360
+ if main_spatial and prop_cbar:
361
+ final_chart = alt.vconcat(main_spatial, prop_cbar).configure_view(
362
+ stroke=None
363
+ )
364
+ elif main_spatial: # Only main_spatial, no prop_cbar
365
+ final_chart = main_spatial
366
+ elif prop_cbar: # Only prop_cbar, no main_spatial
367
+ final_chart = prop_cbar
368
+ final_chart = final_chart.configure_view(grid=False)
369
+
370
+ if final_chart is None:
371
+ # If no charts are available, return an empty chart
372
+ final_chart = (
373
+ alt.Chart(pd.DataFrame())
374
+ .mark_point()
375
+ .properties(width=450, height=350)
376
+ )
377
+
378
+ final_chart = final_chart.configure_view(stroke="black", strokeWidth=1.5)
379
+
380
+ return final_chart
381
+
382
+ @property
383
+ def post_process(self):
384
+ """Get the current post-processing function.
385
+
386
+ Returns:
387
+ Callable | None: The post-processing function, or None if not set.
388
+ """
389
+ return self.post_process_func
390
+
391
+ @post_process.setter
392
+ def post_process(self, func: Callable | None):
393
+ """Set the post-processing function.
394
+
395
+ Args:
396
+ func (Callable | None): Function to apply post-processing to the canvas.
397
+ Should accept the canvas object as its first argument.
398
+ """
399
+ self.post_process_func = func
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Mesa
3
- Version: 3.2.0
3
+ Version: 3.3.0
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
@@ -24,19 +24,24 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Life
24
24
  Requires-Python: >=3.11
25
25
  Requires-Dist: numpy
26
26
  Requires-Dist: pandas
27
+ Requires-Dist: pythran>=0.17.0; sys_platform == 'darwin'
27
28
  Requires-Dist: scipy
28
29
  Requires-Dist: tqdm
29
30
  Provides-Extra: all
30
31
  Requires-Dist: altair; extra == 'all'
31
32
  Requires-Dist: ipython; extra == 'all'
33
+ Requires-Dist: ipython>=9.2.0; extra == 'all'
32
34
  Requires-Dist: matplotlib; extra == 'all'
33
35
  Requires-Dist: myst-nb; extra == 'all'
34
36
  Requires-Dist: myst-parser; extra == 'all'
35
37
  Requires-Dist: networkx; extra == 'all'
38
+ Requires-Dist: playwright; extra == 'all'
36
39
  Requires-Dist: pydata-sphinx-theme; extra == 'all'
37
40
  Requires-Dist: pytest; extra == 'all'
38
41
  Requires-Dist: pytest-cov; extra == 'all'
42
+ Requires-Dist: pytest-ipywidgets; extra == 'all'
39
43
  Requires-Dist: pytest-mock; extra == 'all'
44
+ Requires-Dist: pytest-playwright; extra == 'all'
40
45
  Requires-Dist: ruff; extra == 'all'
41
46
  Requires-Dist: scipy; extra == 'all'
42
47
  Requires-Dist: seaborn; extra == 'all'
@@ -45,11 +50,15 @@ Requires-Dist: sphinx; extra == 'all'
45
50
  Requires-Dist: sphinx-copybutton; extra == 'all'
46
51
  Provides-Extra: dev
47
52
  Requires-Dist: altair; extra == 'dev'
53
+ Requires-Dist: ipython>=9.2.0; extra == 'dev'
48
54
  Requires-Dist: matplotlib; extra == 'dev'
49
55
  Requires-Dist: networkx; extra == 'dev'
56
+ Requires-Dist: playwright; extra == 'dev'
50
57
  Requires-Dist: pytest; extra == 'dev'
51
58
  Requires-Dist: pytest-cov; extra == 'dev'
59
+ Requires-Dist: pytest-ipywidgets; extra == 'dev'
52
60
  Requires-Dist: pytest-mock; extra == 'dev'
61
+ Requires-Dist: pytest-playwright; extra == 'dev'
53
62
  Requires-Dist: ruff; extra == 'dev'
54
63
  Requires-Dist: solara; extra == 'dev'
55
64
  Requires-Dist: sphinx; extra == 'dev'
@@ -125,13 +134,13 @@ pip install -U mesa
125
134
  Starting with Mesa 3.0, we don't install all our dependencies anymore by default.
126
135
  ```bash
127
136
  # You can customize the additional dependencies you need, if you want. Available are:
128
- pip install -U mesa[network,viz]
137
+ pip install -U "mesa[network,viz]"
129
138
 
130
139
  # This is equivalent to our recommended dependencies:
131
- pip install -U mesa[rec]
140
+ pip install -U "mesa[rec]"
132
141
 
133
142
  # To install all, including developer, dependencies:
134
- pip install -U mesa[all]
143
+ pip install -U "mesa[all]"
135
144
  ```
136
145
 
137
146
  You can also use `pip` to install the latest GitHub version:
@@ -1,10 +1,10 @@
1
- mesa/__init__.py,sha256=9HiqFLLUwxZzkQCGvh20H3HSVBaJGB8CVC3-SHYMaEA,678
2
- mesa/agent.py,sha256=7WOqjzlLh_Lkmp_-sFnUGbRD69AZpAharCINfIo66Ow,26684
1
+ mesa/__init__.py,sha256=h25vcSmnMDIvmR2LQL6urke1lrEXpiH-33STC8sXKKY,678
2
+ mesa/agent.py,sha256=OC1OiZoIe4jOyQmx__ijXSr82RmekAkJWihcrv4tEf0,26648
3
3
  mesa/batchrunner.py,sha256=ZeBOQw6-SLnECMUyKSRThh7vecP0DV6F6fGGk8UAboA,8041
4
- mesa/datacollection.py,sha256=vxW0KEmx6BHMM6SnKrRJJr7Eb_siGLyofwuyN8pSWXg,18483
4
+ mesa/datacollection.py,sha256=yZhFeQbwIuncIJ5O3mQB69TS2boqncAM-e0nlUxO2X4,18500
5
5
  mesa/mesa_logging.py,sha256=PEDqUaQ2Y4bkYBkrHVkGT0sF86gUdbSH1T3vCg3qQeE,4949
6
6
  mesa/model.py,sha256=8QZoE8Dy-S7MGznhoeHHT1S8VeUh-UbzcBroJqlXkRY,8365
7
- mesa/space.py,sha256=g57TiwmMCRZLwDqgaHzQfSjF1wNE6oNi4rUjzeQ9E6g,63792
7
+ mesa/space.py,sha256=A3MDPhjh-0CUQavFGkspfRGA2QQ_rgTuAPvDvHGSVKs,63939
8
8
  mesa/discrete_space/__init__.py,sha256=wXVr3eUpJAK-Y9DRlsQxhnQAxWLsrA7X6X9QhukDyTI,1672
9
9
  mesa/discrete_space/cell.py,sha256=lok80RMnby09pxbJA631v14XmrfObwxfpw8EOkcwzao,7222
10
10
  mesa/discrete_space/cell_agent.py,sha256=jSGP0xLVgdAx434piwQ9cQqUnPQSlFtJkiDibPWKXe0,4253
@@ -26,59 +26,62 @@ mesa/examples/advanced/epstein_civil_violence/Epstein Civil Violence.ipynb,sha25
26
26
  mesa/examples/advanced/epstein_civil_violence/Readme.md,sha256=RXuGIZAibz3KVkP51PGjwzcRx2R9Ettmh3qbDTPqDcg,1735
27
27
  mesa/examples/advanced/epstein_civil_violence/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  mesa/examples/advanced/epstein_civil_violence/agents.py,sha256=SMYKkKhNlMCXk-gmeakesxstqB-jpY44FtS8CiMl0l8,5854
29
- mesa/examples/advanced/epstein_civil_violence/app.py,sha256=fFlPijAUDLs_WfROGIlUXRakkkfbWnytcXFTAzdRplU,1890
29
+ mesa/examples/advanced/epstein_civil_violence/app.py,sha256=8uRRzNg7UY0ST1f_K69B9YpLonqmiUG1r6UsK-KHPSM,1991
30
30
  mesa/examples/advanced/epstein_civil_violence/model.py,sha256=_ds6Wrq2Zf66VSxamTN5gK8A3itHU5DEVcydA--hlkY,3909
31
31
  mesa/examples/advanced/pd_grid/Readme.md,sha256=weEQe1qZBKUYBj3J3WyGbRHa5Ia1zje18SFctZm3esE,2242
32
32
  mesa/examples/advanced/pd_grid/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
33
  mesa/examples/advanced/pd_grid/agents.py,sha256=giX63EUq3TzJt916dglTSMsdzkIdtyOmwSoj2ynUQ2c,1743
34
34
  mesa/examples/advanced/pd_grid/analysis.ipynb,sha256=TTSY7mZlIYPjPjpW7cxr7Gzpo-NKKEBpXX4_f0V6NfI,5432
35
- mesa/examples/advanced/pd_grid/app.py,sha256=-_fTP7f_oITKHt7dDVJou7Oa7u7v_C4Ml5yw7D1sbx8,1457
35
+ mesa/examples/advanced/pd_grid/app.py,sha256=LQkXW0zsiTuvSQRK0RCABkxfhB04KFV_dYB3gjbbCy4,1556
36
36
  mesa/examples/advanced/pd_grid/model.py,sha256=2YrTVNVThIf0FH1vKbYef0IYeJiR8Ws6eepsH6UjMLQ,2282
37
37
  mesa/examples/advanced/sugarscape_g1mt/Readme.md,sha256=_q52DMprCQGELsPCJ_jAJ6cFHBc8sE7L8WIa4a3LQPs,3535
38
38
  mesa/examples/advanced/sugarscape_g1mt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
39
  mesa/examples/advanced/sugarscape_g1mt/agents.py,sha256=foix7_00fFop6GLl5uEu1_bmeQ5oH04Fcc9-E06WWkk,8457
40
- mesa/examples/advanced/sugarscape_g1mt/app.py,sha256=fg8ZXBoc4tPI9AfOLF0fgMk3Ey4H8xZu6tUaTwDp3Nk,1952
40
+ mesa/examples/advanced/sugarscape_g1mt/app.py,sha256=CFfM75mcroo16Tt1-tROUOwANNYj9lloLMFLI_B0Pts,2518
41
41
  mesa/examples/advanced/sugarscape_g1mt/model.py,sha256=VwHaLuqrX8g6XP3wHw16Opu5vaW-kyL31pe7Mja-HvQ,5745
42
42
  mesa/examples/advanced/sugarscape_g1mt/sugar-map.txt,sha256=zZtGYciBPT4miZVnbVuoQ5TugTmGrbDWV9yb5KH6tnU,5000
43
- mesa/examples/advanced/sugarscape_g1mt/tests.py,sha256=UNahmZTgLquSqmoi_9GcE3JP0qBHjkrHFZ15NMm0ce8,2517
44
43
  mesa/examples/advanced/wolf_sheep/Readme.md,sha256=oLJSJ1o7WnExDWts8CRKyxVOMeCcp8rGZzvjufpnKZc,2736
45
44
  mesa/examples/advanced/wolf_sheep/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
45
  mesa/examples/advanced/wolf_sheep/agents.py,sha256=kqW8ITdFHtkMqF5auHoP0dHUbXk-rSMt4XI340NZ5Qg,5081
47
- mesa/examples/advanced/wolf_sheep/app.py,sha256=MEoQzjSvXJC0ua_4okUZOucL0UnBfWRZ42ij4iQVMp4,2544
46
+ mesa/examples/advanced/wolf_sheep/app.py,sha256=VCWb9OwZjqHsTOJ6BZxnaxgmbe01yhV6j6BruHtOO98,2584
48
47
  mesa/examples/advanced/wolf_sheep/model.py,sha256=mHmn5r9EdRtoOGSbubcKtlSBClKmjDIri8uhcokIeBE,4558
49
48
  mesa/examples/basic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
49
  mesa/examples/basic/boid_flockers/Readme.md,sha256=z4p0KZmVpH0JK2M-xnAZM7LSoRdjjR7qGe1OPOq2BzQ,873
51
50
  mesa/examples/basic/boid_flockers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
51
  mesa/examples/basic/boid_flockers/agents.py,sha256=oA0A0NilTHi0XYouYaNcMSmpKDdNYPwfS96FNqRuTUI,3309
53
- mesa/examples/basic/boid_flockers/app.py,sha256=9Cf6f2Ctjz0yWYQHCKE2owBOmnIuXqkVkLIJz6hqGCc,1861
52
+ mesa/examples/basic/boid_flockers/app.py,sha256=QKmIN0BIr_AzV0EwW-4sBUgJSQvGuXndY7FCJV4wDBU,1964
54
53
  mesa/examples/basic/boid_flockers/model.py,sha256=RQh9GfsSPvshUQedlmEEjk1dJHuyL8o4VWiAamgH1EU,3551
55
54
  mesa/examples/basic/boltzmann_wealth_model/Readme.md,sha256=tif1-GDqTGkSAYAYgMf3D3nxT3kYeZ3gCLPvuivQxsI,1956
56
55
  mesa/examples/basic/boltzmann_wealth_model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
56
  mesa/examples/basic/boltzmann_wealth_model/agents.py,sha256=GF4mNEjqLS4Vg4vtdeDAetby_t69J-LcFhtQIMOBDNU,1330
58
- mesa/examples/basic/boltzmann_wealth_model/app.py,sha256=GwyNQvwu0S5l7ASRTF70xE9ozjhtT1xAetWGlQmNtDk,2231
57
+ mesa/examples/basic/boltzmann_wealth_model/app.py,sha256=ooOyJO27R0ISWWAhUJB98DNbHaE4yY9KncoMVy8FKHg,2442
59
58
  mesa/examples/basic/boltzmann_wealth_model/model.py,sha256=9d-x5Y2T49R4Pt1u7lY63Z0y8impZ2f47_ahrxohvaY,2828
60
59
  mesa/examples/basic/boltzmann_wealth_model/st_app.py,sha256=PQ65LkYPXn-lx4lCfXuFJmzcmAfVB3oEEdIyuq9a7iU,3454
61
60
  mesa/examples/basic/conways_game_of_life/Readme.md,sha256=SylexP0Owrq1n_v5mJJyqs3wFeKtOMB0pLh0oLDOcV8,1256
62
61
  mesa/examples/basic/conways_game_of_life/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
62
  mesa/examples/basic/conways_game_of_life/agents.py,sha256=pByQeucyW5UDBnl90xbRGJJNJHpM8NLuqSmft5AkVN0,1766
64
- mesa/examples/basic/conways_game_of_life/app.py,sha256=HPzss2X3ntTOgdmg0C0EWw3lmAF7WiN9MZEgGdLW-xU,1997
63
+ mesa/examples/basic/conways_game_of_life/app.py,sha256=tt1W_RVHu_erojvOSdtyNsVLyW8qXgJFU7F1As3xVwc,1843
65
64
  mesa/examples/basic/conways_game_of_life/model.py,sha256=GGHg8Qni1R4RGQrfvJcsqG6btNTuQhCWOwS_9crU6tc,1269
66
65
  mesa/examples/basic/conways_game_of_life/st_app.py,sha256=9qz3o0pOuvLZR-_aPPVHN-RIwFSNzvwWWfxCaD2K5cs,2402
67
- mesa/examples/basic/schelling/Readme.md,sha256=LB1O3unI0a4fr2cOl3umnjeqozMfXQEVBsB45GoK1u8,1877
66
+ mesa/examples/basic/schelling/Readme.md,sha256=7VUHfl58BvE08XkqprNPNwHyOhyturKnt2kquizXFzM,1883
68
67
  mesa/examples/basic/schelling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
- mesa/examples/basic/schelling/agents.py,sha256=jyMzafsAhOTYOfl3rZgasYLhxW3YEHv3oOIh9Re3LmU,1517
68
+ mesa/examples/basic/schelling/agents.py,sha256=WQbyTT4nlnQvkNHTs4ynlTvSKeQ2EvfW7JcPUf-R5Z0,1669
70
69
  mesa/examples/basic/schelling/analysis.ipynb,sha256=UMDoumvBFhZilwJhxl5Mou2bmDDqxguK5RdnoY2gkNc,5910
71
- mesa/examples/basic/schelling/app.py,sha256=eqgqCu6_6jk1RrmT82e_AoEDMvy8eZ0OJnnlITpiBXQ,1067
72
- mesa/examples/basic/schelling/model.py,sha256=dUfQ4bG-nqvYPSUcLNSI7LOTfs8IxTbVi_Clj8y2rS8,2712
70
+ mesa/examples/basic/schelling/app.py,sha256=97RpHp2BTdJdJzP-f6WRHo9k7jxBkCBQp5nKC8nNasU,2523
71
+ mesa/examples/basic/schelling/model.py,sha256=NFXvFjAQ-0rEwsMI0UWmL3WgMm071Yg0YOxnNQQA0sc,2790
72
+ mesa/examples/basic/schelling/resources/blue_happy.png,sha256=5x-_Klytq-wui1-xtgWxXTIkJQ0IwZ5pLtiG7g-RSbk,4053
73
+ mesa/examples/basic/schelling/resources/blue_unhappy.png,sha256=cfD4Rmk-B6-4XDJtjo4c1pwEoKmlZ1O95ZdE7TNa9q4,4054
74
+ mesa/examples/basic/schelling/resources/orange_happy.png,sha256=6P-W83hxOxrDfbTzsZUdFrqRQQp9k8qcTCSNJ4XQyFM,3406
75
+ mesa/examples/basic/schelling/resources/orange_unhappy.png,sha256=amITDukQoQIO4vEyEQP96UIGQa_9dYWiraYsz8TWvHY,3409
73
76
  mesa/examples/basic/virus_on_network/Readme.md,sha256=h3yGmF9Jl7rCuRGnXJoPqxQPs9Nr-KCMIGs3l8JYQG8,2197
74
77
  mesa/examples/basic/virus_on_network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
78
  mesa/examples/basic/virus_on_network/agents.py,sha256=yVPZCiKI53qXlsUus3vdNZ39IG0cLoY2wQXeYZHiahs,1814
76
- mesa/examples/basic/virus_on_network/app.py,sha256=8I8VWQ7pBcOaNGyLDEO4IbNSTRy161-eWg-iEUVQ3-I,2553
79
+ mesa/examples/basic/virus_on_network/app.py,sha256=njeBwy-_2j-tw8Yjfqm5fXyZHDm8HsEY4NlOCLKLk08,3069
77
80
  mesa/examples/basic/virus_on_network/model.py,sha256=sljdQlTPeUCbmWSxnCJJv706lN3uVMF8pS1gAMNHreM,2543
78
81
  mesa/experimental/__init__.py,sha256=9q6lv_NDYoWuKBzBzMdbisdxvzA-T5L6xT8quSArNT4,945
79
82
  mesa/experimental/cell_space/__init__.py,sha256=IOXd0RcJP34kaHvEHv_AeN7PGpvoYPpaZYsx3Mz8dNo,1872
80
83
  mesa/experimental/continuous_space/__init__.py,sha256=JkCkL4zZpe8c0GHqw4huM2-uoGOYqrCyt7J1M454kFA,269
81
- mesa/experimental/continuous_space/continuous_space.py,sha256=UcD-nsi5oEAJzf8ZI7BU26FYn6DdJzsW-dgXqaZIrQk,9530
84
+ mesa/experimental/continuous_space/continuous_space.py,sha256=IFsX3iZ3GTyHmfIqjtEyi7H9oLN7NkX4QaqmNl_JhQc,9531
82
85
  mesa/experimental/continuous_space/continuous_space_agents.py,sha256=859ypIiWMgjknTsER0i8Y6aCWjMpw6MC5cfoKa6l_iA,3044
83
86
  mesa/experimental/devs/__init__.py,sha256=wkDrpqQ3qHGqrsOSTD-UOj-qOw0oFgnCw_ZXr9xFs90,1200
84
87
  mesa/experimental/devs/eventlist.py,sha256=6igPkHJt-syLcdpFV14_n6HGej2F1cM9giDQo85fHPw,7217
@@ -89,17 +92,24 @@ mesa/experimental/mesa_signals/observable_collections.py,sha256=rHEj6BYxLHFFGzSd
89
92
  mesa/experimental/mesa_signals/signals_util.py,sha256=fmq_FsIxsIvGjtmc4A9TGdBUtdliMHhEOpjRXivRDjA,1618
90
93
  mesa/experimental/meta_agents/__init__.py,sha256=UpX_1WpmXtg4iKdPTcPVViCt1H9fRydA-l3a6i4KR1w,949
91
94
  mesa/experimental/meta_agents/meta_agent.py,sha256=v9a09hU3kgKQdgjk5v5DDOaRCqEh_A8Xhzu9V185kZU,14801
92
- mesa/visualization/__init__.py,sha256=h7YZnBUNrgiK5KbIikPIdQgn6KusmgiDh7tMql8Q39Y,730
95
+ mesa/visualization/__init__.py,sha256=qt05BmHoTWWKdvdSOC7u2JSpJnK0RX9Eq9axO6K2pqU,793
93
96
  mesa/visualization/command_console.py,sha256=-sVNYdXxmc5diQyqfFHUByzVSOpP3eoPcdLL2J6gwD4,17086
94
- mesa/visualization/mpl_space_drawing.py,sha256=axIaq7MTaYIb_-ME2z5TbXufREl9jgFLebZSredyfwA,22956
95
- mesa/visualization/solara_viz.py,sha256=coG5o0A5iCOBIqzsrlUG_S2rYrTcOYubESzj4zcW-ro,26274
97
+ mesa/visualization/mpl_space_drawing.py,sha256=_s8YW0cQdcH3wt7o8mnmP7g6LizJB02zlveiGv74_UA,30135
98
+ mesa/visualization/solara_viz.py,sha256=X9pL-HxzHj8dd4OnjCQOKO2RtK9LiYLinRKQ--6uEOg,35056
99
+ mesa/visualization/space_drawers.py,sha256=B7LwovR7v6tXDIIasS_rjduvXFUkeMO6ZidunLWmhVs,26755
100
+ mesa/visualization/space_renderer.py,sha256=FDFDfWP-3WuXIbdZ8CNmAIXr9Vd-La8_PBjF3-_YmOY,14602
96
101
  mesa/visualization/user_param.py,sha256=Dl2WOwLYLf0pfLpabCZtIdFRyKZrK6Qtc3utZx5GPYg,2139
97
102
  mesa/visualization/utils.py,sha256=lJHgRKF5BHLf72Tw3YpwyiWuRoIimaTKQ7xBCw_Rx3A,146
98
- mesa/visualization/components/__init__.py,sha256=Bq3nrPikcaIo9BSs0O3zptWVLlUmAkLo3s0mEmpH1RE,3022
99
- mesa/visualization/components/altair_components.py,sha256=cSce9_QNaJ5EF6sZ8tu2cZ4NIczocKfjdRCxiC8w0fY,16164
100
- mesa/visualization/components/matplotlib_components.py,sha256=xQETaFyHIfmL_9JwrLIgubuIQ7-pp7TMoXT1WMmozus,5441
101
- mesa-3.2.0.dist-info/METADATA,sha256=cpk4OAHWsBqmvJeeHOPy5W1-hy3PqmcE8khaU5af4EA,10700
102
- mesa-3.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
103
- mesa-3.2.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
104
- mesa-3.2.0.dist-info/licenses/NOTICE,sha256=GbsWoK0QWv1JyZ_xer2s-jNilv0RtWl-0UrtlJANHPg,578
105
- mesa-3.2.0.dist-info/RECORD,,
103
+ mesa/visualization/backends/__init__.py,sha256=U37F-zfULEQONawWNbsHMozEvWVWSJCJyhXTVRtap6c,590
104
+ mesa/visualization/backends/abstract_renderer.py,sha256=ckNqGiloS0KMrau-a7o0I1FZ1DcCqG1GedJU11lA7Oc,3216
105
+ mesa/visualization/backends/altair_backend.py,sha256=7lyTYR_at-BIIswm8Uqt77O_5DRrq0zV3TNHSEZHMW4,16031
106
+ mesa/visualization/backends/matplotlib_backend.py,sha256=aqh3IWhTEVwz09etu5oYRz6GL1FmZgy6b_hx9J4GWPI,15378
107
+ mesa/visualization/components/__init__.py,sha256=5_nUk0UzuVEYHXJ-kjsIZQLRvef-gbYBoiXCZd81kGQ,3524
108
+ mesa/visualization/components/altair_components.py,sha256=BuEwvWaMs4EMggRWn1upws4uNsVYSrr1k_IYl4UqT2U,18999
109
+ mesa/visualization/components/matplotlib_components.py,sha256=KfzP7eLT0d3Tqb2JatJ8IfpalyX8lveo6U3IC0EvvB8,5567
110
+ mesa/visualization/components/portrayal_components.py,sha256=FlLz_dZFXiaQobvfpfWsFAUgy4cnHs2R0tm6JikM0mU,4870
111
+ mesa-3.3.0.dist-info/METADATA,sha256=082hZvTM8-_aEHvR99yquciB_9aTbOq66Z-7YjGGTGA,11135
112
+ mesa-3.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
113
+ mesa-3.3.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
114
+ mesa-3.3.0.dist-info/licenses/NOTICE,sha256=GbsWoK0QWv1JyZ_xer2s-jNilv0RtWl-0UrtlJANHPg,578
115
+ mesa-3.3.0.dist-info/RECORD,,
@@ -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
File without changes