Mesa 2.3.0.dev0__py3-none-any.whl → 2.3.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.

@@ -17,7 +17,7 @@ plt.switch_backend("agg")
17
17
  # TODO: Turn this function into a Solara component once the current_step.value
18
18
  # dependency is passed to measure()
19
19
  def Card(
20
- model, measures, agent_portrayal, space_drawer, current_step, color, layout_type
20
+ model, measures, agent_portrayal, space_drawer, dependencies, color, layout_type
21
21
  ):
22
22
  with rv.Card(
23
23
  style_=f"background-color: {color}; width: 100%; height: 100%"
@@ -27,11 +27,11 @@ def Card(
27
27
  if space_drawer == "default":
28
28
  # draw with the default implementation
29
29
  components_matplotlib.SpaceMatplotlib(
30
- model, agent_portrayal, dependencies=[current_step.value]
30
+ model, agent_portrayal, dependencies=dependencies
31
31
  )
32
32
  elif space_drawer == "altair":
33
33
  components_altair.SpaceAltair(
34
- model, agent_portrayal, dependencies=[current_step.value]
34
+ model, agent_portrayal, dependencies=dependencies
35
35
  )
36
36
  elif space_drawer:
37
37
  # if specified, draw agent space with an alternate renderer
@@ -44,7 +44,7 @@ def Card(
44
44
  measure(model)
45
45
  else:
46
46
  components_matplotlib.PlotMatplotlib(
47
- model, measure, dependencies=[current_step.value]
47
+ model, measure, dependencies=dependencies
48
48
  )
49
49
  return main
50
50
 
@@ -58,6 +58,7 @@ def JupyterViz(
58
58
  agent_portrayal=None,
59
59
  space_drawer="default",
60
60
  play_interval=150,
61
+ seed=None,
61
62
  ):
62
63
  """Initialize a component to visualize a model.
63
64
  Args:
@@ -71,6 +72,7 @@ def JupyterViz(
71
72
  simulations with no space to visualize should
72
73
  specify `space_drawer=False`
73
74
  play_interval: play interval (default: 150)
75
+ seed: the random seed used to initialize the model
74
76
  """
75
77
  if name is None:
76
78
  name = model_class.__name__
@@ -78,6 +80,7 @@ def JupyterViz(
78
80
  current_step = solara.use_reactive(0)
79
81
 
80
82
  # 1. Set up model parameters
83
+ reactive_seed = solara.use_reactive(0)
81
84
  user_params, fixed_params = split_model_params(model_params)
82
85
  model_parameters, set_model_parameters = solara.use_state(
83
86
  {**fixed_params, **{k: v.get("value") for k, v in user_params.items()}}
@@ -85,13 +88,21 @@ def JupyterViz(
85
88
 
86
89
  # 2. Set up Model
87
90
  def make_model():
88
- model = model_class(**model_parameters)
91
+ model = model_class.__new__(
92
+ model_class, **model_parameters, seed=reactive_seed.value
93
+ )
94
+ model.__init__(**model_parameters)
89
95
  current_step.value = 0
90
96
  return model
91
97
 
92
98
  reset_counter = solara.use_reactive(0)
93
99
  model = solara.use_memo(
94
- make_model, dependencies=[*list(model_parameters.values()), reset_counter.value]
100
+ make_model,
101
+ dependencies=[
102
+ *list(model_parameters.values()),
103
+ reset_counter.value,
104
+ reactive_seed.value,
105
+ ],
95
106
  )
96
107
 
97
108
  def handle_change_model_params(name: str, value: any):
@@ -103,8 +114,12 @@ def JupyterViz(
103
114
  solara.AppBarTitle(name)
104
115
 
105
116
  # render layout and plot
117
+ def do_reseed():
118
+ reactive_seed.value = model.random.random()
106
119
 
107
120
  # jupyter
121
+ dependencies = [current_step.value, reactive_seed.value]
122
+
108
123
  def render_in_jupyter():
109
124
  with solara.GridFixed(columns=2):
110
125
  UserInputs(user_params, on_change=handle_change_model_params)
@@ -116,11 +131,11 @@ def JupyterViz(
116
131
  if space_drawer == "default":
117
132
  # draw with the default implementation
118
133
  components_matplotlib.SpaceMatplotlib(
119
- model, agent_portrayal, dependencies=[current_step.value]
134
+ model, agent_portrayal, dependencies=dependencies
120
135
  )
121
136
  elif space_drawer == "altair":
122
137
  components_altair.SpaceAltair(
123
- model, agent_portrayal, dependencies=[current_step.value]
138
+ model, agent_portrayal, dependencies=dependencies
124
139
  )
125
140
  elif space_drawer:
126
141
  # if specified, draw agent space with an alternate renderer
@@ -134,7 +149,7 @@ def JupyterViz(
134
149
  measure(model)
135
150
  else:
136
151
  components_matplotlib.PlotMatplotlib(
137
- model, measure, dependencies=[current_step.value]
152
+ model, measure, dependencies=dependencies
138
153
  )
139
154
 
140
155
  def render_in_browser():
@@ -144,15 +159,21 @@ def JupyterViz(
144
159
  if measures:
145
160
  layout_types += [{"Measure": elem} for elem in range(len(measures))]
146
161
 
147
- grid_layout_initial = get_initial_grid_layout(layout_types=layout_types)
162
+ grid_layout_initial = make_initial_grid_layout(layout_types=layout_types)
148
163
  grid_layout, set_grid_layout = solara.use_state(grid_layout_initial)
149
164
 
150
165
  with solara.Sidebar():
151
166
  with solara.Card("Controls", margin=1, elevation=2):
167
+ solara.InputText(
168
+ label="Seed",
169
+ value=reactive_seed,
170
+ continuous_update=True,
171
+ )
152
172
  UserInputs(user_params, on_change=handle_change_model_params)
153
173
  ModelController(model, play_interval, current_step, reset_counter)
154
- with solara.Card("Progress", margin=1, elevation=2):
155
- solara.Markdown(md_text=f"####Step - {current_step}")
174
+ solara.Button(label="Reseed", color="primary", on_click=do_reseed)
175
+ with solara.Card("Information", margin=1, elevation=2):
176
+ solara.Markdown(md_text=f"Step - {current_step}")
156
177
 
157
178
  items = [
158
179
  Card(
@@ -160,7 +181,7 @@ def JupyterViz(
160
181
  measures,
161
182
  agent_portrayal,
162
183
  space_drawer,
163
- current_step,
184
+ dependencies,
164
185
  color="white",
165
186
  layout_type=layout_types[i],
166
187
  )
@@ -241,7 +262,11 @@ def ModelController(model, play_interval, current_step, reset_counter):
241
262
  solara.Style(
242
263
  """
243
264
  .widget-play {
244
- height: 30px;
265
+ height: 35px;
266
+ }
267
+ .widget-play button {
268
+ color: white;
269
+ background-color: #1976D2; // Solara blue color
245
270
  }
246
271
  """
247
272
  )
@@ -361,20 +386,15 @@ def make_text(renderer):
361
386
  return function
362
387
 
363
388
 
364
- def get_initial_grid_layout(layout_types):
365
- grid_lay = []
366
- y_coord = 0
367
- for ii in range(len(layout_types)):
368
- template_layout = {"h": 10, "i": 0, "moved": False, "w": 6, "y": 0, "x": 0}
369
- if ii == 0:
370
- grid_lay.append(template_layout)
371
- else:
372
- template_layout.update({"i": ii})
373
- if ii % 2 == 0:
374
- template_layout.update({"x": 0})
375
- y_coord += 16
376
- else:
377
- template_layout.update({"x": 6})
378
- template_layout.update({"y": y_coord})
379
- grid_lay.append(template_layout)
380
- return grid_lay
389
+ def make_initial_grid_layout(layout_types):
390
+ return [
391
+ {
392
+ "i": i,
393
+ "w": 6,
394
+ "h": 10,
395
+ "moved": False,
396
+ "x": 6 * (i % 2),
397
+ "y": 16 * (i - i % 2),
398
+ }
399
+ for i in range(len(layout_types))
400
+ ]
mesa/model.py CHANGED
@@ -3,6 +3,7 @@ The model class for Mesa framework.
3
3
 
4
4
  Core Objects: Model
5
5
  """
6
+
6
7
  # Mypy; for the `|` operator purpose
7
8
  # Remove this __future__ import once the oldest supported Python is 3.10
8
9
  from __future__ import annotations
@@ -55,7 +56,7 @@ class Model:
55
56
  if obj._seed is None:
56
57
  # We explicitly specify the seed here so that we know its value in
57
58
  # advance.
58
- obj._seed = random.random() # noqa: S311
59
+ obj._seed = random.random()
59
60
  obj.random = random.Random(obj._seed)
60
61
  # TODO: Remove these 2 lines just before Mesa 3.0
61
62
  obj._steps = 0
@@ -76,9 +77,6 @@ class Model:
76
77
  self._steps: int = 0
77
78
  self._time: TimeT = 0 # the model's clock
78
79
 
79
- # Warning flags for current experimental features. These make sure a warning is only printed once per model.
80
- self.agentset_experimental_warning_given = False
81
-
82
80
  @property
83
81
  def agents(self) -> AgentSet:
84
82
  """Provides an AgentSet of all agents in the model, combining agents from all types."""
mesa/space.py CHANGED
@@ -71,6 +71,21 @@ def is_integer(x: Real) -> bool:
71
71
  return isinstance(x, _types_integer)
72
72
 
73
73
 
74
+ def warn_if_agent_has_position_already(placement_func):
75
+ def wrapper(self, agent, *args, **kwargs):
76
+ if agent.pos is not None:
77
+ warnings.warn(
78
+ f"""Agent {agent.unique_id} is being placed with
79
+ place_agent() despite already having the position {agent.pos}. In most
80
+ cases, you'd want to clear the current position with remove_agent()
81
+ before placing the agent again.""",
82
+ stacklevel=2,
83
+ )
84
+ placement_func(self, agent, *args, **kwargs)
85
+
86
+ return wrapper
87
+
88
+
74
89
  class _Grid:
75
90
  """Base class for a rectangular grid.
76
91
 
@@ -135,14 +150,12 @@ class _Grid:
135
150
  self._empties_built = True
136
151
 
137
152
  @overload
138
- def __getitem__(self, index: int | Sequence[Coordinate]) -> list[GridContent]:
139
- ...
153
+ def __getitem__(self, index: int | Sequence[Coordinate]) -> list[GridContent]: ...
140
154
 
141
155
  @overload
142
156
  def __getitem__(
143
157
  self, index: tuple[int | slice, int | slice]
144
- ) -> GridContent | list[GridContent]:
145
- ...
158
+ ) -> GridContent | list[GridContent]: ...
146
159
 
147
160
  def __getitem__(self, index):
148
161
  """Access contents from the grid."""
@@ -405,11 +418,9 @@ class _Grid:
405
418
  """
406
419
  return list(self.iter_cell_list_contents(cell_list))
407
420
 
408
- def place_agent(self, agent: Agent, pos: Coordinate) -> None:
409
- ...
421
+ def place_agent(self, agent: Agent, pos: Coordinate) -> None: ...
410
422
 
411
- def remove_agent(self, agent: Agent) -> None:
412
- ...
423
+ def remove_agent(self, agent: Agent) -> None: ...
413
424
 
414
425
  def move_agent(self, agent: Agent, pos: Coordinate) -> None:
415
426
  """Move an agent from its current position to a new position.
@@ -450,6 +461,7 @@ class _Grid:
450
461
  # Find the closest position without sorting all positions
451
462
  closest_pos = None
452
463
  min_distance = float("inf")
464
+ agent.random.shuffle(pos)
453
465
  for p in pos:
454
466
  distance = self._distance_squared(p, current_pos)
455
467
  if distance < min_distance:
@@ -763,16 +775,14 @@ class _PropertyGrid(_Grid):
763
775
 
764
776
  Attributes:
765
777
  properties (dict): A dictionary mapping property layer names to PropertyLayer instances.
766
- empty_mask: Returns a boolean mask indicating empty cells on the grid.
778
+ empty_mask (np.ndarray): A boolean array indicating empty cells on the grid.
767
779
 
768
780
  Methods:
769
781
  add_property_layer(property_layer): Adds a new property layer to the grid.
770
782
  remove_property_layer(property_name): Removes a property layer from the grid by its name.
771
783
  get_neighborhood_mask(pos, moore, include_center, radius): Generates a boolean mask of the neighborhood.
772
- select_cells_by_properties(conditions, mask, return_list): Selects cells based on multiple property conditions,
773
- optionally with a mask, returning either a list of coordinates or a mask.
774
- select_extreme_value_cells(property_name, mode, mask, return_list): Selects cells with extreme values of a property,
775
- optionally with a mask, returning either a list of coordinates or a mask.
784
+ select_cells(conditions, extreme_values, masks, only_empty, return_list): Selects cells based on multiple conditions,
785
+ extreme values, masks, with an option to select only empty cells, returning either a list of coordinates or a mask.
776
786
 
777
787
  Mask Usage:
778
788
  Several methods in this class accept a mask as an input, which is a NumPy ndarray of boolean values. This mask
@@ -978,6 +988,7 @@ class SingleGrid(_PropertyGrid):
978
988
  the grid for empty spaces.
979
989
  """
980
990
 
991
+ @warn_if_agent_has_position_already
981
992
  def place_agent(self, agent: Agent, pos: Coordinate) -> None:
982
993
  """Place the agent at the specified location, and set its pos variable."""
983
994
  if self.is_cell_empty(pos):
@@ -1026,6 +1037,7 @@ class MultiGrid(_PropertyGrid):
1026
1037
  """Default value for new cell elements."""
1027
1038
  return []
1028
1039
 
1040
+ @warn_if_agent_has_position_already
1029
1041
  def place_agent(self, agent: Agent, pos: Coordinate) -> None:
1030
1042
  """Place the agent at the specified location, and set its pos variable."""
1031
1043
  x, y = pos
@@ -1357,6 +1369,7 @@ class ContinuousSpace:
1357
1369
  self._agent_points = None
1358
1370
  self._index_to_agent = {}
1359
1371
 
1372
+ @warn_if_agent_has_position_already
1360
1373
  def place_agent(self, agent: Agent, pos: FloatCoordinate) -> None:
1361
1374
  """Place a new agent in the space.
1362
1375
 
@@ -1517,6 +1530,7 @@ class NetworkGrid:
1517
1530
  """Default value for a new node."""
1518
1531
  return []
1519
1532
 
1533
+ @warn_if_agent_has_position_already
1520
1534
  def place_agent(self, agent: Agent, node_id: int) -> None:
1521
1535
  """Place an agent in a node."""
1522
1536
  self.G.nodes[node_id]["agent"].append(agent)
mesa/time.py CHANGED
@@ -25,9 +25,7 @@ Key concepts:
25
25
  # Remove this __future__ import once the oldest supported Python is 3.10
26
26
  from __future__ import annotations
27
27
 
28
- import heapq
29
28
  import warnings
30
- import weakref
31
29
  from collections import defaultdict
32
30
  from collections.abc import Iterable
33
31
 
@@ -393,46 +391,7 @@ class RandomActivationByType(BaseScheduler):
393
391
 
394
392
  class DiscreteEventScheduler(BaseScheduler):
395
393
  """
396
- A scheduler for discrete event simulation in Mesa.
397
-
398
- This scheduler manages events where each event is associated with a
399
- specific time and agent. The scheduler advances time not in fixed
400
- increments, but to the moment the next event is scheduled to occur.
401
-
402
- This implementation uses a priority queue (heapq) to manage events. Each
403
- event is a tuple of the form (time, random_value, agent), where:
404
- - time (float): The scheduled time for the event.
405
- - random_value (float): A secondary sorting criterion to randomize
406
- the order of events that are scheduled for the same time.
407
- - agent (Agent): The agent associated with the event.
408
-
409
- The random value for secondary sorting ensures that when two events are
410
- scheduled for the same time, their execution order is randomized, thus
411
- preventing direct comparison issues between different types of agents and
412
- maintaining the integrity of the simulation's randomness.
413
-
414
- Attributes:
415
- model (Model): The model instance associated with the scheduler.
416
- event_queue (list): A priority queue of scheduled events.
417
- time_step (int or float): The fixed time period by which the model advances
418
- on each step. Defaults to 1.
419
-
420
- Methods:
421
- schedule_event(time, agent): Schedule an event for a specific time.
422
- schedule_in(delay, agent): Schedule an event after a specified delay.
423
- step(): Execute all events within the next time_step period.
424
- get_next_event_time(): Returns the time of the next scheduled event.
425
-
426
- Usage:
427
- 1. Instantiate the DiscreteEventScheduler with a model instance and a time_step period.
428
- 2. Add agents to the scheduler using schedule.add(). With schedule_now=True (default),
429
- the first event for the agent will be scheduled immediately.
430
- 3. In the Agent step() method, schedule the next event for the agent
431
- (using schedule_in or schedule_event).
432
- 3. Add self.schedule.step() to the model's step() method, as usual.
433
-
434
- Now, with each model step, the scheduler will execute all events within the
435
- next time_step period, and advance time one time_step forward.
394
+ This class has been deprecated and replaced by the functionality provided by experimental.devs
436
395
  """
437
396
 
438
397
  def __init__(self, model: Model, time_step: TimeT = 1) -> None:
@@ -444,72 +403,6 @@ class DiscreteEventScheduler(BaseScheduler):
444
403
 
445
404
  """
446
405
  super().__init__(model)
447
- self.event_queue: list[tuple[TimeT, float, weakref.ref]] = []
448
- self.time_step: TimeT = time_step # Fixed time period for each step
449
-
450
- warnings.warn(
451
- "The DiscreteEventScheduler is experimental. It may be changed or removed in any and all future releases, including patch releases.\n"
452
- "We would love to hear what you think about this new feature. If you have any thoughts, share them with us here: https://github.com/projectmesa/mesa/discussions/1923",
453
- FutureWarning,
454
- stacklevel=2,
406
+ raise Exception(
407
+ "DiscreteEventScheduler is deprecated in favor of the functionality provided by experimental.devs"
455
408
  )
456
-
457
- def schedule_event(self, time: TimeT, agent: Agent) -> None:
458
- """Schedule an event for an agent at a specific time."""
459
- if time < self.time:
460
- raise ValueError(
461
- f"Scheduled time ({time}) must be >= the current time ({self.time})"
462
- )
463
- if agent not in self._agents:
464
- raise ValueError(
465
- "trying to schedule an event for agent which is not known to the scheduler"
466
- )
467
-
468
- # Create an event, sorted first on time, secondary on a random value
469
- event = (time, self.model.random.random(), weakref.ref(agent))
470
- heapq.heappush(self.event_queue, event)
471
-
472
- def schedule_in(self, delay: TimeT, agent: Agent) -> None:
473
- """Schedule an event for an agent after a specified delay."""
474
- if delay < 0:
475
- raise ValueError("Delay must be non-negative")
476
- event_time = self.time + delay
477
- self.schedule_event(event_time, agent)
478
-
479
- def step(self) -> None:
480
- """Execute the next event and advance the time."""
481
- end_time = self.time + self.time_step
482
-
483
- while self.event_queue and self.event_queue[0][0] <= end_time:
484
- # Get the next event (ignore the random value during unpacking)
485
- time, _, agent = heapq.heappop(self.event_queue)
486
- agent = agent() # unpack weakref
487
-
488
- if agent:
489
- # Advance time to the event's time
490
- self.time = time
491
- # Execute the event
492
- agent.step()
493
-
494
- # After processing events, advance time by the time_step
495
- self.time = end_time
496
- self.steps += 1
497
-
498
- def get_next_event_time(self) -> TimeT | None:
499
- """Returns the time of the next scheduled event."""
500
- if not self.event_queue:
501
- return None
502
- return self.event_queue[0][0]
503
-
504
- def add(self, agent: Agent, schedule_now: bool = True) -> None:
505
- """Add an Agent object to the schedule and optionally schedule its first event.
506
-
507
- Args:
508
- agent: An Agent to be added to the schedule. Must have a step() method.
509
- schedule_now: If True, schedules the first event for the agent immediately.
510
- """
511
- super().add(agent) # Call the add method from BaseScheduler
512
-
513
- if schedule_now:
514
- # Schedule the first event immediately
515
- self.schedule_event(self.time, agent)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: Mesa
3
- Version: 2.3.0.dev0
3
+ Version: 2.3.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
@@ -34,6 +34,7 @@ Requires-Dist: tqdm
34
34
  Provides-Extra: dev
35
35
  Requires-Dist: coverage; extra == 'dev'
36
36
  Requires-Dist: pytest-cov; extra == 'dev'
37
+ Requires-Dist: pytest-mock; extra == 'dev'
37
38
  Requires-Dist: pytest>=4.6; extra == 'dev'
38
39
  Requires-Dist: ruff~=0.1.1; extra == 'dev'
39
40
  Requires-Dist: sphinx; extra == 'dev'
@@ -162,7 +163,7 @@ If you would like to add a feature, please reach out via [ticket](https://github
162
163
  join a dev session (see [Mesa discussions](https://github.com/projectmesa/mesa/discussions)). A feature is most likely
163
164
  to be added if you build it!
164
165
 
165
- Don't forget to checkout the [Contributors guide](https://github.com/projectmesa/mesa/blob/main/CONTRIBUTING.rst).
166
+ Don't forget to checkout the [Contributors guide](https://github.com/projectmesa/mesa/blob/main/CONTRIBUTING.md).
166
167
 
167
168
  ## Citing Mesa
168
169
 
@@ -0,0 +1,45 @@
1
+ mesa/__init__.py,sha256=dspGeuz4yLyjSg4fxTGIW0gCO61g9D8QH_0bNctLdCA,680
2
+ mesa/agent.py,sha256=L_kHMM3lTVLq8EM3UsX1xVLLo-P5IqFrJEqg83gT7xs,12902
3
+ mesa/batchrunner.py,sha256=2A1_FbFlSCkDm8xfv1ZamFiBE4VYce8sKP5SR_CledE,6087
4
+ mesa/datacollection.py,sha256=wJwt-bOU8WuXZomUg8JJhtIg4KMhoqXS0Zvyjv9SCAE,11445
5
+ mesa/main.py,sha256=7MovfNz88VWNnfXP0kcERB6C3GfkVOh0hb0o32hM9LU,1602
6
+ mesa/model.py,sha256=RxTCJUBfEgRIu3dXiMK9oMlxS3owwNQaQIrVRs6HsZY,5823
7
+ mesa/space.py,sha256=K2QsFXbBPPSzsPQMJMxERNX0kJ5dhlp0NNrWxuQpq-Q,62471
8
+ mesa/time.py,sha256=G83UKWeMFMnQV9-79Ps2gbD_Qz3hM07IFYLzf5Rvz1w,15243
9
+ mesa/cookiecutter-mesa/cookiecutter.json,sha256=tBSWli39fOWUXGfiDCTKd92M7uKaBIswXbkOdbUufYY,337
10
+ mesa/cookiecutter-mesa/hooks/post_gen_project.py,sha256=8JoXZKIioRYEWJURC0udj8WS3rg0c4So62sOZSGbrMY,294
11
+ mesa/cookiecutter-mesa/{{cookiecutter.snake}}/README.md,sha256=Yji4lGY-NtQSnW-oBj0_Jhs-XhCfZA8R1mBBM_IllGs,80
12
+ mesa/cookiecutter-mesa/{{cookiecutter.snake}}/run.pytemplate,sha256=7bYSRdq83--T1gnEuFls5aunb7lLNtUKFS2MUrovEg0,74
13
+ mesa/cookiecutter-mesa/{{cookiecutter.snake}}/setup.pytemplate,sha256=UtRpLM_CkeUZRec-Ef_LiO_x7SKaWN11fOiH9T1UmTw,214
14
+ mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/model.pytemplate,sha256=gTxSZ9t8My_Qiwuusqaf8DmspncrLKptxbg9cvfbloc,1842
16
+ mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/server.pytemplate,sha256=nqi6cPjhiyrYw82_Y9hLSrfZtSVCGIhMLOXRB7kKTlQ,823
17
+ mesa/experimental/UserParam.py,sha256=kpFu5yH_RSTI4S2XQxYAGWJgGwQo6j-yCADYJHry4lE,1641
18
+ mesa/experimental/__init__.py,sha256=ncy-EG4IMoSzknYXLMt3Z61nkMwkrH96QbJpGUqOpxQ,168
19
+ mesa/experimental/jupyter_viz.py,sha256=q2Xn-QjH0nqJoxY1RV_SSHC_OgMFZyKWHJjrn5jHCRk,13444
20
+ mesa/experimental/cell_space/__init__.py,sha256=trFVKf2l5RbkCUyxP09Kox_J3ak2YdM4o3t40Tsjjm4,628
21
+ mesa/experimental/cell_space/cell.py,sha256=AUnvVnXWhdgzr0bLKDRDO9c93v22Zkw6W-tWxhEhGdQ,4578
22
+ mesa/experimental/cell_space/cell_agent.py,sha256=G4u9ht4gW9ns1y2L7pFumF3K4HiP6ROuxwrxHZ-mL1M,1107
23
+ mesa/experimental/cell_space/cell_collection.py,sha256=Rjho3zIyKaamO2X9XEZu16qlmEP41tIHyhMST2KHK4o,2293
24
+ mesa/experimental/cell_space/discrete_space.py,sha256=ta__YojsrrhWL4DgMzUqZpSgbeexKMrA6bxlYPJGfK0,1921
25
+ mesa/experimental/cell_space/grid.py,sha256=IltngMSlMwLsJSNYrs6B4J5ylUbL5Vk1vPX_OhWGzTs,6949
26
+ mesa/experimental/cell_space/network.py,sha256=NWEdROFyO18pHOTb6_t9zjjUyGhAztPJm8a9b21c8ZU,1195
27
+ mesa/experimental/components/altair.py,sha256=_atxt79OpRjykAEwockKm0K9dp1jDPmcLeKqffZ0Bfo,2397
28
+ mesa/experimental/components/matplotlib.py,sha256=DVf41wdN1J56IQJXaeonqL4rcwYlsUIUB7C6r5ozdfg,4325
29
+ mesa/experimental/devs/__init__.py,sha256=CWam15vCj-RD_biMyqv4sJfos1fsL823P7MDEGrbwW8,174
30
+ mesa/experimental/devs/eventlist.py,sha256=H9hufe9VmwvlXQr146wCa7PgbzVvivG4Bk9rlEERZ7A,4880
31
+ mesa/experimental/devs/simulator.py,sha256=NQ3rtBIzykBtMWNslG_Fg04NQn2lYT8cmH-7ndr8v0Y,9530
32
+ mesa/experimental/devs/examples/epstein_civil_violence.py,sha256=KqH9KI-A_BYt7oWi9kaOhTzjrf2pETqzSpAQG8ewud0,9667
33
+ mesa/experimental/devs/examples/wolf_sheep.py,sha256=h5z-eDqMpYeOjrq293N2BcQbs_LDVsgtg9vblXJM7XQ,7697
34
+ mesa/flat/__init__.py,sha256=hSqQDjkfIgDu7B3aYtjPeNEUXdlKPHQuNN8HEV0XR6s,218
35
+ mesa/flat/visualization.py,sha256=5aCm8xDCmZij3hoJZvOVmmpzU9ACXSSSvmQr51buLVg,290
36
+ mesa/visualization/ModularVisualization.py,sha256=gT-FYRnvTFFxtehu-N-8eBLShCF8t_Ut8Au4iVPZIlA,60
37
+ mesa/visualization/TextVisualization.py,sha256=BIP0XcmIdYhz0igqe8yRZXlXeOOqJZeu8q9XViJTuLc,57
38
+ mesa/visualization/UserParam.py,sha256=D3qxoX-Cpqhyn06IdIO_C5s0u8nlhv3988lVwkBlcGo,49
39
+ mesa/visualization/__init__.py,sha256=5fwVAzgVsmxAzgoLxdC26l2ZE-m2bWj963xPNSDaQEQ,287
40
+ mesa/visualization/modules.py,sha256=pf6K3KECX51VNNqpFCm2EE5KV0A22UYmfXzTVXPnF_o,47
41
+ mesa-2.3.1.dist-info/METADATA,sha256=Xe3sFfvBz_SMqV-ib9mHBoK_ogWw8VFKIqT2-bbJw1A,7865
42
+ mesa-2.3.1.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
43
+ mesa-2.3.1.dist-info/entry_points.txt,sha256=IOcQtetGF8l4wHpOs_hGb19Rz-FS__BMXOJR10IBPsA,39
44
+ mesa-2.3.1.dist-info/licenses/LICENSE,sha256=OGUgret9fRrm8J3pdsPXETIjf0H8puK_Nmy970ZzT78,572
45
+ mesa-2.3.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.21.1
2
+ Generator: hatchling 1.25.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,33 +0,0 @@
1
- mesa/__init__.py,sha256=OmOIqjTe0C6Mb0z3i5e4e-9To1n-zkoGkSTpbI2NPm8,683
2
- mesa/agent.py,sha256=94Z_DAqBkoSGwI0S12afdJeC7LIwhPC9pFwtEMNUahw,13794
3
- mesa/batchrunner.py,sha256=2A1_FbFlSCkDm8xfv1ZamFiBE4VYce8sKP5SR_CledE,6087
4
- mesa/datacollection.py,sha256=kJc0nzp4anAl9v0X6c9GE-e8_ZMogctD3YxjPTRypd0,11194
5
- mesa/main.py,sha256=7MovfNz88VWNnfXP0kcERB6C3GfkVOh0hb0o32hM9LU,1602
6
- mesa/model.py,sha256=tmRM_ea7w4mt8XQFIZJQTa7JX4xu24ASwwLwmFm6shQ,6011
7
- mesa/space.py,sha256=XDdLFAtQv0gbkzlXAafwrlrs4fUkrZdjJ02O-bJJFp8,61935
8
- mesa/time.py,sha256=BAchKHNFh0ggQqaIMvojHhAF6I3zSQRlDXhQCyKq0NU,20208
9
- mesa/cookiecutter-mesa/cookiecutter.json,sha256=tBSWli39fOWUXGfiDCTKd92M7uKaBIswXbkOdbUufYY,337
10
- mesa/cookiecutter-mesa/hooks/post_gen_project.py,sha256=8JoXZKIioRYEWJURC0udj8WS3rg0c4So62sOZSGbrMY,294
11
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/README.md,sha256=Yji4lGY-NtQSnW-oBj0_Jhs-XhCfZA8R1mBBM_IllGs,80
12
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/run.pytemplate,sha256=7bYSRdq83--T1gnEuFls5aunb7lLNtUKFS2MUrovEg0,74
13
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/setup.pytemplate,sha256=UtRpLM_CkeUZRec-Ef_LiO_x7SKaWN11fOiH9T1UmTw,214
14
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/model.pytemplate,sha256=gTxSZ9t8My_Qiwuusqaf8DmspncrLKptxbg9cvfbloc,1842
16
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/server.pytemplate,sha256=nqi6cPjhiyrYw82_Y9hLSrfZtSVCGIhMLOXRB7kKTlQ,823
17
- mesa/experimental/UserParam.py,sha256=kpFu5yH_RSTI4S2XQxYAGWJgGwQo6j-yCADYJHry4lE,1641
18
- mesa/experimental/__init__.py,sha256=mwy0XqXikmjXorHKPEKr7hoZLzV6IPVtRukfMQeczcc,63
19
- mesa/experimental/jupyter_viz.py,sha256=AE8S6qbco1cKo08S5SLDn1HaaJiwwPSbRqosmLQ4SI0,13007
20
- mesa/experimental/components/altair.py,sha256=L9BeFQBt7f3nrR1xpzByUgEtFGbm0ryP8Qk-G_tb2-0,1900
21
- mesa/experimental/components/matplotlib.py,sha256=Ga3FEu1LxNJ7-d3QhRPW0GOcm6hLoXHHxwtrqAyQHGc,4157
22
- mesa/flat/__init__.py,sha256=hSqQDjkfIgDu7B3aYtjPeNEUXdlKPHQuNN8HEV0XR6s,218
23
- mesa/flat/visualization.py,sha256=5aCm8xDCmZij3hoJZvOVmmpzU9ACXSSSvmQr51buLVg,290
24
- mesa/visualization/ModularVisualization.py,sha256=gT-FYRnvTFFxtehu-N-8eBLShCF8t_Ut8Au4iVPZIlA,60
25
- mesa/visualization/TextVisualization.py,sha256=BIP0XcmIdYhz0igqe8yRZXlXeOOqJZeu8q9XViJTuLc,57
26
- mesa/visualization/UserParam.py,sha256=D3qxoX-Cpqhyn06IdIO_C5s0u8nlhv3988lVwkBlcGo,49
27
- mesa/visualization/__init__.py,sha256=5fwVAzgVsmxAzgoLxdC26l2ZE-m2bWj963xPNSDaQEQ,287
28
- mesa/visualization/modules.py,sha256=pf6K3KECX51VNNqpFCm2EE5KV0A22UYmfXzTVXPnF_o,47
29
- mesa-2.3.0.dev0.dist-info/METADATA,sha256=jwk3kleNbWc8dTSwEy-A89xN1DGFsOd_au7MBIA-GJk,7828
30
- mesa-2.3.0.dev0.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
31
- mesa-2.3.0.dev0.dist-info/entry_points.txt,sha256=IOcQtetGF8l4wHpOs_hGb19Rz-FS__BMXOJR10IBPsA,39
32
- mesa-2.3.0.dev0.dist-info/licenses/LICENSE,sha256=OGUgret9fRrm8J3pdsPXETIjf0H8puK_Nmy970ZzT78,572
33
- mesa-2.3.0.dev0.dist-info/RECORD,,