Mesa 3.0.0__py3-none-any.whl → 3.0.0a0__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 +3 -3
- mesa/agent.py +114 -406
- mesa/batchrunner.py +27 -54
- mesa/cookiecutter-mesa/cookiecutter.json +8 -0
- mesa/cookiecutter-mesa/hooks/post_gen_project.py +11 -0
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/README.md +4 -0
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/app.pytemplate +27 -0
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/setup.pytemplate +11 -0
- mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/model.pytemplate +60 -0
- mesa/datacollection.py +29 -140
- mesa/experimental/__init__.py +1 -11
- mesa/experimental/cell_space/__init__.py +1 -16
- mesa/experimental/cell_space/cell.py +23 -93
- mesa/experimental/cell_space/cell_agent.py +21 -117
- mesa/experimental/cell_space/cell_collection.py +17 -54
- mesa/experimental/cell_space/discrete_space.py +8 -92
- mesa/experimental/cell_space/grid.py +8 -32
- mesa/experimental/cell_space/network.py +7 -12
- mesa/experimental/devs/__init__.py +0 -2
- mesa/experimental/devs/eventlist.py +14 -52
- mesa/experimental/devs/examples/epstein_civil_violence.py +39 -71
- mesa/experimental/devs/examples/wolf_sheep.py +45 -45
- mesa/experimental/devs/simulator.py +15 -55
- mesa/main.py +63 -0
- mesa/model.py +83 -211
- mesa/space.py +149 -215
- mesa/time.py +77 -62
- mesa/{experimental → visualization}/UserParam.py +6 -17
- mesa/visualization/__init__.py +2 -25
- mesa/{experimental → visualization}/components/altair.py +0 -10
- mesa/visualization/components/matplotlib.py +134 -0
- mesa/{experimental/solara_viz.py → visualization/jupyter_viz.py} +110 -65
- {mesa-3.0.0.dist-info → mesa-3.0.0a0.dist-info}/METADATA +13 -65
- mesa-3.0.0a0.dist-info/RECORD +38 -0
- mesa-3.0.0.dist-info/licenses/NOTICE → mesa-3.0.0a0.dist-info/licenses/LICENSE +2 -2
- mesa/examples/README.md +0 -37
- mesa/examples/__init__.py +0 -21
- mesa/examples/advanced/epstein_civil_violence/Epstein Civil Violence.ipynb +0 -116
- mesa/examples/advanced/epstein_civil_violence/Readme.md +0 -34
- mesa/examples/advanced/epstein_civil_violence/__init__.py +0 -0
- mesa/examples/advanced/epstein_civil_violence/agents.py +0 -164
- mesa/examples/advanced/epstein_civil_violence/app.py +0 -73
- mesa/examples/advanced/epstein_civil_violence/model.py +0 -114
- mesa/examples/advanced/pd_grid/Readme.md +0 -43
- mesa/examples/advanced/pd_grid/__init__.py +0 -0
- mesa/examples/advanced/pd_grid/agents.py +0 -50
- mesa/examples/advanced/pd_grid/analysis.ipynb +0 -228
- mesa/examples/advanced/pd_grid/app.py +0 -54
- mesa/examples/advanced/pd_grid/model.py +0 -71
- mesa/examples/advanced/sugarscape_g1mt/Readme.md +0 -64
- mesa/examples/advanced/sugarscape_g1mt/__init__.py +0 -0
- mesa/examples/advanced/sugarscape_g1mt/agents.py +0 -344
- mesa/examples/advanced/sugarscape_g1mt/app.py +0 -62
- mesa/examples/advanced/sugarscape_g1mt/model.py +0 -180
- mesa/examples/advanced/sugarscape_g1mt/sugar-map.txt +0 -50
- mesa/examples/advanced/sugarscape_g1mt/tests.py +0 -69
- mesa/examples/advanced/wolf_sheep/Readme.md +0 -57
- mesa/examples/advanced/wolf_sheep/__init__.py +0 -0
- mesa/examples/advanced/wolf_sheep/agents.py +0 -102
- mesa/examples/advanced/wolf_sheep/app.py +0 -84
- mesa/examples/advanced/wolf_sheep/model.py +0 -137
- mesa/examples/basic/__init__.py +0 -0
- mesa/examples/basic/boid_flockers/Readme.md +0 -22
- mesa/examples/basic/boid_flockers/__init__.py +0 -0
- mesa/examples/basic/boid_flockers/agents.py +0 -71
- mesa/examples/basic/boid_flockers/app.py +0 -58
- mesa/examples/basic/boid_flockers/model.py +0 -69
- mesa/examples/basic/boltzmann_wealth_model/Readme.md +0 -56
- mesa/examples/basic/boltzmann_wealth_model/__init__.py +0 -0
- mesa/examples/basic/boltzmann_wealth_model/agents.py +0 -31
- mesa/examples/basic/boltzmann_wealth_model/app.py +0 -74
- mesa/examples/basic/boltzmann_wealth_model/model.py +0 -43
- mesa/examples/basic/boltzmann_wealth_model/st_app.py +0 -115
- mesa/examples/basic/conways_game_of_life/Readme.md +0 -39
- mesa/examples/basic/conways_game_of_life/__init__.py +0 -0
- mesa/examples/basic/conways_game_of_life/agents.py +0 -47
- mesa/examples/basic/conways_game_of_life/app.py +0 -51
- mesa/examples/basic/conways_game_of_life/model.py +0 -31
- mesa/examples/basic/conways_game_of_life/st_app.py +0 -72
- mesa/examples/basic/schelling/Readme.md +0 -40
- mesa/examples/basic/schelling/__init__.py +0 -0
- mesa/examples/basic/schelling/agents.py +0 -26
- mesa/examples/basic/schelling/analysis.ipynb +0 -205
- mesa/examples/basic/schelling/app.py +0 -42
- mesa/examples/basic/schelling/model.py +0 -59
- mesa/examples/basic/virus_on_network/Readme.md +0 -61
- mesa/examples/basic/virus_on_network/__init__.py +0 -0
- mesa/examples/basic/virus_on_network/agents.py +0 -69
- mesa/examples/basic/virus_on_network/app.py +0 -114
- mesa/examples/basic/virus_on_network/model.py +0 -96
- mesa/experimental/cell_space/voronoi.py +0 -257
- mesa/experimental/components/matplotlib.py +0 -242
- mesa/visualization/components/__init__.py +0 -83
- mesa/visualization/components/altair_components.py +0 -188
- mesa/visualization/components/matplotlib_components.py +0 -175
- mesa/visualization/mpl_space_drawing.py +0 -593
- mesa/visualization/solara_viz.py +0 -458
- mesa/visualization/user_param.py +0 -69
- mesa/visualization/utils.py +0 -9
- mesa-3.0.0.dist-info/RECORD +0 -95
- mesa-3.0.0.dist-info/licenses/LICENSE +0 -202
- /mesa/{examples/advanced → cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}}/__init__.py +0 -0
- {mesa-3.0.0.dist-info → mesa-3.0.0a0.dist-info}/WHEEL +0 -0
- {mesa-3.0.0.dist-info → mesa-3.0.0a0.dist-info}/entry_points.txt +0 -0
|
@@ -1,40 +1,36 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""
|
|
2
|
+
Wolf-Sheep Predation Model
|
|
3
|
+
================================
|
|
4
|
+
|
|
5
|
+
Replication of the model found in NetLogo:
|
|
6
|
+
Wilensky, U. (1997). NetLogo Wolf Sheep Predation model.
|
|
7
|
+
http://ccl.northwestern.edu/netlogo/models/WolfSheepPredation.
|
|
8
|
+
Center for Connected Learning and Computer-Based Modeling,
|
|
9
|
+
Northwestern University, Evanston, IL.
|
|
10
|
+
"""
|
|
2
11
|
|
|
3
12
|
import mesa
|
|
4
|
-
from mesa.experimental.cell_space import FixedAgent
|
|
5
13
|
from mesa.experimental.devs.simulator import ABMSimulator
|
|
6
14
|
|
|
7
15
|
|
|
8
16
|
class Animal(mesa.Agent):
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def __init__(self, model, moore, energy, p_reproduce, energy_from_food):
|
|
12
|
-
"""Initialize Animal instance.
|
|
13
|
-
|
|
14
|
-
Args:
|
|
15
|
-
model: a model instance
|
|
16
|
-
moore: using moore grid or not
|
|
17
|
-
energy: initial energy
|
|
18
|
-
p_reproduce: probability of reproduction
|
|
19
|
-
energy_from_food: energy gained from 1 unit of food
|
|
20
|
-
"""
|
|
21
|
-
super().__init__(model)
|
|
17
|
+
def __init__(self, unique_id, model, moore, energy, p_reproduce, energy_from_food):
|
|
18
|
+
super().__init__(unique_id, model)
|
|
22
19
|
self.energy = energy
|
|
23
20
|
self.p_reproduce = p_reproduce
|
|
24
21
|
self.energy_from_food = energy_from_food
|
|
25
22
|
self.moore = moore
|
|
26
23
|
|
|
27
24
|
def random_move(self):
|
|
28
|
-
"""Move to random neighboring cell."""
|
|
29
25
|
next_moves = self.model.grid.get_neighborhood(self.pos, self.moore, True)
|
|
30
26
|
next_move = self.random.choice(next_moves)
|
|
31
27
|
# Now move:
|
|
32
28
|
self.model.grid.move_agent(self, next_move)
|
|
33
29
|
|
|
34
30
|
def spawn_offspring(self):
|
|
35
|
-
"""Create offspring."""
|
|
36
31
|
self.energy /= 2
|
|
37
32
|
offspring = self.__class__(
|
|
33
|
+
self.model.next_id(),
|
|
38
34
|
self.model,
|
|
39
35
|
self.moore,
|
|
40
36
|
self.energy,
|
|
@@ -43,15 +39,13 @@ class Animal(mesa.Agent):
|
|
|
43
39
|
)
|
|
44
40
|
self.model.grid.place_agent(offspring, self.pos)
|
|
45
41
|
|
|
46
|
-
def feed(self): ...
|
|
42
|
+
def feed(self): ...
|
|
47
43
|
|
|
48
44
|
def die(self):
|
|
49
|
-
"""Die."""
|
|
50
45
|
self.model.grid.remove_agent(self)
|
|
51
46
|
self.remove()
|
|
52
47
|
|
|
53
48
|
def step(self):
|
|
54
|
-
"""Execute one step of the agent."""
|
|
55
49
|
self.random_move()
|
|
56
50
|
self.energy -= 1
|
|
57
51
|
|
|
@@ -64,10 +58,13 @@ class Animal(mesa.Agent):
|
|
|
64
58
|
|
|
65
59
|
|
|
66
60
|
class Sheep(Animal):
|
|
67
|
-
"""
|
|
61
|
+
"""
|
|
62
|
+
A sheep that walks around, reproduces (asexually) and gets eaten.
|
|
63
|
+
|
|
64
|
+
The init is the same as the RandomWalker.
|
|
65
|
+
"""
|
|
68
66
|
|
|
69
67
|
def feed(self):
|
|
70
|
-
"""Eat grass and gain energy."""
|
|
71
68
|
# If there is grass available, eat it
|
|
72
69
|
agents = self.model.grid.get_cell_list_contents(self.pos)
|
|
73
70
|
grass_patch = next(obj for obj in agents if isinstance(obj, GrassPatch))
|
|
@@ -77,10 +74,11 @@ class Sheep(Animal):
|
|
|
77
74
|
|
|
78
75
|
|
|
79
76
|
class Wolf(Animal):
|
|
80
|
-
"""
|
|
77
|
+
"""
|
|
78
|
+
A wolf that walks around, reproduces (asexually) and eats sheep.
|
|
79
|
+
"""
|
|
81
80
|
|
|
82
81
|
def feed(self):
|
|
83
|
-
"""Eat wolf and gain energy."""
|
|
84
82
|
agents = self.model.grid.get_cell_list_contents(self.pos)
|
|
85
83
|
sheep = [obj for obj in agents if isinstance(obj, Sheep)]
|
|
86
84
|
if len(sheep) > 0:
|
|
@@ -91,11 +89,13 @@ class Wolf(Animal):
|
|
|
91
89
|
sheep_to_eat.die()
|
|
92
90
|
|
|
93
91
|
|
|
94
|
-
class GrassPatch(
|
|
95
|
-
"""
|
|
92
|
+
class GrassPatch(mesa.Agent):
|
|
93
|
+
"""
|
|
94
|
+
A patch of grass that grows at a fixed rate and it is eaten by sheep
|
|
95
|
+
"""
|
|
96
96
|
|
|
97
97
|
@property
|
|
98
|
-
def fully_grown(self) -> bool:
|
|
98
|
+
def fully_grown(self) -> bool:
|
|
99
99
|
return self._fully_grown
|
|
100
100
|
|
|
101
101
|
@fully_grown.setter
|
|
@@ -109,16 +109,15 @@ class GrassPatch(FixedAgent):
|
|
|
109
109
|
function_args=[self, "fully_grown", True],
|
|
110
110
|
)
|
|
111
111
|
|
|
112
|
-
def __init__(self, model, fully_grown, countdown, grass_regrowth_time):
|
|
113
|
-
"""
|
|
112
|
+
def __init__(self, unique_id, model, fully_grown, countdown, grass_regrowth_time):
|
|
113
|
+
"""
|
|
114
|
+
Creates a new patch of grass
|
|
114
115
|
|
|
115
116
|
Args:
|
|
116
|
-
|
|
117
|
-
fully_grown: (boolean) Whether the patch of grass is fully grown or not
|
|
117
|
+
grown: (boolean) Whether the patch of grass is fully grown or not
|
|
118
118
|
countdown: Time for the patch of grass to be fully grown again
|
|
119
|
-
grass_regrowth_time: regrowth time for the grass
|
|
120
119
|
"""
|
|
121
|
-
super().__init__(model)
|
|
120
|
+
super().__init__(unique_id, model)
|
|
122
121
|
self._fully_grown = fully_grown
|
|
123
122
|
self.grass_regrowth_time = grass_regrowth_time
|
|
124
123
|
|
|
@@ -127,12 +126,13 @@ class GrassPatch(FixedAgent):
|
|
|
127
126
|
setattr, countdown, function_args=[self, "fully_grown", True]
|
|
128
127
|
)
|
|
129
128
|
|
|
130
|
-
def set_fully_grown(self):
|
|
129
|
+
def set_fully_grown(self):
|
|
131
130
|
self.fully_grown = True
|
|
132
131
|
|
|
133
132
|
|
|
134
133
|
class WolfSheep(mesa.Model):
|
|
135
|
-
"""
|
|
134
|
+
"""
|
|
135
|
+
Wolf-Sheep Predation Model
|
|
136
136
|
|
|
137
137
|
A model for simulating wolf and sheep (predator-prey) ecosystem modelling.
|
|
138
138
|
"""
|
|
@@ -152,11 +152,10 @@ class WolfSheep(mesa.Model):
|
|
|
152
152
|
simulator=None,
|
|
153
153
|
seed=None,
|
|
154
154
|
):
|
|
155
|
-
"""
|
|
155
|
+
"""
|
|
156
|
+
Create a new Wolf-Sheep model with the given parameters.
|
|
156
157
|
|
|
157
158
|
Args:
|
|
158
|
-
height: height of the grid
|
|
159
|
-
width: width of the grid
|
|
160
159
|
initial_sheep: Number of sheep to start with
|
|
161
160
|
initial_wolves: Number of wolves to start with
|
|
162
161
|
sheep_reproduce: Probability of each sheep reproducing each step
|
|
@@ -166,9 +165,7 @@ class WolfSheep(mesa.Model):
|
|
|
166
165
|
grass_regrowth_time: How long it takes for a grass patch to regrow
|
|
167
166
|
once it is eaten
|
|
168
167
|
sheep_gain_from_food: Energy sheep gain from grass, if enabled.
|
|
169
|
-
moore:
|
|
170
|
-
simulator: Simulator to use for simulating wolf and sheep
|
|
171
|
-
seed: Random seed
|
|
168
|
+
moore:
|
|
172
169
|
"""
|
|
173
170
|
super().__init__(seed=seed)
|
|
174
171
|
# Set parameters
|
|
@@ -194,6 +191,7 @@ class WolfSheep(mesa.Model):
|
|
|
194
191
|
)
|
|
195
192
|
energy = self.random.randrange(2 * sheep_gain_from_food)
|
|
196
193
|
sheep = Sheep(
|
|
194
|
+
self.next_id(),
|
|
197
195
|
self,
|
|
198
196
|
moore,
|
|
199
197
|
energy,
|
|
@@ -210,6 +208,7 @@ class WolfSheep(mesa.Model):
|
|
|
210
208
|
)
|
|
211
209
|
energy = self.random.randrange(2 * wolf_gain_from_food)
|
|
212
210
|
wolf = Wolf(
|
|
211
|
+
self.next_id(),
|
|
213
212
|
self,
|
|
214
213
|
moore,
|
|
215
214
|
energy,
|
|
@@ -226,13 +225,14 @@ class WolfSheep(mesa.Model):
|
|
|
226
225
|
countdown = grass_regrowth_time
|
|
227
226
|
else:
|
|
228
227
|
countdown = self.random.randrange(grass_regrowth_time)
|
|
229
|
-
patch = GrassPatch(
|
|
228
|
+
patch = GrassPatch(
|
|
229
|
+
self.next_id(), self, fully_grown, countdown, grass_regrowth_time
|
|
230
|
+
)
|
|
230
231
|
self.grid.place_agent(patch, pos)
|
|
231
232
|
|
|
232
233
|
def step(self):
|
|
233
|
-
"
|
|
234
|
-
self.
|
|
235
|
-
self.agents_by_type[Wolf].shuffle_do("step")
|
|
234
|
+
self.get_agents_of_type(Sheep).shuffle(inplace=True).do("step")
|
|
235
|
+
self.get_agents_of_type(Wolf).shuffle(inplace=True).do("step")
|
|
236
236
|
|
|
237
237
|
|
|
238
238
|
if __name__ == "__main__":
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
"""Provides several simulator classes.
|
|
2
|
-
|
|
3
|
-
A Simulator is responsible for executing a simulation model. It controls time advancement and enables event scheduling.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
1
|
from __future__ import annotations
|
|
9
2
|
|
|
10
3
|
import numbers
|
|
@@ -34,12 +27,6 @@ class Simulator:
|
|
|
34
27
|
# TODO: add experimentation support
|
|
35
28
|
|
|
36
29
|
def __init__(self, time_unit: type, start_time: int | float):
|
|
37
|
-
"""Initialize a Simulator instance.
|
|
38
|
-
|
|
39
|
-
Args:
|
|
40
|
-
time_unit: type of the smulaiton time
|
|
41
|
-
start_time: the starttime of the simulator
|
|
42
|
-
"""
|
|
43
30
|
# should model run in a separate thread,
|
|
44
31
|
# and we can then interact with start, stop, run_until, and step?
|
|
45
32
|
self.event_list = EventList()
|
|
@@ -49,10 +36,10 @@ class Simulator:
|
|
|
49
36
|
self.time = self.start_time
|
|
50
37
|
self.model = None
|
|
51
38
|
|
|
52
|
-
def check_time_unit(self, time: int | float) -> bool: ...
|
|
39
|
+
def check_time_unit(self, time: int | float) -> bool: ...
|
|
53
40
|
|
|
54
41
|
def setup(self, model: Model) -> None:
|
|
55
|
-
"""Set up the simulator with the model to simulate
|
|
42
|
+
"""Set up the simulator with the model to simulate
|
|
56
43
|
|
|
57
44
|
Args:
|
|
58
45
|
model (Model): The model to simulate
|
|
@@ -62,13 +49,12 @@ class Simulator:
|
|
|
62
49
|
self.model = model
|
|
63
50
|
|
|
64
51
|
def reset(self):
|
|
65
|
-
"""Reset the simulator by clearing the event list and removing the model to simulate
|
|
52
|
+
"""Reset the simulator by clearing the event list and removing the model to simulate"""
|
|
66
53
|
self.event_list.clear()
|
|
67
54
|
self.model = None
|
|
68
55
|
self.time = self.start_time
|
|
69
56
|
|
|
70
57
|
def run_until(self, end_time: int | float) -> None:
|
|
71
|
-
"""Run the simulator until the end time."""
|
|
72
58
|
while True:
|
|
73
59
|
try:
|
|
74
60
|
event = self.event_list.pop_event()
|
|
@@ -85,7 +71,7 @@ class Simulator:
|
|
|
85
71
|
break
|
|
86
72
|
|
|
87
73
|
def run_for(self, time_delta: int | float):
|
|
88
|
-
"""
|
|
74
|
+
"""run the simulator for the specified time delta
|
|
89
75
|
|
|
90
76
|
Args:
|
|
91
77
|
time_delta (float| int): The time delta. The simulator is run from the current time to the current time
|
|
@@ -102,7 +88,7 @@ class Simulator:
|
|
|
102
88
|
function_args: list[Any] | None = None,
|
|
103
89
|
function_kwargs: dict[str, Any] | None = None,
|
|
104
90
|
) -> SimulationEvent:
|
|
105
|
-
"""Schedule event for the current time instant
|
|
91
|
+
"""Schedule event for the current time instant
|
|
106
92
|
|
|
107
93
|
Args:
|
|
108
94
|
function (Callable): The callable to execute for this event
|
|
@@ -130,7 +116,7 @@ class Simulator:
|
|
|
130
116
|
function_args: list[Any] | None = None,
|
|
131
117
|
function_kwargs: dict[str, Any] | None = None,
|
|
132
118
|
) -> SimulationEvent:
|
|
133
|
-
"""Schedule event for the specified time instant
|
|
119
|
+
"""Schedule event for the specified time instant
|
|
134
120
|
|
|
135
121
|
Args:
|
|
136
122
|
function (Callable): The callable to execute for this event
|
|
@@ -164,7 +150,7 @@ class Simulator:
|
|
|
164
150
|
function_args: list[Any] | None = None,
|
|
165
151
|
function_kwargs: dict[str, Any] | None = None,
|
|
166
152
|
) -> SimulationEvent:
|
|
167
|
-
"""Schedule event for the current time plus the time delta
|
|
153
|
+
"""Schedule event for the current time plus the time delta
|
|
168
154
|
|
|
169
155
|
Args:
|
|
170
156
|
function (Callable): The callable to execute for this event
|
|
@@ -188,12 +174,13 @@ class Simulator:
|
|
|
188
174
|
return event
|
|
189
175
|
|
|
190
176
|
def cancel_event(self, event: SimulationEvent) -> None:
|
|
191
|
-
"""
|
|
177
|
+
"""remove the event from the event list
|
|
192
178
|
|
|
193
179
|
Args:
|
|
194
180
|
event (SimulationEvent): The simulation event to remove
|
|
195
181
|
|
|
196
182
|
"""
|
|
183
|
+
|
|
197
184
|
self.event_list.remove(event)
|
|
198
185
|
|
|
199
186
|
def _schedule_event(self, event: SimulationEvent):
|
|
@@ -217,29 +204,13 @@ class ABMSimulator(Simulator):
|
|
|
217
204
|
"""
|
|
218
205
|
|
|
219
206
|
def __init__(self):
|
|
220
|
-
"""Initialize a ABM simulator."""
|
|
221
207
|
super().__init__(int, 0)
|
|
222
208
|
|
|
223
209
|
def setup(self, model):
|
|
224
|
-
"""Set up the simulator with the model to simulate.
|
|
225
|
-
|
|
226
|
-
Args:
|
|
227
|
-
model (Model): The model to simulate
|
|
228
|
-
|
|
229
|
-
"""
|
|
230
210
|
super().setup(model)
|
|
231
211
|
self.schedule_event_now(self.model.step, priority=Priority.HIGH)
|
|
232
212
|
|
|
233
213
|
def check_time_unit(self, time) -> bool:
|
|
234
|
-
"""Check whether the time is of the correct unit.
|
|
235
|
-
|
|
236
|
-
Args:
|
|
237
|
-
time (int | float): the time
|
|
238
|
-
|
|
239
|
-
Returns:
|
|
240
|
-
bool: whether the time is of the correct unit
|
|
241
|
-
|
|
242
|
-
"""
|
|
243
214
|
if isinstance(time, int):
|
|
244
215
|
return True
|
|
245
216
|
if isinstance(time, float):
|
|
@@ -254,9 +225,9 @@ class ABMSimulator(Simulator):
|
|
|
254
225
|
function_args: list[Any] | None = None,
|
|
255
226
|
function_kwargs: dict[str, Any] | None = None,
|
|
256
227
|
) -> SimulationEvent:
|
|
257
|
-
"""Schedule a SimulationEvent for the next tick
|
|
228
|
+
"""Schedule a SimulationEvent for the next tick
|
|
258
229
|
|
|
259
|
-
Args
|
|
230
|
+
Args
|
|
260
231
|
function (Callable): the callable to execute
|
|
261
232
|
priority (Priority): the priority of the event
|
|
262
233
|
function_args (List[Any]): List of arguments to pass to the callable
|
|
@@ -272,7 +243,7 @@ class ABMSimulator(Simulator):
|
|
|
272
243
|
)
|
|
273
244
|
|
|
274
245
|
def run_until(self, end_time: int) -> None:
|
|
275
|
-
"""
|
|
246
|
+
"""run the simulator up to and included the specified end time
|
|
276
247
|
|
|
277
248
|
Args:
|
|
278
249
|
end_time (float| int): The end_time delta. The simulator is until the specified end time
|
|
@@ -299,7 +270,7 @@ class ABMSimulator(Simulator):
|
|
|
299
270
|
break
|
|
300
271
|
|
|
301
272
|
def run_for(self, time_delta: int):
|
|
302
|
-
"""
|
|
273
|
+
"""run the simulator for the specified time delta
|
|
303
274
|
|
|
304
275
|
Args:
|
|
305
276
|
time_delta (float| int): The time delta. The simulator is run from the current time to the current time
|
|
@@ -311,24 +282,13 @@ class ABMSimulator(Simulator):
|
|
|
311
282
|
|
|
312
283
|
|
|
313
284
|
class DEVSimulator(Simulator):
|
|
314
|
-
"""A simulator where the unit of time is a float.
|
|
315
|
-
|
|
316
|
-
Can be used for full-blown discrete event simulating using event scheduling.
|
|
285
|
+
"""A simulator where the unit of time is a float. Can be used for full-blown discrete event simulating using
|
|
286
|
+
event scheduling.
|
|
317
287
|
|
|
318
288
|
"""
|
|
319
289
|
|
|
320
290
|
def __init__(self):
|
|
321
|
-
"""Initialize a DEVS simulator."""
|
|
322
291
|
super().__init__(float, 0.0)
|
|
323
292
|
|
|
324
293
|
def check_time_unit(self, time) -> bool:
|
|
325
|
-
"""Check whether the time is of the correct unit.
|
|
326
|
-
|
|
327
|
-
Args:
|
|
328
|
-
time (float): the time
|
|
329
|
-
|
|
330
|
-
Returns:
|
|
331
|
-
bool: whether the time is of the correct unit
|
|
332
|
-
|
|
333
|
-
"""
|
|
334
294
|
return isinstance(time, numbers.Number)
|
mesa/main.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from subprocess import call
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
from mesa import __version__
|
|
9
|
+
|
|
10
|
+
PROJECT_PATH = click.Path(
|
|
11
|
+
exists=True, file_okay=False, dir_okay=True, resolve_path=True
|
|
12
|
+
)
|
|
13
|
+
COOKIECUTTER_DIR = "mesa/cookiecutter-mesa"
|
|
14
|
+
SCRIPTS_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
15
|
+
COOKIECUTTER_PATH = os.path.join(os.path.dirname(SCRIPTS_DIR), COOKIECUTTER_DIR)
|
|
16
|
+
|
|
17
|
+
CONTEXT_SETTINGS = {"help_option_names": ["-h", "--help"]}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@click.group(context_settings=CONTEXT_SETTINGS)
|
|
21
|
+
def cli():
|
|
22
|
+
"Manage Mesa projects"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@cli.command()
|
|
26
|
+
@click.argument("project", type=PROJECT_PATH, default=".")
|
|
27
|
+
def runserver(project):
|
|
28
|
+
"""Run mesa project PROJECT
|
|
29
|
+
|
|
30
|
+
PROJECT is the path to the directory containing `run.py`, or the current
|
|
31
|
+
directory if not specified.
|
|
32
|
+
"""
|
|
33
|
+
run_files = ["run.py", "server.py"]
|
|
34
|
+
for run_file in run_files:
|
|
35
|
+
run_path = Path(project) / run_file
|
|
36
|
+
if not run_path.exists():
|
|
37
|
+
continue
|
|
38
|
+
args = [sys.executable, str(run_path)]
|
|
39
|
+
call(args)
|
|
40
|
+
sys.exit(f"ERROR: file run.py or server.py (in {Path(project)}) does not exist")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@click.command()
|
|
44
|
+
@click.option(
|
|
45
|
+
"--no-input", is_flag=True, help="Do not prompt user for custom mesa model input."
|
|
46
|
+
)
|
|
47
|
+
def startproject(no_input):
|
|
48
|
+
"""Create a new mesa project"""
|
|
49
|
+
args = ["cookiecutter", COOKIECUTTER_PATH]
|
|
50
|
+
if no_input:
|
|
51
|
+
args.append("--no-input")
|
|
52
|
+
call(args)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@click.command()
|
|
56
|
+
def version():
|
|
57
|
+
"""Show the version of mesa"""
|
|
58
|
+
print(f"mesa {__version__}")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
cli.add_command(runserver)
|
|
62
|
+
cli.add_command(startproject)
|
|
63
|
+
cli.add_command(version)
|