Mesa 3.1.0.dev0__py3-none-any.whl → 3.1.1__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 (57) hide show
  1. mesa/__init__.py +3 -3
  2. mesa/agent.py +48 -0
  3. mesa/batchrunner.py +14 -1
  4. mesa/datacollection.py +1 -6
  5. mesa/examples/__init__.py +2 -2
  6. mesa/examples/advanced/epstein_civil_violence/app.py +5 -0
  7. mesa/examples/advanced/pd_grid/agents.py +2 -1
  8. mesa/examples/advanced/pd_grid/app.py +5 -0
  9. mesa/examples/advanced/pd_grid/model.py +3 -5
  10. mesa/examples/advanced/sugarscape_g1mt/agents.py +12 -65
  11. mesa/examples/advanced/sugarscape_g1mt/app.py +24 -19
  12. mesa/examples/advanced/sugarscape_g1mt/model.py +45 -52
  13. mesa/examples/advanced/wolf_sheep/agents.py +3 -1
  14. mesa/examples/advanced/wolf_sheep/model.py +17 -16
  15. mesa/examples/basic/boid_flockers/app.py +5 -0
  16. mesa/examples/basic/boltzmann_wealth_model/app.py +8 -5
  17. mesa/examples/basic/boltzmann_wealth_model/st_app.py +1 -1
  18. mesa/examples/basic/conways_game_of_life/app.py +5 -0
  19. mesa/examples/basic/conways_game_of_life/st_app.py +2 -2
  20. mesa/examples/basic/schelling/agents.py +11 -5
  21. mesa/examples/basic/schelling/app.py +6 -1
  22. mesa/examples/basic/virus_on_network/app.py +5 -0
  23. mesa/experimental/__init__.py +17 -10
  24. mesa/experimental/cell_space/__init__.py +19 -7
  25. mesa/experimental/cell_space/cell.py +22 -37
  26. mesa/experimental/cell_space/cell_agent.py +12 -1
  27. mesa/experimental/cell_space/cell_collection.py +18 -3
  28. mesa/experimental/cell_space/discrete_space.py +15 -64
  29. mesa/experimental/cell_space/grid.py +74 -4
  30. mesa/experimental/cell_space/network.py +13 -1
  31. mesa/experimental/cell_space/property_layer.py +444 -0
  32. mesa/experimental/cell_space/voronoi.py +13 -1
  33. mesa/experimental/devs/__init__.py +20 -2
  34. mesa/experimental/devs/eventlist.py +19 -1
  35. mesa/experimental/devs/simulator.py +24 -8
  36. mesa/experimental/mesa_signals/__init__.py +23 -0
  37. mesa/experimental/mesa_signals/mesa_signal.py +485 -0
  38. mesa/experimental/mesa_signals/observable_collections.py +133 -0
  39. mesa/experimental/mesa_signals/signals_util.py +52 -0
  40. mesa/mesa_logging.py +190 -0
  41. mesa/model.py +17 -23
  42. mesa/visualization/__init__.py +2 -2
  43. mesa/visualization/mpl_space_drawing.py +8 -5
  44. mesa/visualization/solara_viz.py +49 -11
  45. {mesa-3.1.0.dev0.dist-info → mesa-3.1.1.dist-info}/METADATA +1 -1
  46. mesa-3.1.1.dist-info/RECORD +94 -0
  47. {mesa-3.1.0.dev0.dist-info → mesa-3.1.1.dist-info}/WHEEL +1 -1
  48. mesa/experimental/UserParam.py +0 -67
  49. mesa/experimental/components/altair.py +0 -81
  50. mesa/experimental/components/matplotlib.py +0 -242
  51. mesa/experimental/devs/examples/epstein_civil_violence.py +0 -305
  52. mesa/experimental/devs/examples/wolf_sheep.py +0 -250
  53. mesa/experimental/solara_viz.py +0 -453
  54. mesa-3.1.0.dev0.dist-info/RECORD +0 -94
  55. {mesa-3.1.0.dev0.dist-info → mesa-3.1.1.dist-info}/entry_points.txt +0 -0
  56. {mesa-3.1.0.dev0.dist-info → mesa-3.1.1.dist-info}/licenses/LICENSE +0 -0
  57. {mesa-3.1.0.dev0.dist-info → mesa-3.1.1.dist-info}/licenses/NOTICE +0 -0
mesa/mesa_logging.py ADDED
@@ -0,0 +1,190 @@
1
+ """This provides logging functionality for MESA.
2
+
3
+ It is modeled on the default `logging approach that comes with Python <https://docs.python.org/library/logging.html>`_.
4
+
5
+
6
+ """
7
+
8
+ import inspect
9
+ import logging
10
+ from functools import wraps
11
+ from logging import DEBUG, INFO
12
+
13
+ __all__ = [
14
+ "DEBUG",
15
+ "DEFAULT_LEVEL",
16
+ "INFO",
17
+ "LOGGER_NAME",
18
+ "function_logger",
19
+ "get_module_logger",
20
+ "get_rootlogger",
21
+ "log_to_stderr",
22
+ "method_logger",
23
+ ]
24
+ LOGGER_NAME = "MESA"
25
+ DEFAULT_LEVEL = DEBUG
26
+
27
+
28
+ def create_module_logger(name: str | None = None):
29
+ """Helper function for creating a module logger.
30
+
31
+ Args:
32
+ name (str): The name to be given to the logger. If the name is None, the name defaults to the name of the module.
33
+
34
+ """
35
+ if name is None:
36
+ frm = inspect.stack()[1]
37
+ mod = inspect.getmodule(frm[0])
38
+ name = mod.__name__
39
+ logger = logging.getLogger(f"{LOGGER_NAME}.{name}")
40
+
41
+ _module_loggers[name] = logger
42
+ return logger
43
+
44
+
45
+ def get_module_logger(name: str):
46
+ """Helper function for getting the module logger.
47
+
48
+ Args:
49
+ name (str): The name of the module in which the method being decorated is located
50
+
51
+ """
52
+ try:
53
+ logger = _module_loggers[name]
54
+ except KeyError:
55
+ logger = create_module_logger(name)
56
+
57
+ return logger
58
+
59
+
60
+ _rootlogger = None
61
+ _module_loggers = {}
62
+ _logger = get_module_logger(__name__)
63
+
64
+
65
+ class MESAColorFormatter(logging.Formatter):
66
+ """Custom formatter for color based formatting."""
67
+
68
+ grey = "\x1b[38;20m"
69
+ green = "\x1b[32m"
70
+ yellow = "\x1b[33;20m"
71
+ red = "\x1b[31;20m"
72
+ bold_red = "\x1b[31;1m"
73
+ reset = "\x1b[0m"
74
+ format = (
75
+ "[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s [%(filename)s:%(lineno)d]"
76
+ )
77
+
78
+ FORMATS = {
79
+ logging.DEBUG: grey + format + reset,
80
+ logging.INFO: green + format + reset,
81
+ logging.WARNING: yellow + format + reset,
82
+ logging.ERROR: red + format + reset,
83
+ logging.CRITICAL: bold_red + format + reset,
84
+ }
85
+
86
+ def format(self, record):
87
+ """Format record."""
88
+ log_fmt = self.FORMATS.get(record.levelno)
89
+ formatter = logging.Formatter(log_fmt)
90
+ return formatter.format(record)
91
+
92
+
93
+ def method_logger(name: str):
94
+ """Decorator for adding logging to a method.
95
+
96
+ Args:
97
+ name (str): The name of the module in which the method being decorated is located
98
+
99
+ """
100
+ logger = get_module_logger(name)
101
+ classname = inspect.getouterframes(inspect.currentframe())[1][3]
102
+
103
+ def real_decorator(func):
104
+ @wraps(func)
105
+ def wrapper(*args, **kwargs):
106
+ # hack, because log is applied to methods, we can get
107
+ # object instance as first arguments in args
108
+ logger.debug(
109
+ f"calling {classname}.{func.__name__} with {args[1::]} and {kwargs}"
110
+ )
111
+ res = func(*args, **kwargs)
112
+ return res
113
+
114
+ return wrapper
115
+
116
+ return real_decorator
117
+
118
+
119
+ def function_logger(name):
120
+ """Decorator for adding logging to a Function.
121
+
122
+ Args:
123
+ name (str): The name of the module in which the function being decorated is located
124
+
125
+ """
126
+ logger = get_module_logger(name)
127
+
128
+ def real_decorator(func):
129
+ @wraps(func)
130
+ def wrapper(*args, **kwargs):
131
+ logger.debug(f"calling {func.__name__} with {args} and {kwargs}")
132
+ res = func(*args, **kwargs)
133
+ return res
134
+
135
+ return wrapper
136
+
137
+ return real_decorator
138
+
139
+
140
+ def get_rootlogger():
141
+ """Returns root logger used by MESA.
142
+
143
+ Returns:
144
+ the root logger of MESA
145
+
146
+ """
147
+ global _rootlogger # noqa: PLW0603
148
+
149
+ if not _rootlogger:
150
+ _rootlogger = logging.getLogger(LOGGER_NAME)
151
+ _rootlogger.handlers = []
152
+ _rootlogger.addHandler(logging.NullHandler())
153
+ _rootlogger.setLevel(DEBUG)
154
+
155
+ return _rootlogger
156
+
157
+
158
+ def log_to_stderr(level: int | None = None, pass_root_logger_level: bool = False):
159
+ """Turn on logging and add a handler which prints to stderr.
160
+
161
+ Args:
162
+ level: minimum level of the messages that will be logged
163
+ pass_root_logger_level: bool, optional. Default False
164
+ if True, all module loggers will be set to the same logging level as the root logger.
165
+
166
+ """
167
+ if not level:
168
+ level = DEFAULT_LEVEL
169
+
170
+ logger = get_rootlogger()
171
+
172
+ # avoid creation of multiple stream handlers for logging to console
173
+ for entry in logger.handlers:
174
+ if (isinstance(entry, logging.StreamHandler)) and (
175
+ isinstance(entry.formatter, MESAColorFormatter)
176
+ ):
177
+ return logger
178
+
179
+ formatter = MESAColorFormatter()
180
+ handler = logging.StreamHandler()
181
+ handler.setLevel(level)
182
+ handler.setFormatter(formatter)
183
+ logger.addHandler(handler)
184
+ logger.propagate = False
185
+
186
+ if pass_root_logger_level:
187
+ for _, mod_logger in _module_loggers.items():
188
+ mod_logger.setLevel(level)
189
+
190
+ return logger
mesa/model.py CHANGED
@@ -9,7 +9,6 @@ from __future__ import annotations
9
9
 
10
10
  import random
11
11
  import sys
12
- import warnings
13
12
  from collections.abc import Sequence
14
13
 
15
14
  # mypy
@@ -18,11 +17,15 @@ from typing import Any
18
17
  import numpy as np
19
18
 
20
19
  from mesa.agent import Agent, AgentSet
20
+ from mesa.mesa_logging import create_module_logger, method_logger
21
21
 
22
22
  SeedLike = int | np.integer | Sequence[int] | np.random.SeedSequence
23
23
  RNGLike = np.random.Generator | np.random.BitGenerator
24
24
 
25
25
 
26
+ _mesa_logger = create_module_logger()
27
+
28
+
26
29
  class Model:
27
30
  """Base class for models in the Mesa ABM library.
28
31
 
@@ -32,7 +35,6 @@ class Model:
32
35
 
33
36
  Attributes:
34
37
  running: A boolean indicating if the model should continue running.
35
- schedule: An object to manage the order and execution of agent steps.
36
38
  steps: the number of times `model.step()` has been called.
37
39
  random: a seeded python.random number generator.
38
40
  rng : a seeded numpy.random.Generator
@@ -44,6 +46,7 @@ class Model:
44
46
 
45
47
  """
46
48
 
49
+ @method_logger(__name__)
47
50
  def __init__(
48
51
  self,
49
52
  *args: Any,
@@ -102,12 +105,19 @@ class Model:
102
105
  self.step = self._wrapped_step
103
106
 
104
107
  # setup agent registration data structures
105
- self._setup_agent_registration()
108
+ self._agents = {} # the hard references to all agents in the model
109
+ self._agents_by_type: dict[
110
+ type[Agent], AgentSet
111
+ ] = {} # a dict with an agentset for each class of agents
112
+ self._all_agents = AgentSet(
113
+ [], random=self.random
114
+ ) # an agenset with all agents
106
115
 
107
116
  def _wrapped_step(self, *args: Any, **kwargs: Any) -> None:
108
117
  """Automatically increments time and steps after calling the user's step method."""
109
118
  # Automatically increment time and step counters
110
119
  self.steps += 1
120
+ _mesa_logger.info(f"calling model.step for timestep {self.steps} ")
111
121
  # Call the original user-defined step method
112
122
  self._user_step(*args, **kwargs)
113
123
 
@@ -134,16 +144,6 @@ class Model:
134
144
  """A dictionary where the keys are agent types and the values are the corresponding AgentSets."""
135
145
  return self._agents_by_type
136
146
 
137
- def _setup_agent_registration(self):
138
- """Helper method to initialize the agent registration datastructures."""
139
- self._agents = {} # the hard references to all agents in the model
140
- self._agents_by_type: dict[
141
- type[Agent], AgentSet
142
- ] = {} # a dict with an agentset for each class of agents
143
- self._all_agents = AgentSet(
144
- [], random=self.random
145
- ) # an agenset with all agents
146
-
147
147
  def register_agent(self, agent):
148
148
  """Register the agent with the model.
149
149
 
@@ -155,16 +155,6 @@ class Model:
155
155
  if you are subclassing Agent and calling its super in the ``__init__`` method.
156
156
 
157
157
  """
158
- if not hasattr(self, "_agents"):
159
- self._setup_agent_registration()
160
-
161
- warnings.warn(
162
- "The Mesa Model class was not initialized. In the future, you need to explicitly initialize "
163
- "the Model by calling super().__init__() on initialization.",
164
- FutureWarning,
165
- stacklevel=2,
166
- )
167
-
168
158
  self._agents[agent] = None
169
159
 
170
160
  # because AgentSet requires model, we cannot use defaultdict
@@ -180,6 +170,9 @@ class Model:
180
170
  )
181
171
 
182
172
  self._all_agents.add(agent)
173
+ _mesa_logger.debug(
174
+ f"registered {agent.__class__.__name__} with agent_id {agent.unique_id}"
175
+ )
183
176
 
184
177
  def deregister_agent(self, agent):
185
178
  """Deregister the agent with the model.
@@ -194,6 +187,7 @@ class Model:
194
187
  del self._agents[agent]
195
188
  self._agents_by_type[type(agent)].remove(agent)
196
189
  self._all_agents.remove(agent)
190
+ _mesa_logger.debug(f"deregistered agent with agent_id {agent.unique_id}")
197
191
 
198
192
  def run_model(self) -> None:
199
193
  """Run the model until the end condition is reached.
@@ -17,10 +17,10 @@ from .user_param import Slider
17
17
 
18
18
  __all__ = [
19
19
  "JupyterViz",
20
- "SolaraViz",
21
20
  "Slider",
22
- "make_space_altair",
21
+ "SolaraViz",
23
22
  "draw_space",
24
23
  "make_plot_component",
24
+ "make_space_altair",
25
25
  "make_space_component",
26
26
  ]
@@ -178,15 +178,18 @@ def draw_property_layers(
178
178
  property_layers = space.properties
179
179
  except AttributeError:
180
180
  # new style spaces
181
- property_layers = space.property_layers
181
+ property_layers = space._mesa_property_layers
182
182
 
183
183
  for layer_name, portrayal in propertylayer_portrayal.items():
184
184
  layer = property_layers.get(layer_name, None)
185
- if not isinstance(layer, PropertyLayer):
185
+ if not isinstance(
186
+ layer,
187
+ PropertyLayer | mesa.experimental.cell_space.property_layer.PropertyLayer,
188
+ ):
186
189
  continue
187
190
 
188
191
  data = layer.data.astype(float) if layer.data.dtype == bool else layer.data
189
- width, height = data.shape if space is None else (space.width, space.height)
192
+ width, height = data.shape # if space is None else (space.width, space.height)
190
193
 
191
194
  if space and data.shape != (width, height):
192
195
  warnings.warn(
@@ -212,7 +215,7 @@ def draw_property_layers(
212
215
  layer_name, [(0, 0, 0, 0), (*rgba_color[:3], alpha)]
213
216
  )
214
217
  im = ax.imshow(
215
- rgba_data.transpose(1, 0, 2),
218
+ rgba_data,
216
219
  origin="lower",
217
220
  )
218
221
  if colorbar:
@@ -226,7 +229,7 @@ def draw_property_layers(
226
229
  if isinstance(cmap, list):
227
230
  cmap = LinearSegmentedColormap.from_list(layer_name, cmap)
228
231
  im = ax.imshow(
229
- data.T,
232
+ data,
230
233
  cmap=cmap,
231
234
  alpha=alpha,
232
235
  vmin=vmin,
@@ -33,14 +33,18 @@ import solara
33
33
 
34
34
  import mesa.visualization.components.altair_components as components_altair
35
35
  from mesa.experimental.devs.simulator import Simulator
36
+ from mesa.mesa_logging import create_module_logger, function_logger
36
37
  from mesa.visualization.user_param import Slider
37
38
  from mesa.visualization.utils import force_update, update_counter
38
39
 
39
40
  if TYPE_CHECKING:
40
41
  from mesa.model import Model
41
42
 
43
+ _mesa_logger = create_module_logger()
44
+
42
45
 
43
46
  @solara.component
47
+ @function_logger(__name__)
44
48
  def SolaraViz(
45
49
  model: Model | solara.Reactive[Model],
46
50
  components: list[reacton.core.Component]
@@ -98,24 +102,33 @@ def SolaraViz(
98
102
 
99
103
  # set up reactive model_parameters shared by ModelCreator and ModelController
100
104
  reactive_model_parameters = solara.use_reactive({})
105
+ reactive_play_interval = solara.use_reactive(play_interval)
101
106
 
102
107
  with solara.AppBar():
103
108
  solara.AppBarTitle(name if name else model.value.__class__.__name__)
104
109
 
105
110
  with solara.Sidebar(), solara.Column():
106
111
  with solara.Card("Controls"):
112
+ solara.SliderInt(
113
+ label="Play Interval (ms)",
114
+ value=reactive_play_interval,
115
+ on_value=lambda v: reactive_play_interval.set(v),
116
+ min=1,
117
+ max=500,
118
+ step=10,
119
+ )
107
120
  if not isinstance(simulator, Simulator):
108
121
  ModelController(
109
122
  model,
110
123
  model_parameters=reactive_model_parameters,
111
- play_interval=play_interval,
124
+ play_interval=reactive_play_interval,
112
125
  )
113
126
  else:
114
127
  SimulatorController(
115
128
  model,
116
129
  simulator,
117
130
  model_parameters=reactive_model_parameters,
118
- play_interval=play_interval,
131
+ play_interval=reactive_play_interval,
119
132
  )
120
133
  with solara.Card("Model Parameters"):
121
134
  ModelCreator(
@@ -175,7 +188,7 @@ def ModelController(
175
188
  model: solara.Reactive[Model],
176
189
  *,
177
190
  model_parameters: dict | solara.Reactive[dict] = None,
178
- play_interval: int = 100,
191
+ play_interval: int | solara.Reactive[int] = 100,
179
192
  ):
180
193
  """Create controls for model execution (step, play, pause, reset).
181
194
 
@@ -193,25 +206,32 @@ def ModelController(
193
206
 
194
207
  async def step():
195
208
  while playing.value and running.value:
196
- await asyncio.sleep(play_interval / 1000)
209
+ await asyncio.sleep(play_interval.value / 1000)
197
210
  do_step()
198
211
 
199
212
  solara.lab.use_task(
200
213
  step, dependencies=[playing.value, running.value], prefer_threaded=False
201
214
  )
202
215
 
216
+ @function_logger(__name__)
203
217
  def do_step():
204
218
  """Advance the model by one step."""
205
219
  model.value.step()
206
220
  running.value = model.value.running
207
221
  force_update()
208
222
 
223
+ @function_logger(__name__)
209
224
  def do_reset():
210
225
  """Reset the model to its initial state."""
211
226
  playing.value = False
212
227
  running.value = True
228
+ _mesa_logger.log(
229
+ 10,
230
+ f"creating new {model.value.__class__} instance with {model_parameters.value}",
231
+ )
213
232
  model.value = model.value = model.value.__class__(**model_parameters.value)
214
233
 
234
+ @function_logger(__name__)
215
235
  def do_play_pause():
216
236
  """Toggle play/pause."""
217
237
  playing.value = not playing.value
@@ -238,7 +258,7 @@ def SimulatorController(
238
258
  simulator,
239
259
  *,
240
260
  model_parameters: dict | solara.Reactive[dict] = None,
241
- play_interval: int = 100,
261
+ play_interval: int | solara.Reactive[int] = 100,
242
262
  ):
243
263
  """Create controls for model execution (step, play, pause, reset).
244
264
 
@@ -257,7 +277,7 @@ def SimulatorController(
257
277
 
258
278
  async def step():
259
279
  while playing.value and running.value:
260
- await asyncio.sleep(play_interval / 1000)
280
+ await asyncio.sleep(play_interval.value / 1000)
261
281
  do_step()
262
282
 
263
283
  solara.lab.use_task(
@@ -382,12 +402,19 @@ def ModelCreator(
382
402
  )
383
403
  user_params, fixed_params = split_model_params(user_params)
384
404
 
385
- # set model_parameters to the default values for all parameters
386
- model_parameters.value = {
387
- **fixed_params,
388
- **{k: v.get("value") for k, v in user_params.items()},
389
- }
405
+ # Use solara.use_effect to run the initialization code only once
406
+ solara.use_effect(
407
+ # set model_parameters to the default values for all parameters
408
+ lambda: model_parameters.set(
409
+ {
410
+ **fixed_params,
411
+ **{k: v.get("value") for k, v in user_params.items()},
412
+ }
413
+ ),
414
+ [],
415
+ )
390
416
 
417
+ @function_logger(__name__)
391
418
  def on_change(name, value):
392
419
  model_parameters.value = {**model_parameters.value, name: value}
393
420
 
@@ -405,6 +432,17 @@ def _check_model_params(init_func, model_params):
405
432
  ValueError: If a parameter is not valid for the model's initialization function
406
433
  """
407
434
  model_parameters = inspect.signature(init_func).parameters
435
+
436
+ has_var_positional = any(
437
+ param.kind == inspect.Parameter.VAR_POSITIONAL
438
+ for param in model_parameters.values()
439
+ )
440
+
441
+ if has_var_positional:
442
+ raise ValueError(
443
+ "Mesa's visualization requires the use of keyword arguments to ensure the parameters are passed to Solara correctly. Please ensure all model parameters are of form param=value"
444
+ )
445
+
408
446
  for name in model_parameters:
409
447
  if (
410
448
  model_parameters[name].default == inspect.Parameter.empty
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: Mesa
3
- Version: 3.1.0.dev0
3
+ Version: 3.1.1
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,94 @@
1
+ mesa/__init__.py,sha256=4-j7gALmGrWuSOiUaI2o6UN6TyHL1MPwaAUC9C7PP04,611
2
+ mesa/agent.py,sha256=4CXMOFA9KhvTypaV_OHZGqxOR4GVwyX4x8DOtQENUQA,26130
3
+ mesa/batchrunner.py,sha256=w8StV82F_7DAAVQc5V7_Ggp0EL1NYn__UcBE-Nwrgv4,7771
4
+ mesa/datacollection.py,sha256=8loT4pQsXcHArxHSsbRc7HTc2GP5gsEIeKFKr3xya4I,15991
5
+ mesa/mesa_logging.py,sha256=PEDqUaQ2Y4bkYBkrHVkGT0sF86gUdbSH1T3vCg3qQeE,4949
6
+ mesa/model.py,sha256=oVcV-_OZ3GVv1sb3KqyGA9TAWCDQu9qEDWwRi_AXR40,8353
7
+ mesa/space.py,sha256=cfzlRfy9chegp8d89k2aqI29jo9cb18USlz2G2iOZU4,64082
8
+ mesa/examples/README.md,sha256=dNn8kv0BNQem3NNhO5mbOANQoK8UUYOo7rnkCFV9tnE,2882
9
+ mesa/examples/__init__.py,sha256=pyPWFRUxyYtQilJECbH7LY1eYBk8VB0Yg-_SbFEEvFA,825
10
+ mesa/examples/advanced/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ mesa/examples/advanced/epstein_civil_violence/Epstein Civil Violence.ipynb,sha256=yh50ZAK2BVJyJIKsQTTxywnasqWn1IiQUVrwmZKue4w,29032
12
+ mesa/examples/advanced/epstein_civil_violence/Readme.md,sha256=RXuGIZAibz3KVkP51PGjwzcRx2R9Ettmh3qbDTPqDcg,1735
13
+ mesa/examples/advanced/epstein_civil_violence/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ mesa/examples/advanced/epstein_civil_violence/agents.py,sha256=0X4JLj2K2cl1bACkFLI6-K6tKbr2SLZlAy_kjgUDjzA,5863
15
+ mesa/examples/advanced/epstein_civil_violence/app.py,sha256=fFlPijAUDLs_WfROGIlUXRakkkfbWnytcXFTAzdRplU,1890
16
+ mesa/examples/advanced/epstein_civil_violence/model.py,sha256=fcTkjCRhEhDerDC1W_lrezdoWD1y5xIublkGIhCak8w,3918
17
+ mesa/examples/advanced/pd_grid/Readme.md,sha256=UVUQxZRFdfymCKDdQEn3ZEwgSqgp9cKJPsU8oZpLFnY,2367
18
+ mesa/examples/advanced/pd_grid/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ mesa/examples/advanced/pd_grid/agents.py,sha256=8JnezmnwxjcqAUAgXa1iWls0Nz4yBS-TJi1TSVcHbqM,1752
20
+ mesa/examples/advanced/pd_grid/analysis.ipynb,sha256=ReYtRe2JVyCCXoMBONvynXDQ_eGtQSWhNcuJY3CYTTI,82323
21
+ mesa/examples/advanced/pd_grid/app.py,sha256=-_fTP7f_oITKHt7dDVJou7Oa7u7v_C4Ml5yw7D1sbx8,1457
22
+ mesa/examples/advanced/pd_grid/model.py,sha256=-ytTSW0a_TQGTQW02k7XKAMiMak_b2XkJUw5kkGNHMQ,2291
23
+ mesa/examples/advanced/sugarscape_g1mt/Readme.md,sha256=x3kKw1Rre2FPkNhGDLtdzeThmH089mxsGYUPZUeu26k,3595
24
+ mesa/examples/advanced/sugarscape_g1mt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ mesa/examples/advanced/sugarscape_g1mt/agents.py,sha256=ugTNvWjQNm_jMInv9d0sOIFaChIDs-TWazN78YrDP9g,8466
26
+ mesa/examples/advanced/sugarscape_g1mt/app.py,sha256=7BnjOEkzltfUSx_Hz8h7QXqWARrnAIULodReXd4joRo,2479
27
+ mesa/examples/advanced/sugarscape_g1mt/model.py,sha256=s4n9SRaaMNY9CXFtry83BELZU69UJOCa4DMrw_eehr4,5763
28
+ mesa/examples/advanced/sugarscape_g1mt/sugar-map.txt,sha256=zZtGYciBPT4miZVnbVuoQ5TugTmGrbDWV9yb5KH6tnU,5000
29
+ mesa/examples/advanced/sugarscape_g1mt/tests.py,sha256=UNahmZTgLquSqmoi_9GcE3JP0qBHjkrHFZ15NMm0ce8,2517
30
+ mesa/examples/advanced/wolf_sheep/Readme.md,sha256=6zrtCg4Fb-hgQxqdLMpTkIYMwD6owCv8BMz_qn0N98Q,3165
31
+ mesa/examples/advanced/wolf_sheep/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
+ mesa/examples/advanced/wolf_sheep/agents.py,sha256=QH0WsJbxcKjAeHY63j7dVXCUGIPc5G1vl7MaC-k8UZw,3829
33
+ mesa/examples/advanced/wolf_sheep/app.py,sha256=IIl-gDh1O3oYIvrXXGmKHbW5Iw3ZpCn691dGwKgyI3E,2508
34
+ mesa/examples/advanced/wolf_sheep/model.py,sha256=IUN1STm6jCGuzXo2sCF86r1U-dI63yhLhnI14tu9BSw,4567
35
+ mesa/examples/basic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
+ mesa/examples/basic/boid_flockers/Readme.md,sha256=4KJinsLPtUciQSMzvaX3tU5r1HTUg3AFOFDKy73W5RE,894
37
+ mesa/examples/basic/boid_flockers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
+ mesa/examples/basic/boid_flockers/agents.py,sha256=72oL4jWEiJfSgshSEcL44irptIY6WAQDRAQ0cO2MxS8,3827
39
+ mesa/examples/basic/boid_flockers/app.py,sha256=oJbv_CbeiXu97q1W_2xlsXIVAqqLvfxshn2Y70_7PyA,1244
40
+ mesa/examples/basic/boid_flockers/model.py,sha256=scy0OaYzQVY5vVarsI7dUydynwoH3-uYoYcsBTtwtyA,3399
41
+ mesa/examples/basic/boltzmann_wealth_model/Readme.md,sha256=wl1ylO9KWoTiuIJKOnk2FGdcmyVUqJ5wiSbVUa3WWAc,2725
42
+ mesa/examples/basic/boltzmann_wealth_model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
+ mesa/examples/basic/boltzmann_wealth_model/agents.py,sha256=Jol2aspw--UtQn0EiReXVmlWtzpdC2o_YUTAyu1sDk4,1546
44
+ mesa/examples/basic/boltzmann_wealth_model/app.py,sha256=wTQBu9A3uscTZSPqZ5jYssykGPiseye2YBjMngYI48A,2233
45
+ mesa/examples/basic/boltzmann_wealth_model/model.py,sha256=ED4EFHJlrrcF12WYOEpXpPt5asK2T6uzpq_S97EtfHo,2941
46
+ mesa/examples/basic/boltzmann_wealth_model/st_app.py,sha256=PQ65LkYPXn-lx4lCfXuFJmzcmAfVB3oEEdIyuq9a7iU,3454
47
+ mesa/examples/basic/conways_game_of_life/Readme.md,sha256=VRgN6roF6leQ_IMYwxFypSfFjZo9jnCd-rkPTjpp7II,1453
48
+ mesa/examples/basic/conways_game_of_life/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
+ mesa/examples/basic/conways_game_of_life/agents.py,sha256=ETn87GV8it9p0nlSn6f1qu5CDEmqokkr6Rq7KWaT-5U,1627
50
+ mesa/examples/basic/conways_game_of_life/app.py,sha256=HPzss2X3ntTOgdmg0C0EWw3lmAF7WiN9MZEgGdLW-xU,1997
51
+ mesa/examples/basic/conways_game_of_life/model.py,sha256=8L88m8F_YauwWeDef6UA2myQoAwC0B5sH5jsfyLn-u8,1221
52
+ mesa/examples/basic/conways_game_of_life/st_app.py,sha256=9qz3o0pOuvLZR-_aPPVHN-RIwFSNzvwWWfxCaD2K5cs,2402
53
+ mesa/examples/basic/schelling/Readme.md,sha256=CRKBfYtnLJLlTKLsTRQ-7gsQRxVxDooOBN5uP8PEtaU,2296
54
+ mesa/examples/basic/schelling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
+ mesa/examples/basic/schelling/agents.py,sha256=WdDM-BYeOUuIL_2U5rlZz4Rs_5orstHY2Z6G6zvQEyg,1224
56
+ mesa/examples/basic/schelling/analysis.ipynb,sha256=JDJy6-U6eO-LrHWxZr1c3lkvtoY0DNHa-kJ4J-Z-wwo,5804
57
+ mesa/examples/basic/schelling/app.py,sha256=DOu7aWjDeFGjD1yXlBbQ9qCUHguDDkYh4bmFBjM0Vb8,1065
58
+ mesa/examples/basic/schelling/model.py,sha256=ruqiMNBBsWV81srYZgdsfDVwgMWYuw2VAzSQhsK5E98,2762
59
+ mesa/examples/basic/virus_on_network/Readme.md,sha256=qmXGx4Fo0tRBvJiiJ684bkWJPn2gcFaiikLwgc5APWI,2336
60
+ mesa/examples/basic/virus_on_network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
+ mesa/examples/basic/virus_on_network/agents.py,sha256=a_WhqYblJlW6od67eXfU-nb7IMRyYpgxtf0le--VYoA,1975
62
+ mesa/examples/basic/virus_on_network/app.py,sha256=8I8VWQ7pBcOaNGyLDEO4IbNSTRy161-eWg-iEUVQ3-I,2553
63
+ mesa/examples/basic/virus_on_network/model.py,sha256=jQoCmvygwCvhUrlL0l7V8GcDLv94CgwtuK7DDGU8q8g,2813
64
+ mesa/experimental/__init__.py,sha256=32D_blj5droexwyh83MjPska0_xYzL1ncJFgyuyBaWs,905
65
+ mesa/experimental/cell_space/__init__.py,sha256=0A3YTen0Lk-e3Q73VEXK7N2UEHb9f50gW11H_jx7DXc,1744
66
+ mesa/experimental/cell_space/cell.py,sha256=Dl0ek7W_vgAZOp6zXBvkwYTG7E36OQ-4zZ5bW43mKtw,6600
67
+ mesa/experimental/cell_space/cell_agent.py,sha256=LOTLKR2To9hU-igKsauA5sikS7k8wgwlt-Pi0C7lGU0,4262
68
+ mesa/experimental/cell_space/cell_collection.py,sha256=VnD3I4bqnwgFxKSzTElYYJIBFJGdaEaNTggrbFKgPrc,4715
69
+ mesa/experimental/cell_space/discrete_space.py,sha256=qNGez9SV4E83Outs_12suuS0ZtTHcwyv6ZB1xzTXUWk,3846
70
+ mesa/experimental/cell_space/grid.py,sha256=d-1S2iXijGkoJ9yc271pB8iXlzsX13usJjcjevCs_rU,10432
71
+ mesa/experimental/cell_space/network.py,sha256=ujN2dV1i9hcXh6H0s7gwTuPT6gh7BCaziOUYPCybQKk,1862
72
+ mesa/experimental/cell_space/property_layer.py,sha256=HFpBWOjI7PFU_K8VDb_pl9h62MftCBWL7PUKQNT3Ke8,17379
73
+ mesa/experimental/cell_space/voronoi.py,sha256=5D9j45FW2IVPcZrp-hskw_z84QwHIdduwXLdTKeqWMQ,10472
74
+ mesa/experimental/devs/__init__.py,sha256=wkDrpqQ3qHGqrsOSTD-UOj-qOw0oFgnCw_ZXr9xFs90,1200
75
+ mesa/experimental/devs/eventlist.py,sha256=6igPkHJt-syLcdpFV14_n6HGej2F1cM9giDQo85fHPw,7217
76
+ mesa/experimental/devs/simulator.py,sha256=UiVRIlNodSIveD2mS_8-vj0T_FulU8vhXxSxCfsK1Vc,12991
77
+ mesa/experimental/mesa_signals/__init__.py,sha256=QjG4FSKQl5ZSzV9ctiaB7UqYDR3FARAyUc7HbGtQjX4,840
78
+ mesa/experimental/mesa_signals/mesa_signal.py,sha256=Vxo4gIV6a959MANL3RMANsGh0R9lkZTNO19XIYzvKSM,16860
79
+ mesa/experimental/mesa_signals/observable_collections.py,sha256=rHEj6BYxLHFFGzSdoDKAdtzJ6y-IHHfcP3qEDJJsY6Y,3917
80
+ mesa/experimental/mesa_signals/signals_util.py,sha256=fmq_FsIxsIvGjtmc4A9TGdBUtdliMHhEOpjRXivRDjA,1618
81
+ mesa/visualization/__init__.py,sha256=YW-oHEOTjbtDKD_TylAMtVnt8mrsz1Fw7ifdc4WeHxA,743
82
+ mesa/visualization/mpl_space_drawing.py,sha256=ZqZ-THsmdyTcwaUMik_S8990K8_FqliLeQMZwY45waM,20140
83
+ mesa/visualization/solara_viz.py,sha256=BjhmH2FLlVc8rxfAze9Ex1wj_0jkVOH-_bXz2MYzd2A,19325
84
+ mesa/visualization/user_param.py,sha256=Dl2WOwLYLf0pfLpabCZtIdFRyKZrK6Qtc3utZx5GPYg,2139
85
+ mesa/visualization/utils.py,sha256=lJHgRKF5BHLf72Tw3YpwyiWuRoIimaTKQ7xBCw_Rx3A,146
86
+ mesa/visualization/components/__init__.py,sha256=Bq3nrPikcaIo9BSs0O3zptWVLlUmAkLo3s0mEmpH1RE,3022
87
+ mesa/visualization/components/altair_components.py,sha256=wotpFFQgMY-ZR3lNVm_fRos-iDg0Wjnj6Tk67_7f1SQ,5847
88
+ mesa/visualization/components/matplotlib_components.py,sha256=xQETaFyHIfmL_9JwrLIgubuIQ7-pp7TMoXT1WMmozus,5441
89
+ mesa-3.1.1.dist-info/METADATA,sha256=s-5wsI5DiH4EK2qbn1UhNObxe-jB9hOoBvh5GwEU-eg,9906
90
+ mesa-3.1.1.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
91
+ mesa-3.1.1.dist-info/entry_points.txt,sha256=IOcQtetGF8l4wHpOs_hGb19Rz-FS__BMXOJR10IBPsA,39
92
+ mesa-3.1.1.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
93
+ mesa-3.1.1.dist-info/licenses/NOTICE,sha256=GbsWoK0QWv1JyZ_xer2s-jNilv0RtWl-0UrtlJANHPg,578
94
+ mesa-3.1.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.26.1
2
+ Generator: hatchling 1.26.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any