Mesa 3.0.0a5__py3-none-any.whl → 3.0.0b1__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.

Files changed (91) hide show
  1. examples/README.md +37 -0
  2. examples/__init__.py +0 -0
  3. examples/advanced/__init__.py +0 -0
  4. examples/advanced/epstein_civil_violence/Epstein Civil Violence.ipynb +116 -0
  5. examples/advanced/epstein_civil_violence/Readme.md +33 -0
  6. examples/advanced/epstein_civil_violence/epstein_civil_violence/__init__.py +0 -0
  7. examples/advanced/epstein_civil_violence/epstein_civil_violence/agent.py +158 -0
  8. examples/advanced/epstein_civil_violence/epstein_civil_violence/model.py +146 -0
  9. examples/advanced/epstein_civil_violence/epstein_civil_violence/portrayal.py +33 -0
  10. examples/advanced/epstein_civil_violence/epstein_civil_violence/server.py +81 -0
  11. examples/advanced/epstein_civil_violence/requirements.txt +3 -0
  12. examples/advanced/epstein_civil_violence/run.py +3 -0
  13. examples/advanced/pd_grid/analysis.ipynb +228 -0
  14. examples/advanced/pd_grid/pd_grid/__init__.py +0 -0
  15. examples/advanced/pd_grid/pd_grid/agent.py +50 -0
  16. examples/advanced/pd_grid/pd_grid/model.py +72 -0
  17. examples/advanced/pd_grid/pd_grid/portrayal.py +19 -0
  18. examples/advanced/pd_grid/pd_grid/server.py +21 -0
  19. examples/advanced/pd_grid/readme.md +42 -0
  20. examples/advanced/pd_grid/requirements.txt +3 -0
  21. examples/advanced/pd_grid/run.py +3 -0
  22. examples/advanced/sugarscape_g1mt/Readme.md +87 -0
  23. examples/advanced/sugarscape_g1mt/app.py +61 -0
  24. examples/advanced/sugarscape_g1mt/requirements.txt +6 -0
  25. examples/advanced/sugarscape_g1mt/run.py +105 -0
  26. examples/advanced/sugarscape_g1mt/sugarscape_g1mt/__init__.py +0 -0
  27. examples/advanced/sugarscape_g1mt/sugarscape_g1mt/model.py +180 -0
  28. examples/advanced/sugarscape_g1mt/sugarscape_g1mt/resource_agents.py +26 -0
  29. examples/advanced/sugarscape_g1mt/sugarscape_g1mt/server.py +61 -0
  30. examples/advanced/sugarscape_g1mt/sugarscape_g1mt/sugar-map.txt +50 -0
  31. examples/advanced/sugarscape_g1mt/sugarscape_g1mt/trader_agents.py +321 -0
  32. examples/advanced/sugarscape_g1mt/tests.py +72 -0
  33. examples/advanced/wolf_sheep/Readme.md +57 -0
  34. examples/advanced/wolf_sheep/__init__.py +0 -0
  35. examples/advanced/wolf_sheep/requirements.txt +1 -0
  36. examples/advanced/wolf_sheep/run.py +3 -0
  37. examples/advanced/wolf_sheep/wolf_sheep/__init__.py +0 -0
  38. examples/advanced/wolf_sheep/wolf_sheep/agents.py +102 -0
  39. examples/advanced/wolf_sheep/wolf_sheep/model.py +136 -0
  40. examples/advanced/wolf_sheep/wolf_sheep/resources/sheep.png +0 -0
  41. examples/advanced/wolf_sheep/wolf_sheep/resources/wolf.png +0 -0
  42. examples/advanced/wolf_sheep/wolf_sheep/server.py +78 -0
  43. examples/basic/__init__.py +13 -0
  44. examples/basic/boid_flockers/Readme.md +43 -0
  45. examples/basic/boid_flockers/agents.py +71 -0
  46. examples/basic/boid_flockers/app.py +59 -0
  47. examples/basic/boid_flockers/model.py +70 -0
  48. examples/basic/boltzmann_wealth_model/Readme.md +60 -0
  49. examples/basic/boltzmann_wealth_model/agents.py +31 -0
  50. examples/basic/boltzmann_wealth_model/app.py +66 -0
  51. examples/basic/boltzmann_wealth_model/model.py +44 -0
  52. examples/basic/boltzmann_wealth_model/st_app.py +115 -0
  53. examples/basic/conways_game_of_life/Readme.md +35 -0
  54. examples/basic/conways_game_of_life/agents.py +47 -0
  55. examples/basic/conways_game_of_life/model.py +32 -0
  56. examples/basic/conways_game_of_life/portrayal.py +18 -0
  57. examples/basic/conways_game_of_life/requirements.txt +1 -0
  58. examples/basic/conways_game_of_life/server.py +11 -0
  59. examples/basic/conways_game_of_life/st_app.py +71 -0
  60. examples/basic/schelling/README.md +47 -0
  61. examples/basic/schelling/agents.py +26 -0
  62. examples/basic/schelling/analysis.ipynb +205 -0
  63. examples/basic/schelling/app.py +43 -0
  64. examples/basic/schelling/model.py +60 -0
  65. examples/basic/virus_on_network/README.md +61 -0
  66. examples/basic/virus_on_network/agents.py +69 -0
  67. examples/basic/virus_on_network/app.py +133 -0
  68. examples/basic/virus_on_network/model.py +99 -0
  69. mesa/__init__.py +4 -1
  70. mesa/agent.py +24 -43
  71. mesa/batchrunner.py +7 -0
  72. mesa/examples.py +3 -0
  73. mesa/experimental/__init__.py +8 -2
  74. mesa/experimental/cell_space/__init__.py +7 -1
  75. mesa/experimental/cell_space/cell.py +35 -6
  76. mesa/experimental/cell_space/cell_agent.py +114 -23
  77. mesa/experimental/cell_space/discrete_space.py +70 -3
  78. mesa/experimental/cell_space/grid.py +13 -0
  79. mesa/experimental/cell_space/network.py +3 -0
  80. mesa/experimental/devs/examples/wolf_sheep.py +2 -1
  81. mesa/model.py +71 -21
  82. mesa/time.py +7 -5
  83. mesa/visualization/components/matplotlib.py +184 -90
  84. mesa/visualization/solara_viz.py +25 -61
  85. {mesa-3.0.0a5.dist-info → mesa-3.0.0b1.dist-info}/METADATA +55 -13
  86. mesa-3.0.0b1.dist-info/RECORD +114 -0
  87. mesa-3.0.0b1.dist-info/licenses/LICENSE +202 -0
  88. mesa-3.0.0a5.dist-info/licenses/LICENSE → mesa-3.0.0b1.dist-info/licenses/NOTICE +2 -2
  89. mesa-3.0.0a5.dist-info/RECORD +0 -44
  90. {mesa-3.0.0a5.dist-info → mesa-3.0.0b1.dist-info}/WHEEL +0 -0
  91. {mesa-3.0.0a5.dist-info → mesa-3.0.0b1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,35 @@
1
+ # Conway's Game Of "Life"
2
+
3
+ ## Summary
4
+
5
+ [The Game of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life), also known simply as "Life", is a cellular automaton devised by the British mathematician John Horton Conway in 1970.
6
+
7
+ The "game" is a zero-player game, meaning that its evolution is determined by its initial state, requiring no further input by a human. One interacts with the Game of "Life" by creating an initial configuration and observing how it evolves, or, for advanced "players", by creating patterns with particular properties.
8
+
9
+
10
+ ## How to Run
11
+
12
+ To run the model interactively, run ``mesa runserver`` in this directory. e.g.
13
+
14
+ ```
15
+ $ mesa runserver
16
+ ```
17
+
18
+ Then open your browser to [http://127.0.0.1:8521/](http://127.0.0.1:8521/) and press ``run``.
19
+
20
+ ## Files
21
+
22
+ * ``agents.py``: Defines the behavior of an individual cell, which can be in two states: DEAD or ALIVE.
23
+ * ``model.py``: Defines the model itself, initialized with a random configuration of alive and dead cells.
24
+ * ``portrayal.py``: Describes for the front end how to render a cell.
25
+ * ``st_app.py``: Defines an interactive visualization using Streamlit.
26
+
27
+ ## Optional
28
+
29
+ * ``conways_game_of_life/st_app.py``: can be used to run the simulation via the streamlit interface.
30
+ * For this some additional packages like ``streamlit`` and ``altair`` needs to be installed.
31
+ * Once installed, the app can be opened in the browser using : ``streamlit run st_app.py``
32
+
33
+
34
+ ## Further Reading
35
+ [Conway's Game of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life)
@@ -0,0 +1,47 @@
1
+ from mesa import Agent
2
+
3
+
4
+ class Cell(Agent):
5
+ """Represents a single ALIVE or DEAD cell in the simulation."""
6
+
7
+ DEAD = 0
8
+ ALIVE = 1
9
+
10
+ def __init__(self, pos, model, init_state=DEAD):
11
+ """Create a cell, in the given state, at the given x, y position."""
12
+ super().__init__(model)
13
+ self.x, self.y = pos
14
+ self.state = init_state
15
+ self._nextState = None
16
+
17
+ @property
18
+ def isAlive(self):
19
+ return self.state == self.ALIVE
20
+
21
+ @property
22
+ def neighbors(self):
23
+ return self.model.grid.iter_neighbors((self.x, self.y), True)
24
+
25
+ def determine_state(self):
26
+ """Compute if the cell will be dead or alive at the next tick. This is
27
+ based on the number of alive or dead neighbors. The state is not
28
+ changed here, but is just computed and stored in self._nextState,
29
+ because our current state may still be necessary for our neighbors
30
+ to calculate their next state.
31
+ """
32
+ # Get the neighbors and apply the rules on whether to be alive or dead
33
+ # at the next tick.
34
+ live_neighbors = sum(neighbor.isAlive for neighbor in self.neighbors)
35
+
36
+ # Assume nextState is unchanged, unless changed below.
37
+ self._nextState = self.state
38
+ if self.isAlive:
39
+ if live_neighbors < 2 or live_neighbors > 3:
40
+ self._nextState = self.DEAD
41
+ else:
42
+ if live_neighbors == 3:
43
+ self._nextState = self.ALIVE
44
+
45
+ def assume_state(self):
46
+ """Set the state to the new computed state -- computed in step()."""
47
+ self.state = self._nextState
@@ -0,0 +1,32 @@
1
+ from mesa import Model
2
+ from mesa.space import SingleGrid
3
+
4
+ from .agents import Cell
5
+
6
+
7
+ class ConwaysGameOfLife(Model):
8
+ """Represents the 2-dimensional array of cells in Conway's Game of Life."""
9
+
10
+ def __init__(self, width=50, height=50):
11
+ """Create a new playing area of (width, height) cells."""
12
+ super().__init__()
13
+ # Use a simple grid, where edges wrap around.
14
+ self.grid = SingleGrid(width, height, torus=True)
15
+
16
+ # Place a cell at each location, with some initialized to
17
+ # ALIVE and some to DEAD.
18
+ for _contents, (x, y) in self.grid.coord_iter():
19
+ cell = Cell((x, y), self)
20
+ if self.random.random() < 0.1:
21
+ cell.state = cell.ALIVE
22
+ self.grid.place_agent(cell, (x, y))
23
+
24
+ self.running = True
25
+
26
+ def step(self):
27
+ """Perform the model step in two stages:
28
+ - First, all cells assume their next state (whether they will be dead or alive)
29
+ - Then, all cells change state to their next state.
30
+ """
31
+ self.agents.do("determine_state")
32
+ self.agents.do("assume_state")
@@ -0,0 +1,18 @@
1
+ def portrayCell(cell):
2
+ """This function is registered with the visualization server to be called
3
+ each tick to indicate how to draw the cell in its current state.
4
+ :param cell: the cell in the simulation
5
+ :return: the portrayal dictionary.
6
+ """
7
+ if cell is None:
8
+ raise AssertionError
9
+ return {
10
+ "Shape": "rect",
11
+ "w": 1,
12
+ "h": 1,
13
+ "Filled": "true",
14
+ "Layer": 0,
15
+ "x": cell.x,
16
+ "y": cell.y,
17
+ "Color": "black" if cell.isAlive else "white",
18
+ }
@@ -0,0 +1 @@
1
+ mesa~=2.0
@@ -0,0 +1,11 @@
1
+ import mesa
2
+
3
+ from .model import ConwaysGameOfLife
4
+ from .portrayal import portrayCell
5
+
6
+ # Make a world that is 50x50, on a 250x250 display.
7
+ canvas_element = mesa.visualization.CanvasGrid(portrayCell, 50, 50, 250, 250)
8
+
9
+ server = mesa.visualization.ModularServer(
10
+ ConwaysGameOfLife, [canvas_element], "Game of Life", {"height": 50, "width": 50}
11
+ )
@@ -0,0 +1,71 @@
1
+ import time
2
+
3
+ import altair as alt
4
+ import numpy as np
5
+ import pandas as pd
6
+ import streamlit as st
7
+ from model import ConwaysGameOfLife
8
+
9
+ model = st.title("Conway's Game of Life")
10
+ num_ticks = st.slider("Select number of Steps", min_value=1, max_value=100, value=50)
11
+ height = st.slider("Select Grid Height", min_value=10, max_value=100, step=10, value=15)
12
+ width = st.slider("Select Grid Width", min_value=10, max_value=100, step=10, value=20)
13
+ model = ConwaysGameOfLife(height, width)
14
+
15
+ col1, col2, col3 = st.columns(3)
16
+ status_text = st.empty()
17
+ # step_mode = st.checkbox('Run Step-by-Step')
18
+ run = st.button("Run Simulation")
19
+
20
+
21
+ if run:
22
+ tick = time.time()
23
+ step = 0
24
+ # init grid
25
+ df_grid = pd.DataFrame()
26
+ agent_counts = np.zeros((model.grid.width, model.grid.height))
27
+ for x in range(width):
28
+ for y in range(height):
29
+ df_grid = pd.concat(
30
+ [df_grid, pd.DataFrame({"x": [x], "y": [y], "state": [0]})],
31
+ ignore_index=True,
32
+ )
33
+
34
+ heatmap = (
35
+ alt.Chart(df_grid)
36
+ .mark_point(size=100)
37
+ .encode(x="x", y="y", color=alt.Color("state"))
38
+ .interactive()
39
+ .properties(width=800, height=600)
40
+ )
41
+
42
+ # init progress bar
43
+ my_bar = st.progress(0, text="Simulation Progress") # progress
44
+ placeholder = st.empty()
45
+ st.subheader("Agent Grid")
46
+ chart = st.altair_chart(heatmap, use_container_width=True)
47
+ color_scale = alt.Scale(domain=[0, 1], range=["red", "yellow"])
48
+ for i in range(num_ticks):
49
+ model.step()
50
+ my_bar.progress((i / num_ticks), text="Simulation progress")
51
+ placeholder.text("Step = %d" % i)
52
+ for contents, (x, y) in model.grid.coord_iter():
53
+ # print('x:',x,'y:',y, 'state:',contents)
54
+ selected_row = df_grid[(df_grid["x"] == x) & (df_grid["y"] == y)]
55
+ df_grid.loc[selected_row.index, "state"] = (
56
+ contents.state
57
+ ) # random.choice([1,2])
58
+
59
+ heatmap = (
60
+ alt.Chart(df_grid)
61
+ .mark_circle(size=100)
62
+ .encode(x="x", y="y", color=alt.Color("state", scale=color_scale))
63
+ .interactive()
64
+ .properties(width=800, height=600)
65
+ )
66
+ chart.altair_chart(heatmap)
67
+
68
+ time.sleep(0.1)
69
+
70
+ tock = time.time()
71
+ st.success(f"Simulation completed in {tock - tick:.2f} secs")
@@ -0,0 +1,47 @@
1
+ # Schelling Segregation Model
2
+
3
+ ## Summary
4
+
5
+ The Schelling segregation model is a classic agent-based model, demonstrating how even a mild preference for similar neighbors can lead to a much higher degree of segregation than we would intuitively expect. The model consists of agents on a square grid, where each grid cell can contain at most one agent. Agents come in two colors: red and blue. They are happy if a certain number of their eight possible neighbors are of the same color, and unhappy otherwise. Unhappy agents will pick a random empty cell to move to each step, until they are happy. The model keeps running until there are no unhappy agents.
6
+
7
+ By default, the number of similar neighbors the agents need to be happy is set to 3. That means the agents would be perfectly happy with a majority of their neighbors being of a different color (e.g. a Blue agent would be happy with five Red neighbors and three Blue ones). Despite this, the model consistently leads to a high degree of segregation, with most agents ending up with no neighbors of a different color.
8
+
9
+ ## Installation
10
+
11
+ To install the dependencies use pip and the requirements.txt in this directory. e.g.
12
+
13
+ ```
14
+ $ pip install -r requirements.txt
15
+ ```
16
+
17
+ ## How to Run
18
+
19
+ To run the model interactively, in this directory, run the following command
20
+
21
+ ```
22
+ $ solara run app.py
23
+ ```
24
+
25
+ Then open your browser to [http://127.0.0.1:8765/](http://127.0.0.1:8765/) and click the Play button.
26
+
27
+ 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/).
28
+
29
+ ## How to Run without the GUI
30
+
31
+ To run the model with the grid displayed as an ASCII text, run `python run_ascii.py` in this directory.
32
+
33
+ ## Files
34
+
35
+ * ``app.py``: Code for the interactive visualization.
36
+ * ``schelling.py``: Contains the agent class, and the overall model class.
37
+ * ``analysis.ipynb``: Notebook demonstrating how to run experiments and parameter sweeps on the model.
38
+
39
+ ## Further Reading
40
+
41
+ Schelling's original paper describing the model:
42
+
43
+ [Schelling, Thomas C. Dynamic Models of Segregation. Journal of Mathematical Sociology. 1971, Vol. 1, pp 143-186.](https://www.stat.berkeley.edu/~aldous/157/Papers/Schelling_Seg_Models.pdf)
44
+
45
+ An interactive, browser-based explanation and implementation:
46
+
47
+ [Parable of the Polygons](http://ncase.me/polygons/), by Vi Hart and Nicky Case.
@@ -0,0 +1,26 @@
1
+ from mesa import Agent, Model
2
+
3
+
4
+ class SchellingAgent(Agent):
5
+ """Schelling segregation agent."""
6
+
7
+ def __init__(self, model: Model, agent_type: int) -> None:
8
+ """Create a new Schelling agent.
9
+
10
+ Args:
11
+ agent_type: Indicator for the agent's type (minority=1, majority=0)
12
+ """
13
+ super().__init__(model)
14
+ self.type = agent_type
15
+
16
+ def step(self) -> None:
17
+ neighbors = self.model.grid.iter_neighbors(
18
+ self.pos, moore=True, radius=self.model.radius
19
+ )
20
+ similar = sum(1 for neighbor in neighbors if neighbor.type == self.type)
21
+
22
+ # If unhappy, move:
23
+ if similar < self.model.homophily:
24
+ self.model.grid.move_to_empty(self)
25
+ else:
26
+ self.model.happy += 1
@@ -0,0 +1,205 @@
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {},
6
+ "source": [
7
+ "# Schelling Segregation Model\n",
8
+ "\n",
9
+ "## Background\n",
10
+ "\n",
11
+ "The Schelling (1971) segregation model is a classic of agent-based modeling, demonstrating how agents following simple rules lead to the emergence of qualitatively different macro-level outcomes. Agents are randomly placed on a grid. There are two types of agents, one constituting the majority and the other the minority. All agents want a certain number (generally, 3) of their 8 surrounding neighbors to be of the same type in order for them to be happy. Unhappy agents will move to a random available grid space. While individual agents do not have a preference for a segregated outcome (e.g. they would be happy with 3 similar neighbors and 5 different ones), the aggregate outcome is nevertheless heavily segregated.\n",
12
+ "\n",
13
+ "## Implementation\n",
14
+ "\n",
15
+ "This is a demonstration of running a Mesa model in an IPython Notebook. The actual model and agent code are implemented in Schelling.py, in the same directory as this notebook. Below, we will import the model class, instantiate it, run it, and plot the time series of the number of happy agents."
16
+ ]
17
+ },
18
+ {
19
+ "cell_type": "code",
20
+ "metadata": {},
21
+ "source": [
22
+ "import matplotlib.pyplot as plt\n",
23
+ "import pandas as pd\n",
24
+ "\n",
25
+ "%matplotlib inline\n",
26
+ "\n",
27
+ "from model import Schelling"
28
+ ],
29
+ "outputs": [],
30
+ "execution_count": null
31
+ },
32
+ {
33
+ "cell_type": "markdown",
34
+ "metadata": {},
35
+ "source": [
36
+ "Now we instantiate a model instance: a 10x10 grid, with an 80% change of an agent being placed in each cell, approximately 20% of agents set as minorities, and agents wanting at least 3 similar neighbors."
37
+ ]
38
+ },
39
+ {
40
+ "cell_type": "code",
41
+ "metadata": {},
42
+ "source": "model = Schelling(height=10, width=10, homophily=3, density=0.8, minority_pc=0.2)",
43
+ "outputs": [],
44
+ "execution_count": null
45
+ },
46
+ {
47
+ "cell_type": "markdown",
48
+ "metadata": {},
49
+ "source": [
50
+ "We want to run the model until all the agents are happy with where they are. However, there's no guarantee that a given model instantiation will *ever* settle down. So let's run it for either 100 steps or until it stops on its own, whichever comes first:"
51
+ ]
52
+ },
53
+ {
54
+ "cell_type": "code",
55
+ "metadata": {},
56
+ "source": [
57
+ "while model.running and model.steps < 100:\n",
58
+ " model.step()\n",
59
+ "print(model.steps) # Show how many steps have actually run"
60
+ ],
61
+ "outputs": [],
62
+ "execution_count": null
63
+ },
64
+ {
65
+ "cell_type": "markdown",
66
+ "metadata": {},
67
+ "source": [
68
+ "The model has a DataCollector object, which checks and stores how many agents are happy at the end of each step. It can also generate a pandas DataFrame of the data it has collected:"
69
+ ]
70
+ },
71
+ {
72
+ "cell_type": "code",
73
+ "metadata": {},
74
+ "source": [
75
+ "model_out = model.datacollector.get_model_vars_dataframe()"
76
+ ],
77
+ "outputs": [],
78
+ "execution_count": null
79
+ },
80
+ {
81
+ "cell_type": "code",
82
+ "metadata": {},
83
+ "source": [
84
+ "model_out.head()"
85
+ ],
86
+ "outputs": [],
87
+ "execution_count": null
88
+ },
89
+ {
90
+ "cell_type": "markdown",
91
+ "metadata": {},
92
+ "source": [
93
+ "Finally, we can plot the 'happy' series:"
94
+ ]
95
+ },
96
+ {
97
+ "cell_type": "code",
98
+ "metadata": {},
99
+ "source": [
100
+ "model_out.happy.plot()"
101
+ ],
102
+ "outputs": [],
103
+ "execution_count": null
104
+ },
105
+ {
106
+ "cell_type": "markdown",
107
+ "metadata": {},
108
+ "source": [
109
+ "# Effect of Homophily on happiness\n",
110
+ "\n",
111
+ "Now, we can do a parameter sweep to see how happiness changes with homophily.\n",
112
+ "\n",
113
+ "First, we create a function which takes a model instance and returns what fraction of agents are segregated -- that is, have no neighbors of the opposite type."
114
+ ]
115
+ },
116
+ {
117
+ "cell_type": "code",
118
+ "metadata": {},
119
+ "source": "from mesa.batchrunner import batch_run",
120
+ "outputs": [],
121
+ "execution_count": null
122
+ },
123
+ {
124
+ "cell_type": "markdown",
125
+ "metadata": {},
126
+ "source": [
127
+ "Now, we set up the batch run, with a dictionary of fixed and changing parameters. Let's hold everything fixed except for Homophily."
128
+ ]
129
+ },
130
+ {
131
+ "cell_type": "code",
132
+ "metadata": {},
133
+ "source": [
134
+ "fixed_params = {\"height\": 10, \"width\": 10, \"density\": 0.8, \"minority_pc\": 0.2}\n",
135
+ "variable_parms = {\"homophily\": range(1, 9)}\n",
136
+ "all_params = fixed_params | variable_parms"
137
+ ],
138
+ "outputs": [],
139
+ "execution_count": null
140
+ },
141
+ {
142
+ "cell_type": "code",
143
+ "metadata": {},
144
+ "source": [
145
+ "results = batch_run(\n",
146
+ " Schelling,\n",
147
+ " parameters=all_params,\n",
148
+ " iterations=10,\n",
149
+ " max_steps=200,\n",
150
+ ")"
151
+ ],
152
+ "outputs": [],
153
+ "execution_count": null
154
+ },
155
+ {
156
+ "metadata": {},
157
+ "cell_type": "code",
158
+ "source": [
159
+ "df = pd.DataFrame(results)\n",
160
+ "df"
161
+ ],
162
+ "outputs": [],
163
+ "execution_count": null
164
+ },
165
+ {
166
+ "cell_type": "code",
167
+ "metadata": {},
168
+ "source": [
169
+ "plt.scatter(df.homophily, df.happy)\n",
170
+ "plt.xlabel(\"Homophily\")\n",
171
+ "plt.ylabel(\"Happy Agents\")\n",
172
+ "plt.grid()\n",
173
+ "plt.title(\"Effect of Homophily on segregation\")\n",
174
+ "plt.show()"
175
+ ],
176
+ "outputs": [],
177
+ "execution_count": null
178
+ }
179
+ ],
180
+ "metadata": {
181
+ "kernelspec": {
182
+ "display_name": "Python 3 (ipykernel)",
183
+ "language": "python",
184
+ "name": "python3"
185
+ },
186
+ "language_info": {
187
+ "codemirror_mode": {
188
+ "name": "ipython",
189
+ "version": 3
190
+ },
191
+ "file_extension": ".py",
192
+ "mimetype": "text/x-python",
193
+ "name": "python",
194
+ "nbconvert_exporter": "python",
195
+ "pygments_lexer": "ipython3",
196
+ "version": "3.9.9"
197
+ },
198
+ "widgets": {
199
+ "state": {},
200
+ "version": "1.1.2"
201
+ }
202
+ },
203
+ "nbformat": 4,
204
+ "nbformat_minor": 1
205
+ }
@@ -0,0 +1,43 @@
1
+ import solara
2
+
3
+ from mesa.visualization import (
4
+ Slider,
5
+ SolaraViz,
6
+ make_plot_measure,
7
+ make_space_matplotlib,
8
+ )
9
+
10
+ from .model import Schelling
11
+
12
+
13
+ def get_happy_agents(model):
14
+ """Display a text count of how many happy agents there are."""
15
+ return solara.Markdown(f"**Happy agents: {model.happy}**")
16
+
17
+
18
+ def agent_portrayal(agent):
19
+ return {"color": "tab:orange" if agent.type == 0 else "tab:blue"}
20
+
21
+
22
+ model_params = {
23
+ "density": Slider("Agent density", 0.8, 0.1, 1.0, 0.1),
24
+ "minority_pc": Slider("Fraction minority", 0.2, 0.0, 1.0, 0.05),
25
+ "homophily": Slider("Homophily", 3, 0, 8, 1),
26
+ "width": 20,
27
+ "height": 20,
28
+ }
29
+
30
+ model1 = Schelling(20, 20, 0.8, 0.2, 3)
31
+
32
+ HappyPlot = make_plot_measure("happy")
33
+
34
+ page = SolaraViz(
35
+ model1,
36
+ components=[
37
+ make_space_matplotlib(agent_portrayal),
38
+ make_plot_measure("happy"),
39
+ get_happy_agents,
40
+ ],
41
+ model_params=model_params,
42
+ )
43
+ page # noqa
@@ -0,0 +1,60 @@
1
+ import mesa
2
+ from mesa import Model
3
+
4
+ from .agents import SchellingAgent
5
+
6
+
7
+ class Schelling(Model):
8
+ """Model class for the Schelling segregation model."""
9
+
10
+ def __init__(
11
+ self,
12
+ height=20,
13
+ width=20,
14
+ homophily=3,
15
+ radius=1,
16
+ density=0.8,
17
+ minority_pc=0.2,
18
+ seed=None,
19
+ ):
20
+ """Create a new Schelling model.
21
+
22
+ Args:
23
+ width, height: Size of the space.
24
+ density: Initial Chance for a cell to populated
25
+ minority_pc: Chances for an agent to be in minority class
26
+ homophily: Minimum number of agents of same class needed to be happy
27
+ radius: Search radius for checking similarity
28
+ seed: Seed for Reproducibility
29
+ """
30
+ super().__init__(seed=seed)
31
+ self.homophily = homophily
32
+ self.radius = radius
33
+
34
+ self.grid = mesa.space.SingleGrid(width, height, torus=True)
35
+
36
+ self.happy = 0
37
+ self.datacollector = mesa.DataCollector(
38
+ model_reporters={"happy": "happy"}, # Model-level count of happy agents
39
+ )
40
+
41
+ # Set up agents
42
+ # We use a grid iterator that returns
43
+ # the coordinates of a cell as well as
44
+ # its contents. (coord_iter)
45
+ for _, pos in self.grid.coord_iter():
46
+ if self.random.random() < density:
47
+ agent_type = 1 if self.random.random() < minority_pc else 0
48
+ agent = SchellingAgent(self, agent_type)
49
+ self.grid.place_agent(agent, pos)
50
+
51
+ self.datacollector.collect(self)
52
+
53
+ def step(self):
54
+ """Run one step of the model."""
55
+ self.happy = 0 # Reset counter of happy agents
56
+ self.agents.shuffle_do("step")
57
+
58
+ self.datacollector.collect(self)
59
+
60
+ self.running = self.happy != len(self.agents)
@@ -0,0 +1,61 @@
1
+ # Virus on a Network
2
+
3
+ ## Summary
4
+
5
+ This model is based on the NetLogo model "Virus on Network". It demonstrates the spread of a virus through a network and follows the SIR model, commonly seen in epidemiology.
6
+
7
+ The SIR model is one of the simplest compartmental models, and many models are derivatives of this basic form. The model consists of three compartments:
8
+
9
+ S: The number of susceptible individuals. When a susceptible and an infectious individual come into "infectious contact", the susceptible individual contracts the disease and transitions to the infectious compartment.
10
+ I: The number of infectious individuals. These are individuals who have been infected and are capable of infecting susceptible individuals.
11
+ R for the number of removed (and immune) or deceased individuals. These are individuals who have been infected and have either recovered from the disease and entered the removed compartment, or died. It is assumed that the number of deaths is negligible with respect to the total population. This compartment may also be called "recovered" or "resistant".
12
+
13
+ For more information about this model, read the NetLogo's web page: http://ccl.northwestern.edu/netlogo/models/VirusonaNetwork.
14
+
15
+ JavaScript library used in this example to render the network: [d3.js](https://d3js.org/).
16
+
17
+ ## Installation
18
+
19
+ To install the dependencies use pip and the requirements.txt in this directory. e.g.
20
+
21
+ ```
22
+ $ pip install -r requirements.txt
23
+ ```
24
+
25
+ ## How to Run
26
+
27
+ To run the model interactively, run ``mesa runserver`` in this directory. e.g.
28
+
29
+ ```
30
+ $ mesa runserver
31
+ ```
32
+
33
+ Then open your browser to [http://127.0.0.1:8521/](http://127.0.0.1:8521/) and press Reset, then Run.
34
+
35
+ or
36
+
37
+ Directly run the file ``run.py`` in the terminal. e.g.
38
+
39
+ ```
40
+ $ python run.py
41
+ ```
42
+
43
+
44
+ ## Files
45
+
46
+ * ``model.py``: Contains the agent class, and the overall model class.
47
+ * ``agents.py``: Contains the agent class.
48
+ * ``app.py``: Contains the code for the interactive Solara visualization.
49
+
50
+ ## Further Reading
51
+
52
+ The full tutorial describing how the model is built can be found at:
53
+ https://mesa.readthedocs.io/en/latest/tutorials/intro_tutorial.html
54
+
55
+
56
+ [Stonedahl, F. and Wilensky, U. (2008). NetLogo Virus on a Network model](http://ccl.northwestern.edu/netlogo/models/VirusonaNetwork).
57
+ Center for Connected Learning and Computer-Based Modeling, Northwestern University, Evanston, IL.
58
+
59
+
60
+ [Wilensky, U. (1999). NetLogo](http://ccl.northwestern.edu/netlogo/)
61
+ Center for Connected Learning and Computer-Based Modeling, Northwestern University, Evanston, IL.