Mesa 3.1.2__py3-none-any.whl → 3.1.4__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.
- mesa/__init__.py +1 -1
- mesa/datacollection.py +62 -2
- mesa/examples/advanced/sugarscape_g1mt/app.py +15 -37
- mesa/examples/basic/boid_flockers/agents.py +26 -38
- mesa/examples/basic/boid_flockers/app.py +6 -1
- mesa/examples/basic/boid_flockers/model.py +30 -37
- mesa/experimental/__init__.py +2 -2
- mesa/experimental/cell_space/grid.py +8 -8
- mesa/experimental/cell_space/voronoi.py +1 -4
- mesa/experimental/continuous_space/__init__.py +8 -0
- mesa/experimental/continuous_space/continuous_space.py +273 -0
- mesa/experimental/continuous_space/continuous_space_agents.py +101 -0
- mesa/model.py +1 -1
- mesa/space.py +7 -0
- mesa/visualization/__init__.py +1 -2
- mesa/visualization/components/altair_components.py +10 -8
- mesa/visualization/mpl_space_drawing.py +160 -101
- mesa/visualization/solara_viz.py +35 -8
- {mesa-3.1.2.dist-info → mesa-3.1.4.dist-info}/METADATA +14 -10
- {mesa-3.1.2.dist-info → mesa-3.1.4.dist-info}/RECORD +23 -21
- mesa-3.1.2.dist-info/entry_points.txt +0 -2
- {mesa-3.1.2.dist-info → mesa-3.1.4.dist-info}/WHEEL +0 -0
- {mesa-3.1.2.dist-info → mesa-3.1.4.dist-info}/licenses/LICENSE +0 -0
- {mesa-3.1.2.dist-info → mesa-3.1.4.dist-info}/licenses/NOTICE +0 -0
mesa/__init__.py
CHANGED
mesa/datacollection.py
CHANGED
|
@@ -117,6 +117,9 @@ class DataCollector:
|
|
|
117
117
|
self._agenttype_records = {}
|
|
118
118
|
self.tables = {}
|
|
119
119
|
|
|
120
|
+
# add the signal of the validation of model reporter
|
|
121
|
+
self._validated = False
|
|
122
|
+
|
|
120
123
|
if model_reporters is not None:
|
|
121
124
|
for name, reporter in model_reporters.items():
|
|
122
125
|
self._new_model_reporter(name, reporter)
|
|
@@ -134,13 +137,66 @@ class DataCollector:
|
|
|
134
137
|
for name, columns in tables.items():
|
|
135
138
|
self._new_table(name, columns)
|
|
136
139
|
|
|
140
|
+
def _validate_model_reporter(self, name, reporter, model):
|
|
141
|
+
"""Validate model reporter and handle validation results appropriately.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
name: Name of the reporter
|
|
145
|
+
reporter: Reporter definition (lambda/method/attribute/function list)
|
|
146
|
+
model: Model instance
|
|
147
|
+
|
|
148
|
+
Raises:
|
|
149
|
+
ValueError: If reporter is None or has invalid format
|
|
150
|
+
AttributeError: If model attribute doesn't exist
|
|
151
|
+
TypeError: If reporter type is not supported
|
|
152
|
+
RuntimeError: If reporter execution fails
|
|
153
|
+
"""
|
|
154
|
+
self._validated = True # put the change of signal firstly avoid losing efficacy
|
|
155
|
+
|
|
156
|
+
# Type 1: Lambda function
|
|
157
|
+
if isinstance(reporter, types.LambdaType):
|
|
158
|
+
try:
|
|
159
|
+
reporter(model)
|
|
160
|
+
except Exception as e:
|
|
161
|
+
raise RuntimeError(
|
|
162
|
+
f"Lambda reporter '{name}' failed validation: {e!s}\n"
|
|
163
|
+
f"Example: lambda m: len(m.agents)"
|
|
164
|
+
) from e
|
|
165
|
+
|
|
166
|
+
# Type 2: Method of class/instance
|
|
167
|
+
if not callable(reporter) and not isinstance(reporter, types.LambdaType):
|
|
168
|
+
pass
|
|
169
|
+
|
|
170
|
+
# Type 3: Model attribute (string)
|
|
171
|
+
if isinstance(reporter, str):
|
|
172
|
+
try:
|
|
173
|
+
if not hasattr(model, reporter):
|
|
174
|
+
raise AttributeError(
|
|
175
|
+
f"Model reporter '{name}' references non-existent attribute '{reporter}'\n"
|
|
176
|
+
)
|
|
177
|
+
getattr(model, reporter) # 验证属性是否可访问
|
|
178
|
+
except AttributeError as e:
|
|
179
|
+
raise AttributeError(
|
|
180
|
+
f"Model reporter '{name}' attribute validation failed: {e!s}\n"
|
|
181
|
+
) from e
|
|
182
|
+
|
|
183
|
+
# Type 4: Function with parameters in list
|
|
184
|
+
if isinstance(reporter, list) and (not reporter or not callable(reporter[0])):
|
|
185
|
+
raise ValueError(
|
|
186
|
+
f"Invalid function list format for reporter '{name}'\n"
|
|
187
|
+
f"Expected: [function, [param1, param2]], got: {reporter}"
|
|
188
|
+
)
|
|
189
|
+
|
|
137
190
|
def _new_model_reporter(self, name, reporter):
|
|
138
191
|
"""Add a new model-level reporter to collect.
|
|
139
192
|
|
|
140
193
|
Args:
|
|
141
194
|
name: Name of the model-level variable to collect.
|
|
142
|
-
reporter:
|
|
143
|
-
|
|
195
|
+
reporter: Can be one of four types:
|
|
196
|
+
1. Attribute name (str): "attribute_name"
|
|
197
|
+
2. Lambda function: lambda m: len(m.agents)
|
|
198
|
+
3. Method: model.get_count or Model.get_count
|
|
199
|
+
4. List of [function, [parameters]]
|
|
144
200
|
"""
|
|
145
201
|
self.model_reporters[name] = reporter
|
|
146
202
|
self.model_vars[name] = []
|
|
@@ -262,6 +318,10 @@ class DataCollector:
|
|
|
262
318
|
def collect(self, model):
|
|
263
319
|
"""Collect all the data for the given model object."""
|
|
264
320
|
if self.model_reporters:
|
|
321
|
+
if not self._validated:
|
|
322
|
+
for name, reporter in self.model_reporters.items():
|
|
323
|
+
self._validate_model_reporter(name, reporter, model)
|
|
324
|
+
|
|
265
325
|
for var, reporter in self.model_reporters.items():
|
|
266
326
|
# Check if lambda or partial function
|
|
267
327
|
if isinstance(reporter, types.LambdaType | partial):
|
|
@@ -1,46 +1,24 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
import solara
|
|
3
|
-
from matplotlib.figure import Figure
|
|
4
|
-
|
|
5
1
|
from mesa.examples.advanced.sugarscape_g1mt.model import SugarscapeG1mt
|
|
6
2
|
from mesa.visualization import Slider, SolaraViz, make_plot_component
|
|
3
|
+
from mesa.visualization.components.matplotlib_components import make_mpl_space_component
|
|
4
|
+
|
|
7
5
|
|
|
6
|
+
def agent_portrayal(agent):
|
|
7
|
+
return {"marker": "o", "color": "red", "size": 10}
|
|
8
8
|
|
|
9
|
-
def SpaceDrawer(model):
|
|
10
|
-
def portray(g):
|
|
11
|
-
layers = {
|
|
12
|
-
"trader": {"x": [], "y": [], "c": "tab:red", "marker": "o", "s": 10},
|
|
13
|
-
}
|
|
14
9
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return layers
|
|
10
|
+
propertylayer_portrayal = {
|
|
11
|
+
"sugar": {"color": "blue", "alpha": 0.8, "colorbar": True, "vmin": 0, "vmax": 10},
|
|
12
|
+
"spice": {"color": "red", "alpha": 0.8, "colorbar": True, "vmin": 0, "vmax": 10},
|
|
13
|
+
}
|
|
20
14
|
|
|
21
|
-
fig = Figure()
|
|
22
|
-
ax = fig.subplots()
|
|
23
|
-
out = portray(model.grid)
|
|
24
|
-
# Sugar
|
|
25
|
-
# Important note: imshow by default draws from upper left. You have to
|
|
26
|
-
# always explicitly specify origin="lower".
|
|
27
|
-
im = ax.imshow(
|
|
28
|
-
np.ma.masked_where(model.grid.sugar.data <= 1, model.grid.sugar.data),
|
|
29
|
-
cmap="spring",
|
|
30
|
-
origin="lower",
|
|
31
|
-
)
|
|
32
|
-
fig.colorbar(im, orientation="vertical")
|
|
33
|
-
# Spice
|
|
34
|
-
ax.imshow(
|
|
35
|
-
np.ma.masked_where(model.grid.spice.data <= 1, model.grid.spice.data),
|
|
36
|
-
cmap="winter",
|
|
37
|
-
origin="lower",
|
|
38
|
-
)
|
|
39
|
-
# Trader
|
|
40
|
-
ax.scatter(**out["trader"])
|
|
41
|
-
ax.set_axis_off()
|
|
42
|
-
return solara.FigureMatplotlib(fig)
|
|
43
15
|
|
|
16
|
+
sugarscape_space = make_mpl_space_component(
|
|
17
|
+
agent_portrayal=agent_portrayal,
|
|
18
|
+
propertylayer_portrayal=propertylayer_portrayal,
|
|
19
|
+
post_process=None,
|
|
20
|
+
draw_grid=False,
|
|
21
|
+
)
|
|
44
22
|
|
|
45
23
|
model_params = {
|
|
46
24
|
"seed": {
|
|
@@ -72,7 +50,7 @@ model = SugarscapeG1mt()
|
|
|
72
50
|
page = SolaraViz(
|
|
73
51
|
model,
|
|
74
52
|
components=[
|
|
75
|
-
|
|
53
|
+
sugarscape_space,
|
|
76
54
|
make_plot_component("#Traders"),
|
|
77
55
|
make_plot_component("Price"),
|
|
78
56
|
],
|
|
@@ -6,10 +6,10 @@ of flocking behavior.
|
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
|
|
9
|
-
from mesa import
|
|
9
|
+
from mesa.experimental.continuous_space import ContinuousSpaceAgent
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class Boid(
|
|
12
|
+
class Boid(ContinuousSpaceAgent):
|
|
13
13
|
"""A Boid-style flocker agent.
|
|
14
14
|
|
|
15
15
|
The agent follows three behaviors to flock:
|
|
@@ -26,10 +26,12 @@ class Boid(Agent):
|
|
|
26
26
|
def __init__(
|
|
27
27
|
self,
|
|
28
28
|
model,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
space,
|
|
30
|
+
position=(0, 0),
|
|
31
|
+
speed=1,
|
|
32
|
+
direction=(1, 1),
|
|
33
|
+
vision=1,
|
|
34
|
+
separation=1,
|
|
33
35
|
cohere=0.03,
|
|
34
36
|
separate=0.015,
|
|
35
37
|
match=0.05,
|
|
@@ -46,7 +48,8 @@ class Boid(Agent):
|
|
|
46
48
|
separate: Relative importance of avoiding close neighbors (default: 0.015)
|
|
47
49
|
match: Relative importance of matching neighbors' directions (default: 0.05)
|
|
48
50
|
"""
|
|
49
|
-
super().__init__(model)
|
|
51
|
+
super().__init__(space, model)
|
|
52
|
+
self.position = position
|
|
50
53
|
self.speed = speed
|
|
51
54
|
self.direction = direction
|
|
52
55
|
self.vision = vision
|
|
@@ -58,46 +61,31 @@ class Boid(Agent):
|
|
|
58
61
|
|
|
59
62
|
def step(self):
|
|
60
63
|
"""Get the Boid's neighbors, compute the new vector, and move accordingly."""
|
|
61
|
-
|
|
64
|
+
neighbors, distances = self.get_neighbors_in_radius(radius=self.vision)
|
|
65
|
+
self.neighbors = [n for n in neighbors if n is not self]
|
|
62
66
|
|
|
63
67
|
# If no neighbors, maintain current direction
|
|
64
|
-
if not
|
|
65
|
-
|
|
66
|
-
self.model.space.move_agent(self, new_pos)
|
|
68
|
+
if not neighbors:
|
|
69
|
+
self.position += self.direction * self.speed
|
|
67
70
|
return
|
|
68
71
|
|
|
69
|
-
|
|
70
|
-
cohere = np.zeros(2) # Cohesion vector
|
|
71
|
-
match_vector = np.zeros(2) # Alignment vector
|
|
72
|
-
separation_vector = np.zeros(2) # Separation vector
|
|
72
|
+
delta = self.space.calculate_difference_vector(self.position, agents=neighbors)
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
# Separation - avoid getting too close
|
|
83
|
-
if distance < self.separation:
|
|
84
|
-
separation_vector -= heading
|
|
85
|
-
|
|
86
|
-
# Alignment - match neighbors' flying direction
|
|
87
|
-
match_vector += neighbor.direction
|
|
88
|
-
|
|
89
|
-
# Weight each behavior by its factor and normalize by number of neighbors
|
|
90
|
-
n = len(self.neighbors)
|
|
91
|
-
cohere = cohere * self.cohere_factor
|
|
92
|
-
separation_vector = separation_vector * self.separate_factor
|
|
93
|
-
match_vector = match_vector * self.match_factor
|
|
74
|
+
cohere_vector = delta.sum(axis=0) * self.cohere_factor
|
|
75
|
+
separation_vector = (
|
|
76
|
+
-1 * delta[distances < self.separation].sum(axis=0) * self.separate_factor
|
|
77
|
+
)
|
|
78
|
+
match_vector = (
|
|
79
|
+
np.asarray([n.direction for n in neighbors]).sum(axis=0) * self.match_factor
|
|
80
|
+
)
|
|
94
81
|
|
|
95
82
|
# Update direction based on the three behaviors
|
|
96
|
-
self.direction += (
|
|
83
|
+
self.direction += (cohere_vector + separation_vector + match_vector) / len(
|
|
84
|
+
neighbors
|
|
85
|
+
)
|
|
97
86
|
|
|
98
87
|
# Normalize direction vector
|
|
99
88
|
self.direction /= np.linalg.norm(self.direction)
|
|
100
89
|
|
|
101
90
|
# Move boid
|
|
102
|
-
|
|
103
|
-
self.model.space.move_agent(self, new_pos)
|
|
91
|
+
self.position += self.direction * self.speed
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
sys.path.insert(0, os.path.abspath("../../../.."))
|
|
5
|
+
|
|
1
6
|
from mesa.examples.basic.boid_flockers.model import BoidFlockers
|
|
2
7
|
from mesa.visualization import Slider, SolaraViz, make_space_component
|
|
3
8
|
|
|
@@ -17,7 +22,7 @@ model_params = {
|
|
|
17
22
|
"value": 42,
|
|
18
23
|
"label": "Random Seed",
|
|
19
24
|
},
|
|
20
|
-
"
|
|
25
|
+
"population_size": Slider(
|
|
21
26
|
label="Number of boids",
|
|
22
27
|
value=100,
|
|
23
28
|
min=10,
|
|
@@ -5,11 +5,17 @@ A Mesa implementation of Craig Reynolds's Boids flocker model.
|
|
|
5
5
|
Uses numpy arrays to represent vectors.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
sys.path.insert(0, os.path.abspath("../../../.."))
|
|
12
|
+
|
|
13
|
+
|
|
8
14
|
import numpy as np
|
|
9
15
|
|
|
10
16
|
from mesa import Model
|
|
11
17
|
from mesa.examples.basic.boid_flockers.agents import Boid
|
|
12
|
-
from mesa.
|
|
18
|
+
from mesa.experimental.continuous_space import ContinuousSpace
|
|
13
19
|
|
|
14
20
|
|
|
15
21
|
class BoidFlockers(Model):
|
|
@@ -17,7 +23,7 @@ class BoidFlockers(Model):
|
|
|
17
23
|
|
|
18
24
|
def __init__(
|
|
19
25
|
self,
|
|
20
|
-
|
|
26
|
+
population_size=100,
|
|
21
27
|
width=100,
|
|
22
28
|
height=100,
|
|
23
29
|
speed=1,
|
|
@@ -31,7 +37,7 @@ class BoidFlockers(Model):
|
|
|
31
37
|
"""Create a new Boids Flocking model.
|
|
32
38
|
|
|
33
39
|
Args:
|
|
34
|
-
|
|
40
|
+
population_size: Number of Boids in the simulation (default: 100)
|
|
35
41
|
width: Width of the space (default: 100)
|
|
36
42
|
height: Height of the space (default: 100)
|
|
37
43
|
speed: How fast the Boids move (default: 1)
|
|
@@ -44,48 +50,35 @@ class BoidFlockers(Model):
|
|
|
44
50
|
"""
|
|
45
51
|
super().__init__(seed=seed)
|
|
46
52
|
|
|
47
|
-
# Model Parameters
|
|
48
|
-
self.population = population
|
|
49
|
-
self.vision = vision
|
|
50
|
-
self.speed = speed
|
|
51
|
-
self.separation = separation
|
|
52
|
-
|
|
53
53
|
# Set up the space
|
|
54
|
-
self.space = ContinuousSpace(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
self.space = ContinuousSpace(
|
|
55
|
+
[[0, width], [0, height]],
|
|
56
|
+
torus=True,
|
|
57
|
+
random=self.random,
|
|
58
|
+
n_agents=population_size,
|
|
59
|
+
)
|
|
58
60
|
|
|
59
61
|
# Create and place the Boid agents
|
|
60
|
-
self.
|
|
62
|
+
positions = self.rng.random(size=(population_size, 2)) * self.space.size
|
|
63
|
+
directions = self.rng.uniform(-1, 1, size=(population_size, 2))
|
|
64
|
+
Boid.create_agents(
|
|
65
|
+
self,
|
|
66
|
+
population_size,
|
|
67
|
+
self.space,
|
|
68
|
+
position=positions,
|
|
69
|
+
direction=directions,
|
|
70
|
+
cohere=cohere,
|
|
71
|
+
separate=separate,
|
|
72
|
+
match=match,
|
|
73
|
+
speed=speed,
|
|
74
|
+
vision=vision,
|
|
75
|
+
separation=separation,
|
|
76
|
+
)
|
|
61
77
|
|
|
62
78
|
# For tracking statistics
|
|
63
79
|
self.average_heading = None
|
|
64
80
|
self.update_average_heading()
|
|
65
81
|
|
|
66
|
-
def make_agents(self):
|
|
67
|
-
"""Create and place all Boid agents randomly in the space."""
|
|
68
|
-
for _ in range(self.population):
|
|
69
|
-
# Random position
|
|
70
|
-
x = self.random.random() * self.space.x_max
|
|
71
|
-
y = self.random.random() * self.space.y_max
|
|
72
|
-
pos = np.array((x, y))
|
|
73
|
-
|
|
74
|
-
# Random initial direction
|
|
75
|
-
direction = np.random.random(2) * 2 - 1 # Random vector between -1 and 1
|
|
76
|
-
direction /= np.linalg.norm(direction) # Normalize
|
|
77
|
-
|
|
78
|
-
# Create and place the Boid
|
|
79
|
-
boid = Boid(
|
|
80
|
-
model=self,
|
|
81
|
-
speed=self.speed,
|
|
82
|
-
direction=direction,
|
|
83
|
-
vision=self.vision,
|
|
84
|
-
separation=self.separation,
|
|
85
|
-
**self.factors,
|
|
86
|
-
)
|
|
87
|
-
self.space.place_agent(boid, pos)
|
|
88
|
-
|
|
89
82
|
def update_average_heading(self):
|
|
90
83
|
"""Calculate the average heading (direction) of all Boids."""
|
|
91
84
|
if not self.agents:
|
mesa/experimental/__init__.py
CHANGED
|
@@ -15,6 +15,6 @@ Notes:
|
|
|
15
15
|
- Features graduate from experimental status once their APIs are stabilized
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
from mesa.experimental import cell_space, devs, mesa_signals
|
|
18
|
+
from mesa.experimental import cell_space, continuous_space, devs, mesa_signals
|
|
19
19
|
|
|
20
|
-
__all__ = ["cell_space", "devs", "mesa_signals"]
|
|
20
|
+
__all__ = ["cell_space", "continuous_space", "devs", "mesa_signals"]
|
|
@@ -273,20 +273,20 @@ class HexGrid(Grid[T]):
|
|
|
273
273
|
def _connect_cells_2d(self) -> None:
|
|
274
274
|
# fmt: off
|
|
275
275
|
even_offsets = [
|
|
276
|
-
(-1, -1), (-1
|
|
277
|
-
(
|
|
278
|
-
( 1,
|
|
276
|
+
(-1, -1), (0, -1),
|
|
277
|
+
( -1, 0), ( 1, 0),
|
|
278
|
+
( -1, 1), (0, 1),
|
|
279
279
|
]
|
|
280
280
|
odd_offsets = [
|
|
281
|
-
(-1
|
|
282
|
-
(
|
|
283
|
-
(
|
|
281
|
+
(0, -1), (1, -1),
|
|
282
|
+
( -1, 0), ( 1, 0),
|
|
283
|
+
( 0, 1), ( 1, 1),
|
|
284
284
|
]
|
|
285
285
|
# fmt: on
|
|
286
286
|
|
|
287
287
|
for cell in self.all_cells:
|
|
288
|
-
i = cell.coordinate[
|
|
289
|
-
offsets = even_offsets if i % 2
|
|
288
|
+
i = cell.coordinate[1]
|
|
289
|
+
offsets = even_offsets if i % 2 else odd_offsets
|
|
290
290
|
self._connect_single_cell_2d(cell, offsets=offsets)
|
|
291
291
|
|
|
292
292
|
def _connect_cells_nd(self) -> None:
|
|
@@ -186,7 +186,6 @@ class VoronoiGrid(DiscreteSpace):
|
|
|
186
186
|
random: Random | None = None,
|
|
187
187
|
cell_klass: type[Cell] = Cell,
|
|
188
188
|
capacity_function: callable = round_float,
|
|
189
|
-
cell_coloring_property: str | None = None,
|
|
190
189
|
) -> None:
|
|
191
190
|
"""A Voronoi Tessellation Grid.
|
|
192
191
|
|
|
@@ -200,7 +199,7 @@ class VoronoiGrid(DiscreteSpace):
|
|
|
200
199
|
random (Random): random number generator
|
|
201
200
|
cell_klass (type[Cell]): type of cell class
|
|
202
201
|
capacity_function (Callable): function to compute (int) capacity according to (float) area
|
|
203
|
-
|
|
202
|
+
|
|
204
203
|
"""
|
|
205
204
|
super().__init__(capacity=capacity, random=random, cell_klass=cell_klass)
|
|
206
205
|
self.centroids_coordinates = centroids_coordinates
|
|
@@ -215,7 +214,6 @@ class VoronoiGrid(DiscreteSpace):
|
|
|
215
214
|
self.triangulation = None
|
|
216
215
|
self.voronoi_coordinates = None
|
|
217
216
|
self.capacity_function = capacity_function
|
|
218
|
-
self.cell_coloring_property = cell_coloring_property
|
|
219
217
|
|
|
220
218
|
self._connect_cells()
|
|
221
219
|
self._build_cell_polygons()
|
|
@@ -266,4 +264,3 @@ class VoronoiGrid(DiscreteSpace):
|
|
|
266
264
|
polygon_area = self._compute_polygon_area(polygon)
|
|
267
265
|
self._cells[region].properties["area"] = polygon_area
|
|
268
266
|
self._cells[region].capacity = self.capacity_function(polygon_area)
|
|
269
|
-
self._cells[region].properties[self.cell_coloring_property] = 0
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""Continuous space support."""
|
|
2
|
+
|
|
3
|
+
from mesa.experimental.continuous_space.continuous_space import ContinuousSpace
|
|
4
|
+
from mesa.experimental.continuous_space.continuous_space_agents import (
|
|
5
|
+
ContinuousSpaceAgent,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
__all__ = ["ContinuousSpace", "ContinuousSpaceAgent"]
|