Mesa 3.1.5__py3-none-any.whl → 3.2.0__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 +3 -1
- mesa/agent.py +26 -9
- mesa/discrete_space/__init__.py +50 -0
- mesa/{experimental/cell_space → discrete_space}/cell.py +29 -10
- mesa/{experimental/cell_space → discrete_space}/cell_agent.py +1 -1
- mesa/{experimental/cell_space → discrete_space}/cell_collection.py +3 -3
- mesa/{experimental/cell_space → discrete_space}/discrete_space.py +65 -3
- mesa/{experimental/cell_space → discrete_space}/grid.py +2 -2
- mesa/{experimental/cell_space → discrete_space}/network.py +22 -2
- mesa/{experimental/cell_space → discrete_space}/property_layer.py +1 -10
- mesa/{experimental/cell_space → discrete_space}/voronoi.py +2 -2
- mesa/examples/README.md +1 -1
- mesa/examples/__init__.py +2 -0
- mesa/examples/advanced/alliance_formation/Readme.md +50 -0
- mesa/examples/advanced/alliance_formation/__init__ .py +0 -0
- mesa/examples/advanced/alliance_formation/agents.py +20 -0
- mesa/examples/advanced/alliance_formation/app.py +71 -0
- mesa/examples/advanced/alliance_formation/model.py +184 -0
- mesa/examples/advanced/epstein_civil_violence/agents.py +1 -1
- mesa/examples/advanced/epstein_civil_violence/model.py +1 -1
- mesa/examples/advanced/pd_grid/Readme.md +4 -6
- mesa/examples/advanced/pd_grid/agents.py +1 -1
- mesa/examples/advanced/pd_grid/model.py +1 -1
- mesa/examples/advanced/sugarscape_g1mt/Readme.md +4 -5
- mesa/examples/advanced/sugarscape_g1mt/agents.py +1 -1
- mesa/examples/advanced/sugarscape_g1mt/model.py +2 -2
- mesa/examples/advanced/wolf_sheep/Readme.md +2 -17
- mesa/examples/advanced/wolf_sheep/agents.py +1 -1
- mesa/examples/advanced/wolf_sheep/app.py +2 -1
- mesa/examples/advanced/wolf_sheep/model.py +1 -1
- mesa/examples/basic/boid_flockers/Readme.md +6 -1
- mesa/examples/basic/boid_flockers/agents.py +1 -0
- mesa/examples/basic/boid_flockers/app.py +17 -2
- mesa/examples/basic/boid_flockers/model.py +12 -0
- mesa/examples/basic/boltzmann_wealth_model/Readme.md +2 -12
- mesa/examples/basic/boltzmann_wealth_model/agents.py +6 -11
- mesa/examples/basic/boltzmann_wealth_model/app.py +2 -2
- mesa/examples/basic/boltzmann_wealth_model/model.py +7 -11
- mesa/examples/basic/conways_game_of_life/Readme.md +1 -9
- mesa/examples/basic/conways_game_of_life/agents.py +13 -5
- mesa/examples/basic/conways_game_of_life/model.py +10 -7
- mesa/examples/basic/schelling/Readme.md +0 -8
- mesa/examples/basic/schelling/agents.py +13 -8
- mesa/examples/basic/schelling/model.py +6 -9
- mesa/examples/basic/virus_on_network/Readme.md +0 -4
- mesa/examples/basic/virus_on_network/agents.py +13 -17
- mesa/examples/basic/virus_on_network/model.py +20 -24
- mesa/experimental/__init__.py +2 -2
- mesa/experimental/cell_space/__init__.py +18 -8
- mesa/experimental/meta_agents/__init__.py +25 -0
- mesa/experimental/meta_agents/meta_agent.py +387 -0
- mesa/model.py +3 -3
- mesa/space.py +1 -12
- mesa/visualization/__init__.py +2 -0
- mesa/visualization/command_console.py +482 -0
- mesa/visualization/components/altair_components.py +276 -16
- mesa/visualization/mpl_space_drawing.py +17 -9
- mesa/visualization/solara_viz.py +150 -21
- {mesa-3.1.5.dist-info → mesa-3.2.0.dist-info}/METADATA +12 -8
- mesa-3.2.0.dist-info/RECORD +105 -0
- mesa-3.1.5.dist-info/RECORD +0 -96
- {mesa-3.1.5.dist-info → mesa-3.2.0.dist-info}/WHEEL +0 -0
- {mesa-3.1.5.dist-info → mesa-3.2.0.dist-info}/licenses/LICENSE +0 -0
- {mesa-3.1.5.dist-info → mesa-3.2.0.dist-info}/licenses/NOTICE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from mesa import Model
|
|
2
|
+
from mesa.discrete_space import OrthogonalMooreGrid
|
|
2
3
|
from mesa.examples.basic.conways_game_of_life.agents import Cell
|
|
3
|
-
from mesa.space import SingleGrid
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class ConwaysGameOfLife(Model):
|
|
@@ -10,15 +10,18 @@ class ConwaysGameOfLife(Model):
|
|
|
10
10
|
"""Create a new playing area of (width, height) cells."""
|
|
11
11
|
super().__init__(seed=seed)
|
|
12
12
|
# Use a simple grid, where edges wrap around.
|
|
13
|
-
self.grid =
|
|
13
|
+
self.grid = OrthogonalMooreGrid((width, height), capacity=1, torus=True)
|
|
14
14
|
|
|
15
15
|
# Place a cell at each location, with some initialized to
|
|
16
16
|
# ALIVE and some to DEAD.
|
|
17
|
-
for
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
cell
|
|
21
|
-
|
|
17
|
+
for cell in self.grid.all_cells:
|
|
18
|
+
Cell(
|
|
19
|
+
self,
|
|
20
|
+
cell,
|
|
21
|
+
init_state=Cell.ALIVE
|
|
22
|
+
if self.random.random() < initial_fraction_alive
|
|
23
|
+
else Cell.DEAD,
|
|
24
|
+
)
|
|
22
25
|
|
|
23
26
|
self.running = True
|
|
24
27
|
|
|
@@ -14,14 +14,6 @@ To run the model interactively, in this directory, run the following command
|
|
|
14
14
|
$ solara run app.py
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Then open your browser to [http://127.0.0.1:8765/](http://127.0.0.1:8765/) and click the Play button.
|
|
18
|
-
|
|
19
|
-
To view and run some example model analyses, launch the IPython Notebook and open ``analysis.ipynb``. Visualizing the analysis also requires [matplotlib](http://matplotlib.org/).
|
|
20
|
-
|
|
21
|
-
## How to Run without the GUI
|
|
22
|
-
|
|
23
|
-
To run the model with the grid displayed as an ASCII text, run `python run_ascii.py` in this directory.
|
|
24
|
-
|
|
25
17
|
## Files
|
|
26
18
|
|
|
27
19
|
* ``model.py``: Contains the Schelling model class
|
|
@@ -1,23 +1,28 @@
|
|
|
1
|
-
from mesa import
|
|
1
|
+
from mesa.discrete_space import CellAgent
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class SchellingAgent(
|
|
4
|
+
class SchellingAgent(CellAgent):
|
|
5
5
|
"""Schelling segregation agent."""
|
|
6
6
|
|
|
7
|
-
def __init__(
|
|
7
|
+
def __init__(
|
|
8
|
+
self, model, cell, agent_type: int, homophily: float = 0.4, radius: int = 1
|
|
9
|
+
) -> None:
|
|
8
10
|
"""Create a new Schelling agent.
|
|
9
11
|
Args:
|
|
10
12
|
model: The model instance the agent belongs to
|
|
11
13
|
agent_type: Indicator for the agent's type (minority=1, majority=0)
|
|
14
|
+
homophily: Minimum number of similar neighbors needed for happiness
|
|
15
|
+
radius: Search radius for checking neighbor similarity
|
|
12
16
|
"""
|
|
13
17
|
super().__init__(model)
|
|
18
|
+
self.cell = cell
|
|
14
19
|
self.type = agent_type
|
|
20
|
+
self.homophily = homophily
|
|
21
|
+
self.radius = radius
|
|
15
22
|
|
|
16
23
|
def step(self) -> None:
|
|
17
24
|
"""Determine if agent is happy and move if necessary."""
|
|
18
|
-
neighbors = self.
|
|
19
|
-
self.pos, moore=True, radius=self.model.radius
|
|
20
|
-
)
|
|
25
|
+
neighbors = list(self.cell.get_neighborhood(radius=self.radius).agents)
|
|
21
26
|
|
|
22
27
|
# Count similar neighbors
|
|
23
28
|
similar_neighbors = len([n for n in neighbors if n.type == self.type])
|
|
@@ -30,7 +35,7 @@ class SchellingAgent(Agent):
|
|
|
30
35
|
similarity_fraction = 0.0
|
|
31
36
|
|
|
32
37
|
# Move if unhappy
|
|
33
|
-
if similarity_fraction < self.
|
|
34
|
-
self.model.grid.
|
|
38
|
+
if similarity_fraction < self.homophily:
|
|
39
|
+
self.cell = self.model.grid.select_random_empty_cell()
|
|
35
40
|
else:
|
|
36
41
|
self.model.happy += 1
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from mesa import Model
|
|
2
2
|
from mesa.datacollection import DataCollector
|
|
3
|
+
from mesa.discrete_space import OrthogonalMooreGrid
|
|
3
4
|
from mesa.examples.basic.schelling.agents import SchellingAgent
|
|
4
|
-
from mesa.space import SingleGrid
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class Schelling(Model):
|
|
@@ -31,15 +31,11 @@ class Schelling(Model):
|
|
|
31
31
|
super().__init__(seed=seed)
|
|
32
32
|
|
|
33
33
|
# Model parameters
|
|
34
|
-
self.height = height
|
|
35
|
-
self.width = width
|
|
36
34
|
self.density = density
|
|
37
35
|
self.minority_pc = minority_pc
|
|
38
|
-
self.homophily = homophily
|
|
39
|
-
self.radius = radius
|
|
40
36
|
|
|
41
37
|
# Initialize grid
|
|
42
|
-
self.grid =
|
|
38
|
+
self.grid = OrthogonalMooreGrid((width, height), random=self.random, capacity=1)
|
|
43
39
|
|
|
44
40
|
# Track happiness
|
|
45
41
|
self.happy = 0
|
|
@@ -64,11 +60,12 @@ class Schelling(Model):
|
|
|
64
60
|
)
|
|
65
61
|
|
|
66
62
|
# Create agents and place them on the grid
|
|
67
|
-
for
|
|
63
|
+
for cell in self.grid.all_cells:
|
|
68
64
|
if self.random.random() < self.density:
|
|
69
65
|
agent_type = 1 if self.random.random() < minority_pc else 0
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
SchellingAgent(
|
|
67
|
+
self, cell, agent_type, homophily=homophily, radius=radius
|
|
68
|
+
)
|
|
72
69
|
|
|
73
70
|
# Collect initial state
|
|
74
71
|
self.datacollector.collect(self)
|
|
@@ -38,10 +38,6 @@ To run the model interactively, in this directory, run the following command
|
|
|
38
38
|
|
|
39
39
|
## Further Reading
|
|
40
40
|
|
|
41
|
-
The full tutorial describing how the model is built can be found at:
|
|
42
|
-
https://mesa.readthedocs.io/en/latest/tutorials/intro_tutorial.html
|
|
43
|
-
|
|
44
|
-
|
|
45
41
|
[Stonedahl, F. and Wilensky, U. (2008). NetLogo Virus on a Network model](http://ccl.northwestern.edu/netlogo/models/VirusonaNetwork).
|
|
46
42
|
Center for Connected Learning and Computer-Based Modeling, Northwestern University, Evanston, IL.
|
|
47
43
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
2
|
|
|
3
|
-
from mesa import
|
|
3
|
+
from mesa.discrete_space import FixedAgent
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class State(Enum):
|
|
@@ -9,7 +9,7 @@ class State(Enum):
|
|
|
9
9
|
RESISTANT = 2
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class VirusAgent(
|
|
12
|
+
class VirusAgent(FixedAgent):
|
|
13
13
|
"""Individual Agent definition and its properties/interaction methods."""
|
|
14
14
|
|
|
15
15
|
def __init__(
|
|
@@ -20,6 +20,7 @@ class VirusAgent(Agent):
|
|
|
20
20
|
virus_check_frequency,
|
|
21
21
|
recovery_chance,
|
|
22
22
|
gain_resistance_chance,
|
|
23
|
+
cell,
|
|
23
24
|
):
|
|
24
25
|
super().__init__(model)
|
|
25
26
|
|
|
@@ -29,19 +30,14 @@ class VirusAgent(Agent):
|
|
|
29
30
|
self.virus_check_frequency = virus_check_frequency
|
|
30
31
|
self.recovery_chance = recovery_chance
|
|
31
32
|
self.gain_resistance_chance = gain_resistance_chance
|
|
33
|
+
self.cell = cell
|
|
32
34
|
|
|
33
35
|
def try_to_infect_neighbors(self):
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
for agent in self.model.grid.get_cell_list_contents(neighbors_nodes)
|
|
40
|
-
if agent.state is State.SUSCEPTIBLE
|
|
41
|
-
]
|
|
42
|
-
for a in susceptible_neighbors:
|
|
43
|
-
if self.random.random() < self.virus_spread_chance:
|
|
44
|
-
a.state = State.INFECTED
|
|
36
|
+
for agent in self.cell.neighborhood.agents:
|
|
37
|
+
if (agent.state is State.SUSCEPTIBLE) and (
|
|
38
|
+
self.random.random() < self.virus_spread_chance
|
|
39
|
+
):
|
|
40
|
+
agent.state = State.INFECTED
|
|
45
41
|
|
|
46
42
|
def try_gain_resistance(self):
|
|
47
43
|
if self.random.random() < self.gain_resistance_chance:
|
|
@@ -57,13 +53,13 @@ class VirusAgent(Agent):
|
|
|
57
53
|
# Failed
|
|
58
54
|
self.state = State.INFECTED
|
|
59
55
|
|
|
60
|
-
def
|
|
61
|
-
if (self.
|
|
62
|
-
self.
|
|
56
|
+
def check_situation(self):
|
|
57
|
+
if (self.state is State.INFECTED) and (
|
|
58
|
+
self.random.random() < self.virus_check_frequency
|
|
63
59
|
):
|
|
64
60
|
self.try_remove_infection()
|
|
65
61
|
|
|
66
62
|
def step(self):
|
|
67
63
|
if self.state is State.INFECTED:
|
|
68
64
|
self.try_to_infect_neighbors()
|
|
69
|
-
self.
|
|
65
|
+
self.check_situation()
|
|
@@ -4,11 +4,12 @@ import networkx as nx
|
|
|
4
4
|
|
|
5
5
|
import mesa
|
|
6
6
|
from mesa import Model
|
|
7
|
+
from mesa.discrete_space import CellCollection, Network
|
|
7
8
|
from mesa.examples.basic.virus_on_network.agents import State, VirusAgent
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def number_state(model, state):
|
|
11
|
-
return sum(1 for a in model.grid.
|
|
12
|
+
return sum(1 for a in model.grid.all_cells.agents if a.state is state)
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
def number_infected(model):
|
|
@@ -38,18 +39,13 @@ class VirusOnNetwork(Model):
|
|
|
38
39
|
seed=None,
|
|
39
40
|
):
|
|
40
41
|
super().__init__(seed=seed)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
self.
|
|
44
|
-
self.grid = mesa.space.NetworkGrid(self.G)
|
|
42
|
+
prob = avg_node_degree / num_nodes
|
|
43
|
+
graph = nx.erdos_renyi_graph(n=num_nodes, p=prob)
|
|
44
|
+
self.grid = Network(graph, capacity=1, random=self.random)
|
|
45
45
|
|
|
46
46
|
self.initial_outbreak_size = (
|
|
47
47
|
initial_outbreak_size if initial_outbreak_size <= num_nodes else num_nodes
|
|
48
48
|
)
|
|
49
|
-
self.virus_spread_chance = virus_spread_chance
|
|
50
|
-
self.virus_check_frequency = virus_check_frequency
|
|
51
|
-
self.recovery_chance = recovery_chance
|
|
52
|
-
self.gain_resistance_chance = gain_resistance_chance
|
|
53
49
|
|
|
54
50
|
self.datacollector = mesa.DataCollector(
|
|
55
51
|
{
|
|
@@ -60,23 +56,23 @@ class VirusOnNetwork(Model):
|
|
|
60
56
|
}
|
|
61
57
|
)
|
|
62
58
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
# Add the agent to the node
|
|
75
|
-
self.grid.place_agent(a, node)
|
|
59
|
+
VirusAgent.create_agents(
|
|
60
|
+
self,
|
|
61
|
+
num_nodes,
|
|
62
|
+
State.SUSCEPTIBLE,
|
|
63
|
+
virus_spread_chance,
|
|
64
|
+
virus_check_frequency,
|
|
65
|
+
recovery_chance,
|
|
66
|
+
gain_resistance_chance,
|
|
67
|
+
list(self.grid.all_cells),
|
|
68
|
+
)
|
|
76
69
|
|
|
77
70
|
# Infect some nodes
|
|
78
|
-
infected_nodes =
|
|
79
|
-
|
|
71
|
+
infected_nodes = CellCollection(
|
|
72
|
+
self.random.sample(list(self.grid.all_cells), self.initial_outbreak_size),
|
|
73
|
+
random=self.random,
|
|
74
|
+
)
|
|
75
|
+
for a in infected_nodes.agents:
|
|
80
76
|
a.state = State.INFECTED
|
|
81
77
|
|
|
82
78
|
self.running = True
|
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
|
|
18
|
+
from mesa.experimental import continuous_space, devs, mesa_signals, meta_agents
|
|
19
19
|
|
|
20
|
-
__all__ = ["
|
|
20
|
+
__all__ = ["continuous_space", "devs", "mesa_signals", "meta_agents"]
|
|
@@ -15,23 +15,25 @@ like resource growth, pollution diffusion, or infrastructure networks. The cell
|
|
|
15
15
|
space system is experimental and under active development.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
import warnings
|
|
19
|
+
|
|
20
|
+
from mesa.discrete_space.cell import Cell
|
|
21
|
+
from mesa.discrete_space.cell_agent import (
|
|
20
22
|
CellAgent,
|
|
21
23
|
FixedAgent,
|
|
22
24
|
Grid2DMovingAgent,
|
|
23
25
|
)
|
|
24
|
-
from mesa.
|
|
25
|
-
from mesa.
|
|
26
|
-
from mesa.
|
|
26
|
+
from mesa.discrete_space.cell_collection import CellCollection
|
|
27
|
+
from mesa.discrete_space.discrete_space import DiscreteSpace
|
|
28
|
+
from mesa.discrete_space.grid import (
|
|
27
29
|
Grid,
|
|
28
30
|
HexGrid,
|
|
29
31
|
OrthogonalMooreGrid,
|
|
30
32
|
OrthogonalVonNeumannGrid,
|
|
31
33
|
)
|
|
32
|
-
from mesa.
|
|
33
|
-
from mesa.
|
|
34
|
-
from mesa.
|
|
34
|
+
from mesa.discrete_space.network import Network
|
|
35
|
+
from mesa.discrete_space.property_layer import PropertyLayer
|
|
36
|
+
from mesa.discrete_space.voronoi import VoronoiGrid
|
|
35
37
|
|
|
36
38
|
__all__ = [
|
|
37
39
|
"Cell",
|
|
@@ -48,3 +50,11 @@ __all__ = [
|
|
|
48
50
|
"PropertyLayer",
|
|
49
51
|
"VoronoiGrid",
|
|
50
52
|
]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
warnings.warn(
|
|
56
|
+
"you are importing from mesa.experimental.cell_space, "
|
|
57
|
+
"all cell spaces have been moved to mesa.discrete_space",
|
|
58
|
+
DeprecationWarning,
|
|
59
|
+
stacklevel=2,
|
|
60
|
+
)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""This method is for dynamically creating new agents (meta-agents).
|
|
2
|
+
|
|
3
|
+
Meta-agents are defined as agents composed of existing agents.
|
|
4
|
+
|
|
5
|
+
Meta-agents are created dynamically with a pointer to the model, name of the meta-agent,,
|
|
6
|
+
iterable of agents to belong to the new meta-agents, any new functions for the meta-agent,
|
|
7
|
+
any new attributes for the meta-agent, whether to retain sub-agent functions,
|
|
8
|
+
whether to retain sub-agent attributes.
|
|
9
|
+
|
|
10
|
+
Examples of meta-agents:
|
|
11
|
+
- An autonomous car where the subagents are the wheels, sensors,
|
|
12
|
+
battery, computer etc. and the meta-agent is the car itself.
|
|
13
|
+
- A company where the subagents are employees, departments, buildings, etc.
|
|
14
|
+
- A city where the subagents are people, buildings, streets, etc.
|
|
15
|
+
|
|
16
|
+
Currently meta-agents are restricted to one parent agent for each subagent/
|
|
17
|
+
one meta-agent per subagent.
|
|
18
|
+
|
|
19
|
+
Goal is to assess usage and expand functionality.
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from .meta_agent import MetaAgent
|
|
24
|
+
|
|
25
|
+
__all__ = ["MetaAgent"]
|