Mesa 3.0.0a3__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.

Files changed (40) hide show
  1. mesa/__init__.py +2 -3
  2. mesa/agent.py +193 -75
  3. mesa/batchrunner.py +18 -23
  4. mesa/cookiecutter-mesa/hooks/post_gen_project.py +2 -0
  5. mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/__init__.py +1 -0
  6. mesa/datacollection.py +138 -27
  7. mesa/experimental/UserParam.py +67 -0
  8. mesa/experimental/__init__.py +5 -1
  9. mesa/experimental/cell_space/__init__.py +7 -0
  10. mesa/experimental/cell_space/cell.py +61 -20
  11. mesa/experimental/cell_space/cell_agent.py +12 -7
  12. mesa/experimental/cell_space/cell_collection.py +54 -17
  13. mesa/experimental/cell_space/discrete_space.py +16 -5
  14. mesa/experimental/cell_space/grid.py +19 -8
  15. mesa/experimental/cell_space/network.py +9 -7
  16. mesa/experimental/cell_space/voronoi.py +26 -33
  17. mesa/experimental/components/altair.py +81 -0
  18. mesa/experimental/components/matplotlib.py +242 -0
  19. mesa/experimental/devs/__init__.py +2 -0
  20. mesa/experimental/devs/eventlist.py +36 -15
  21. mesa/experimental/devs/examples/epstein_civil_violence.py +71 -39
  22. mesa/experimental/devs/examples/wolf_sheep.py +43 -44
  23. mesa/experimental/devs/simulator.py +55 -15
  24. mesa/experimental/solara_viz.py +453 -0
  25. mesa/main.py +6 -4
  26. mesa/model.py +64 -61
  27. mesa/space.py +154 -123
  28. mesa/time.py +57 -67
  29. mesa/visualization/UserParam.py +19 -6
  30. mesa/visualization/__init__.py +14 -2
  31. mesa/visualization/components/altair.py +18 -1
  32. mesa/visualization/components/matplotlib.py +26 -2
  33. mesa/visualization/solara_viz.py +231 -225
  34. mesa/visualization/utils.py +9 -0
  35. {mesa-3.0.0a3.dist-info → mesa-3.0.0a5.dist-info}/METADATA +2 -1
  36. mesa-3.0.0a5.dist-info/RECORD +44 -0
  37. mesa-3.0.0a3.dist-info/RECORD +0 -39
  38. {mesa-3.0.0a3.dist-info → mesa-3.0.0a5.dist-info}/WHEEL +0 -0
  39. {mesa-3.0.0a3.dist-info → mesa-3.0.0a5.dist-info}/entry_points.txt +0 -0
  40. {mesa-3.0.0a3.dist-info → mesa-3.0.0a5.dist-info}/licenses/LICENSE +0 -0
mesa/model.py CHANGED
@@ -1,5 +1,4 @@
1
- """
2
- The model class for Mesa framework.
1
+ """The model class for Mesa framework.
3
2
 
4
3
  Core Objects: Model
5
4
  """
@@ -28,23 +27,8 @@ class Model:
28
27
  Attributes:
29
28
  running: A boolean indicating if the model should continue running.
30
29
  schedule: An object to manage the order and execution of agent steps.
31
- current_id: A counter for assigning unique IDs to agents.
32
-
33
- Properties:
34
- agents: An AgentSet containing all agents in the model
35
- agent_types: A list of different agent types present in the model.
36
- steps: An integer representing the number of steps the model has taken.
37
- It increases automatically at the start of each step() call.
38
-
39
- Methods:
40
- get_agents_of_type: Returns an AgentSet of agents of the specified type.
41
- run_model: Runs the model's simulation until a defined end condition is reached.
42
- step: Executes a single step of the model's simulation process.
43
- next_id: Generates and returns the next unique identifier for an agent.
44
- reset_randomizer: Resets the model's random number generator with a new or existing seed.
45
- initialize_data_collector: Sets up the data collector for the model, requiring an initialized scheduler and agents.
46
- register_agent : register an agent with the model
47
- deregister_agent : remove an agent from the model
30
+ steps: the number of times `model.step()` has been called.
31
+ random: a seeded random number generator.
48
32
 
49
33
  Notes:
50
34
  Model.agents returns the AgentSet containing all agents registered with the model. Changing
@@ -53,30 +37,30 @@ class Model:
53
37
 
54
38
  """
55
39
 
56
- def __new__(cls, *args: Any, **kwargs: Any) -> Any:
57
- """Create a new model object and instantiate its RNG automatically."""
58
- obj = object.__new__(cls)
59
- obj._seed = kwargs.get("seed")
60
- if obj._seed is None:
61
- # We explicitly specify the seed here so that we know its value in
62
- # advance.
63
- obj._seed = random.random()
64
- obj.random = random.Random(obj._seed)
65
- return obj
66
-
67
- def __init__(self, *args: Any, **kwargs: Any) -> None:
68
- """Create a new model. Overload this method with the actual code to
69
- start the model. Always start with super().__init__() to initialize the
70
- model object properly.
71
- """
40
+ def __init__(self, *args: Any, seed: float | None = None, **kwargs: Any) -> None:
41
+ """Create a new model.
72
42
 
43
+ Overload this method with the actual code to initialize the model. Always start with super().__init__()
44
+ to initialize the model object properly.
45
+
46
+ Args:
47
+ args: arguments to pass onto super
48
+ seed: the seed for the random number generator
49
+ kwargs: keyword arguments to pass onto super
50
+ """
73
51
  self.running = True
74
52
  self.schedule = None
75
- self.current_id = 0
76
53
  self.steps: int = 0
77
54
 
78
55
  self._setup_agent_registration()
79
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)
63
+
80
64
  # Wrap the user-defined step method
81
65
  self._user_step = self.step
82
66
  self.step = self._wrapped_step
@@ -88,6 +72,14 @@ class Model:
88
72
  # Call the original user-defined step method
89
73
  self._user_step(*args, **kwargs)
90
74
 
75
+ def next_id(self) -> int: # noqa: D102
76
+ warnings.warn(
77
+ "using model.next_id() is deprecated. Agents track their unique ID automatically",
78
+ DeprecationWarning,
79
+ stacklevel=2,
80
+ )
81
+ return 0
82
+
91
83
  @property
92
84
  def agents(self) -> AgentSet:
93
85
  """Provides an AgentSet of all agents in the model, combining agents from all types."""
@@ -106,29 +98,31 @@ class Model:
106
98
  """Return a list of all unique agent types registered with the model."""
107
99
  return list(self._agents_by_type.keys())
108
100
 
109
- def get_agents_of_type(self, agenttype: type[Agent]) -> AgentSet:
110
- """Retrieves an AgentSet containing all agents of the specified type.
111
-
112
- Args:
113
- agenttype: The type of agent to retrieve.
114
-
115
- Raises:
116
- KeyError: If agenttype does not exist
117
-
101
+ @property
102
+ def agents_by_type(self) -> dict[type[Agent], AgentSet]:
103
+ """A dictionary where the keys are agent types and the values are the corresponding AgentSets."""
104
+ return self._agents_by_type
118
105
 
119
- """
120
- return self._agents_by_type[agenttype]
106
+ def get_agents_of_type(self, agenttype: type[Agent]) -> AgentSet:
107
+ """Deprecated: Retrieves an AgentSet containing all agents of the specified type."""
108
+ warnings.warn(
109
+ f"Model.get_agents_of_type() is deprecated, please replace get_agents_of_type({agenttype})"
110
+ f"with the property agents_by_type[{agenttype}].",
111
+ DeprecationWarning,
112
+ stacklevel=2,
113
+ )
114
+ return self.agents_by_type[agenttype]
121
115
 
122
116
  def _setup_agent_registration(self):
123
- """helper method to initialize the agent registration datastructures"""
117
+ """Helper method to initialize the agent registration datastructures."""
124
118
  self._agents = {} # the hard references to all agents in the model
125
119
  self._agents_by_type: dict[
126
- type, AgentSet
120
+ type[Agent], AgentSet
127
121
  ] = {} # a dict with an agentset for each class of agents
128
122
  self._all_agents = AgentSet([], self) # an agenset with all agents
129
123
 
130
124
  def register_agent(self, agent):
131
- """Register the agent with the model
125
+ """Register the agent with the model.
132
126
 
133
127
  Args:
134
128
  agent: The agent to register.
@@ -165,10 +159,13 @@ class Model:
165
159
  self._all_agents.add(agent)
166
160
 
167
161
  def deregister_agent(self, agent):
168
- """Deregister the agent with the model
162
+ """Deregister the agent with the model.
163
+
164
+ Args:
165
+ agent: The agent to deregister.
169
166
 
170
- Notes::
171
- This method is called automatically by ``Agent.remove``
167
+ Notes:
168
+ This method is called automatically by ``Agent.remove``
172
169
 
173
170
  """
174
171
  del self._agents[agent]
@@ -176,8 +173,9 @@ class Model:
176
173
  self._all_agents.remove(agent)
177
174
 
178
175
  def run_model(self) -> None:
179
- """Run the model until the end condition is reached. Overload as
180
- needed.
176
+ """Run the model until the end condition is reached.
177
+
178
+ Overload as needed.
181
179
  """
182
180
  while self.running:
183
181
  self.step()
@@ -185,18 +183,12 @@ class Model:
185
183
  def step(self) -> None:
186
184
  """A single step. Fill in here."""
187
185
 
188
- def next_id(self) -> int:
189
- """Return the next unique ID for agents, increment current_id"""
190
- self.current_id += 1
191
- return self.current_id
192
-
193
186
  def reset_randomizer(self, seed: int | None = None) -> None:
194
187
  """Reset the model random number generator.
195
188
 
196
189
  Args:
197
190
  seed: A new seed for the RNG; if None, reset using the current seed
198
191
  """
199
-
200
192
  if seed is None:
201
193
  seed = self._seed
202
194
  self.random.seed(seed)
@@ -206,8 +198,18 @@ class Model:
206
198
  self,
207
199
  model_reporters=None,
208
200
  agent_reporters=None,
201
+ agenttype_reporters=None,
209
202
  tables=None,
210
203
  ) -> None:
204
+ """Initialize the data collector for the model.
205
+
206
+ Args:
207
+ model_reporters: model reporters to collect
208
+ agent_reporters: agent reporters to collect
209
+ agenttype_reporters: agent type reporters to collect
210
+ tables: tables to collect
211
+
212
+ """
211
213
  if not hasattr(self, "schedule") or self.schedule is None:
212
214
  raise RuntimeError(
213
215
  "You must initialize the scheduler (self.schedule) before initializing the data collector."
@@ -219,6 +221,7 @@ class Model:
219
221
  self.datacollector = DataCollector(
220
222
  model_reporters=model_reporters,
221
223
  agent_reporters=agent_reporters,
224
+ agenttype_reporters=agenttype_reporters,
222
225
  tables=tables,
223
226
  )
224
227
  # Collect data for the first time during initialization.