Mesa 3.0.0a4__tar.gz → 3.0.0a5__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 (149) hide show
  1. {mesa-3.0.0a4 → mesa-3.0.0a5}/.github/workflows/build_lint.yml +1 -5
  2. {mesa-3.0.0a4 → mesa-3.0.0a5}/HISTORY.md +46 -0
  3. {mesa-3.0.0a4 → mesa-3.0.0a5}/PKG-INFO +1 -1
  4. mesa-3.0.0a5/benchmarks/BoltzmannWealth/__init__.py +1 -0
  5. {mesa-3.0.0a4 → mesa-3.0.0a5}/benchmarks/BoltzmannWealth/boltzmann_wealth.py +39 -4
  6. mesa-3.0.0a5/benchmarks/Flocking/__init__.py +1 -0
  7. {mesa-3.0.0a4 → mesa-3.0.0a5}/benchmarks/Flocking/flocking.py +18 -24
  8. mesa-3.0.0a5/benchmarks/Schelling/__init__.py +1 -0
  9. {mesa-3.0.0a4 → mesa-3.0.0a5}/benchmarks/Schelling/schelling.py +21 -24
  10. mesa-3.0.0a5/benchmarks/WolfSheep/__init__.py +1 -0
  11. {mesa-3.0.0a4 → mesa-3.0.0a5}/benchmarks/WolfSheep/wolf_sheep.py +34 -29
  12. {mesa-3.0.0a4 → mesa-3.0.0a5}/benchmarks/compare_timings.py +13 -2
  13. {mesa-3.0.0a4 → mesa-3.0.0a5}/benchmarks/configurations.py +2 -0
  14. {mesa-3.0.0a4 → mesa-3.0.0a5}/benchmarks/global_benchmark.py +19 -0
  15. mesa-3.0.0a5/docs/apis/agent.md +8 -0
  16. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/apis/api_main.md +2 -1
  17. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/apis/batchrunner.md +2 -0
  18. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/apis/datacollection.md +2 -0
  19. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/apis/experimental.md +1 -5
  20. mesa-3.0.0a5/docs/apis/model.md +7 -0
  21. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/apis/space.md +2 -0
  22. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/apis/time.md +2 -0
  23. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/conf.py +4 -3
  24. mesa-3.0.0a5/docs/migration_guide.md +294 -0
  25. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/tutorials/MoneyModel.py +19 -4
  26. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/tutorials/intro_tutorial.ipynb +31 -31
  27. {mesa-3.0.0a4 → mesa-3.0.0a5}/maintenance/fetch_unlabeled_prs.py +2 -1
  28. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/__init__.py +2 -3
  29. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/agent.py +106 -61
  30. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/batchrunner.py +15 -23
  31. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/cookiecutter-mesa/hooks/post_gen_project.py +2 -0
  32. mesa-3.0.0a5/mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/__init__.py +1 -0
  33. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/datacollection.py +138 -27
  34. {mesa-3.0.0a4/mesa/visualization → mesa-3.0.0a5/mesa/experimental}/UserParam.py +17 -6
  35. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/__init__.py +2 -0
  36. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/cell_space/__init__.py +7 -0
  37. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/cell_space/cell.py +61 -20
  38. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/cell_space/cell_agent.py +10 -5
  39. mesa-3.0.0a5/mesa/experimental/cell_space/cell_collection.py +118 -0
  40. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/cell_space/discrete_space.py +16 -5
  41. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/cell_space/grid.py +19 -8
  42. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/cell_space/network.py +9 -7
  43. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/cell_space/voronoi.py +26 -33
  44. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/components/altair.py +10 -0
  45. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/components/matplotlib.py +18 -0
  46. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/devs/__init__.py +2 -0
  47. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/devs/eventlist.py +36 -15
  48. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/devs/examples/epstein_civil_violence.py +65 -29
  49. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/devs/examples/wolf_sheep.py +38 -34
  50. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/devs/simulator.py +55 -15
  51. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/experimental/solara_viz.py +10 -19
  52. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/main.py +6 -4
  53. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/model.py +43 -45
  54. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/space.py +145 -120
  55. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/time.py +57 -67
  56. {mesa-3.0.0a4/mesa/experimental → mesa-3.0.0a5/mesa/visualization}/UserParam.py +19 -6
  57. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/visualization/__init__.py +3 -2
  58. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/visualization/components/altair.py +4 -2
  59. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/visualization/components/matplotlib.py +6 -4
  60. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/visualization/solara_viz.py +157 -83
  61. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/visualization/utils.py +3 -1
  62. {mesa-3.0.0a4 → mesa-3.0.0a5}/pyproject.toml +3 -0
  63. mesa-3.0.0a5/tests/__init__.py +1 -0
  64. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/read_requirements.py +1 -0
  65. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/test_agent.py +110 -4
  66. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/test_batch_run.py +31 -15
  67. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/test_cell_space.py +103 -65
  68. mesa-3.0.0a5/tests/test_datacollector.py +387 -0
  69. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/test_devs.py +6 -0
  70. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/test_examples.py +7 -5
  71. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/test_grid.py +38 -88
  72. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/test_import_namespace.py +7 -2
  73. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/test_lifespan.py +15 -12
  74. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/test_model.py +11 -0
  75. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/test_scaffold.py +4 -5
  76. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/test_solara_viz.py +24 -14
  77. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/test_space.py +118 -172
  78. mesa-3.0.0a4/benchmarks/BoltzmannWealth/__init__.py +0 -0
  79. mesa-3.0.0a4/benchmarks/Flocking/__init__.py +0 -0
  80. mesa-3.0.0a4/benchmarks/Schelling/__init__.py +0 -0
  81. mesa-3.0.0a4/benchmarks/WolfSheep/__init__.py +0 -0
  82. mesa-3.0.0a4/docs/apis/init.md +0 -11
  83. mesa-3.0.0a4/docs/migration_guide.md +0 -67
  84. mesa-3.0.0a4/mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/__init__.py +0 -0
  85. mesa-3.0.0a4/mesa/experimental/cell_space/cell_collection.py +0 -81
  86. mesa-3.0.0a4/tests/__init__.py +0 -0
  87. mesa-3.0.0a4/tests/test_datacollector.py +0 -226
  88. mesa-3.0.0a4/tests/test_time.py +0 -342
  89. {mesa-3.0.0a4 → mesa-3.0.0a5}/.codespellignore +0 -0
  90. {mesa-3.0.0a4 → mesa-3.0.0a5}/.coveragerc +0 -0
  91. {mesa-3.0.0a4 → mesa-3.0.0a5}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
  92. {mesa-3.0.0a4 → mesa-3.0.0a5}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  93. {mesa-3.0.0a4 → mesa-3.0.0a5}/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
  94. {mesa-3.0.0a4 → mesa-3.0.0a5}/.github/PULL_REQUEST_TEMPLATE/bug.md +0 -0
  95. {mesa-3.0.0a4 → mesa-3.0.0a5}/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -0
  96. {mesa-3.0.0a4 → mesa-3.0.0a5}/.github/dependabot.yml +0 -0
  97. {mesa-3.0.0a4 → mesa-3.0.0a5}/.github/release.yml +0 -0
  98. {mesa-3.0.0a4 → mesa-3.0.0a5}/.github/workflows/benchmarks.yml +0 -0
  99. {mesa-3.0.0a4 → mesa-3.0.0a5}/.github/workflows/release.yml +0 -0
  100. {mesa-3.0.0a4 → mesa-3.0.0a5}/.gitignore +0 -0
  101. {mesa-3.0.0a4 → mesa-3.0.0a5}/.pre-commit-config.yaml +0 -0
  102. {mesa-3.0.0a4 → mesa-3.0.0a5}/.readthedocs.yml +0 -0
  103. {mesa-3.0.0a4 → mesa-3.0.0a5}/CITATION.bib +0 -0
  104. {mesa-3.0.0a4 → mesa-3.0.0a5}/CODE_OF_CONDUCT.md +0 -0
  105. {mesa-3.0.0a4 → mesa-3.0.0a5}/CONTRIBUTING.md +0 -0
  106. {mesa-3.0.0a4 → mesa-3.0.0a5}/Dockerfile +0 -0
  107. {mesa-3.0.0a4 → mesa-3.0.0a5}/LICENSE +0 -0
  108. {mesa-3.0.0a4 → mesa-3.0.0a5}/README.md +0 -0
  109. {mesa-3.0.0a4 → mesa-3.0.0a5}/codecov.yaml +0 -0
  110. {mesa-3.0.0a4 → mesa-3.0.0a5}/docker-compose.yml +0 -0
  111. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/Makefile +0 -0
  112. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/README.md +0 -0
  113. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/apis/visualization.md +0 -0
  114. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/best-practices.md +0 -0
  115. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/howto.md +0 -0
  116. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/Mesa_Screenshot.png +0 -0
  117. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/mesa_logo.ico +0 -0
  118. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/mesa_logo.png +0 -0
  119. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/tutorial/br_ginis.png +0 -0
  120. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/tutorial/dc_endwealth.png +0 -0
  121. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/tutorial/dc_gini.png +0 -0
  122. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/tutorial/dc_oneagent.png +0 -0
  123. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/tutorial/first_hist.png +0 -0
  124. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/tutorial/multirun_hist.png +0 -0
  125. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/tutorial/numpy_grid.png +0 -0
  126. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/tutorial/viz_chart.png +0 -0
  127. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/tutorial/viz_empty.png +0 -0
  128. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/tutorial/viz_greycircles.png +0 -0
  129. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/tutorial/viz_histogram.png +0 -0
  130. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/images/tutorial/viz_redcircles.png +0 -0
  131. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/index.md +0 -0
  132. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/make.bat +0 -0
  133. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/mesa.md +0 -0
  134. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/overview.md +0 -0
  135. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/packages.md +0 -0
  136. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/tutorials/files/viz_chart.png +0 -0
  137. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/tutorials/files/viz_empty.png +0 -0
  138. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/tutorials/files/viz_greycircles.png +0 -0
  139. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/tutorials/files/viz_histogram.png +0 -0
  140. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/tutorials/files/viz_redcircles.png +0 -0
  141. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/tutorials/files/viz_slider.png +0 -0
  142. {mesa-3.0.0a4 → mesa-3.0.0a5}/docs/tutorials/visualization_tutorial.ipynb +0 -0
  143. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/cookiecutter-mesa/cookiecutter.json +0 -0
  144. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/cookiecutter-mesa/{{cookiecutter.snake}}/README.md +0 -0
  145. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/cookiecutter-mesa/{{cookiecutter.snake}}/app.pytemplate +0 -0
  146. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/cookiecutter-mesa/{{cookiecutter.snake}}/setup.pytemplate +0 -0
  147. {mesa-3.0.0a4 → mesa-3.0.0a5}/mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/model.pytemplate +0 -0
  148. {mesa-3.0.0a4 → mesa-3.0.0a5}/mypy.ini +0 -0
  149. {mesa-3.0.0a4 → mesa-3.0.0a5}/tests/test_end_to_end_viz.sh +0 -0
@@ -53,12 +53,8 @@ jobs:
53
53
  cache: 'pip'
54
54
  - name: Install uv
55
55
  run: pip install uv
56
- - name: Install Mesa with uv pip
56
+ - name: Install Mesa and dependencies
57
57
  run: uv pip install --system .[dev]
58
- if: matrix.python-version != '3.13'
59
- - name: Install Mesa with pip
60
- run: pip install .[dev]
61
- if: matrix.python-version == '3.13'
62
58
  - name: Test with pytest
63
59
  run: pytest --durations=10 --cov=mesa tests/ --cov-report=xml
64
60
  - if: matrix.os == 'ubuntu'
@@ -1,6 +1,52 @@
1
1
  ---
2
2
  title: Release History
3
3
  ---
4
+ # 3.0.0a5 (2024-09-21)
5
+ ## Highlights
6
+ Mesa v3.0 alpha 5 release contains many quality of life updates, a big new feature for the DataCollector and a major deprecation.
7
+
8
+ The entire `mesa.time` module, including all schedulers, has been deprecated ([#2306](https://github.com/projectmesa/mesa/pull/2306)). Users are encouraged to transition to AgentSet functionality for more flexible and explicit agent activation patterns. Check the [migration guide](https://mesa.readthedocs.io/en/latest/migration_guide.html#time-and-schedulers) on how to upgrade.
9
+
10
+ The DataCollector now supports collecting data from specific Agent subclasses using the new `agenttype_reporters` parameter ([#2300](https://github.com/projectmesa/mesa/pull/2300)). This allows collecting different metrics for different agent types. For example:
11
+
12
+ ```python
13
+ self.datacollector = DataCollector(
14
+ agenttype_reporters={
15
+ Wolf: {"sheep_eaten": "sheep_eaten"},
16
+ Sheep: {"wool": "wool_amount"}
17
+ }
18
+ )
19
+ ```
20
+
21
+ Furthermore, a new `shuffle_do()` method for AgentSets provides a faster way to perform `shuffle().do()` ([#2283](https://github.com/projectmesa/mesa/pull/2283)). The GroupBy class gained `count()` and `agg()` methods to count the number of agents in groups and aggregate variables of them ([#2290](https://github.com/projectmesa/mesa/pull/2290)). The `CellCollection.select` method was updated to use `at_most` instead of `n`, aligning with the AgentSet API ([#2307](https://github.com/projectmesa/mesa/pull/2307)). Additionally, the Cell class now features a dedicated `neighborhood` property for direct neighbors (default radius=1) and a `get_neighborhood` method for larger radii ([#2309](https://github.com/projectmesa/mesa/pull/2309)).
22
+
23
+ Finally, SolaraViz received updates improving its interface and performance ([#2299](https://github.com/projectmesa/mesa/pull/2299), [#2304](https://github.com/projectmesa/mesa/pull/2304)). Cell connections in grids and networks are now public and named for more intuitive agent movements ([#2296](https://github.com/projectmesa/mesa/pull/2296)). The Model class initialization process was simplified by moving random seed and random object creation to `__init__` ([#1940](https://github.com/projectmesa/mesa/pull/1940)). Documentation has been extensively updated, including enforcing Google docstrings ([#2294](https://github.com/projectmesa/mesa/pull/2294)) and reorganizing the API documentation ([#2298](https://github.com/projectmesa/mesa/pull/2298)) for better clarity and navigation.
24
+
25
+ While the Mesa 3.0 timeline is still being discussed, we're aiming at the first Mesa 3.0 beta in October followed by a stable release in November. Testing new features and sharing feedback is appreciated!
26
+
27
+ ## What's Changed
28
+ ### 🎉 New features added
29
+ * GroupBy: Add `count` and `agg` methods by @EwoutH in https://github.com/projectmesa/mesa/pull/2290
30
+ * datacollector: Allow collecting data from Agent (sub)classes by @EwoutH in https://github.com/projectmesa/mesa/pull/2300
31
+ * Add optimized shuffle_do() method to AgentSet by @EwoutH in https://github.com/projectmesa/mesa/pull/2283
32
+ ### 🛠 Enhancements made
33
+ * Make cell connections public and named by @Corvince in https://github.com/projectmesa/mesa/pull/2296
34
+ * SolaraViz Updates by @Corvince in https://github.com/projectmesa/mesa/pull/2299
35
+ * Solara viz: use_task for non-threaded continuous play by @Corvince in https://github.com/projectmesa/mesa/pull/2304
36
+ * Update to CellCollection.select by @quaquel in https://github.com/projectmesa/mesa/pull/2307
37
+ ### 📜 Documentation improvements
38
+ * Enforce google docstrings by @quaquel in https://github.com/projectmesa/mesa/pull/2294
39
+ * Api docs by @quaquel in https://github.com/projectmesa/mesa/pull/2298
40
+ * update migration guide to describe solaraviz updates by @Corvince in https://github.com/projectmesa/mesa/pull/2297
41
+ * Migration Guide: Add Model initialization requirement and automatic Agent.unique_id assignment by @EwoutH in https://github.com/projectmesa/mesa/pull/2302
42
+ * Deprecate Time module and all its Schedulers by @EwoutH in https://github.com/projectmesa/mesa/pull/2306
43
+ ### 🔧 Maintenance
44
+ * make typing behavior of AgentSet.get explicit by @quaquel in https://github.com/projectmesa/mesa/pull/2293
45
+ * model: Move random seed and random to __init__ by @rht in https://github.com/projectmesa/mesa/pull/1940
46
+ * Remove schedulers from benchmark models. by @quaquel in https://github.com/projectmesa/mesa/pull/2308
47
+
48
+ **Full Changelog**: https://github.com/projectmesa/mesa/compare/v3.0.0a4...v3.0.0a5
49
+
4
50
  # 3.0.0a4 (2024-09-09)
5
51
  ## Highlights
6
52
  Mesa 3.0.0a4 contains two major breaking changes:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: Mesa
3
- Version: 3.0.0a4
3
+ Version: 3.0.0a5
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
@@ -0,0 +1 @@
1
+ """init file for BoltzmannWealth module."""
@@ -1,8 +1,21 @@
1
- # https://github.com/projectmesa/mesa-examples/blob/main/examples/boltzmann_wealth_model_experimental/model.py
1
+ """boltmann wealth model for performance benchmarking.
2
+
3
+ https://github.com/projectmesa/mesa-examples/blob/main/examples/boltzmann_wealth_model_experimental/model.py
4
+ """
5
+
2
6
  import mesa
3
7
 
4
8
 
5
9
  def compute_gini(model):
10
+ """Calculate gini for wealth in model.
11
+
12
+ Args:
13
+ model: a Model instance
14
+
15
+ Returns:
16
+ float: gini score
17
+
18
+ """
6
19
  agent_wealths = [agent.wealth for agent in model.agents]
7
20
  x = sorted(agent_wealths)
8
21
  n = model.num_agents
@@ -19,10 +32,17 @@ class BoltzmannWealth(mesa.Model):
19
32
  """
20
33
 
21
34
  def __init__(self, seed=None, n=100, width=10, height=10):
22
- super().__init__()
35
+ """Initializes the model.
36
+
37
+ Args:
38
+ seed: the seed for random number generator
39
+ n: the number of agents
40
+ width: the width of the grid
41
+ height: the height of the grid
42
+ """
43
+ super().__init__(seed)
23
44
  self.num_agents = n
24
45
  self.grid = mesa.space.MultiGrid(width, height, True)
25
- self.schedule = mesa.time.RandomActivation(self)
26
46
  self.datacollector = mesa.DataCollector(
27
47
  model_reporters={"Gini": compute_gini}, agent_reporters={"Wealth": "wealth"}
28
48
  )
@@ -38,11 +58,18 @@ class BoltzmannWealth(mesa.Model):
38
58
  self.datacollector.collect(self)
39
59
 
40
60
  def step(self):
41
- self.agents.shuffle().do("step")
61
+ """Run the model for a single step."""
62
+ self.agents.shuffle_do("step")
42
63
  # collect data
43
64
  self.datacollector.collect(self)
44
65
 
45
66
  def run_model(self, n):
67
+ """Run the model for n steps.
68
+
69
+ Args:
70
+ n: the number of steps for which to run the model
71
+
72
+ """
46
73
  for _i in range(n):
47
74
  self.step()
48
75
 
@@ -51,10 +78,16 @@ class MoneyAgent(mesa.Agent):
51
78
  """An agent with fixed initial wealth."""
52
79
 
53
80
  def __init__(self, model):
81
+ """Instantiate an agent.
82
+
83
+ Args:
84
+ model: a Model instance
85
+ """
54
86
  super().__init__(model)
55
87
  self.wealth = 1
56
88
 
57
89
  def move(self):
90
+ """Move the agent to a random neighboring cell."""
58
91
  possible_steps = self.model.grid.get_neighborhood(
59
92
  self.pos, moore=True, include_center=False
60
93
  )
@@ -62,6 +95,7 @@ class MoneyAgent(mesa.Agent):
62
95
  self.model.grid.move_agent(self, new_position)
63
96
 
64
97
  def give_money(self):
98
+ """Give money to a random cell mate."""
65
99
  cellmates = self.model.grid.get_cell_list_contents([self.pos])
66
100
  cellmates.pop(
67
101
  cellmates.index(self)
@@ -72,6 +106,7 @@ class MoneyAgent(mesa.Agent):
72
106
  self.wealth -= 1
73
107
 
74
108
  def step(self):
109
+ """Run the agent for 1 step."""
75
110
  self.move()
76
111
  if self.wealth > 0:
77
112
  self.give_money()
@@ -0,0 +1 @@
1
+ """initi for flocking benchmark model."""
@@ -1,7 +1,5 @@
1
- """
2
- Flockers
3
- =============================================================
4
- A Mesa implementation of Craig Reynolds's Boids flocker model.
1
+ """A Mesa implementation of Craig Reynolds's Boids flocker model.
2
+
5
3
  Uses numpy arrays to represent vectors.
6
4
  """
7
5
 
@@ -11,8 +9,7 @@ import mesa
11
9
 
12
10
 
13
11
  class Boid(mesa.Agent):
14
- """
15
- A Boid-style flocker agent.
12
+ """A Boid-style flocker agent.
16
13
 
17
14
  The agent follows three behaviors to flock:
18
15
  - Cohesion: steering towards neighboring agents.
@@ -36,10 +33,10 @@ class Boid(mesa.Agent):
36
33
  separate=0.015,
37
34
  match=0.05,
38
35
  ):
39
- """
40
- Create a new Boid flocker agent.
36
+ """Create a new Boid flocker agent.
41
37
 
42
38
  Args:
39
+ model: a Model instance
43
40
  speed: Distance to move per step.
44
41
  direction: numpy vector for the Boid's direction of movement.
45
42
  vision: Radius to look around for nearby Boids.
@@ -59,10 +56,7 @@ class Boid(mesa.Agent):
59
56
  self.match_factor = match
60
57
 
61
58
  def step(self):
62
- """
63
- Get the Boid's neighbors, compute the new vector, and move accordingly.
64
- """
65
-
59
+ """Get the Boid's neighbors, compute the new vector, and move accordingly."""
66
60
  neighbors = self.model.space.get_neighbors(self.pos, self.vision, False)
67
61
  n = 0
68
62
  match_vector, separation_vector, cohere = np.zeros((3, 2))
@@ -84,9 +78,7 @@ class Boid(mesa.Agent):
84
78
 
85
79
 
86
80
  class BoidFlockers(mesa.Model):
87
- """
88
- Flocker model class. Handles agent creation, placement and scheduling.
89
- """
81
+ """Flocker model class. Handles agent creation, placement and scheduling."""
90
82
 
91
83
  def __init__(
92
84
  self,
@@ -102,18 +94,21 @@ class BoidFlockers(mesa.Model):
102
94
  match=0.05,
103
95
  simulator=None,
104
96
  ):
105
- """
106
- Create a new Flockers model.
97
+ """Create a new Flockers model.
107
98
 
108
99
  Args:
100
+ seed: seed for random number generator
109
101
  population: Number of Boids
110
- width, height: Size of the space.
102
+ width: the width of the space
103
+ height: the height of the space
111
104
  speed: How fast should the Boids move.
112
105
  vision: How far around should each Boid look for its neighbors
113
- separation: What's the minimum distance each Boid will attempt to
114
- keep from any other
115
- cohere, separate, match: factors for the relative importance of
106
+ separation: What's the minimum distance each Boid will attempt to keep from any other
107
+ cohere: the relative importance of matching neighbors' positions'
108
+ separate: the relative importance of avoiding close neighbors
109
+ match: factors for the relative importance of
116
110
  the three drives.
111
+ simulator: a Simulator Instance
117
112
  """
118
113
  super().__init__(seed=seed)
119
114
  self.population = population
@@ -121,7 +116,6 @@ class BoidFlockers(mesa.Model):
121
116
  self.height = height
122
117
  self.simulator = simulator
123
118
 
124
- self.schedule = mesa.time.RandomActivation(self)
125
119
  self.space = mesa.space.ContinuousSpace(self.width, self.height, True)
126
120
  self.factors = {
127
121
  "cohere": cohere,
@@ -143,10 +137,10 @@ class BoidFlockers(mesa.Model):
143
137
  **self.factors,
144
138
  )
145
139
  self.space.place_agent(boid, pos)
146
- self.schedule.add(boid)
147
140
 
148
141
  def step(self):
149
- self.schedule.step()
142
+ """Run the model for one step."""
143
+ self.agents.shuffle_do("step")
150
144
 
151
145
 
152
146
  if __name__ == "__main__":
@@ -0,0 +1 @@
1
+ """Schelling separation for performance benchmarking."""
@@ -1,19 +1,20 @@
1
+ """Schelling separation for performance benchmarking."""
2
+
1
3
  from mesa import Model
2
4
  from mesa.experimental.cell_space import CellAgent, OrthogonalMooreGrid
3
- from mesa.time import RandomActivation
4
5
 
5
6
 
6
7
  class SchellingAgent(CellAgent):
7
- """
8
- Schelling segregation agent
9
- """
8
+ """Schelling segregation agent."""
10
9
 
11
10
  def __init__(self, model, agent_type, radius, homophily):
12
- """
13
- Create a new Schelling agent.
11
+ """Create a new Schelling agent.
12
+
14
13
  Args:
15
- x, y: Agent initial location.
16
- agent_type: Indicator for the agent's type (minority=1, majority=0)
14
+ model: model instance
15
+ agent_type: type of agent (minority=1, majority=0)
16
+ radius: size of neighborhood of agent
17
+ homophily: fraction of neighbors of the same type that triggers movement
17
18
  """
18
19
  super().__init__(model)
19
20
  self.type = agent_type
@@ -21,8 +22,9 @@ class SchellingAgent(CellAgent):
21
22
  self.homophily = homophily
22
23
 
23
24
  def step(self):
25
+ """Run one step of the agent."""
24
26
  similar = 0
25
- neighborhood = self.cell.neighborhood(radius=self.radius)
27
+ neighborhood = self.cell.get_neighborhood(radius=self.radius)
26
28
  for neighbor in neighborhood.agents:
27
29
  if neighbor.type == self.type:
28
30
  similar += 1
@@ -35,9 +37,7 @@ class SchellingAgent(CellAgent):
35
37
 
36
38
 
37
39
  class Schelling(Model):
38
- """
39
- Model class for the Schelling segregation model.
40
- """
40
+ """Model class for the Schelling segregation model."""
41
41
 
42
42
  def __init__(
43
43
  self,
@@ -50,22 +50,22 @@ class Schelling(Model):
50
50
  seed=None,
51
51
  simulator=None,
52
52
  ):
53
- """
54
- Create a new Schelling model.
53
+ """Create a new Schelling model.
55
54
 
56
55
  Args:
57
- height, width: Size of the space.
58
- density: Initial Chance for a cell to populated
59
- minority_pc: Chances for an agent to be in minority class
56
+ height: height of the grid
57
+ width: width of the grid
60
58
  homophily: Minimum number of agents of same class needed to be happy
61
59
  radius: Search radius for checking similarity
62
- seed: Seed for Reproducibility
60
+ density: Initial Chance for a cell to populated
61
+ minority_pc: Chances for an agent to be in minority class
62
+ seed: the seed for the random number generator
63
+ simulator: a simulator instance
63
64
  """
64
65
  super().__init__(seed=seed)
65
66
  self.minority_pc = minority_pc
66
67
  self.simulator = simulator
67
68
 
68
- self.schedule = RandomActivation(self)
69
69
  self.grid = OrthogonalMooreGrid(
70
70
  [height, width],
71
71
  torus=True,
@@ -82,14 +82,11 @@ class Schelling(Model):
82
82
  agent_type = 1 if self.random.random() < self.minority_pc else 0
83
83
  agent = SchellingAgent(self, agent_type, radius, homophily)
84
84
  agent.move_to(cell)
85
- self.schedule.add(agent)
86
85
 
87
86
  def step(self):
88
- """
89
- Run one step of the model.
90
- """
87
+ """Run one step of the model."""
91
88
  self.happy = 0 # Reset counter of happy agents
92
- self.schedule.step()
89
+ self.agents.shuffle_do("step")
93
90
 
94
91
 
95
92
  if __name__ == "__main__":
@@ -0,0 +1 @@
1
+ """Wolf-Sheep Predation Model for performance benchmarking."""
@@ -1,6 +1,4 @@
1
- """
2
- Wolf-Sheep Predation Model
3
- ================================
1
+ """Wolf-Sheep Predation Model for performance benchmarking.
4
2
 
5
3
  Replication of the model found in NetLogo:
6
4
  Wilensky, U. (1997). NetLogo Wolf Sheep Predation model.
@@ -17,16 +15,28 @@ from mesa.experimental.devs import ABMSimulator
17
15
 
18
16
 
19
17
  class Animal(CellAgent):
18
+ """The base animal class."""
19
+
20
20
  def __init__(self, model, energy, p_reproduce, energy_from_food):
21
+ """Initializes an animal.
22
+
23
+ Args:
24
+ model: a model instance
25
+ energy: starting amount of energy
26
+ p_reproduce: probability of sexless reproduction
27
+ energy_from_food: energy obtained from 1 unit of food
28
+ """
21
29
  super().__init__(model)
22
30
  self.energy = energy
23
31
  self.p_reproduce = p_reproduce
24
32
  self.energy_from_food = energy_from_food
25
33
 
26
34
  def random_move(self):
27
- self.move_to(self.cell.neighborhood().select_random_cell())
35
+ """Move to a random neighboring cell."""
36
+ self.move_to(self.cell.neighborhood.select_random_cell())
28
37
 
29
38
  def spawn_offspring(self):
39
+ """Create offspring."""
30
40
  self.energy /= 2
31
41
  offspring = self.__class__(
32
42
  self.model,
@@ -36,13 +46,15 @@ class Animal(CellAgent):
36
46
  )
37
47
  offspring.move_to(self.cell)
38
48
 
39
- def feed(self): ...
49
+ def feed(self): ... # noqa: D102
40
50
 
41
51
  def die(self):
52
+ """Die."""
42
53
  self.cell.remove_agent(self)
43
54
  self.remove()
44
55
 
45
56
  def step(self):
57
+ """One step of the agent."""
46
58
  self.random_move()
47
59
  self.energy -= 1
48
60
 
@@ -55,13 +67,10 @@ class Animal(CellAgent):
55
67
 
56
68
 
57
69
  class Sheep(Animal):
58
- """
59
- A sheep that walks around, reproduces (asexually) and gets eaten.
60
-
61
- The init is the same as the RandomWalker.
62
- """
70
+ """A sheep that walks around, reproduces (asexually) and gets eaten."""
63
71
 
64
72
  def feed(self):
73
+ """If possible eat the food in the current location."""
65
74
  # If there is grass available, eat it
66
75
  grass_patch = next(
67
76
  obj for obj in self.cell.agents if isinstance(obj, GrassPatch)
@@ -72,11 +81,10 @@ class Sheep(Animal):
72
81
 
73
82
 
74
83
  class Wolf(Animal):
75
- """
76
- A wolf that walks around, reproduces (asexually) and eats sheep.
77
- """
84
+ """A wolf that walks around, reproduces (asexually) and eats sheep."""
78
85
 
79
86
  def feed(self):
87
+ """If possible eat the food in the current location."""
80
88
  sheep = [obj for obj in self.cell.agents if isinstance(obj, Sheep)]
81
89
  if len(sheep) > 0:
82
90
  sheep_to_eat = self.random.choice(sheep)
@@ -87,12 +95,10 @@ class Wolf(Animal):
87
95
 
88
96
 
89
97
  class GrassPatch(CellAgent):
90
- """
91
- A patch of grass that grows at a fixed rate and it is eaten by sheep
92
- """
98
+ """A patch of grass that grows at a fixed rate and it is eaten by sheep."""
93
99
 
94
100
  @property
95
- def fully_grown(self):
101
+ def fully_grown(self): # noqa: D102
96
102
  return self._fully_grown
97
103
 
98
104
  @fully_grown.setter
@@ -107,17 +113,15 @@ class GrassPatch(CellAgent):
107
113
  )
108
114
 
109
115
  def __init__(self, model, fully_grown, countdown, grass_regrowth_time):
110
- """
111
- TODO:: fully grown can just be an int --> so one less param (i.e. countdown)
112
-
113
- Creates a new patch of grass
116
+ """Creates a new patch of grass.
114
117
 
115
118
  Args:
119
+ model: a model instance
116
120
  fully_grown: (boolean) Whether the patch of grass is fully grown or not
117
121
  countdown: Time for the patch of grass to be fully grown again
118
122
  grass_regrowth_time : time to fully regrow grass
119
- countdown : Time for the patch of grass to be fully regrown if fully grown is False
120
123
  """
124
+ # TODO:: fully grown can just be an int --> so one less param (i.e. countdown)
121
125
  super().__init__(model)
122
126
  self._fully_grown = fully_grown
123
127
  self.grass_regrowth_time = grass_regrowth_time
@@ -129,8 +133,7 @@ class GrassPatch(CellAgent):
129
133
 
130
134
 
131
135
  class WolfSheep(Model):
132
- """
133
- Wolf-Sheep Predation Model
136
+ """Wolf-Sheep Predation Model.
134
137
 
135
138
  A model for simulating wolf and sheep (predator-prey) ecosystem modelling.
136
139
  """
@@ -149,18 +152,19 @@ class WolfSheep(Model):
149
152
  sheep_gain_from_food=5,
150
153
  seed=None,
151
154
  ):
152
- """
153
- Create a new Wolf-Sheep model with the given parameters.
155
+ """Create a new Wolf-Sheep model with the given parameters.
154
156
 
155
157
  Args:
156
158
  simulator: ABMSimulator instance
159
+ width: width of the grid
160
+ height: height of the grid
157
161
  initial_sheep: Number of sheep to start with
158
162
  initial_wolves: Number of wolves to start with
159
163
  sheep_reproduce: Probability of each sheep reproducing each step
160
164
  wolf_reproduce: Probability of each wolf reproducing each step
161
- wolf_gain_from_food: Energy a wolf gains from eating a sheep
162
165
  grass_regrowth_time: How long it takes for a grass patch to regrow
163
166
  once it is eaten
167
+ wolf_gain_from_food: Energy a wolf gains from eating a sheep
164
168
  sheep_gain_from_food: Energy sheep gain from grass, if enabled.
165
169
  seed : the random seed
166
170
  """
@@ -222,8 +226,9 @@ class WolfSheep(Model):
222
226
  patch.move_to(cell)
223
227
 
224
228
  def step(self):
225
- self.agents_by_type[Sheep].shuffle(inplace=True).do("step")
226
- self.agents_by_type[Wolf].shuffle(inplace=True).do("step")
229
+ """Run one step of the model."""
230
+ self.agents_by_type[Sheep].shuffle_do("step")
231
+ self.agents_by_type[Wolf].shuffle_do("step")
227
232
 
228
233
 
229
234
  if __name__ == "__main__":
@@ -1,3 +1,5 @@
1
+ """compare timings across 2 benchmarks."""
2
+
1
3
  import pickle
2
4
 
3
5
  import numpy as np
@@ -13,8 +15,17 @@ with open(f"{filename2}.pickle", "rb") as handle:
13
15
  timings_2 = pickle.load(handle) # noqa: S301
14
16
 
15
17
 
16
- # Function to calculate the percentage change and perform bootstrap to estimate the confidence interval
17
18
  def bootstrap_percentage_change_confidence_interval(data1, data2, n=1000):
19
+ """Calculate the percentage change and perform bootstrap to estimate the confidence interval.
20
+
21
+ Args:
22
+ data1: benchmark dataset 1
23
+ data2: benchmark dataset 2
24
+ n: bootstrap sample size
25
+
26
+ Returns:
27
+ float, mean, and lower and upper bound of confidence interval.
28
+ """
18
29
  change_samples = []
19
30
  for _ in range(n):
20
31
  sampled_indices = np.random.choice(
@@ -32,8 +43,8 @@ def bootstrap_percentage_change_confidence_interval(data1, data2, n=1000):
32
43
  results_df = pd.DataFrame()
33
44
 
34
45
 
35
- # Function to determine the emoji based on change and confidence interval
36
46
  def performance_emoji(lower, upper):
47
+ """Function to determine the emoji based on change and confidence interval."""
37
48
  if upper < -3:
38
49
  return "🟢" # Emoji for faster performance
39
50
  elif lower > 3:
@@ -1,3 +1,5 @@
1
+ """configurations for benchmarks."""
2
+
1
3
  from BoltzmannWealth.boltzmann_wealth import BoltzmannWealth
2
4
  from Flocking.flocking import BoidFlockers
3
5
  from Schelling.schelling import Schelling
@@ -1,3 +1,5 @@
1
+ """runner for global performance benchmarks."""
2
+
1
3
  import gc
2
4
  import os
3
5
  import pickle
@@ -16,6 +18,16 @@ sys.path.insert(0, os.path.abspath(".."))
16
18
 
17
19
  # Generic function to initialize and run a model
18
20
  def run_model(model_class, seed, parameters):
21
+ """Run model for given seed and parameter values.
22
+
23
+ Args:
24
+ model_class: a model class
25
+ seed: the seed
26
+ parameters: parameters for the run
27
+
28
+ Returns:
29
+ startup time and run time
30
+ """
19
31
  no_simulator = ["BoltzmannWealth"]
20
32
  start_init = timeit.default_timer()
21
33
  if model_class.__name__ in no_simulator:
@@ -39,6 +51,13 @@ def run_model(model_class, seed, parameters):
39
51
 
40
52
  # Function to run experiments and save the fastest replication for each seed
41
53
  def run_experiments(model_class, config):
54
+ """Run performance benchmarks.
55
+
56
+ Args:
57
+ model_class: the model class to use for the benchmark
58
+ config: the benchmark configuration
59
+
60
+ """
42
61
  gc.enable()
43
62
  sys.path.insert(0, os.path.abspath("."))
44
63
 
@@ -0,0 +1,8 @@
1
+ # Agent
2
+
3
+
4
+ ```{eval-rst}
5
+ .. automodule:: mesa.agent
6
+ :members:
7
+ :inherited-members:
8
+ ```
@@ -3,7 +3,8 @@
3
3
  ```{toctree}
4
4
  :maxdepth: 3
5
5
 
6
- Base Classes <init>
6
+ model
7
+ agent
7
8
  time
8
9
  space
9
10
  datacollection
@@ -1,3 +1,5 @@
1
+ # Batchrunner
2
+
1
3
  ```{eval-rst}
2
4
  .. automodule:: batchrunner
3
5
  :members:
@@ -1,3 +1,5 @@
1
+ # Data collection
2
+
1
3
  ```{eval-rst}
2
4
  .. automodule:: datacollection
3
5
  :members:
@@ -1,9 +1,5 @@
1
1
  # Experimental
2
-
3
- ```{eval-rst}
4
- .. automodule:: experimental.__init__
5
- :members:
6
- ```
2
+ This namespace contains experimental features. These are under development, and their API is not necessarily stable.
7
3
 
8
4
  ## Cell Space
9
5