Mesa 3.0.0a5__py3-none-any.whl → 3.0.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of Mesa might be problematic. Click here for more details.

Files changed (91) hide show
  1. examples/README.md +37 -0
  2. examples/__init__.py +0 -0
  3. examples/advanced/__init__.py +0 -0
  4. examples/advanced/epstein_civil_violence/Epstein Civil Violence.ipynb +116 -0
  5. examples/advanced/epstein_civil_violence/Readme.md +33 -0
  6. examples/advanced/epstein_civil_violence/epstein_civil_violence/__init__.py +0 -0
  7. examples/advanced/epstein_civil_violence/epstein_civil_violence/agent.py +158 -0
  8. examples/advanced/epstein_civil_violence/epstein_civil_violence/model.py +146 -0
  9. examples/advanced/epstein_civil_violence/epstein_civil_violence/portrayal.py +33 -0
  10. examples/advanced/epstein_civil_violence/epstein_civil_violence/server.py +81 -0
  11. examples/advanced/epstein_civil_violence/requirements.txt +3 -0
  12. examples/advanced/epstein_civil_violence/run.py +3 -0
  13. examples/advanced/pd_grid/analysis.ipynb +228 -0
  14. examples/advanced/pd_grid/pd_grid/__init__.py +0 -0
  15. examples/advanced/pd_grid/pd_grid/agent.py +50 -0
  16. examples/advanced/pd_grid/pd_grid/model.py +72 -0
  17. examples/advanced/pd_grid/pd_grid/portrayal.py +19 -0
  18. examples/advanced/pd_grid/pd_grid/server.py +21 -0
  19. examples/advanced/pd_grid/readme.md +42 -0
  20. examples/advanced/pd_grid/requirements.txt +3 -0
  21. examples/advanced/pd_grid/run.py +3 -0
  22. examples/advanced/sugarscape_g1mt/Readme.md +87 -0
  23. examples/advanced/sugarscape_g1mt/app.py +61 -0
  24. examples/advanced/sugarscape_g1mt/requirements.txt +6 -0
  25. examples/advanced/sugarscape_g1mt/run.py +105 -0
  26. examples/advanced/sugarscape_g1mt/sugarscape_g1mt/__init__.py +0 -0
  27. examples/advanced/sugarscape_g1mt/sugarscape_g1mt/model.py +180 -0
  28. examples/advanced/sugarscape_g1mt/sugarscape_g1mt/resource_agents.py +26 -0
  29. examples/advanced/sugarscape_g1mt/sugarscape_g1mt/server.py +61 -0
  30. examples/advanced/sugarscape_g1mt/sugarscape_g1mt/sugar-map.txt +50 -0
  31. examples/advanced/sugarscape_g1mt/sugarscape_g1mt/trader_agents.py +321 -0
  32. examples/advanced/sugarscape_g1mt/tests.py +72 -0
  33. examples/advanced/wolf_sheep/Readme.md +57 -0
  34. examples/advanced/wolf_sheep/__init__.py +0 -0
  35. examples/advanced/wolf_sheep/requirements.txt +1 -0
  36. examples/advanced/wolf_sheep/run.py +3 -0
  37. examples/advanced/wolf_sheep/wolf_sheep/__init__.py +0 -0
  38. examples/advanced/wolf_sheep/wolf_sheep/agents.py +102 -0
  39. examples/advanced/wolf_sheep/wolf_sheep/model.py +136 -0
  40. examples/advanced/wolf_sheep/wolf_sheep/resources/sheep.png +0 -0
  41. examples/advanced/wolf_sheep/wolf_sheep/resources/wolf.png +0 -0
  42. examples/advanced/wolf_sheep/wolf_sheep/server.py +78 -0
  43. examples/basic/__init__.py +13 -0
  44. examples/basic/boid_flockers/Readme.md +43 -0
  45. examples/basic/boid_flockers/agents.py +71 -0
  46. examples/basic/boid_flockers/app.py +59 -0
  47. examples/basic/boid_flockers/model.py +70 -0
  48. examples/basic/boltzmann_wealth_model/Readme.md +60 -0
  49. examples/basic/boltzmann_wealth_model/agents.py +31 -0
  50. examples/basic/boltzmann_wealth_model/app.py +66 -0
  51. examples/basic/boltzmann_wealth_model/model.py +44 -0
  52. examples/basic/boltzmann_wealth_model/st_app.py +115 -0
  53. examples/basic/conways_game_of_life/Readme.md +35 -0
  54. examples/basic/conways_game_of_life/agents.py +47 -0
  55. examples/basic/conways_game_of_life/model.py +32 -0
  56. examples/basic/conways_game_of_life/portrayal.py +18 -0
  57. examples/basic/conways_game_of_life/requirements.txt +1 -0
  58. examples/basic/conways_game_of_life/server.py +11 -0
  59. examples/basic/conways_game_of_life/st_app.py +71 -0
  60. examples/basic/schelling/README.md +47 -0
  61. examples/basic/schelling/agents.py +26 -0
  62. examples/basic/schelling/analysis.ipynb +205 -0
  63. examples/basic/schelling/app.py +43 -0
  64. examples/basic/schelling/model.py +60 -0
  65. examples/basic/virus_on_network/README.md +61 -0
  66. examples/basic/virus_on_network/agents.py +69 -0
  67. examples/basic/virus_on_network/app.py +133 -0
  68. examples/basic/virus_on_network/model.py +99 -0
  69. mesa/__init__.py +4 -1
  70. mesa/agent.py +24 -43
  71. mesa/batchrunner.py +7 -0
  72. mesa/examples.py +3 -0
  73. mesa/experimental/__init__.py +8 -2
  74. mesa/experimental/cell_space/__init__.py +7 -1
  75. mesa/experimental/cell_space/cell.py +35 -6
  76. mesa/experimental/cell_space/cell_agent.py +114 -23
  77. mesa/experimental/cell_space/discrete_space.py +70 -3
  78. mesa/experimental/cell_space/grid.py +13 -0
  79. mesa/experimental/cell_space/network.py +3 -0
  80. mesa/experimental/devs/examples/wolf_sheep.py +2 -1
  81. mesa/model.py +71 -21
  82. mesa/time.py +7 -5
  83. mesa/visualization/components/matplotlib.py +184 -90
  84. mesa/visualization/solara_viz.py +25 -61
  85. {mesa-3.0.0a5.dist-info → mesa-3.0.0b1.dist-info}/METADATA +55 -13
  86. mesa-3.0.0b1.dist-info/RECORD +114 -0
  87. mesa-3.0.0b1.dist-info/licenses/LICENSE +202 -0
  88. mesa-3.0.0a5.dist-info/licenses/LICENSE → mesa-3.0.0b1.dist-info/licenses/NOTICE +2 -2
  89. mesa-3.0.0a5.dist-info/RECORD +0 -44
  90. {mesa-3.0.0a5.dist-info → mesa-3.0.0b1.dist-info}/WHEEL +0 -0
  91. {mesa-3.0.0a5.dist-info → mesa-3.0.0b1.dist-info}/entry_points.txt +0 -0
@@ -2,41 +2,132 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING
5
+ from typing import TYPE_CHECKING, Protocol
6
6
 
7
- from mesa import Agent, Model
7
+ from mesa.agent import Agent
8
8
 
9
9
  if TYPE_CHECKING:
10
- from mesa.experimental.cell_space.cell import Cell
10
+ from mesa.experimental.cell_space import Cell
11
11
 
12
12
 
13
- class CellAgent(Agent):
14
- """Cell Agent is an extension of the Agent class and adds behavior for moving in discrete spaces.
13
+ class HasCellProtocol(Protocol):
14
+ """Protocol for discrete space cell holders."""
15
15
 
16
- Attributes:
17
- unique_id (int): A unique identifier for this agent.
18
- model (Model): The model instance to which the agent belongs
19
- pos: (Position | None): The position of the agent in the space
20
- cell: (Cell | None): the cell which the agent occupies
21
- """
16
+ cell: Cell
22
17
 
23
- def __init__(self, model: Model) -> None:
24
- """Create a new agent.
25
18
 
26
- Args:
27
- model (Model): The model instance in which the agent exists.
28
- """
29
- super().__init__(model)
30
- self.cell: Cell | None = None
19
+ class HasCell:
20
+ """Descriptor for cell movement behavior."""
31
21
 
32
- def move_to(self, cell) -> None:
33
- """Move agent to cell.
22
+ _mesa_cell: Cell | None = None
34
23
 
35
- Args:
36
- cell: cell to which agent is to move
24
+ @property
25
+ def cell(self) -> Cell | None: # noqa: D102
26
+ return self._mesa_cell
37
27
 
38
- """
28
+ @cell.setter
29
+ def cell(self, cell: Cell | None) -> None:
30
+ # remove from current cell
39
31
  if self.cell is not None:
40
32
  self.cell.remove_agent(self)
33
+
34
+ # update private attribute
35
+ self._mesa_cell = cell
36
+
37
+ # add to new cell
38
+ if cell is not None:
39
+ cell.add_agent(self)
40
+
41
+
42
+ class BasicMovement:
43
+ """Mixin for moving agents in discrete space."""
44
+
45
+ def move_to(self: HasCellProtocol, cell: Cell) -> None:
46
+ """Move to a new cell."""
41
47
  self.cell = cell
48
+
49
+ def move_relative(self: HasCellProtocol, direction: tuple[int, ...]):
50
+ """Move to a cell relative to the current cell.
51
+
52
+ Args:
53
+ direction: The direction to move in.
54
+ """
55
+ new_cell = self.cell.connections.get(direction)
56
+ if new_cell is not None:
57
+ self.cell = new_cell
58
+ else:
59
+ raise ValueError(f"No cell in direction {direction}")
60
+
61
+
62
+ class FixedCell(HasCell):
63
+ """Mixin for agents that are fixed to a cell."""
64
+
65
+ @property
66
+ def cell(self) -> Cell | None: # noqa: D102
67
+ return self._mesa_cell
68
+
69
+ @cell.setter
70
+ def cell(self, cell: Cell) -> None:
71
+ if self.cell is not None:
72
+ raise ValueError("Cannot move agent in FixedCell")
73
+ self._mesa_cell = cell
74
+
42
75
  cell.add_agent(self)
76
+
77
+
78
+ class CellAgent(Agent, HasCell, BasicMovement):
79
+ """Cell Agent is an extension of the Agent class and adds behavior for moving in discrete spaces.
80
+
81
+ Attributes:
82
+ cell (Cell): The cell the agent is currently in.
83
+ """
84
+
85
+ def remove(self):
86
+ """Remove the agent from the model."""
87
+ super().remove()
88
+ self.cell = None # ensures that we are also removed from cell
89
+
90
+
91
+ class FixedAgent(Agent, FixedCell):
92
+ """A patch in a 2D grid."""
93
+
94
+ def remove(self):
95
+ """Remove the agent from the model."""
96
+ super().remove()
97
+
98
+ # fixme we leave self._mesa_cell on the original value
99
+ # so you cannot hijack remove() to move patches
100
+ self.cell.remove_agent(self)
101
+
102
+
103
+ class Grid2DMovingAgent(CellAgent):
104
+ """Mixin for moving agents in 2D grids."""
105
+
106
+ # fmt: off
107
+ DIRECTION_MAP = {
108
+ "n": (-1, 0), "north": (-1, 0), "up": (-1, 0),
109
+ "s": (1, 0), "south": (1, 0), "down": (1, 0),
110
+ "e": (0, 1), "east": (0, 1), "right": (0, 1),
111
+ "w": (0, -1), "west": (0, -1), "left": (0, -1),
112
+ "ne": (-1, 1), "northeast": (-1, 1), "upright": (-1, 1),
113
+ "nw": (-1, -1), "northwest": (-1, -1), "upleft": (-1, -1),
114
+ "se": (1, 1), "southeast": (1, 1), "downright": (1, 1),
115
+ "sw": (1, -1), "southwest": (1, -1), "downleft": (1, -1)
116
+ }
117
+ # fmt: on
118
+
119
+ def move(self, direction: str, distance: int = 1):
120
+ """Move the agent in a cardinal direction.
121
+
122
+ Args:
123
+ direction: The cardinal direction to move in.
124
+ distance: The distance to move.
125
+ """
126
+ direction = direction.lower() # Convert direction to lowercase
127
+
128
+ if direction not in self.DIRECTION_MAP:
129
+ raise ValueError(f"Invalid direction: {direction}")
130
+
131
+ move_vector = self.DIRECTION_MAP[direction]
132
+ for _ in range(distance):
133
+ self.move_relative(move_vector)
@@ -2,12 +2,14 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from collections.abc import Callable
5
6
  from functools import cached_property
6
7
  from random import Random
7
- from typing import Generic, TypeVar
8
+ from typing import Any, Generic, TypeVar
8
9
 
9
10
  from mesa.experimental.cell_space.cell import Cell
10
11
  from mesa.experimental.cell_space.cell_collection import CellCollection
12
+ from mesa.space import PropertyLayer
11
13
 
12
14
  T = TypeVar("T", bound=Cell)
13
15
 
@@ -20,8 +22,8 @@ class DiscreteSpace(Generic[T]):
20
22
  all_cells (CellCollection): The cells composing the discrete space
21
23
  random (Random): The random number generator
22
24
  cell_klass (Type) : the type of cell class
23
- empties (CellCollection) : collecction of all cells that are empty
24
-
25
+ empties (CellCollection) : collection of all cells that are empty
26
+ property_layers (dict[str, PropertyLayer]): the property layers of the discrete space
25
27
  """
26
28
 
27
29
  def __init__(
@@ -47,11 +49,13 @@ class DiscreteSpace(Generic[T]):
47
49
 
48
50
  self._empties: dict[tuple[int, ...], None] = {}
49
51
  self._empties_initialized = False
52
+ self.property_layers: dict[str, PropertyLayer] = {}
50
53
 
51
54
  @property
52
55
  def cutoff_empties(self): # noqa
53
56
  return 7.953 * len(self._cells) ** 0.384
54
57
 
58
+ def _connect_cells(self): ...
55
59
  def _connect_single_cell(self, cell: T): ...
56
60
 
57
61
  @cached_property
@@ -73,3 +77,66 @@ class DiscreteSpace(Generic[T]):
73
77
  def select_random_empty_cell(self) -> T:
74
78
  """Select random empty cell."""
75
79
  return self.random.choice(list(self.empties))
80
+
81
+ # PropertyLayer methods
82
+ def add_property_layer(
83
+ self, property_layer: PropertyLayer, add_to_cells: bool = True
84
+ ):
85
+ """Add a property layer to the grid.
86
+
87
+ Args:
88
+ property_layer: the property layer to add
89
+ add_to_cells: whether to add the property layer to all cells (default: True)
90
+ """
91
+ if property_layer.name in self.property_layers:
92
+ raise ValueError(f"Property layer {property_layer.name} already exists.")
93
+ self.property_layers[property_layer.name] = property_layer
94
+ if add_to_cells:
95
+ for cell in self._cells.values():
96
+ cell._mesa_property_layers[property_layer.name] = property_layer
97
+
98
+ def remove_property_layer(self, property_name: str, remove_from_cells: bool = True):
99
+ """Remove a property layer from the grid.
100
+
101
+ Args:
102
+ property_name: the name of the property layer to remove
103
+ remove_from_cells: whether to remove the property layer from all cells (default: True)
104
+ """
105
+ del self.property_layers[property_name]
106
+ if remove_from_cells:
107
+ for cell in self._cells.values():
108
+ del cell._mesa_property_layers[property_name]
109
+
110
+ def set_property(
111
+ self, property_name: str, value, condition: Callable[[T], bool] | None = None
112
+ ):
113
+ """Set the value of a property for all cells in the grid.
114
+
115
+ Args:
116
+ property_name: the name of the property to set
117
+ value: the value to set
118
+ condition: a function that takes a cell and returns a boolean
119
+ """
120
+ self.property_layers[property_name].set_cells(value, condition)
121
+
122
+ def modify_properties(
123
+ self,
124
+ property_name: str,
125
+ operation: Callable,
126
+ value: Any = None,
127
+ condition: Callable[[T], bool] | None = None,
128
+ ):
129
+ """Modify the values of a specific property for all cells in the grid.
130
+
131
+ Args:
132
+ property_name: the name of the property to modify
133
+ operation: the operation to perform
134
+ value: the value to use in the operation
135
+ condition: a function that takes a cell and returns a boolean (used to filter cells)
136
+ """
137
+ self.property_layers[property_name].modify_cells(operation, value, condition)
138
+
139
+ def __setstate__(self, state):
140
+ """Set the state of the discrete space and rebuild the connections."""
141
+ self.__dict__ = state
142
+ self._connect_cells()
@@ -22,8 +22,21 @@ class Grid(DiscreteSpace[T], Generic[T]):
22
22
  random (Random): the random number generator
23
23
  _try_random (bool): whether to get empty cell be repeatedly trying random cell
24
24
 
25
+ Notes:
26
+ width and height are accessible via properties, higher dimensions can be retrieved via dimensions
27
+
25
28
  """
26
29
 
30
+ @property
31
+ def width(self) -> int:
32
+ """Convenience access to the width of the grid."""
33
+ return self.dimensions[0]
34
+
35
+ @property
36
+ def height(self) -> int:
37
+ """Convenience access to the height of the grid."""
38
+ return self.dimensions[1]
39
+
27
40
  def __init__(
28
41
  self,
29
42
  dimensions: Sequence[int],
@@ -34,6 +34,9 @@ class Network(DiscreteSpace[Cell]):
34
34
  node_id, capacity, random=self.random
35
35
  )
36
36
 
37
+ self._connect_cells()
38
+
39
+ def _connect_cells(self) -> None:
37
40
  for cell in self.all_cells:
38
41
  self._connect_single_cell(cell)
39
42
 
@@ -1,6 +1,7 @@
1
1
  """Example of using ABM simulator for Wolf-Sheep Predation Model."""
2
2
 
3
3
  import mesa
4
+ from mesa.experimental.cell_space import FixedAgent
4
5
  from mesa.experimental.devs.simulator import ABMSimulator
5
6
 
6
7
 
@@ -90,7 +91,7 @@ class Wolf(Animal):
90
91
  sheep_to_eat.die()
91
92
 
92
93
 
93
- class GrassPatch(mesa.Agent):
94
+ class GrassPatch(FixedAgent):
94
95
  """A patch of grass that grows at a fixed rate and it is eaten by sheep."""
95
96
 
96
97
  @property
mesa/model.py CHANGED
@@ -8,14 +8,21 @@ Core Objects: Model
8
8
  from __future__ import annotations
9
9
 
10
10
  import random
11
+ import sys
11
12
  import warnings
13
+ from collections.abc import Sequence
12
14
 
13
15
  # mypy
14
16
  from typing import Any
15
17
 
18
+ import numpy as np
19
+
16
20
  from mesa.agent import Agent, AgentSet
17
21
  from mesa.datacollection import DataCollector
18
22
 
23
+ SeedLike = int | np.integer | Sequence[int] | np.random.SeedSequence
24
+ RNGLike = np.random.Generator | np.random.BitGenerator
25
+
19
26
 
20
27
  class Model:
21
28
  """Base class for models in the Mesa ABM library.
@@ -28,7 +35,8 @@ class Model:
28
35
  running: A boolean indicating if the model should continue running.
29
36
  schedule: An object to manage the order and execution of agent steps.
30
37
  steps: the number of times `model.step()` has been called.
31
- random: a seeded random number generator.
38
+ random: a seeded python.random number generator.
39
+ rng : a seeded numpy.random.Generator
32
40
 
33
41
  Notes:
34
42
  Model.agents returns the AgentSet containing all agents registered with the model. Changing
@@ -37,7 +45,13 @@ class Model:
37
45
 
38
46
  """
39
47
 
40
- def __init__(self, *args: Any, seed: float | None = None, **kwargs: Any) -> None:
48
+ def __init__(
49
+ self,
50
+ *args: Any,
51
+ seed: float | None = None,
52
+ rng: RNGLike | SeedLike | None = None,
53
+ **kwargs: Any,
54
+ ) -> None:
41
55
  """Create a new model.
42
56
 
43
57
  Overload this method with the actual code to initialize the model. Always start with super().__init__()
@@ -46,25 +60,51 @@ class Model:
46
60
  Args:
47
61
  args: arguments to pass onto super
48
62
  seed: the seed for the random number generator
63
+ rng : Pseudorandom number generator state. When `rng` is None, a new `numpy.random.Generator` is created
64
+ using entropy from the operating system. Types other than `numpy.random.Generator` are passed to
65
+ `numpy.random.default_rng` to instantiate a `Generator`.
49
66
  kwargs: keyword arguments to pass onto super
67
+
68
+ Notes:
69
+ you have to pass either seed or rng, but not both.
70
+
50
71
  """
72
+ super().__init__(*args, **kwargs)
51
73
  self.running = True
52
- self.schedule = None
53
74
  self.steps: int = 0
54
75
 
55
- self._setup_agent_registration()
56
-
57
- self._seed = seed
58
- if self._seed is None:
59
- # We explicitly specify the seed here so that we know its value in
60
- # advance.
61
- self._seed = random.random()
62
- self.random = random.Random(self._seed)
76
+ if (seed is not None) and (rng is not None):
77
+ raise ValueError("you have to pass either rng or seed, not both")
78
+ elif seed is None:
79
+ self.rng: np.random.Generator = np.random.default_rng(rng)
80
+ self._rng = (
81
+ self.rng.bit_generator.state
82
+ ) # this allows for reproducing the rng
83
+
84
+ try:
85
+ self.random = random.Random(rng)
86
+ except TypeError:
87
+ seed = int(self.rng.integers(np.iinfo(np.int32).max))
88
+ self.random = random.Random(seed)
89
+ self._seed = seed # this allows for reproducing stdlib.random
90
+ elif rng is None:
91
+ self.random = random.Random(seed)
92
+ self._seed = seed # this allows for reproducing stdlib.random
93
+
94
+ try:
95
+ self.rng: np.random.Generator = np.random.default_rng(rng)
96
+ except TypeError:
97
+ rng = self.random.randint(0, sys.maxsize)
98
+ self.rng: np.random.Generator = np.random.default_rng(rng)
99
+ self._rng = self.rng.bit_generator.state
63
100
 
64
101
  # Wrap the user-defined step method
65
102
  self._user_step = self.step
66
103
  self.step = self._wrapped_step
67
104
 
105
+ # setup agent registration data structures
106
+ self._setup_agent_registration()
107
+
68
108
  def _wrapped_step(self, *args: Any, **kwargs: Any) -> None:
69
109
  """Automatically increments time and steps after calling the user's step method."""
70
110
  # Automatically increment time and step counters
@@ -119,7 +159,9 @@ class Model:
119
159
  self._agents_by_type: dict[
120
160
  type[Agent], AgentSet
121
161
  ] = {} # a dict with an agentset for each class of agents
122
- self._all_agents = AgentSet([], self) # an agenset with all agents
162
+ self._all_agents = AgentSet(
163
+ [], random=self.random
164
+ ) # an agenset with all agents
123
165
 
124
166
  def register_agent(self, agent):
125
167
  """Register the agent with the model.
@@ -153,7 +195,7 @@ class Model:
153
195
  [
154
196
  agent,
155
197
  ],
156
- self,
198
+ random=self.random,
157
199
  )
158
200
 
159
201
  self._all_agents.add(agent)
@@ -194,6 +236,15 @@ class Model:
194
236
  self.random.seed(seed)
195
237
  self._seed = seed
196
238
 
239
+ def reset_rng(self, rng: RNGLike | SeedLike | None = None) -> None:
240
+ """Reset the model random number generator.
241
+
242
+ Args:
243
+ rng: A new seed for the RNG; if None, reset using the current seed
244
+ """
245
+ self.rng = np.random.default_rng(rng)
246
+ self._rng = self.rng.bit_generator.state
247
+
197
248
  def initialize_data_collector(
198
249
  self,
199
250
  model_reporters=None,
@@ -210,14 +261,13 @@ class Model:
210
261
  tables: tables to collect
211
262
 
212
263
  """
213
- if not hasattr(self, "schedule") or self.schedule is None:
214
- raise RuntimeError(
215
- "You must initialize the scheduler (self.schedule) before initializing the data collector."
216
- )
217
- if self.schedule.get_agent_count() == 0:
218
- raise RuntimeError(
219
- "You must add agents to the scheduler before initializing the data collector."
220
- )
264
+ warnings.warn(
265
+ "initialize_data_collector() is deprecated. Please use the DataCollector class directly. "
266
+ "by using `self.datacollector = DataCollector(...)`.",
267
+ DeprecationWarning,
268
+ stacklevel=2,
269
+ )
270
+
221
271
  self.datacollector = DataCollector(
222
272
  model_reporters=model_reporters,
223
273
  agent_reporters=agent_reporters,
mesa/time.py CHANGED
@@ -3,7 +3,7 @@
3
3
  .. warning::
4
4
  The time module and all its Schedulers are deprecated and will be removed in a future version.
5
5
  They can be replaced with AgentSet functionality. See the migration guide for details:
6
- https://mesa.readthedocs.io/en/latest/migration_guide.html#time-and-schedulers
6
+ https://mesa.readthedocs.io/latest/migration_guide.html#time-and-schedulers
7
7
 
8
8
  Objects for handling the time component of a model. In particular, this module
9
9
  contains Schedulers, which handle agent activation. A Scheduler is an object
@@ -65,7 +65,7 @@ class BaseScheduler:
65
65
  warnings.warn(
66
66
  "The time module and all its Schedulers are deprecated and will be removed in a future version. "
67
67
  "They can be replaced with AgentSet functionality. See the migration guide for details. "
68
- "https://mesa.readthedocs.io/en/latest/migration_guide.html#time-and-schedulers",
68
+ "https://mesa.readthedocs.io/latest/migration_guide.html#time-and-schedulers",
69
69
  DeprecationWarning,
70
70
  stacklevel=2,
71
71
  )
@@ -77,7 +77,7 @@ class BaseScheduler:
77
77
  if agents is None:
78
78
  agents = []
79
79
 
80
- self._agents: AgentSet = AgentSet(agents, model)
80
+ self._agents: AgentSet = AgentSet(agents, model.random)
81
81
 
82
82
  self._remove_warning_given = False
83
83
  self._agents_key_warning_given = False
@@ -312,7 +312,9 @@ class RandomActivationByType(BaseScheduler):
312
312
  try:
313
313
  self._agents_by_type[type(agent)].add(agent)
314
314
  except KeyError:
315
- self._agents_by_type[type(agent)] = AgentSet([agent], self.model)
315
+ self._agents_by_type[type(agent)] = AgentSet(
316
+ [agent], self.model.random
317
+ )
316
318
 
317
319
  def add(self, agent: Agent) -> None:
318
320
  """Add an Agent object to the schedule.
@@ -325,7 +327,7 @@ class RandomActivationByType(BaseScheduler):
325
327
  try:
326
328
  self._agents_by_type[type(agent)].add(agent)
327
329
  except KeyError:
328
- self._agents_by_type[type(agent)] = AgentSet([agent], self.model)
330
+ self._agents_by_type[type(agent)] = AgentSet([agent], self.model.random)
329
331
 
330
332
  def remove(self, agent: Agent) -> None:
331
333
  """Remove all instances of a given agent from the schedule.