Mesa 3.0.0a0__py3-none-any.whl → 3.0.0a2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of Mesa might be problematic. Click here for more details.
- mesa/__init__.py +1 -1
- mesa/agent.py +26 -25
- mesa/batchrunner.py +4 -4
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/app.pytemplate +2 -2
- mesa/experimental/devs/eventlist.py +11 -0
- mesa/model.py +4 -7
- mesa/space.py +3 -3
- mesa/visualization/__init__.py +2 -2
- mesa/visualization/components/matplotlib.py +60 -23
- mesa/visualization/{jupyter_viz.py → solara_viz.py} +46 -86
- {mesa-3.0.0a0.dist-info → mesa-3.0.0a2.dist-info}/METADATA +10 -5
- {mesa-3.0.0a0.dist-info → mesa-3.0.0a2.dist-info}/RECORD +15 -15
- {mesa-3.0.0a0.dist-info → mesa-3.0.0a2.dist-info}/WHEEL +0 -0
- {mesa-3.0.0a0.dist-info → mesa-3.0.0a2.dist-info}/entry_points.txt +0 -0
- {mesa-3.0.0a0.dist-info → mesa-3.0.0a2.dist-info}/licenses/LICENSE +0 -0
mesa/__init__.py
CHANGED
|
@@ -24,7 +24,7 @@ __all__ = [
|
|
|
24
24
|
]
|
|
25
25
|
|
|
26
26
|
__title__ = "mesa"
|
|
27
|
-
__version__ = "3.0.
|
|
27
|
+
__version__ = "3.0.0a2"
|
|
28
28
|
__license__ = "Apache 2.0"
|
|
29
29
|
_this_year = datetime.datetime.now(tz=datetime.timezone.utc).date().year
|
|
30
30
|
__copyright__ = f"Copyright {_this_year} Project Mesa Team"
|
mesa/agent.py
CHANGED
|
@@ -11,9 +11,7 @@ from __future__ import annotations
|
|
|
11
11
|
import contextlib
|
|
12
12
|
import copy
|
|
13
13
|
import operator
|
|
14
|
-
import warnings
|
|
15
14
|
import weakref
|
|
16
|
-
from collections import defaultdict
|
|
17
15
|
from collections.abc import Callable, Iterable, Iterator, MutableSet, Sequence
|
|
18
16
|
from random import Random
|
|
19
17
|
|
|
@@ -52,17 +50,11 @@ class Agent:
|
|
|
52
50
|
# register agent
|
|
53
51
|
try:
|
|
54
52
|
self.model.agents_[type(self)][self] = None
|
|
55
|
-
except AttributeError:
|
|
53
|
+
except AttributeError as err:
|
|
56
54
|
# model super has not been called
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
warnings.warn(
|
|
62
|
-
"The Mesa Model class was not initialized. In the future, you need to explicitly initialize the Model by calling super().__init__() on initialization.",
|
|
63
|
-
FutureWarning,
|
|
64
|
-
stacklevel=2,
|
|
65
|
-
)
|
|
55
|
+
raise RuntimeError(
|
|
56
|
+
"The Mesa Model class was not initialized. You must explicitly initialize the Model by calling super().__init__() on initialization."
|
|
57
|
+
) from err
|
|
66
58
|
|
|
67
59
|
def remove(self) -> None:
|
|
68
60
|
"""Remove and delete the agent from the model."""
|
|
@@ -100,8 +92,6 @@ class AgentSet(MutableSet, Sequence):
|
|
|
100
92
|
which means that agents not referenced elsewhere in the program may be automatically removed from the AgentSet.
|
|
101
93
|
"""
|
|
102
94
|
|
|
103
|
-
agentset_experimental_warning_given = False
|
|
104
|
-
|
|
105
95
|
def __init__(self, agents: Iterable[Agent], model: Model):
|
|
106
96
|
"""
|
|
107
97
|
Initializes the AgentSet with a collection of agents and a reference to the model.
|
|
@@ -227,26 +217,37 @@ class AgentSet(MutableSet, Sequence):
|
|
|
227
217
|
return self
|
|
228
218
|
|
|
229
219
|
def do(
|
|
230
|
-
self,
|
|
220
|
+
self, method: str | Callable, *args, return_results: bool = False, **kwargs
|
|
231
221
|
) -> AgentSet | list[Any]:
|
|
232
222
|
"""
|
|
233
|
-
Invoke a method on each agent in the AgentSet.
|
|
223
|
+
Invoke a method or function on each agent in the AgentSet.
|
|
234
224
|
|
|
235
225
|
Args:
|
|
236
|
-
|
|
226
|
+
method (str, callable): the callable to do on each agents
|
|
227
|
+
|
|
228
|
+
* in case of str, the name of the method to call on each agent.
|
|
229
|
+
* in case of callable, the function to be called with each agent as first argument
|
|
230
|
+
|
|
237
231
|
return_results (bool, optional): If True, returns the results of the method calls; otherwise, returns the AgentSet itself. Defaults to False, so you can chain method calls.
|
|
238
|
-
*args: Variable length argument list passed to the
|
|
239
|
-
**kwargs: Arbitrary keyword arguments passed to the
|
|
232
|
+
*args: Variable length argument list passed to the callable being called.
|
|
233
|
+
**kwargs: Arbitrary keyword arguments passed to the callable being called.
|
|
240
234
|
|
|
241
235
|
Returns:
|
|
242
|
-
AgentSet | list[Any]: The results of the
|
|
236
|
+
AgentSet | list[Any]: The results of the callable calls if return_results is True, otherwise the AgentSet itself.
|
|
243
237
|
"""
|
|
244
238
|
# we iterate over the actual weakref keys and check if weakref is alive before calling the method
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
239
|
+
if isinstance(method, str):
|
|
240
|
+
res = [
|
|
241
|
+
getattr(agent, method)(*args, **kwargs)
|
|
242
|
+
for agentref in self._agents.keyrefs()
|
|
243
|
+
if (agent := agentref()) is not None
|
|
244
|
+
]
|
|
245
|
+
else:
|
|
246
|
+
res = [
|
|
247
|
+
method(agent, *args, **kwargs)
|
|
248
|
+
for agentref in self._agents.keyrefs()
|
|
249
|
+
if (agent := agentref()) is not None
|
|
250
|
+
]
|
|
250
251
|
|
|
251
252
|
return res if return_results else self
|
|
252
253
|
|
mesa/batchrunner.py
CHANGED
|
@@ -132,14 +132,14 @@ def _model_run_func(
|
|
|
132
132
|
"""
|
|
133
133
|
run_id, iteration, kwargs = run
|
|
134
134
|
model = model_cls(**kwargs)
|
|
135
|
-
while model.running and model.
|
|
135
|
+
while model.running and model._steps <= max_steps:
|
|
136
136
|
model.step()
|
|
137
137
|
|
|
138
138
|
data = []
|
|
139
139
|
|
|
140
|
-
steps = list(range(0, model.
|
|
141
|
-
if not steps or steps[-1] != model.
|
|
142
|
-
steps.append(model.
|
|
140
|
+
steps = list(range(0, model._steps, data_collection_period))
|
|
141
|
+
if not steps or steps[-1] != model._steps - 1:
|
|
142
|
+
steps.append(model._steps - 1)
|
|
143
143
|
|
|
144
144
|
for step in steps:
|
|
145
145
|
model_data, all_agents_data = _collect_data(model, step)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Configure visualization elements and instantiate a server
|
|
3
3
|
"""
|
|
4
|
-
from mesa.visualization import
|
|
4
|
+
from mesa.visualization import SolaraViz
|
|
5
5
|
|
|
6
6
|
from {{ cookiecutter.snake }}.model import {{ cookiecutter.model }}, {{ cookiecutter.agent }} # noqa
|
|
7
7
|
|
|
@@ -18,7 +18,7 @@ def circle_portrayal_example(agent):
|
|
|
18
18
|
|
|
19
19
|
model_params = {"num_agents": 10, "width": 10, "height": 10}
|
|
20
20
|
|
|
21
|
-
page =
|
|
21
|
+
page = SolaraViz(
|
|
22
22
|
{{cookiecutter.model}},
|
|
23
23
|
model_params,
|
|
24
24
|
measures=["num_agents"],
|
|
@@ -155,6 +155,17 @@ class EventList:
|
|
|
155
155
|
def __len__(self) -> int:
|
|
156
156
|
return len(self._events)
|
|
157
157
|
|
|
158
|
+
def __repr__(self) -> str:
|
|
159
|
+
"""Return a string representation of the event list"""
|
|
160
|
+
events_str = ", ".join(
|
|
161
|
+
[
|
|
162
|
+
f"Event(time={e.time}, priority={e.priority}, id={e.unique_id})"
|
|
163
|
+
for e in self._events
|
|
164
|
+
if not e.CANCELED
|
|
165
|
+
]
|
|
166
|
+
)
|
|
167
|
+
return f"EventList([{events_str}])"
|
|
168
|
+
|
|
158
169
|
def remove(self, event: SimulationEvent) -> None:
|
|
159
170
|
"""remove an event from the event list"""
|
|
160
171
|
# we cannot simply remove items from _eventlist because this breaks
|
mesa/model.py
CHANGED
|
@@ -10,7 +10,6 @@ from __future__ import annotations
|
|
|
10
10
|
|
|
11
11
|
import itertools
|
|
12
12
|
import random
|
|
13
|
-
import warnings
|
|
14
13
|
from collections import defaultdict
|
|
15
14
|
|
|
16
15
|
# mypy
|
|
@@ -89,12 +88,10 @@ class Model:
|
|
|
89
88
|
|
|
90
89
|
@agents.setter
|
|
91
90
|
def agents(self, agents: Any) -> None:
|
|
92
|
-
|
|
93
|
-
"You are trying to set model.agents. In
|
|
94
|
-
"by
|
|
95
|
-
"Please adjust your code to use a different attribute name for custom agent storage"
|
|
96
|
-
UserWarning,
|
|
97
|
-
stacklevel=2,
|
|
91
|
+
raise AttributeError(
|
|
92
|
+
"You are trying to set model.agents. In Mesa 3.0 and higher, this attribute will be "
|
|
93
|
+
"used by Mesa itself, so you cannot use it directly anymore."
|
|
94
|
+
"Please adjust your code to use a different attribute name for custom agent storage."
|
|
98
95
|
)
|
|
99
96
|
|
|
100
97
|
self._agents = agents
|
mesa/space.py
CHANGED
|
@@ -586,7 +586,7 @@ class PropertyLayer:
|
|
|
586
586
|
aggregate_property(operation): Performs an aggregate operation over all cells.
|
|
587
587
|
"""
|
|
588
588
|
|
|
589
|
-
|
|
589
|
+
propertylayer_experimental_warning_given = False
|
|
590
590
|
|
|
591
591
|
def __init__(
|
|
592
592
|
self, name: str, width: int, height: int, default_value, dtype=np.float64
|
|
@@ -633,14 +633,14 @@ class PropertyLayer:
|
|
|
633
633
|
|
|
634
634
|
self.data = np.full((width, height), default_value, dtype=dtype)
|
|
635
635
|
|
|
636
|
-
if not self.__class__.
|
|
636
|
+
if not self.__class__.propertylayer_experimental_warning_given:
|
|
637
637
|
warnings.warn(
|
|
638
638
|
"The new PropertyLayer and _PropertyGrid classes experimental. It may be changed or removed in any and all future releases, including patch releases.\n"
|
|
639
639
|
"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/1932",
|
|
640
640
|
FutureWarning,
|
|
641
641
|
stacklevel=2,
|
|
642
642
|
)
|
|
643
|
-
self.__class__.
|
|
643
|
+
self.__class__.propertylayer_experimental_warning_given = True
|
|
644
644
|
|
|
645
645
|
def set_cell(self, position: Coordinate, value):
|
|
646
646
|
"""
|
mesa/visualization/__init__.py
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from .
|
|
1
|
+
from .solara_viz import JupyterViz, Slider, SolaraViz, make_text
|
|
2
2
|
|
|
3
|
-
__all__ = ["JupyterViz", "make_text", "Slider"]
|
|
3
|
+
__all__ = ["JupyterViz", "make_text", "Slider", "SolaraViz"]
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from collections import defaultdict
|
|
2
|
+
|
|
1
3
|
import networkx as nx
|
|
2
4
|
import solara
|
|
3
5
|
from matplotlib.figure import Figure
|
|
@@ -23,12 +25,44 @@ def SpaceMatplotlib(model, agent_portrayal, dependencies: list[any] | None = Non
|
|
|
23
25
|
solara.FigureMatplotlib(space_fig, format="png", dependencies=dependencies)
|
|
24
26
|
|
|
25
27
|
|
|
28
|
+
# matplotlib scatter does not allow for multiple shapes in one call
|
|
29
|
+
def _split_and_scatter(portray_data, space_ax):
|
|
30
|
+
grouped_data = defaultdict(lambda: {"x": [], "y": [], "s": [], "c": []})
|
|
31
|
+
|
|
32
|
+
# Extract data from the dictionary
|
|
33
|
+
x = portray_data["x"]
|
|
34
|
+
y = portray_data["y"]
|
|
35
|
+
s = portray_data["s"]
|
|
36
|
+
c = portray_data["c"]
|
|
37
|
+
m = portray_data["m"]
|
|
38
|
+
|
|
39
|
+
if not (len(x) == len(y) == len(s) == len(c) == len(m)):
|
|
40
|
+
raise ValueError(
|
|
41
|
+
"Length mismatch in portrayal data lists: "
|
|
42
|
+
f"x: {len(x)}, y: {len(y)}, size: {len(s)}, "
|
|
43
|
+
f"color: {len(c)}, marker: {len(m)}"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# Group the data by marker
|
|
47
|
+
for i in range(len(x)):
|
|
48
|
+
marker = m[i]
|
|
49
|
+
grouped_data[marker]["x"].append(x[i])
|
|
50
|
+
grouped_data[marker]["y"].append(y[i])
|
|
51
|
+
grouped_data[marker]["s"].append(s[i])
|
|
52
|
+
grouped_data[marker]["c"].append(c[i])
|
|
53
|
+
|
|
54
|
+
# Plot each group with the same marker
|
|
55
|
+
for marker, data in grouped_data.items():
|
|
56
|
+
space_ax.scatter(data["x"], data["y"], s=data["s"], c=data["c"], marker=marker)
|
|
57
|
+
|
|
58
|
+
|
|
26
59
|
def _draw_grid(space, space_ax, agent_portrayal):
|
|
27
60
|
def portray(g):
|
|
28
61
|
x = []
|
|
29
62
|
y = []
|
|
30
63
|
s = [] # size
|
|
31
64
|
c = [] # color
|
|
65
|
+
m = [] # shape
|
|
32
66
|
for i in range(g.width):
|
|
33
67
|
for j in range(g.height):
|
|
34
68
|
content = g._grid[i][j]
|
|
@@ -41,23 +75,23 @@ def _draw_grid(space, space_ax, agent_portrayal):
|
|
|
41
75
|
data = agent_portrayal(agent)
|
|
42
76
|
x.append(i)
|
|
43
77
|
y.append(j)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
78
|
+
|
|
79
|
+
# This is the default value for the marker size, which auto-scales
|
|
80
|
+
# according to the grid area.
|
|
81
|
+
default_size = (180 / max(g.width, g.height)) ** 2
|
|
82
|
+
# establishing a default prevents misalignment if some agents are not given size, color, etc.
|
|
83
|
+
size = data.get("size", default_size)
|
|
84
|
+
s.append(size)
|
|
85
|
+
color = data.get("color", "tab:blue")
|
|
86
|
+
c.append(color)
|
|
87
|
+
mark = data.get("shape", "o")
|
|
88
|
+
m.append(mark)
|
|
89
|
+
out = {"x": x, "y": y, "s": s, "c": c, "m": m}
|
|
56
90
|
return out
|
|
57
91
|
|
|
58
92
|
space_ax.set_xlim(-1, space.width)
|
|
59
93
|
space_ax.set_ylim(-1, space.height)
|
|
60
|
-
|
|
94
|
+
_split_and_scatter(portray(space), space_ax)
|
|
61
95
|
|
|
62
96
|
|
|
63
97
|
def _draw_network_grid(space, space_ax, agent_portrayal):
|
|
@@ -77,20 +111,23 @@ def _draw_continuous_space(space, space_ax, agent_portrayal):
|
|
|
77
111
|
y = []
|
|
78
112
|
s = [] # size
|
|
79
113
|
c = [] # color
|
|
114
|
+
m = [] # shape
|
|
80
115
|
for agent in space._agent_to_index:
|
|
81
116
|
data = agent_portrayal(agent)
|
|
82
117
|
_x, _y = agent.pos
|
|
83
118
|
x.append(_x)
|
|
84
119
|
y.append(_y)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
120
|
+
|
|
121
|
+
# This is matplotlib's default marker size
|
|
122
|
+
default_size = 20
|
|
123
|
+
# establishing a default prevents misalignment if some agents are not given size, color, etc.
|
|
124
|
+
size = data.get("size", default_size)
|
|
125
|
+
s.append(size)
|
|
126
|
+
color = data.get("color", "tab:blue")
|
|
127
|
+
c.append(color)
|
|
128
|
+
mark = data.get("shape", "o")
|
|
129
|
+
m.append(mark)
|
|
130
|
+
out = {"x": x, "y": y, "s": s, "c": c, "m": m}
|
|
94
131
|
return out
|
|
95
132
|
|
|
96
133
|
# Determine border style based on space.torus
|
|
@@ -110,7 +147,7 @@ def _draw_continuous_space(space, space_ax, agent_portrayal):
|
|
|
110
147
|
space_ax.set_ylim(space.y_min - y_padding, space.y_max + y_padding)
|
|
111
148
|
|
|
112
149
|
# Portray and scatter the agents in the space
|
|
113
|
-
|
|
150
|
+
_split_and_scatter(portray(space), space_ax)
|
|
114
151
|
|
|
115
152
|
|
|
116
153
|
@solara.component
|
|
@@ -5,7 +5,7 @@ This module provides components to create browser- and Jupyter notebook-based vi
|
|
|
5
5
|
Mesa models, allowing users to watch models run step-by-step and interact with model parameters.
|
|
6
6
|
|
|
7
7
|
Key features:
|
|
8
|
-
-
|
|
8
|
+
- SolaraViz: Main component for creating visualizations, supporting grid displays and plots
|
|
9
9
|
- ModelController: Handles model execution controls (step, play, pause, reset)
|
|
10
10
|
- UserInputs: Generates UI elements for adjusting model parameters
|
|
11
11
|
- Card: Renders individual visualization elements (space, measures)
|
|
@@ -17,13 +17,12 @@ custom visualization components.
|
|
|
17
17
|
Usage:
|
|
18
18
|
1. Define an agent_portrayal function to specify how agents should be displayed
|
|
19
19
|
2. Set up model_params to define adjustable parameters
|
|
20
|
-
3. Create a
|
|
20
|
+
3. Create a SolaraViz instance with your model, parameters, and desired measures
|
|
21
21
|
4. Display the visualization in a Jupyter notebook or run as a Solara app
|
|
22
22
|
|
|
23
23
|
See the Visualization Tutorial and example models for more details.
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
|
-
import sys
|
|
27
26
|
import threading
|
|
28
27
|
|
|
29
28
|
import reacton.ipywidgets as widgets
|
|
@@ -71,7 +70,7 @@ def Card(
|
|
|
71
70
|
)
|
|
72
71
|
elif space_drawer:
|
|
73
72
|
# if specified, draw agent space with an alternate renderer
|
|
74
|
-
space_drawer(model, agent_portrayal)
|
|
73
|
+
space_drawer(model, agent_portrayal, dependencies=dependencies)
|
|
75
74
|
elif "Measure" in layout_type:
|
|
76
75
|
rv.CardTitle(children=["Measure"])
|
|
77
76
|
measure = measures[layout_type["Measure"]]
|
|
@@ -86,7 +85,7 @@ def Card(
|
|
|
86
85
|
|
|
87
86
|
|
|
88
87
|
@solara.component
|
|
89
|
-
def
|
|
88
|
+
def SolaraViz(
|
|
90
89
|
model_class,
|
|
91
90
|
model_params,
|
|
92
91
|
measures=None,
|
|
@@ -104,7 +103,8 @@ def JupyterViz(
|
|
|
104
103
|
model_params: Parameters for initializing the model
|
|
105
104
|
measures: List of callables or data attributes to plot
|
|
106
105
|
name: Name for display
|
|
107
|
-
agent_portrayal: Options for rendering agents (dictionary)
|
|
106
|
+
agent_portrayal: Options for rendering agents (dictionary);
|
|
107
|
+
Default drawer supports custom `"size"`, `"color"`, and `"shape"`.
|
|
108
108
|
space_drawer: Method to render the agent space for
|
|
109
109
|
the model; default implementation is the `SpaceMatplotlib` component;
|
|
110
110
|
simulations with no space to visualize should
|
|
@@ -158,92 +158,52 @@ def JupyterViz(
|
|
|
158
158
|
"""Update the random seed for the model."""
|
|
159
159
|
reactive_seed.value = model.random.random()
|
|
160
160
|
|
|
161
|
-
# jupyter
|
|
162
161
|
dependencies = [current_step.value, reactive_seed.value]
|
|
163
162
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
with solara.GridFixed(columns=2):
|
|
167
|
-
UserInputs(user_params, on_change=handle_change_model_params)
|
|
168
|
-
ModelController(model, play_interval, current_step, reset_counter)
|
|
169
|
-
solara.Markdown(md_text=f"###Step - {current_step}")
|
|
163
|
+
# if space drawer is disabled, do not include it
|
|
164
|
+
layout_types = [{"Space": "default"}] if space_drawer else []
|
|
170
165
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
# if specified, draw agent space with an alternate renderer
|
|
184
|
-
space_drawer(model, agent_portrayal)
|
|
185
|
-
# otherwise, do nothing (do not draw space)
|
|
186
|
-
|
|
187
|
-
# 5. Plots
|
|
188
|
-
if measures:
|
|
189
|
-
for measure in measures:
|
|
190
|
-
if callable(measure):
|
|
191
|
-
# Is a custom object
|
|
192
|
-
measure(model)
|
|
193
|
-
else:
|
|
194
|
-
components_matplotlib.PlotMatplotlib(
|
|
195
|
-
model, measure, dependencies=dependencies
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
def render_in_browser():
|
|
199
|
-
"""Render the visualization components in a web browser."""
|
|
200
|
-
# if space drawer is disabled, do not include it
|
|
201
|
-
layout_types = [{"Space": "default"}] if space_drawer else []
|
|
202
|
-
|
|
203
|
-
if measures:
|
|
204
|
-
layout_types += [{"Measure": elem} for elem in range(len(measures))]
|
|
205
|
-
|
|
206
|
-
grid_layout_initial = make_initial_grid_layout(layout_types=layout_types)
|
|
207
|
-
grid_layout, set_grid_layout = solara.use_state(grid_layout_initial)
|
|
208
|
-
|
|
209
|
-
with solara.Sidebar():
|
|
210
|
-
with solara.Card("Controls", margin=1, elevation=2):
|
|
211
|
-
solara.InputText(
|
|
212
|
-
label="Seed",
|
|
213
|
-
value=reactive_seed,
|
|
214
|
-
continuous_update=True,
|
|
215
|
-
)
|
|
216
|
-
UserInputs(user_params, on_change=handle_change_model_params)
|
|
217
|
-
ModelController(model, play_interval, current_step, reset_counter)
|
|
218
|
-
solara.Button(label="Reseed", color="primary", on_click=do_reseed)
|
|
219
|
-
with solara.Card("Information", margin=1, elevation=2):
|
|
220
|
-
solara.Markdown(md_text=f"Step - {current_step}")
|
|
221
|
-
|
|
222
|
-
items = [
|
|
223
|
-
Card(
|
|
224
|
-
model,
|
|
225
|
-
measures,
|
|
226
|
-
agent_portrayal,
|
|
227
|
-
space_drawer,
|
|
228
|
-
dependencies,
|
|
229
|
-
color="white",
|
|
230
|
-
layout_type=layout_types[i],
|
|
166
|
+
if measures:
|
|
167
|
+
layout_types += [{"Measure": elem} for elem in range(len(measures))]
|
|
168
|
+
|
|
169
|
+
grid_layout_initial = make_initial_grid_layout(layout_types=layout_types)
|
|
170
|
+
grid_layout, set_grid_layout = solara.use_state(grid_layout_initial)
|
|
171
|
+
|
|
172
|
+
with solara.Sidebar():
|
|
173
|
+
with solara.Card("Controls", margin=1, elevation=2):
|
|
174
|
+
solara.InputText(
|
|
175
|
+
label="Seed",
|
|
176
|
+
value=reactive_seed,
|
|
177
|
+
continuous_update=True,
|
|
231
178
|
)
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
179
|
+
UserInputs(user_params, on_change=handle_change_model_params)
|
|
180
|
+
ModelController(model, play_interval, current_step, reset_counter)
|
|
181
|
+
solara.Button(label="Reseed", color="primary", on_click=do_reseed)
|
|
182
|
+
with solara.Card("Information", margin=1, elevation=2):
|
|
183
|
+
solara.Markdown(md_text=f"Step - {current_step}")
|
|
184
|
+
|
|
185
|
+
items = [
|
|
186
|
+
Card(
|
|
187
|
+
model,
|
|
188
|
+
measures,
|
|
189
|
+
agent_portrayal,
|
|
190
|
+
space_drawer,
|
|
191
|
+
dependencies,
|
|
192
|
+
color="white",
|
|
193
|
+
layout_type=layout_types[i],
|
|
240
194
|
)
|
|
195
|
+
for i in range(len(layout_types))
|
|
196
|
+
]
|
|
197
|
+
solara.GridDraggable(
|
|
198
|
+
items=items,
|
|
199
|
+
grid_layout=grid_layout,
|
|
200
|
+
resizable=True,
|
|
201
|
+
draggable=True,
|
|
202
|
+
on_grid_layout=set_grid_layout,
|
|
203
|
+
)
|
|
204
|
+
|
|
241
205
|
|
|
242
|
-
|
|
243
|
-
# When in Jupyter or Google Colab
|
|
244
|
-
render_in_jupyter()
|
|
245
|
-
else:
|
|
246
|
-
render_in_browser()
|
|
206
|
+
JupyterViz = SolaraViz
|
|
247
207
|
|
|
248
208
|
|
|
249
209
|
@solara.component
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: Mesa
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.0a2
|
|
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
|
|
@@ -30,7 +30,6 @@ Requires-Dist: pandas
|
|
|
30
30
|
Requires-Dist: solara
|
|
31
31
|
Requires-Dist: tqdm
|
|
32
32
|
Provides-Extra: dev
|
|
33
|
-
Requires-Dist: coverage; extra == 'dev'
|
|
34
33
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
35
34
|
Requires-Dist: pytest-mock; extra == 'dev'
|
|
36
35
|
Requires-Dist: pytest>=4.6; extra == 'dev'
|
|
@@ -75,13 +74,19 @@ can be displayed in browser windows or Jupyter.*
|
|
|
75
74
|
|
|
76
75
|
## Using Mesa
|
|
77
76
|
|
|
78
|
-
|
|
77
|
+
To install our latest stable release (2.3.x), run:
|
|
79
78
|
|
|
80
79
|
``` bash
|
|
81
|
-
pip install mesa
|
|
80
|
+
pip install -U mesa
|
|
82
81
|
```
|
|
83
82
|
|
|
84
|
-
|
|
83
|
+
To install our latest pre-release (3.0.0 alpha), run:
|
|
84
|
+
|
|
85
|
+
``` bash
|
|
86
|
+
pip install -U --pre mesa
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
You can also use `pip` to install the latest GitHub version:
|
|
85
90
|
|
|
86
91
|
``` bash
|
|
87
92
|
pip install -U -e git+https://github.com/projectmesa/mesa@main#egg=mesa
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
mesa/__init__.py,sha256=
|
|
2
|
-
mesa/agent.py,sha256=
|
|
3
|
-
mesa/batchrunner.py,sha256=
|
|
1
|
+
mesa/__init__.py,sha256=MvmhX7S8OWq9FLM52bF7lnSUTTNZegQPsSheI37L2og,618
|
|
2
|
+
mesa/agent.py,sha256=xqpjpMHii82nts-gO5DPpcUjujHQoaJB2fKi0VrrWHs,13067
|
|
3
|
+
mesa/batchrunner.py,sha256=92MabDDR38XGTZw_IB7nNDNH0PX7zL_jGyZJ2grisaY,6023
|
|
4
4
|
mesa/datacollection.py,sha256=CQ2QsW-mkEVbDVTsOkLy8NAQEKeoILdLB0zWS2sxnyk,11444
|
|
5
5
|
mesa/main.py,sha256=7MovfNz88VWNnfXP0kcERB6C3GfkVOh0hb0o32hM9LU,1602
|
|
6
|
-
mesa/model.py,sha256=
|
|
7
|
-
mesa/space.py,sha256=
|
|
6
|
+
mesa/model.py,sha256=Jqj6ob-zuTwAWwYAkbEsoC-bTA7ptoAD9qDvPfIX-80,5761
|
|
7
|
+
mesa/space.py,sha256=zC96qoNjhLmBXY2ZaEQmF7w30WZAtPpEY4mwcet-Dio,62462
|
|
8
8
|
mesa/time.py,sha256=9gNoyUqYkt_gUPFBMhm38pK87mcntwAZ1lJzxqW3BSA,15211
|
|
9
9
|
mesa/cookiecutter-mesa/cookiecutter.json,sha256=tBSWli39fOWUXGfiDCTKd92M7uKaBIswXbkOdbUufYY,337
|
|
10
10
|
mesa/cookiecutter-mesa/hooks/post_gen_project.py,sha256=8JoXZKIioRYEWJURC0udj8WS3rg0c4So62sOZSGbrMY,294
|
|
11
11
|
mesa/cookiecutter-mesa/{{cookiecutter.snake}}/README.md,sha256=Yji4lGY-NtQSnW-oBj0_Jhs-XhCfZA8R1mBBM_IllGs,80
|
|
12
|
-
mesa/cookiecutter-mesa/{{cookiecutter.snake}}/app.pytemplate,sha256=
|
|
12
|
+
mesa/cookiecutter-mesa/{{cookiecutter.snake}}/app.pytemplate,sha256=36f9k9CH6TK6VrXsPvTFXGUfCKzCLwgYTeK-Gt27GNg,584
|
|
13
13
|
mesa/cookiecutter-mesa/{{cookiecutter.snake}}/setup.pytemplate,sha256=UtRpLM_CkeUZRec-Ef_LiO_x7SKaWN11fOiH9T1UmTw,214
|
|
14
14
|
mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/model.pytemplate,sha256=Aml4Z6E1yj7E7DtHNSUqnKNRUdkxG9WWtJyW8fkxCng,1870
|
|
@@ -22,17 +22,17 @@ mesa/experimental/cell_space/discrete_space.py,sha256=ta__YojsrrhWL4DgMzUqZpSgbe
|
|
|
22
22
|
mesa/experimental/cell_space/grid.py,sha256=gYDExuFBMF3OThUkhbXmolQFKBOqTukcibjfgXicP00,6948
|
|
23
23
|
mesa/experimental/cell_space/network.py,sha256=mAaFHBdd4s9kxUWHbViovLW2-pU2yXH0dtY_vF8sCJg,1179
|
|
24
24
|
mesa/experimental/devs/__init__.py,sha256=CWam15vCj-RD_biMyqv4sJfos1fsL823P7MDEGrbwW8,174
|
|
25
|
-
mesa/experimental/devs/eventlist.py,sha256=
|
|
25
|
+
mesa/experimental/devs/eventlist.py,sha256=nyUFNDWnnSPQnrMtj7Qj1PexxKyOwSJuIGBoxtSwVI0,5269
|
|
26
26
|
mesa/experimental/devs/simulator.py,sha256=0SMC7daIOyL2rYfoQOOTaTOYDos0gLeBUbU1Krd42HA,9557
|
|
27
27
|
mesa/experimental/devs/examples/epstein_civil_violence.py,sha256=KqH9KI-A_BYt7oWi9kaOhTzjrf2pETqzSpAQG8ewud0,9667
|
|
28
28
|
mesa/experimental/devs/examples/wolf_sheep.py,sha256=h5z-eDqMpYeOjrq293N2BcQbs_LDVsgtg9vblXJM7XQ,7697
|
|
29
29
|
mesa/visualization/UserParam.py,sha256=WgnY3Q0padtGqUCaezgYzd6cZ7LziuIQnGKP3DBuHZY,1641
|
|
30
|
-
mesa/visualization/__init__.py,sha256=
|
|
31
|
-
mesa/visualization/
|
|
30
|
+
mesa/visualization/__init__.py,sha256=zsAzEY3-0O9CZUfiUL6p8zCR1mvvL5Sai2WzoiQ2pmY,127
|
|
31
|
+
mesa/visualization/solara_viz.py,sha256=GuhDFcsHp6rSjaYMM7lgB-sWJGfEqJrYnmMxncnZF8A,15192
|
|
32
32
|
mesa/visualization/components/altair.py,sha256=V2CQ-Zr7PeijgWtYBNH3VklGVfrf1ee70XVh0DBBONQ,2366
|
|
33
|
-
mesa/visualization/components/matplotlib.py,sha256=
|
|
34
|
-
mesa-3.0.
|
|
35
|
-
mesa-3.0.
|
|
36
|
-
mesa-3.0.
|
|
37
|
-
mesa-3.0.
|
|
38
|
-
mesa-3.0.
|
|
33
|
+
mesa/visualization/components/matplotlib.py,sha256=gUTteu_VEA4J2je760aq_esYto0Uj1DZP9gjev8TlcU,5851
|
|
34
|
+
mesa-3.0.0a2.dist-info/METADATA,sha256=zAMPJhtCHtWiXvm6dl5iCqU048qhtZpBkGsKO6RtaEM,7862
|
|
35
|
+
mesa-3.0.0a2.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
|
36
|
+
mesa-3.0.0a2.dist-info/entry_points.txt,sha256=IOcQtetGF8l4wHpOs_hGb19Rz-FS__BMXOJR10IBPsA,39
|
|
37
|
+
mesa-3.0.0a2.dist-info/licenses/LICENSE,sha256=OGUgret9fRrm8J3pdsPXETIjf0H8puK_Nmy970ZzT78,572
|
|
38
|
+
mesa-3.0.0a2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|