Mesa 3.0.0a4__py3-none-any.whl → 3.0.0a5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of Mesa might be problematic. Click here for more details.
- mesa/__init__.py +2 -3
- mesa/agent.py +106 -61
- mesa/batchrunner.py +15 -23
- mesa/cookiecutter-mesa/hooks/post_gen_project.py +2 -0
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/__init__.py +1 -0
- mesa/datacollection.py +138 -27
- mesa/experimental/UserParam.py +17 -6
- mesa/experimental/__init__.py +2 -0
- mesa/experimental/cell_space/__init__.py +7 -0
- mesa/experimental/cell_space/cell.py +61 -20
- mesa/experimental/cell_space/cell_agent.py +10 -5
- mesa/experimental/cell_space/cell_collection.py +54 -17
- mesa/experimental/cell_space/discrete_space.py +16 -5
- mesa/experimental/cell_space/grid.py +19 -8
- mesa/experimental/cell_space/network.py +9 -7
- mesa/experimental/cell_space/voronoi.py +26 -33
- mesa/experimental/components/altair.py +10 -0
- mesa/experimental/components/matplotlib.py +18 -0
- mesa/experimental/devs/__init__.py +2 -0
- mesa/experimental/devs/eventlist.py +36 -15
- mesa/experimental/devs/examples/epstein_civil_violence.py +65 -29
- mesa/experimental/devs/examples/wolf_sheep.py +38 -34
- mesa/experimental/devs/simulator.py +55 -15
- mesa/experimental/solara_viz.py +10 -19
- mesa/main.py +6 -4
- mesa/model.py +43 -45
- mesa/space.py +145 -120
- mesa/time.py +57 -67
- mesa/visualization/UserParam.py +19 -6
- mesa/visualization/__init__.py +3 -2
- mesa/visualization/components/altair.py +4 -2
- mesa/visualization/components/matplotlib.py +6 -4
- mesa/visualization/solara_viz.py +157 -83
- mesa/visualization/utils.py +3 -1
- {mesa-3.0.0a4.dist-info → mesa-3.0.0a5.dist-info}/METADATA +1 -1
- mesa-3.0.0a5.dist-info/RECORD +44 -0
- mesa-3.0.0a4.dist-info/RECORD +0 -44
- {mesa-3.0.0a4.dist-info → mesa-3.0.0a5.dist-info}/WHEEL +0 -0
- {mesa-3.0.0a4.dist-info → mesa-3.0.0a5.dist-info}/entry_points.txt +0 -0
- {mesa-3.0.0a4.dist-info → mesa-3.0.0a5.dist-info}/licenses/LICENSE +0 -0
mesa/__init__.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Mesa Agent-Based Modeling Framework
|
|
1
|
+
"""Mesa Agent-Based Modeling Framework.
|
|
3
2
|
|
|
4
3
|
Core Objects: Model, and Agent.
|
|
5
4
|
"""
|
|
@@ -24,7 +23,7 @@ __all__ = [
|
|
|
24
23
|
]
|
|
25
24
|
|
|
26
25
|
__title__ = "mesa"
|
|
27
|
-
__version__ = "3.0.
|
|
26
|
+
__version__ = "3.0.0a5"
|
|
28
27
|
__license__ = "Apache 2.0"
|
|
29
28
|
_this_year = datetime.datetime.now(tz=datetime.timezone.utc).date().year
|
|
30
29
|
__copyright__ = f"Copyright {_this_year} Project Mesa Team"
|
mesa/agent.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
"""
|
|
2
|
-
The agent class for Mesa framework.
|
|
1
|
+
"""Agent related classes.
|
|
3
2
|
|
|
4
|
-
Core Objects: Agent
|
|
3
|
+
Core Objects: Agent and AgentSet.
|
|
5
4
|
"""
|
|
6
5
|
|
|
7
6
|
# Mypy; for the `|` operator purpose
|
|
@@ -16,11 +15,11 @@ import operator
|
|
|
16
15
|
import warnings
|
|
17
16
|
import weakref
|
|
18
17
|
from collections import defaultdict
|
|
19
|
-
from collections.abc import Callable, Iterable, Iterator, MutableSet, Sequence
|
|
18
|
+
from collections.abc import Callable, Hashable, Iterable, Iterator, MutableSet, Sequence
|
|
20
19
|
from random import Random
|
|
21
20
|
|
|
22
21
|
# mypy
|
|
23
|
-
from typing import TYPE_CHECKING, Any, Literal
|
|
22
|
+
from typing import TYPE_CHECKING, Any, Literal, overload
|
|
24
23
|
|
|
25
24
|
if TYPE_CHECKING:
|
|
26
25
|
# We ensure that these are not imported during runtime to prevent cyclic
|
|
@@ -30,8 +29,7 @@ if TYPE_CHECKING:
|
|
|
30
29
|
|
|
31
30
|
|
|
32
31
|
class Agent:
|
|
33
|
-
"""
|
|
34
|
-
Base class for a model agent in Mesa.
|
|
32
|
+
"""Base class for a model agent in Mesa.
|
|
35
33
|
|
|
36
34
|
Attributes:
|
|
37
35
|
model (Model): A reference to the model instance.
|
|
@@ -49,11 +47,12 @@ class Agent:
|
|
|
49
47
|
_ids = defaultdict(functools.partial(itertools.count, 1))
|
|
50
48
|
|
|
51
49
|
def __init__(self, *args, **kwargs) -> None:
|
|
52
|
-
"""
|
|
53
|
-
Create a new agent.
|
|
50
|
+
"""Create a new agent.
|
|
54
51
|
|
|
55
52
|
Args:
|
|
56
53
|
model (Model): The model instance in which the agent exists.
|
|
54
|
+
args: currently ignored, to be fixed in 3.1
|
|
55
|
+
kwargs: currently ignored, to be fixed in 3.1
|
|
57
56
|
"""
|
|
58
57
|
# TODO: Cleanup in future Mesa version (3.1+)
|
|
59
58
|
match args:
|
|
@@ -89,28 +88,25 @@ class Agent:
|
|
|
89
88
|
def step(self) -> None:
|
|
90
89
|
"""A single step of the agent."""
|
|
91
90
|
|
|
92
|
-
def advance(self) -> None:
|
|
91
|
+
def advance(self) -> None: # noqa: D102
|
|
93
92
|
pass
|
|
94
93
|
|
|
95
94
|
@property
|
|
96
95
|
def random(self) -> Random:
|
|
96
|
+
"""Return a seeded rng."""
|
|
97
97
|
return self.model.random
|
|
98
98
|
|
|
99
99
|
|
|
100
100
|
class AgentSet(MutableSet, Sequence):
|
|
101
|
-
"""
|
|
102
|
-
|
|
103
|
-
extends both MutableSet and Sequence, providing set-like functionality with order preservation and
|
|
101
|
+
"""A collection class that represents an ordered set of agents within an agent-based model (ABM).
|
|
102
|
+
|
|
103
|
+
This class extends both MutableSet and Sequence, providing set-like functionality with order preservation and
|
|
104
104
|
sequence operations.
|
|
105
105
|
|
|
106
106
|
Attributes:
|
|
107
107
|
model (Model): The ABM model instance to which this AgentSet belongs.
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
__len__, __iter__, __contains__, select, shuffle, sort, _update, do, get, __getitem__,
|
|
111
|
-
add, discard, remove, __getstate__, __setstate__, random
|
|
112
|
-
|
|
113
|
-
Note:
|
|
109
|
+
Notes:
|
|
114
110
|
The AgentSet maintains weak references to agents, allowing for efficient management of agent lifecycles
|
|
115
111
|
without preventing garbage collection. It is associated with a specific model instance, enabling
|
|
116
112
|
interactions with the model's environment and other agents.The implementation uses a WeakKeyDictionary to store agents,
|
|
@@ -118,14 +114,12 @@ class AgentSet(MutableSet, Sequence):
|
|
|
118
114
|
"""
|
|
119
115
|
|
|
120
116
|
def __init__(self, agents: Iterable[Agent], model: Model):
|
|
121
|
-
"""
|
|
122
|
-
Initializes the AgentSet with a collection of agents and a reference to the model.
|
|
117
|
+
"""Initializes the AgentSet with a collection of agents and a reference to the model.
|
|
123
118
|
|
|
124
119
|
Args:
|
|
125
120
|
agents (Iterable[Agent]): An iterable of Agent objects to be included in the set.
|
|
126
121
|
model (Model): The ABM model instance to which this AgentSet belongs.
|
|
127
122
|
"""
|
|
128
|
-
|
|
129
123
|
self.model = model
|
|
130
124
|
self._agents = weakref.WeakKeyDictionary({agent: None for agent in agents})
|
|
131
125
|
|
|
@@ -149,8 +143,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
149
143
|
agent_type: type[Agent] | None = None,
|
|
150
144
|
n: int | None = None,
|
|
151
145
|
) -> AgentSet:
|
|
152
|
-
"""
|
|
153
|
-
Select a subset of agents from the AgentSet based on a filter function and/or quantity limit.
|
|
146
|
+
"""Select a subset of agents from the AgentSet based on a filter function and/or quantity limit.
|
|
154
147
|
|
|
155
148
|
Args:
|
|
156
149
|
filter_func (Callable[[Agent], bool], optional): A function that takes an Agent and returns True if the
|
|
@@ -160,6 +153,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
160
153
|
- If a float between 0 and 1, at most that fraction of original the agents are selected.
|
|
161
154
|
inplace (bool, optional): If True, modifies the current AgentSet; otherwise, returns a new AgentSet. Defaults to False.
|
|
162
155
|
agent_type (type[Agent], optional): The class type of the agents to select. Defaults to None, meaning no type filtering is applied.
|
|
156
|
+
n (int): deprecated, use at_most instead
|
|
163
157
|
|
|
164
158
|
Returns:
|
|
165
159
|
AgentSet: A new AgentSet containing the selected agents, unless inplace is True, in which case the current AgentSet is updated.
|
|
@@ -200,8 +194,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
200
194
|
return AgentSet(agents, self.model) if not inplace else self._update(agents)
|
|
201
195
|
|
|
202
196
|
def shuffle(self, inplace: bool = False) -> AgentSet:
|
|
203
|
-
"""
|
|
204
|
-
Randomly shuffle the order of agents in the AgentSet.
|
|
197
|
+
"""Randomly shuffle the order of agents in the AgentSet.
|
|
205
198
|
|
|
206
199
|
Args:
|
|
207
200
|
inplace (bool, optional): If True, shuffles the agents in the current AgentSet; otherwise, returns a new shuffled AgentSet. Defaults to False.
|
|
@@ -230,8 +223,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
230
223
|
ascending: bool = False,
|
|
231
224
|
inplace: bool = False,
|
|
232
225
|
) -> AgentSet:
|
|
233
|
-
"""
|
|
234
|
-
Sort the agents in the AgentSet based on a specified attribute or custom function.
|
|
226
|
+
"""Sort the agents in the AgentSet based on a specified attribute or custom function.
|
|
235
227
|
|
|
236
228
|
Args:
|
|
237
229
|
key (Callable[[Agent], Any] | str): A function or attribute name based on which the agents are sorted.
|
|
@@ -254,15 +246,14 @@ class AgentSet(MutableSet, Sequence):
|
|
|
254
246
|
|
|
255
247
|
def _update(self, agents: Iterable[Agent]):
|
|
256
248
|
"""Update the AgentSet with a new set of agents.
|
|
249
|
+
|
|
257
250
|
This is a private method primarily used internally by other methods like select, shuffle, and sort.
|
|
258
251
|
"""
|
|
259
|
-
|
|
260
252
|
self._agents = weakref.WeakKeyDictionary({agent: None for agent in agents})
|
|
261
253
|
return self
|
|
262
254
|
|
|
263
255
|
def do(self, method: str | Callable, *args, **kwargs) -> AgentSet:
|
|
264
|
-
"""
|
|
265
|
-
Invoke a method or function on each agent in the AgentSet.
|
|
256
|
+
"""Invoke a method or function on each agent in the AgentSet.
|
|
266
257
|
|
|
267
258
|
Args:
|
|
268
259
|
method (str, callable): the callable to do on each agent
|
|
@@ -302,9 +293,25 @@ class AgentSet(MutableSet, Sequence):
|
|
|
302
293
|
|
|
303
294
|
return self
|
|
304
295
|
|
|
305
|
-
def
|
|
296
|
+
def shuffle_do(self, method: str | Callable, *args, **kwargs) -> AgentSet:
|
|
297
|
+
"""Shuffle the agents in the AgentSet and then invoke a method or function on each agent.
|
|
298
|
+
|
|
299
|
+
It's a fast, optimized version of calling shuffle() followed by do().
|
|
306
300
|
"""
|
|
307
|
-
|
|
301
|
+
agents = list(self._agents.keys())
|
|
302
|
+
self.random.shuffle(agents)
|
|
303
|
+
|
|
304
|
+
if isinstance(method, str):
|
|
305
|
+
for agent in agents:
|
|
306
|
+
getattr(agent, method)(*args, **kwargs)
|
|
307
|
+
else:
|
|
308
|
+
for agent in agents:
|
|
309
|
+
method(agent, *args, **kwargs)
|
|
310
|
+
|
|
311
|
+
return self
|
|
312
|
+
|
|
313
|
+
def map(self, method: str | Callable, *args, **kwargs) -> list[Any]:
|
|
314
|
+
"""Invoke a method or function on each agent in the AgentSet and return the results.
|
|
308
315
|
|
|
309
316
|
Args:
|
|
310
317
|
method (str, callable): the callable to apply on each agent
|
|
@@ -335,8 +342,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
335
342
|
return res
|
|
336
343
|
|
|
337
344
|
def agg(self, attribute: str, func: Callable) -> Any:
|
|
338
|
-
"""
|
|
339
|
-
Aggregate an attribute of all agents in the AgentSet using a specified function.
|
|
345
|
+
"""Aggregate an attribute of all agents in the AgentSet using a specified function.
|
|
340
346
|
|
|
341
347
|
Args:
|
|
342
348
|
attribute (str): The name of the attribute to aggregate.
|
|
@@ -348,14 +354,29 @@ class AgentSet(MutableSet, Sequence):
|
|
|
348
354
|
values = self.get(attribute)
|
|
349
355
|
return func(values)
|
|
350
356
|
|
|
357
|
+
@overload
|
|
351
358
|
def get(
|
|
352
359
|
self,
|
|
353
|
-
attr_names: str
|
|
360
|
+
attr_names: str,
|
|
354
361
|
handle_missing: Literal["error", "default"] = "error",
|
|
355
362
|
default_value: Any = None,
|
|
356
|
-
) -> list[Any]
|
|
357
|
-
|
|
358
|
-
|
|
363
|
+
) -> list[Any]: ...
|
|
364
|
+
|
|
365
|
+
@overload
|
|
366
|
+
def get(
|
|
367
|
+
self,
|
|
368
|
+
attr_names: list[str],
|
|
369
|
+
handle_missing: Literal["error", "default"] = "error",
|
|
370
|
+
default_value: Any = None,
|
|
371
|
+
) -> list[list[Any]]: ...
|
|
372
|
+
|
|
373
|
+
def get(
|
|
374
|
+
self,
|
|
375
|
+
attr_names,
|
|
376
|
+
handle_missing="error",
|
|
377
|
+
default_value=None,
|
|
378
|
+
):
|
|
379
|
+
"""Retrieve the specified attribute(s) from each agent in the AgentSet.
|
|
359
380
|
|
|
360
381
|
Args:
|
|
361
382
|
attr_names (str | list[str]): The name(s) of the attribute(s) to retrieve from each agent.
|
|
@@ -402,8 +423,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
402
423
|
)
|
|
403
424
|
|
|
404
425
|
def set(self, attr_name: str, value: Any) -> AgentSet:
|
|
405
|
-
"""
|
|
406
|
-
Set a specified attribute to a given value for all agents in the AgentSet.
|
|
426
|
+
"""Set a specified attribute to a given value for all agents in the AgentSet.
|
|
407
427
|
|
|
408
428
|
Args:
|
|
409
429
|
attr_name (str): The name of the attribute to set.
|
|
@@ -417,8 +437,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
417
437
|
return self
|
|
418
438
|
|
|
419
439
|
def __getitem__(self, item: int | slice) -> Agent:
|
|
420
|
-
"""
|
|
421
|
-
Retrieve an agent or a slice of agents from the AgentSet.
|
|
440
|
+
"""Retrieve an agent or a slice of agents from the AgentSet.
|
|
422
441
|
|
|
423
442
|
Args:
|
|
424
443
|
item (int | slice): The index or slice for selecting agents.
|
|
@@ -429,8 +448,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
429
448
|
return list(self._agents.keys())[item]
|
|
430
449
|
|
|
431
450
|
def add(self, agent: Agent):
|
|
432
|
-
"""
|
|
433
|
-
Add an agent to the AgentSet.
|
|
451
|
+
"""Add an agent to the AgentSet.
|
|
434
452
|
|
|
435
453
|
Args:
|
|
436
454
|
agent (Agent): The agent to add to the set.
|
|
@@ -441,8 +459,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
441
459
|
self._agents[agent] = None
|
|
442
460
|
|
|
443
461
|
def discard(self, agent: Agent):
|
|
444
|
-
"""
|
|
445
|
-
Remove an agent from the AgentSet if it exists.
|
|
462
|
+
"""Remove an agent from the AgentSet if it exists.
|
|
446
463
|
|
|
447
464
|
This method does not raise an error if the agent is not present.
|
|
448
465
|
|
|
@@ -456,8 +473,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
456
473
|
del self._agents[agent]
|
|
457
474
|
|
|
458
475
|
def remove(self, agent: Agent):
|
|
459
|
-
"""
|
|
460
|
-
Remove an agent from the AgentSet.
|
|
476
|
+
"""Remove an agent from the AgentSet.
|
|
461
477
|
|
|
462
478
|
This method raises an error if the agent is not present.
|
|
463
479
|
|
|
@@ -470,8 +486,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
470
486
|
del self._agents[agent]
|
|
471
487
|
|
|
472
488
|
def __getstate__(self):
|
|
473
|
-
"""
|
|
474
|
-
Retrieve the state of the AgentSet for serialization.
|
|
489
|
+
"""Retrieve the state of the AgentSet for serialization.
|
|
475
490
|
|
|
476
491
|
Returns:
|
|
477
492
|
dict: A dictionary representing the state of the AgentSet.
|
|
@@ -479,8 +494,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
479
494
|
return {"agents": list(self._agents.keys()), "model": self.model}
|
|
480
495
|
|
|
481
496
|
def __setstate__(self, state):
|
|
482
|
-
"""
|
|
483
|
-
Set the state of the AgentSet during deserialization.
|
|
497
|
+
"""Set the state of the AgentSet during deserialization.
|
|
484
498
|
|
|
485
499
|
Args:
|
|
486
500
|
state (dict): A dictionary representing the state to restore.
|
|
@@ -490,8 +504,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
490
504
|
|
|
491
505
|
@property
|
|
492
506
|
def random(self) -> Random:
|
|
493
|
-
"""
|
|
494
|
-
Provide access to the model's random number generator.
|
|
507
|
+
"""Provide access to the model's random number generator.
|
|
495
508
|
|
|
496
509
|
Returns:
|
|
497
510
|
Random: The random number generator associated with the model.
|
|
@@ -499,8 +512,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
499
512
|
return self.model.random
|
|
500
513
|
|
|
501
514
|
def groupby(self, by: Callable | str, result_type: str = "agentset") -> GroupBy:
|
|
502
|
-
"""
|
|
503
|
-
Group agents by the specified attribute or return from the callable
|
|
515
|
+
"""Group agents by the specified attribute or return from the callable.
|
|
504
516
|
|
|
505
517
|
Args:
|
|
506
518
|
by (Callable, str): used to determine what to group agents by
|
|
@@ -510,6 +522,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
510
522
|
* if ``by`` is a str, it should refer to an attribute on the agent and the value
|
|
511
523
|
of this attribute will be used for grouping
|
|
512
524
|
result_type (str, optional): The datatype for the resulting groups {"agentset", "list"}
|
|
525
|
+
|
|
513
526
|
Returns:
|
|
514
527
|
GroupBy
|
|
515
528
|
|
|
@@ -541,8 +554,7 @@ class AgentSet(MutableSet, Sequence):
|
|
|
541
554
|
|
|
542
555
|
|
|
543
556
|
class GroupBy:
|
|
544
|
-
"""Helper class for AgentSet.groupby
|
|
545
|
-
|
|
557
|
+
"""Helper class for AgentSet.groupby.
|
|
546
558
|
|
|
547
559
|
Attributes:
|
|
548
560
|
groups (dict): A dictionary with the group_name as key and group as values
|
|
@@ -550,6 +562,12 @@ class GroupBy:
|
|
|
550
562
|
"""
|
|
551
563
|
|
|
552
564
|
def __init__(self, groups: dict[Any, list | AgentSet]):
|
|
565
|
+
"""Initialize a GroupBy instance.
|
|
566
|
+
|
|
567
|
+
Args:
|
|
568
|
+
groups (dict): A dictionary with the group_name as key and group as values
|
|
569
|
+
|
|
570
|
+
"""
|
|
553
571
|
self.groups: dict[Any, list | AgentSet] = groups
|
|
554
572
|
|
|
555
573
|
def map(self, method: Callable | str, *args, **kwargs) -> dict[Any, Any]:
|
|
@@ -562,6 +580,8 @@ class GroupBy:
|
|
|
562
580
|
* if ``method`` is a str, it should refer to a method on the group
|
|
563
581
|
|
|
564
582
|
Additional arguments and keyword arguments will be passed on to the callable.
|
|
583
|
+
args: arguments to pass to the callable
|
|
584
|
+
kwargs: keyword arguments to pass to the callable
|
|
565
585
|
|
|
566
586
|
Returns:
|
|
567
587
|
dict with group_name as key and the return of the method as value
|
|
@@ -579,7 +599,7 @@ class GroupBy:
|
|
|
579
599
|
return {k: method(v, *args, **kwargs) for k, v in self.groups.items()}
|
|
580
600
|
|
|
581
601
|
def do(self, method: Callable | str, *args, **kwargs) -> GroupBy:
|
|
582
|
-
"""Apply the specified callable to each group
|
|
602
|
+
"""Apply the specified callable to each group.
|
|
583
603
|
|
|
584
604
|
Args:
|
|
585
605
|
method (Callable, str): The callable to apply to each group,
|
|
@@ -588,6 +608,8 @@ class GroupBy:
|
|
|
588
608
|
* if ``method`` is a str, it should refer to a method on the group
|
|
589
609
|
|
|
590
610
|
Additional arguments and keyword arguments will be passed on to the callable.
|
|
611
|
+
args: arguments to pass to the callable
|
|
612
|
+
kwargs: keyword arguments to pass to the callable
|
|
591
613
|
|
|
592
614
|
Returns:
|
|
593
615
|
the original GroupBy instance
|
|
@@ -606,8 +628,31 @@ class GroupBy:
|
|
|
606
628
|
|
|
607
629
|
return self
|
|
608
630
|
|
|
609
|
-
def
|
|
631
|
+
def count(self) -> dict[Any, int]:
|
|
632
|
+
"""Return the count of agents in each group.
|
|
633
|
+
|
|
634
|
+
Returns:
|
|
635
|
+
dict: A dictionary mapping group names to the number of agents in each group.
|
|
636
|
+
"""
|
|
637
|
+
return {k: len(v) for k, v in self.groups.items()}
|
|
638
|
+
|
|
639
|
+
def agg(self, attr_name: str, func: Callable) -> dict[Hashable, Any]:
|
|
640
|
+
"""Aggregate the values of a specific attribute across each group using the provided function.
|
|
641
|
+
|
|
642
|
+
Args:
|
|
643
|
+
attr_name (str): The name of the attribute to aggregate.
|
|
644
|
+
func (Callable): The function to apply (e.g., sum, min, max, mean).
|
|
645
|
+
|
|
646
|
+
Returns:
|
|
647
|
+
dict[Hashable, Any]: A dictionary mapping group names to the result of applying the aggregation function.
|
|
648
|
+
"""
|
|
649
|
+
return {
|
|
650
|
+
group_name: func([getattr(agent, attr_name) for agent in group])
|
|
651
|
+
for group_name, group in self.groups.items()
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
def __iter__(self): # noqa: D105
|
|
610
655
|
return iter(self.groups.items())
|
|
611
656
|
|
|
612
|
-
def __len__(self):
|
|
657
|
+
def __len__(self): # noqa: D105
|
|
613
658
|
return len(self.groups)
|
mesa/batchrunner.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"""batchrunner for running a factorial experiment design over a model."""
|
|
2
|
+
|
|
1
3
|
import itertools
|
|
2
4
|
import multiprocessing
|
|
3
5
|
from collections.abc import Iterable, Mapping
|
|
@@ -24,29 +26,19 @@ def batch_run(
|
|
|
24
26
|
) -> list[dict[str, Any]]:
|
|
25
27
|
"""Batch run a mesa model with a set of parameter values.
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
iterations : int, optional
|
|
36
|
-
Number of iterations for each parameter combination, by default 1
|
|
37
|
-
data_collection_period : int, optional
|
|
38
|
-
Number of steps after which data gets collected, by default -1 (end of episode)
|
|
39
|
-
max_steps : int, optional
|
|
40
|
-
Maximum number of model steps after which the model halts, by default 1000
|
|
41
|
-
display_progress : bool, optional
|
|
42
|
-
Display batch run process, by default True
|
|
29
|
+
Args:
|
|
30
|
+
model_cls (Type[Model]): The model class to batch-run
|
|
31
|
+
parameters (Mapping[str, Union[Any, Iterable[Any]]]): Dictionary with model parameters over which to run the model. You can either pass single values or iterables.
|
|
32
|
+
number_processes (int, optional): Number of processes used, by default 1. Set this to None if you want to use all CPUs.
|
|
33
|
+
iterations (int, optional): Number of iterations for each parameter combination, by default 1
|
|
34
|
+
data_collection_period (int, optional): Number of steps after which data gets collected, by default -1 (end of episode)
|
|
35
|
+
max_steps (int, optional): Maximum number of model steps after which the model halts, by default 1000
|
|
36
|
+
display_progress (bool, optional): Display batch run process, by default True
|
|
43
37
|
|
|
44
|
-
Returns
|
|
45
|
-
|
|
46
|
-
List[Dict[str, Any]]
|
|
47
|
-
[description]
|
|
48
|
-
"""
|
|
38
|
+
Returns:
|
|
39
|
+
List[Dict[str, Any]]
|
|
49
40
|
|
|
41
|
+
"""
|
|
50
42
|
runs_list = []
|
|
51
43
|
run_id = 0
|
|
52
44
|
for iteration in range(iterations):
|
|
@@ -88,7 +80,7 @@ def _make_model_kwargs(
|
|
|
88
80
|
parameters : Mapping[str, Union[Any, Iterable[Any]]]
|
|
89
81
|
Single or multiple values for each model parameter name
|
|
90
82
|
|
|
91
|
-
Returns
|
|
83
|
+
Returns:
|
|
92
84
|
-------
|
|
93
85
|
List[Dict[str, Any]]
|
|
94
86
|
A list of all kwargs combinations.
|
|
@@ -128,7 +120,7 @@ def _model_run_func(
|
|
|
128
120
|
data_collection_period : int
|
|
129
121
|
Number of steps after which data gets collected
|
|
130
122
|
|
|
131
|
-
Returns
|
|
123
|
+
Returns:
|
|
132
124
|
-------
|
|
133
125
|
List[Dict[str, Any]]
|
|
134
126
|
Return model_data, agent_data from the reporters
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""helper modules."""
|