Mesa 3.0.0a1__tar.gz → 3.0.0a2__tar.gz

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 (127) hide show
  1. {mesa-3.0.0a1 → mesa-3.0.0a2}/.github/workflows/build_lint.yml +1 -1
  2. {mesa-3.0.0a1 → mesa-3.0.0a2}/.pre-commit-config.yaml +2 -2
  3. {mesa-3.0.0a1 → mesa-3.0.0a2}/HISTORY.md +31 -0
  4. {mesa-3.0.0a1 → mesa-3.0.0a2}/PKG-INFO +10 -5
  5. {mesa-3.0.0a1 → mesa-3.0.0a2}/README.md +9 -3
  6. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/conf.py +1 -1
  7. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/tutorials/intro_tutorial.ipynb +60 -54
  8. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/tutorials/visualization_tutorial.ipynb +7 -2
  9. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/__init__.py +1 -1
  10. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/agent.py +26 -25
  11. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/experimental/devs/eventlist.py +11 -0
  12. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/model.py +4 -7
  13. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/space.py +3 -3
  14. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/visualization/components/matplotlib.py +60 -23
  15. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/visualization/solara_viz.py +3 -2
  16. {mesa-3.0.0a1 → mesa-3.0.0a2}/pyproject.toml +0 -1
  17. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_agent.py +67 -1
  18. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_solara_viz.py +3 -1
  19. {mesa-3.0.0a1 → mesa-3.0.0a2}/.codespellignore +0 -0
  20. {mesa-3.0.0a1 → mesa-3.0.0a2}/.coveragerc +0 -0
  21. {mesa-3.0.0a1 → mesa-3.0.0a2}/.github/ISSUE_TEMPLATE/asking-help.md +0 -0
  22. {mesa-3.0.0a1 → mesa-3.0.0a2}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
  23. {mesa-3.0.0a1 → mesa-3.0.0a2}/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
  24. {mesa-3.0.0a1 → mesa-3.0.0a2}/.github/dependabot.yml +0 -0
  25. {mesa-3.0.0a1 → mesa-3.0.0a2}/.github/release.yml +0 -0
  26. {mesa-3.0.0a1 → mesa-3.0.0a2}/.github/workflows/benchmarks.yml +0 -0
  27. {mesa-3.0.0a1 → mesa-3.0.0a2}/.github/workflows/release.yml +0 -0
  28. {mesa-3.0.0a1 → mesa-3.0.0a2}/.gitignore +0 -0
  29. {mesa-3.0.0a1 → mesa-3.0.0a2}/.readthedocs.yml +0 -0
  30. {mesa-3.0.0a1 → mesa-3.0.0a2}/CITATION.bib +0 -0
  31. {mesa-3.0.0a1 → mesa-3.0.0a2}/CODE_OF_CONDUCT.md +0 -0
  32. {mesa-3.0.0a1 → mesa-3.0.0a2}/CONTRIBUTING.md +0 -0
  33. {mesa-3.0.0a1 → mesa-3.0.0a2}/Dockerfile +0 -0
  34. {mesa-3.0.0a1 → mesa-3.0.0a2}/LICENSE +0 -0
  35. {mesa-3.0.0a1 → mesa-3.0.0a2}/benchmarks/Flocking/__init__.py +0 -0
  36. {mesa-3.0.0a1 → mesa-3.0.0a2}/benchmarks/Flocking/flocking.py +0 -0
  37. {mesa-3.0.0a1 → mesa-3.0.0a2}/benchmarks/Schelling/__init__.py +0 -0
  38. {mesa-3.0.0a1 → mesa-3.0.0a2}/benchmarks/Schelling/schelling.py +0 -0
  39. {mesa-3.0.0a1 → mesa-3.0.0a2}/benchmarks/WolfSheep/__init__.py +0 -0
  40. {mesa-3.0.0a1 → mesa-3.0.0a2}/benchmarks/WolfSheep/wolf_sheep.py +0 -0
  41. {mesa-3.0.0a1 → mesa-3.0.0a2}/benchmarks/compare_timings.py +0 -0
  42. {mesa-3.0.0a1 → mesa-3.0.0a2}/benchmarks/configurations.py +0 -0
  43. {mesa-3.0.0a1 → mesa-3.0.0a2}/benchmarks/global_benchmark.py +0 -0
  44. {mesa-3.0.0a1 → mesa-3.0.0a2}/codecov.yaml +0 -0
  45. {mesa-3.0.0a1 → mesa-3.0.0a2}/docker-compose.yml +0 -0
  46. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/Makefile +0 -0
  47. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/README.md +0 -0
  48. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/apis/api_main.md +0 -0
  49. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/apis/batchrunner.md +0 -0
  50. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/apis/datacollection.md +0 -0
  51. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/apis/experimental.md +0 -0
  52. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/apis/init.md +0 -0
  53. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/apis/space.md +0 -0
  54. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/apis/time.md +0 -0
  55. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/apis/visualization.md +0 -0
  56. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/best-practices.md +0 -0
  57. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/howto.md +0 -0
  58. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/Mesa_Screenshot.png +0 -0
  59. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/mesa_logo.ico +0 -0
  60. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/mesa_logo.png +0 -0
  61. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/tutorial/br_ginis.png +0 -0
  62. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/tutorial/dc_endwealth.png +0 -0
  63. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/tutorial/dc_gini.png +0 -0
  64. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/tutorial/dc_oneagent.png +0 -0
  65. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/tutorial/first_hist.png +0 -0
  66. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/tutorial/multirun_hist.png +0 -0
  67. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/tutorial/numpy_grid.png +0 -0
  68. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/tutorial/viz_chart.png +0 -0
  69. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/tutorial/viz_empty.png +0 -0
  70. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/tutorial/viz_greycircles.png +0 -0
  71. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/tutorial/viz_histogram.png +0 -0
  72. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/images/tutorial/viz_redcircles.png +0 -0
  73. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/index.md +0 -0
  74. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/make.bat +0 -0
  75. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/mesa.md +0 -0
  76. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/overview.md +0 -0
  77. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/packages.md +0 -0
  78. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/tutorials/MoneyModel.py +0 -0
  79. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/tutorials/files/viz_chart.png +0 -0
  80. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/tutorials/files/viz_empty.png +0 -0
  81. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/tutorials/files/viz_greycircles.png +0 -0
  82. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/tutorials/files/viz_histogram.png +0 -0
  83. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/tutorials/files/viz_redcircles.png +0 -0
  84. {mesa-3.0.0a1 → mesa-3.0.0a2}/docs/tutorials/files/viz_slider.png +0 -0
  85. {mesa-3.0.0a1 → mesa-3.0.0a2}/maintenance/fetch_unlabeled_prs.py +0 -0
  86. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/batchrunner.py +0 -0
  87. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/cookiecutter-mesa/cookiecutter.json +0 -0
  88. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/cookiecutter-mesa/hooks/post_gen_project.py +0 -0
  89. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/cookiecutter-mesa/{{cookiecutter.snake}}/README.md +0 -0
  90. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/cookiecutter-mesa/{{cookiecutter.snake}}/app.pytemplate +0 -0
  91. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/cookiecutter-mesa/{{cookiecutter.snake}}/setup.pytemplate +0 -0
  92. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/__init__.py +0 -0
  93. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/model.pytemplate +0 -0
  94. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/datacollection.py +0 -0
  95. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/experimental/__init__.py +0 -0
  96. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/experimental/cell_space/__init__.py +0 -0
  97. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/experimental/cell_space/cell.py +0 -0
  98. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/experimental/cell_space/cell_agent.py +0 -0
  99. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/experimental/cell_space/cell_collection.py +0 -0
  100. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/experimental/cell_space/discrete_space.py +0 -0
  101. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/experimental/cell_space/grid.py +0 -0
  102. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/experimental/cell_space/network.py +0 -0
  103. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/experimental/devs/__init__.py +0 -0
  104. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/experimental/devs/examples/epstein_civil_violence.py +0 -0
  105. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/experimental/devs/examples/wolf_sheep.py +0 -0
  106. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/experimental/devs/simulator.py +0 -0
  107. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/main.py +0 -0
  108. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/time.py +0 -0
  109. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/visualization/UserParam.py +0 -0
  110. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/visualization/__init__.py +0 -0
  111. {mesa-3.0.0a1 → mesa-3.0.0a2}/mesa/visualization/components/altair.py +0 -0
  112. {mesa-3.0.0a1 → mesa-3.0.0a2}/mypy.ini +0 -0
  113. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/__init__.py +0 -0
  114. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/read_requirements.py +0 -0
  115. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_batch_run.py +0 -0
  116. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_cell_space.py +0 -0
  117. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_datacollector.py +0 -0
  118. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_devs.py +0 -0
  119. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_end_to_end_viz.sh +0 -0
  120. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_examples.py +0 -0
  121. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_grid.py +0 -0
  122. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_import_namespace.py +0 -0
  123. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_lifespan.py +0 -0
  124. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_model.py +0 -0
  125. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_scaffold.py +0 -0
  126. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_space.py +0 -0
  127. {mesa-3.0.0a1 → mesa-3.0.0a2}/tests/test_time.py +0 -0
@@ -80,4 +80,4 @@ jobs:
80
80
  - name: Test examples
81
81
  run: |
82
82
  cd mesa-examples
83
- pytest test_examples.py
83
+ pytest -rA -Werror test_examples.py
@@ -4,7 +4,7 @@ ci:
4
4
  repos:
5
5
  - repo: https://github.com/astral-sh/ruff-pre-commit
6
6
  # Ruff version.
7
- rev: v0.5.0
7
+ rev: v0.5.6
8
8
  hooks:
9
9
  # Run the linter.
10
10
  - id: ruff
@@ -14,7 +14,7 @@ repos:
14
14
  - id: ruff-format
15
15
  types_or: [ python, pyi, jupyter ]
16
16
  - repo: https://github.com/asottile/pyupgrade
17
- rev: v3.16.0
17
+ rev: v3.17.0
18
18
  hooks:
19
19
  - id: pyupgrade
20
20
  args: [--py310-plus]
@@ -1,6 +1,37 @@
1
1
  ---
2
2
  title: Release History
3
3
  ---
4
+ # 3.0.0a2 (2024-08-21)
5
+ ## Highlights
6
+ In Mesa 3.0 alpha 2 (`v3.0.0a2`) we've done more clean-up in preparation for Mesa 3.0. We now [require](https://github.com/projectmesa/mesa/pull/2218) `super().__init__()` to run on initializing a Mesa model subclass, `Model.agents` is now fully reserved for the Model's internal AgentSet and we fixed a bug in our Solara space_drawer.
7
+
8
+ A new feature was added in [#2219](https://github.com/projectmesa/mesa/pull/2219), which now also allows `AgentSet.do()` to take any callable function, instead of only a string referencing to an Agent method. The argument name was changed from `method_name` to `method`.
9
+
10
+ The new Solara visualisation now allows portraying agents in different shapes, checkout some examples in [#2214](https://github.com/projectmesa/mesa/pull/2214).
11
+
12
+ We're also working hard on our [example models](https://github.com/projectmesa/mesa-examples). All model warnings were [resolved](https://github.com/projectmesa/mesa-examples/pull/153) and we've [replaced](https://github.com/projectmesa/mesa-examples/pull/161) a lot of schedulers with simpler and more flexible AgentSet functionality. Checkout our [open issues](https://github.com/projectmesa/mesa-examples/issues) if you want to help improve our example models further!
13
+
14
+ ## What's Changed
15
+ ### ⚠️ Breaking changes
16
+ * breaking: Add dependencies argument to custom space_drawer by @rht in https://github.com/projectmesa/mesa/pull/2209
17
+ * Require Mesa models to be initialized with `super().__init__()` by @EwoutH in https://github.com/projectmesa/mesa/pull/2218
18
+ * Allow AgentSet.do() to take Callable function by @quaquel in https://github.com/projectmesa/mesa/pull/2219
19
+ * Change warning when setting model.agents to error by @EwoutH in https://github.com/projectmesa/mesa/pull/2225
20
+ ### 🧪 Experimental features
21
+ * devs/eventlist: Add repr method to print EventList pretty by @EwoutH in https://github.com/projectmesa/mesa/pull/2195
22
+ ### 🛠 Enhancements made
23
+ * Visualisation: Allow specifying Agent shapes in agent_portrayal by @rmhopkins4 in https://github.com/projectmesa/mesa/pull/2214
24
+ ### 📜 Documentation improvements
25
+ * docs/conf.py: Use modern `intersphinx_mapping` format by @EwoutH in https://github.com/projectmesa/mesa/pull/2206
26
+ * docs: Update Readme and tutorials to mention Mesa 3.0 pre-releases by @EwoutH in https://github.com/projectmesa/mesa/pull/2203
27
+ ### 🔧 Maintenance
28
+ * CI: Let pytest treat warnings as errors for examples by @EwoutH in https://github.com/projectmesa/mesa/pull/2204
29
+
30
+ ## New Contributors
31
+ * @rmhopkins4 made their first contribution in https://github.com/projectmesa/mesa/pull/2214
32
+
33
+ **Full Changelog**: https://github.com/projectmesa/mesa/compare/v3.0.0a1...v3.0.0a2
34
+
4
35
  # 3.0.0a1 (2024-08-01)
5
36
  ## Highlights
6
37
  Mesa 3.0 alpha 1 (`v3.0.0a1`) is another step towards our next major version. This release introduces a name change from JupyterViz (jupyter_viz) to SolaraViz (solara_viz), to better represent the tech stack being used. It also includes two bugfixes also present in 2.3.2.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: Mesa
3
- Version: 3.0.0a1
3
+ Version: 3.0.0a2
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
@@ -30,7 +30,6 @@ Requires-Dist: pandas
30
30
  Requires-Dist: solara
31
31
  Requires-Dist: tqdm
32
32
  Provides-Extra: dev
33
- Requires-Dist: coverage; extra == 'dev'
34
33
  Requires-Dist: pytest-cov; extra == 'dev'
35
34
  Requires-Dist: pytest-mock; extra == 'dev'
36
35
  Requires-Dist: pytest>=4.6; extra == 'dev'
@@ -75,13 +74,19 @@ can be displayed in browser windows or Jupyter.*
75
74
 
76
75
  ## Using Mesa
77
76
 
78
- Getting started quickly:
77
+ To install our latest stable release (2.3.x), run:
79
78
 
80
79
  ``` bash
81
- pip install mesa
80
+ pip install -U mesa
82
81
  ```
83
82
 
84
- You can also use `pip` to install the github version:
83
+ To install our latest pre-release (3.0.0 alpha), run:
84
+
85
+ ``` bash
86
+ pip install -U --pre mesa
87
+ ```
88
+
89
+ You can also use `pip` to install the latest GitHub version:
85
90
 
86
91
  ``` bash
87
92
  pip install -U -e git+https://github.com/projectmesa/mesa@main#egg=mesa
@@ -28,13 +28,19 @@ can be displayed in browser windows or Jupyter.*
28
28
 
29
29
  ## Using Mesa
30
30
 
31
- Getting started quickly:
31
+ To install our latest stable release (2.3.x), run:
32
32
 
33
33
  ``` bash
34
- pip install mesa
34
+ pip install -U mesa
35
35
  ```
36
36
 
37
- You can also use `pip` to install the github version:
37
+ To install our latest pre-release (3.0.0 alpha), run:
38
+
39
+ ``` bash
40
+ pip install -U --pre mesa
41
+ ```
42
+
43
+ You can also use `pip` to install the latest GitHub version:
38
44
 
39
45
  ``` bash
40
46
  pip install -U -e git+https://github.com/projectmesa/mesa@main#egg=mesa
@@ -279,4 +279,4 @@ texinfo_documents = [
279
279
 
280
280
 
281
281
  # Example configuration for intersphinx: refer to the Python standard library.
282
- intersphinx_mapping = {"http://docs.python.org/": None}
282
+ intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
@@ -66,6 +66,12 @@
66
66
  "pip install --upgrade mesa\n",
67
67
  "```\n",
68
68
  "\n",
69
+ "If you want to use our newest features, you can also opt to install our latest pre-release version:\n",
70
+ "\n",
71
+ "```bash\n",
72
+ "pip install --upgrade --pre mesa\n",
73
+ "```\n",
74
+ "\n",
69
75
  "Install Jupyter Notebook (optional):\n",
70
76
  "\n",
71
77
  "```bash\n",
@@ -1209,15 +1215,19 @@
1209
1215
  },
1210
1216
  {
1211
1217
  "cell_type": "markdown",
1212
- "source": [
1213
- "We can create different kinds of plot from this filtered DataFrame. For example, a point plot with error bars."
1214
- ],
1215
1218
  "metadata": {
1216
1219
  "collapsed": false
1217
- }
1220
+ },
1221
+ "source": [
1222
+ "We can create different kinds of plot from this filtered DataFrame. For example, a point plot with error bars."
1223
+ ]
1218
1224
  },
1219
1225
  {
1220
1226
  "cell_type": "code",
1227
+ "execution_count": null,
1228
+ "metadata": {
1229
+ "collapsed": false
1230
+ },
1221
1231
  "outputs": [],
1222
1232
  "source": [
1223
1233
  "# Create a point plot with error bars\n",
@@ -1228,11 +1238,7 @@
1228
1238
  " ylabel=\"Gini coefficient\",\n",
1229
1239
  " title=\"Gini coefficient vs. number of agents\",\n",
1230
1240
  ");"
1231
- ],
1232
- "metadata": {
1233
- "collapsed": false
1234
- },
1235
- "execution_count": null
1241
+ ]
1236
1242
  },
1237
1243
  {
1238
1244
  "cell_type": "markdown",
@@ -1284,16 +1290,20 @@
1284
1290
  },
1285
1291
  {
1286
1292
  "cell_type": "markdown",
1293
+ "metadata": {
1294
+ "collapsed": false
1295
+ },
1287
1296
  "source": [
1288
1297
  "### Analyzing model reporters: Comparing 5 scenarios\n",
1289
1298
  "Other insights might be gathered when we compare the Gini coefficient of different scenarios. For example, we can compare the Gini coefficient of a population with 25 agents to the Gini coefficient of a population with 400 agents. While doing this, we increase the number of iterations to 25 to get a better estimate of the Gini coefficient for each population size and get usable error estimations."
1290
- ],
1291
- "metadata": {
1292
- "collapsed": false
1293
- }
1299
+ ]
1294
1300
  },
1295
1301
  {
1296
1302
  "cell_type": "code",
1303
+ "execution_count": null,
1304
+ "metadata": {
1305
+ "collapsed": false
1306
+ },
1297
1307
  "outputs": [],
1298
1308
  "source": [
1299
1309
  "params = {\"width\": 10, \"height\": 10, \"N\": [5, 10, 20, 40, 80]}\n",
@@ -1309,27 +1319,27 @@
1309
1319
  ")\n",
1310
1320
  "\n",
1311
1321
  "results_5s_df = pd.DataFrame(results_5s)"
1312
- ],
1313
- "metadata": {
1314
- "collapsed": false
1315
- },
1316
- "execution_count": null
1322
+ ]
1317
1323
  },
1318
1324
  {
1319
1325
  "cell_type": "code",
1326
+ "execution_count": null,
1327
+ "metadata": {
1328
+ "collapsed": false
1329
+ },
1320
1330
  "outputs": [],
1321
1331
  "source": [
1322
1332
  "# Again filter the results to only contain the data of one agent (the Gini coefficient will be the same for the entire population at any time)\n",
1323
1333
  "results_5s_df_filtered = results_5s_df[(results_5s_df.AgentID == 0)]\n",
1324
1334
  "results_5s_df_filtered.head(3)"
1325
- ],
1326
- "metadata": {
1327
- "collapsed": false
1328
- },
1329
- "execution_count": null
1335
+ ]
1330
1336
  },
1331
1337
  {
1332
1338
  "cell_type": "code",
1339
+ "execution_count": null,
1340
+ "metadata": {
1341
+ "collapsed": false
1342
+ },
1333
1343
  "outputs": [],
1334
1344
  "source": [
1335
1345
  "# Create a lineplot with error bars\n",
@@ -1344,35 +1354,35 @@
1344
1354
  "g.figure.set_size_inches(8, 4)\n",
1345
1355
  "plot_title = \"Gini coefficient for different population sizes\\n(mean over 100 runs, with 95% confidence interval)\"\n",
1346
1356
  "g.set(title=plot_title, ylabel=\"Gini coefficient\");"
1347
- ],
1348
- "metadata": {
1349
- "collapsed": false
1350
- },
1351
- "execution_count": null
1357
+ ]
1352
1358
  },
1353
1359
  {
1354
1360
  "cell_type": "markdown",
1355
- "source": [
1356
- "In this case it looks like the Gini coefficient increases slower for smaller populations. This can be because of different things, either because the Gini coefficient is a measure of inequality and the smaller the population, the more likely it is that the agents are all in the same wealth class, or because there are less interactions between agents in smaller populations, which means that the wealth of an agent is less likely to change."
1357
- ],
1358
1361
  "metadata": {
1359
1362
  "collapsed": false
1360
- }
1363
+ },
1364
+ "source": [
1365
+ "In this case it looks like the Gini coefficient increases slower for smaller populations. This can be because of different things, either because the Gini coefficient is a measure of inequality and the smaller the population, the more likely it is that the agents are all in the same wealth class, or because there are less interactions between agents in smaller populations, which means that the wealth of an agent is less likely to change."
1366
+ ]
1361
1367
  },
1362
1368
  {
1363
1369
  "cell_type": "markdown",
1370
+ "metadata": {
1371
+ "collapsed": false
1372
+ },
1364
1373
  "source": [
1365
1374
  "### Analyzing agent reporters\n",
1366
1375
  "From the agents we collected the wealth and the number of consecutive rounds without a transaction. We can compare the 5 different population sizes by plotting the average number of consecutive rounds without a transaction for each population size.\n",
1367
1376
  "\n",
1368
1377
  "Note that we're aggregating multiple times here: First we take the average of all agents for each single replication. Then we plot the averages for all replications, with the error band showing the 95% confidence interval of that first average (over all agents). So this error band is representing the uncertainty of the mean value of the number of consecutive rounds without a transaction for each population size."
1369
- ],
1370
- "metadata": {
1371
- "collapsed": false
1372
- }
1378
+ ]
1373
1379
  },
1374
1380
  {
1375
1381
  "cell_type": "code",
1382
+ "execution_count": null,
1383
+ "metadata": {
1384
+ "collapsed": false
1385
+ },
1376
1386
  "outputs": [],
1377
1387
  "source": [
1378
1388
  "# Calculate the mean of the wealth and the number of consecutive rounds for all agents in each episode\n",
@@ -1382,14 +1392,14 @@
1382
1392
  " .reset_index()\n",
1383
1393
  ")\n",
1384
1394
  "agg_results_df.head(3)"
1385
- ],
1386
- "metadata": {
1387
- "collapsed": false
1388
- },
1389
- "execution_count": null
1395
+ ]
1390
1396
  },
1391
1397
  {
1392
1398
  "cell_type": "code",
1399
+ "execution_count": null,
1400
+ "metadata": {
1401
+ "collapsed": false
1402
+ },
1393
1403
  "outputs": [],
1394
1404
  "source": [
1395
1405
  "# Create a line plot with error bars\n",
@@ -1401,23 +1411,22 @@
1401
1411
  " title=\"Average number of consecutive rounds without a transaction for different population sizes\\n(mean with 95% confidence interval)\",\n",
1402
1412
  " ylabel=\"Consecutive rounds without a transaction\",\n",
1403
1413
  ");"
1404
- ],
1405
- "metadata": {
1406
- "collapsed": false
1407
- },
1408
- "execution_count": null
1414
+ ]
1409
1415
  },
1410
1416
  {
1411
1417
  "cell_type": "markdown",
1412
- "source": [
1413
- "It can be clearly seen that the lower the number of agents, the higher the number of consecutive rounds without a transaction. This is because the agents have fewer interactions with each other and therefore the wealth of an agent is less likely to change."
1414
- ],
1415
1418
  "metadata": {
1416
1419
  "collapsed": false
1417
- }
1420
+ },
1421
+ "source": [
1422
+ "It can be clearly seen that the lower the number of agents, the higher the number of consecutive rounds without a transaction. This is because the agents have fewer interactions with each other and therefore the wealth of an agent is less likely to change."
1423
+ ]
1418
1424
  },
1419
1425
  {
1420
1426
  "cell_type": "markdown",
1427
+ "metadata": {
1428
+ "collapsed": false
1429
+ },
1421
1430
  "source": [
1422
1431
  "#### General steps for analyzing results\n",
1423
1432
  "\n",
@@ -1430,10 +1439,7 @@
1430
1439
  "5. Transform, filter and aggregate the results to get the data you want to analyze. Make sure it's in long format, so that each row represents a single value.\n",
1431
1440
  "6. Choose a plot type, what to plot on the x and y axis, which columns to use for the hue. Seaborn also has an amazing [Example Gallery](https://seaborn.pydata.org/examples/index.html).\n",
1432
1441
  "7. Plot the data and analyze the results."
1433
- ],
1434
- "metadata": {
1435
- "collapsed": false
1436
- }
1442
+ ]
1437
1443
  },
1438
1444
  {
1439
1445
  "cell_type": "markdown",
@@ -11,6 +11,8 @@
11
11
  "cell_type": "markdown",
12
12
  "metadata": {},
13
13
  "source": [
14
+ "*This version of the visualisation tutorial is updated for Mesa 3.0, and works with Mesa `3.0.0a1` and above. If you are using Mesa 2.3.x, check out the [stable version](https://mesa.readthedocs.io/en/stable/tutorials/visualization_tutorial.html) of this tutorial on Readthedocs.*\n",
15
+ "\n",
14
16
  "**Important:** \n",
15
17
  "- If you are just exploring Mesa and want the fastest way to execute the code we recommend executing this tutorial online in a Colab notebook. [![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/projectmesa/mesa/blob/main/docs/tutorials/visualization_tutorial.ipynb)\n",
16
18
  "- If you have installed mesa and are running locally, please ensure that your [Mesa version](https://pypi.org/project/Mesa/) is up-to-date in order to run this tutorial.\n",
@@ -39,8 +41,10 @@
39
41
  },
40
42
  "outputs": [],
41
43
  "source": [
42
- "%pip install --quiet mesa\n",
44
+ "# Install and import the latest Mesa pre-release version\n",
45
+ "%pip install --quiet --upgrade --pre mesa\n",
43
46
  "import mesa\n",
47
+ "print(f\"Mesa version: {mesa.__version__}\")\n",
44
48
  "\n",
45
49
  "# You can either define the BoltzmannWealthModel (aka MoneyModel) or install mesa-models:\n",
46
50
  "%pip install --quiet -U git+https://github.com/projectmesa/mesa-examples#egg=mesa-models\n",
@@ -138,7 +142,8 @@
138
142
  "source": [
139
143
  "#### Changing the agents\n",
140
144
  "\n",
141
- "In the visualization above, all we could see is the agents moving around -- but not how much money they had, or anything else of interest. Let's change it so that agents who are broke (wealth 0) are drawn in red, smaller. (TODO: currently, we can't predict the drawing order of the circles, so a broke agent may be overshadowed by a wealthy agent. We should fix this by doing a hollow circle instead)\n",
145
+ "In the visualization above, all we could see is the agents moving around -- but not how much money they had, or anything else of interest. Let's change it so that agents who are broke (wealth 0) are drawn in red, smaller. (TODO: Currently, we can't predict the drawing order of the circles, so a broke agent may be overshadowed by a wealthy agent. We should fix this by doing a hollow circle instead)\n",
146
+ "In addition to size and color, an agent's shape can also be customized when using the default drawer. The allowed values for shapes can be found [here](https://matplotlib.org/stable/api/markers_api.html).\n",
142
147
  "\n",
143
148
  "To do this, we go back to our `agent_portrayal` code and add some code to change the portrayal based on the agent properties and launch the server again."
144
149
  ]
@@ -24,7 +24,7 @@ __all__ = [
24
24
  ]
25
25
 
26
26
  __title__ = "mesa"
27
- __version__ = "3.0.0a1"
27
+ __version__ = "3.0.0a2"
28
28
  __license__ = "Apache 2.0"
29
29
  _this_year = datetime.datetime.now(tz=datetime.timezone.utc).date().year
30
30
  __copyright__ = f"Copyright {_this_year} Project Mesa Team"
@@ -11,9 +11,7 @@ from __future__ import annotations
11
11
  import contextlib
12
12
  import copy
13
13
  import operator
14
- import warnings
15
14
  import weakref
16
- from collections import defaultdict
17
15
  from collections.abc import Callable, Iterable, Iterator, MutableSet, Sequence
18
16
  from random import Random
19
17
 
@@ -52,17 +50,11 @@ class Agent:
52
50
  # register agent
53
51
  try:
54
52
  self.model.agents_[type(self)][self] = None
55
- except AttributeError:
53
+ except AttributeError as err:
56
54
  # model super has not been called
57
- self.model.agents_ = defaultdict(dict)
58
- self.model.agents_[type(self)][self] = None
59
- self.model.agentset_experimental_warning_given = False
60
-
61
- warnings.warn(
62
- "The Mesa Model class was not initialized. In the future, you need to explicitly initialize the Model by calling super().__init__() on initialization.",
63
- FutureWarning,
64
- stacklevel=2,
65
- )
55
+ raise RuntimeError(
56
+ "The Mesa Model class was not initialized. You must explicitly initialize the Model by calling super().__init__() on initialization."
57
+ ) from err
66
58
 
67
59
  def remove(self) -> None:
68
60
  """Remove and delete the agent from the model."""
@@ -100,8 +92,6 @@ class AgentSet(MutableSet, Sequence):
100
92
  which means that agents not referenced elsewhere in the program may be automatically removed from the AgentSet.
101
93
  """
102
94
 
103
- agentset_experimental_warning_given = False
104
-
105
95
  def __init__(self, agents: Iterable[Agent], model: Model):
106
96
  """
107
97
  Initializes the AgentSet with a collection of agents and a reference to the model.
@@ -227,26 +217,37 @@ class AgentSet(MutableSet, Sequence):
227
217
  return self
228
218
 
229
219
  def do(
230
- self, method_name: str, *args, return_results: bool = False, **kwargs
220
+ self, method: str | Callable, *args, return_results: bool = False, **kwargs
231
221
  ) -> AgentSet | list[Any]:
232
222
  """
233
- Invoke a method on each agent in the AgentSet.
223
+ Invoke a method or function on each agent in the AgentSet.
234
224
 
235
225
  Args:
236
- method_name (str): The name of the method to call on each agent.
226
+ method (str, callable): the callable to do on each agents
227
+
228
+ * in case of str, the name of the method to call on each agent.
229
+ * in case of callable, the function to be called with each agent as first argument
230
+
237
231
  return_results (bool, optional): If True, returns the results of the method calls; otherwise, returns the AgentSet itself. Defaults to False, so you can chain method calls.
238
- *args: Variable length argument list passed to the method being called.
239
- **kwargs: Arbitrary keyword arguments passed to the method being called.
232
+ *args: Variable length argument list passed to the callable being called.
233
+ **kwargs: Arbitrary keyword arguments passed to the callable being called.
240
234
 
241
235
  Returns:
242
- AgentSet | list[Any]: The results of the method calls if return_results is True, otherwise the AgentSet itself.
236
+ AgentSet | list[Any]: The results of the callable calls if return_results is True, otherwise the AgentSet itself.
243
237
  """
244
238
  # we iterate over the actual weakref keys and check if weakref is alive before calling the method
245
- res = [
246
- getattr(agent, method_name)(*args, **kwargs)
247
- for agentref in self._agents.keyrefs()
248
- if (agent := agentref()) is not None
249
- ]
239
+ if isinstance(method, str):
240
+ res = [
241
+ getattr(agent, method)(*args, **kwargs)
242
+ for agentref in self._agents.keyrefs()
243
+ if (agent := agentref()) is not None
244
+ ]
245
+ else:
246
+ res = [
247
+ method(agent, *args, **kwargs)
248
+ for agentref in self._agents.keyrefs()
249
+ if (agent := agentref()) is not None
250
+ ]
250
251
 
251
252
  return res if return_results else self
252
253
 
@@ -155,6 +155,17 @@ class EventList:
155
155
  def __len__(self) -> int:
156
156
  return len(self._events)
157
157
 
158
+ def __repr__(self) -> str:
159
+ """Return a string representation of the event list"""
160
+ events_str = ", ".join(
161
+ [
162
+ f"Event(time={e.time}, priority={e.priority}, id={e.unique_id})"
163
+ for e in self._events
164
+ if not e.CANCELED
165
+ ]
166
+ )
167
+ return f"EventList([{events_str}])"
168
+
158
169
  def remove(self, event: SimulationEvent) -> None:
159
170
  """remove an event from the event list"""
160
171
  # we cannot simply remove items from _eventlist because this breaks
@@ -10,7 +10,6 @@ from __future__ import annotations
10
10
 
11
11
  import itertools
12
12
  import random
13
- import warnings
14
13
  from collections import defaultdict
15
14
 
16
15
  # mypy
@@ -89,12 +88,10 @@ class Model:
89
88
 
90
89
  @agents.setter
91
90
  def agents(self, agents: Any) -> None:
92
- warnings.warn(
93
- "You are trying to set model.agents. In a next release, this attribute is used "
94
- "by MESA itself so you cannot use it directly anymore."
95
- "Please adjust your code to use a different attribute name for custom agent storage",
96
- UserWarning,
97
- stacklevel=2,
91
+ raise AttributeError(
92
+ "You are trying to set model.agents. In Mesa 3.0 and higher, this attribute will be "
93
+ "used by Mesa itself, so you cannot use it directly anymore."
94
+ "Please adjust your code to use a different attribute name for custom agent storage."
98
95
  )
99
96
 
100
97
  self._agents = agents
@@ -586,7 +586,7 @@ class PropertyLayer:
586
586
  aggregate_property(operation): Performs an aggregate operation over all cells.
587
587
  """
588
588
 
589
- agentset_experimental_warning_given = False
589
+ propertylayer_experimental_warning_given = False
590
590
 
591
591
  def __init__(
592
592
  self, name: str, width: int, height: int, default_value, dtype=np.float64
@@ -633,14 +633,14 @@ class PropertyLayer:
633
633
 
634
634
  self.data = np.full((width, height), default_value, dtype=dtype)
635
635
 
636
- if not self.__class__.agentset_experimental_warning_given:
636
+ if not self.__class__.propertylayer_experimental_warning_given:
637
637
  warnings.warn(
638
638
  "The new PropertyLayer and _PropertyGrid classes experimental. It may be changed or removed in any and all future releases, including patch releases.\n"
639
639
  "We would love to hear what you think about this new feature. If you have any thoughts, share them with us here: https://github.com/projectmesa/mesa/discussions/1932",
640
640
  FutureWarning,
641
641
  stacklevel=2,
642
642
  )
643
- self.__class__.agentset_experimental_warning_given = True
643
+ self.__class__.propertylayer_experimental_warning_given = True
644
644
 
645
645
  def set_cell(self, position: Coordinate, value):
646
646
  """