Mesa 3.0.0__py3-none-any.whl → 3.0.0a1__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 (104) hide show
  1. mesa/__init__.py +3 -3
  2. mesa/agent.py +114 -406
  3. mesa/batchrunner.py +27 -54
  4. mesa/cookiecutter-mesa/cookiecutter.json +8 -0
  5. mesa/cookiecutter-mesa/hooks/post_gen_project.py +11 -0
  6. mesa/cookiecutter-mesa/{{cookiecutter.snake}}/README.md +4 -0
  7. mesa/cookiecutter-mesa/{{cookiecutter.snake}}/app.pytemplate +27 -0
  8. mesa/cookiecutter-mesa/{{cookiecutter.snake}}/setup.pytemplate +11 -0
  9. mesa/cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}/model.pytemplate +60 -0
  10. mesa/datacollection.py +29 -140
  11. mesa/experimental/__init__.py +1 -11
  12. mesa/experimental/cell_space/__init__.py +1 -16
  13. mesa/experimental/cell_space/cell.py +23 -93
  14. mesa/experimental/cell_space/cell_agent.py +21 -117
  15. mesa/experimental/cell_space/cell_collection.py +17 -54
  16. mesa/experimental/cell_space/discrete_space.py +8 -92
  17. mesa/experimental/cell_space/grid.py +8 -32
  18. mesa/experimental/cell_space/network.py +7 -12
  19. mesa/experimental/devs/__init__.py +0 -2
  20. mesa/experimental/devs/eventlist.py +14 -52
  21. mesa/experimental/devs/examples/epstein_civil_violence.py +39 -71
  22. mesa/experimental/devs/examples/wolf_sheep.py +45 -45
  23. mesa/experimental/devs/simulator.py +15 -55
  24. mesa/main.py +63 -0
  25. mesa/model.py +83 -211
  26. mesa/space.py +149 -215
  27. mesa/time.py +77 -62
  28. mesa/{experimental → visualization}/UserParam.py +6 -17
  29. mesa/visualization/__init__.py +2 -25
  30. mesa/{experimental → visualization}/components/altair.py +0 -10
  31. mesa/visualization/components/matplotlib.py +134 -0
  32. mesa/visualization/solara_viz.py +266 -267
  33. {mesa-3.0.0.dist-info → mesa-3.0.0a1.dist-info}/METADATA +13 -65
  34. mesa-3.0.0a1.dist-info/RECORD +38 -0
  35. mesa-3.0.0.dist-info/licenses/NOTICE → mesa-3.0.0a1.dist-info/licenses/LICENSE +2 -2
  36. mesa/examples/README.md +0 -37
  37. mesa/examples/__init__.py +0 -21
  38. mesa/examples/advanced/epstein_civil_violence/Epstein Civil Violence.ipynb +0 -116
  39. mesa/examples/advanced/epstein_civil_violence/Readme.md +0 -34
  40. mesa/examples/advanced/epstein_civil_violence/__init__.py +0 -0
  41. mesa/examples/advanced/epstein_civil_violence/agents.py +0 -164
  42. mesa/examples/advanced/epstein_civil_violence/app.py +0 -73
  43. mesa/examples/advanced/epstein_civil_violence/model.py +0 -114
  44. mesa/examples/advanced/pd_grid/Readme.md +0 -43
  45. mesa/examples/advanced/pd_grid/__init__.py +0 -0
  46. mesa/examples/advanced/pd_grid/agents.py +0 -50
  47. mesa/examples/advanced/pd_grid/analysis.ipynb +0 -228
  48. mesa/examples/advanced/pd_grid/app.py +0 -54
  49. mesa/examples/advanced/pd_grid/model.py +0 -71
  50. mesa/examples/advanced/sugarscape_g1mt/Readme.md +0 -64
  51. mesa/examples/advanced/sugarscape_g1mt/__init__.py +0 -0
  52. mesa/examples/advanced/sugarscape_g1mt/agents.py +0 -344
  53. mesa/examples/advanced/sugarscape_g1mt/app.py +0 -62
  54. mesa/examples/advanced/sugarscape_g1mt/model.py +0 -180
  55. mesa/examples/advanced/sugarscape_g1mt/sugar-map.txt +0 -50
  56. mesa/examples/advanced/sugarscape_g1mt/tests.py +0 -69
  57. mesa/examples/advanced/wolf_sheep/Readme.md +0 -57
  58. mesa/examples/advanced/wolf_sheep/__init__.py +0 -0
  59. mesa/examples/advanced/wolf_sheep/agents.py +0 -102
  60. mesa/examples/advanced/wolf_sheep/app.py +0 -84
  61. mesa/examples/advanced/wolf_sheep/model.py +0 -137
  62. mesa/examples/basic/__init__.py +0 -0
  63. mesa/examples/basic/boid_flockers/Readme.md +0 -22
  64. mesa/examples/basic/boid_flockers/__init__.py +0 -0
  65. mesa/examples/basic/boid_flockers/agents.py +0 -71
  66. mesa/examples/basic/boid_flockers/app.py +0 -58
  67. mesa/examples/basic/boid_flockers/model.py +0 -69
  68. mesa/examples/basic/boltzmann_wealth_model/Readme.md +0 -56
  69. mesa/examples/basic/boltzmann_wealth_model/__init__.py +0 -0
  70. mesa/examples/basic/boltzmann_wealth_model/agents.py +0 -31
  71. mesa/examples/basic/boltzmann_wealth_model/app.py +0 -74
  72. mesa/examples/basic/boltzmann_wealth_model/model.py +0 -43
  73. mesa/examples/basic/boltzmann_wealth_model/st_app.py +0 -115
  74. mesa/examples/basic/conways_game_of_life/Readme.md +0 -39
  75. mesa/examples/basic/conways_game_of_life/__init__.py +0 -0
  76. mesa/examples/basic/conways_game_of_life/agents.py +0 -47
  77. mesa/examples/basic/conways_game_of_life/app.py +0 -51
  78. mesa/examples/basic/conways_game_of_life/model.py +0 -31
  79. mesa/examples/basic/conways_game_of_life/st_app.py +0 -72
  80. mesa/examples/basic/schelling/Readme.md +0 -40
  81. mesa/examples/basic/schelling/__init__.py +0 -0
  82. mesa/examples/basic/schelling/agents.py +0 -26
  83. mesa/examples/basic/schelling/analysis.ipynb +0 -205
  84. mesa/examples/basic/schelling/app.py +0 -42
  85. mesa/examples/basic/schelling/model.py +0 -59
  86. mesa/examples/basic/virus_on_network/Readme.md +0 -61
  87. mesa/examples/basic/virus_on_network/__init__.py +0 -0
  88. mesa/examples/basic/virus_on_network/agents.py +0 -69
  89. mesa/examples/basic/virus_on_network/app.py +0 -114
  90. mesa/examples/basic/virus_on_network/model.py +0 -96
  91. mesa/experimental/cell_space/voronoi.py +0 -257
  92. mesa/experimental/components/matplotlib.py +0 -242
  93. mesa/experimental/solara_viz.py +0 -453
  94. mesa/visualization/components/__init__.py +0 -83
  95. mesa/visualization/components/altair_components.py +0 -188
  96. mesa/visualization/components/matplotlib_components.py +0 -175
  97. mesa/visualization/mpl_space_drawing.py +0 -593
  98. mesa/visualization/user_param.py +0 -69
  99. mesa/visualization/utils.py +0 -9
  100. mesa-3.0.0.dist-info/RECORD +0 -95
  101. mesa-3.0.0.dist-info/licenses/LICENSE +0 -202
  102. /mesa/{examples/advanced → cookiecutter-mesa/{{cookiecutter.snake}}/{{cookiecutter.snake}}}/__init__.py +0 -0
  103. {mesa-3.0.0.dist-info → mesa-3.0.0a1.dist-info}/WHEEL +0 -0
  104. {mesa-3.0.0.dist-info → mesa-3.0.0a1.dist-info}/entry_points.txt +0 -0
@@ -1,205 +0,0 @@
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
- }
@@ -1,42 +0,0 @@
1
- import solara
2
-
3
- from mesa.examples.basic.schelling.model import Schelling
4
- from mesa.visualization import (
5
- Slider,
6
- SolaraViz,
7
- make_plot_component,
8
- make_space_component,
9
- )
10
-
11
-
12
- def get_happy_agents(model):
13
- """Display a text count of how many happy agents there are."""
14
- return solara.Markdown(f"**Happy agents: {model.happy}**")
15
-
16
-
17
- def agent_portrayal(agent):
18
- return {"color": "tab:orange" if agent.type == 0 else "tab:blue"}
19
-
20
-
21
- model_params = {
22
- "density": Slider("Agent density", 0.8, 0.1, 1.0, 0.1),
23
- "minority_pc": Slider("Fraction minority", 0.2, 0.0, 1.0, 0.05),
24
- "homophily": Slider("Homophily", 3, 0, 8, 1),
25
- "width": 20,
26
- "height": 20,
27
- }
28
-
29
- model1 = Schelling(20, 20, 0.8, 0.2, 3)
30
-
31
- HappyPlot = make_plot_component({"happy": "tab:green"})
32
-
33
- page = SolaraViz(
34
- model1,
35
- components=[
36
- make_space_component(agent_portrayal),
37
- HappyPlot,
38
- get_happy_agents,
39
- ],
40
- model_params=model_params,
41
- )
42
- page # noqa
@@ -1,59 +0,0 @@
1
- import mesa
2
- from mesa import Model
3
- from mesa.examples.basic.schelling.agents import SchellingAgent
4
-
5
-
6
- class Schelling(Model):
7
- """Model class for the Schelling segregation model."""
8
-
9
- def __init__(
10
- self,
11
- height=20,
12
- width=20,
13
- homophily=3,
14
- radius=1,
15
- density=0.8,
16
- minority_pc=0.2,
17
- seed=None,
18
- ):
19
- """Create a new Schelling model.
20
-
21
- Args:
22
- width, height: Size of the space.
23
- density: Initial Chance for a cell to populated
24
- minority_pc: Chances for an agent to be in minority class
25
- homophily: Minimum number of agents of same class needed to be happy
26
- radius: Search radius for checking similarity
27
- seed: Seed for Reproducibility
28
- """
29
- super().__init__(seed=seed)
30
- self.homophily = homophily
31
- self.radius = radius
32
-
33
- self.grid = mesa.space.SingleGrid(width, height, torus=True)
34
-
35
- self.happy = 0
36
- self.datacollector = mesa.DataCollector(
37
- model_reporters={"happy": "happy"}, # Model-level count of happy agents
38
- )
39
-
40
- # Set up agents
41
- # We use a grid iterator that returns
42
- # the coordinates of a cell as well as
43
- # its contents. (coord_iter)
44
- for _, pos in self.grid.coord_iter():
45
- if self.random.random() < density:
46
- agent_type = 1 if self.random.random() < minority_pc else 0
47
- agent = SchellingAgent(self, agent_type)
48
- self.grid.place_agent(agent, pos)
49
-
50
- self.datacollector.collect(self)
51
-
52
- def step(self):
53
- """Run one step of the model."""
54
- self.happy = 0 # Reset counter of happy agents
55
- self.agents.shuffle_do("step")
56
-
57
- self.datacollector.collect(self)
58
-
59
- self.running = self.happy != len(self.agents)
@@ -1,61 +0,0 @@
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.
File without changes
@@ -1,69 +0,0 @@
1
- from enum import Enum
2
-
3
- from mesa import Agent
4
-
5
-
6
- class State(Enum):
7
- SUSCEPTIBLE = 0
8
- INFECTED = 1
9
- RESISTANT = 2
10
-
11
-
12
- class VirusAgent(Agent):
13
- """Individual Agent definition and its properties/interaction methods."""
14
-
15
- def __init__(
16
- self,
17
- model,
18
- initial_state,
19
- virus_spread_chance,
20
- virus_check_frequency,
21
- recovery_chance,
22
- gain_resistance_chance,
23
- ):
24
- super().__init__(model)
25
-
26
- self.state = initial_state
27
-
28
- self.virus_spread_chance = virus_spread_chance
29
- self.virus_check_frequency = virus_check_frequency
30
- self.recovery_chance = recovery_chance
31
- self.gain_resistance_chance = gain_resistance_chance
32
-
33
- def try_to_infect_neighbors(self):
34
- neighbors_nodes = self.model.grid.get_neighborhood(
35
- self.pos, include_center=False
36
- )
37
- susceptible_neighbors = [
38
- agent
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
45
-
46
- def try_gain_resistance(self):
47
- if self.random.random() < self.gain_resistance_chance:
48
- self.state = State.RESISTANT
49
-
50
- def try_remove_infection(self):
51
- # Try to remove
52
- if self.random.random() < self.recovery_chance:
53
- # Success
54
- self.state = State.SUSCEPTIBLE
55
- self.try_gain_resistance()
56
- else:
57
- # Failed
58
- self.state = State.INFECTED
59
-
60
- def try_check_situation(self):
61
- if (self.random.random() < self.virus_check_frequency) and (
62
- self.state is State.INFECTED
63
- ):
64
- self.try_remove_infection()
65
-
66
- def step(self):
67
- if self.state is State.INFECTED:
68
- self.try_to_infect_neighbors()
69
- self.try_check_situation()
@@ -1,114 +0,0 @@
1
- import math
2
-
3
- import solara
4
-
5
- from mesa.examples.basic.virus_on_network.model import (
6
- State,
7
- VirusOnNetwork,
8
- number_infected,
9
- )
10
- from mesa.visualization import (
11
- Slider,
12
- SolaraViz,
13
- make_plot_component,
14
- make_space_component,
15
- )
16
-
17
-
18
- def agent_portrayal(agent):
19
- node_color_dict = {
20
- State.INFECTED: "tab:red",
21
- State.SUSCEPTIBLE: "tab:green",
22
- State.RESISTANT: "tab:gray",
23
- }
24
- return {"color": node_color_dict[agent.state], "size": 10}
25
-
26
-
27
- def get_resistant_susceptible_ratio(model):
28
- ratio = model.resistant_susceptible_ratio()
29
- ratio_text = r"$\infty$" if ratio is math.inf else f"{ratio:.2f}"
30
- infected_text = str(number_infected(model))
31
-
32
- return solara.Markdown(
33
- f"Resistant/Susceptible Ratio: {ratio_text}<br>Infected Remaining: {infected_text}"
34
- )
35
-
36
-
37
- model_params = {
38
- "num_nodes": Slider(
39
- label="Number of agents",
40
- value=10,
41
- min=10,
42
- max=100,
43
- step=1,
44
- ),
45
- "avg_node_degree": Slider(
46
- label="Avg Node Degree",
47
- value=3,
48
- min=3,
49
- max=8,
50
- step=1,
51
- ),
52
- "initial_outbreak_size": Slider(
53
- label="Initial Outbreak Size",
54
- value=1,
55
- min=1,
56
- max=10,
57
- step=1,
58
- ),
59
- "virus_spread_chance": Slider(
60
- label="Virus Spread Chance",
61
- value=0.4,
62
- min=0.0,
63
- max=1.0,
64
- step=0.1,
65
- ),
66
- "virus_check_frequency": Slider(
67
- label="Virus Check Frequency",
68
- value=0.4,
69
- min=0.0,
70
- max=1.0,
71
- step=0.1,
72
- ),
73
- "recovery_chance": Slider(
74
- label="Recovery Chance",
75
- value=0.3,
76
- min=0.0,
77
- max=1.0,
78
- step=0.1,
79
- ),
80
- "gain_resistance_chance": Slider(
81
- label="Gain Resistance Chance",
82
- value=0.5,
83
- min=0.0,
84
- max=1.0,
85
- step=0.1,
86
- ),
87
- }
88
-
89
-
90
- def post_process_lineplot(ax):
91
- ax.set_ylim(ymin=0)
92
- ax.set_ylabel("# people")
93
- ax.legend(bbox_to_anchor=(1.05, 1.0), loc="upper left")
94
-
95
-
96
- SpacePlot = make_space_component(agent_portrayal)
97
- StatePlot = make_plot_component(
98
- {"Infected": "tab:red", "Susceptible": "tab:green", "Resistant": "tab:gray"},
99
- post_process=post_process_lineplot,
100
- )
101
-
102
- model1 = VirusOnNetwork()
103
-
104
- page = SolaraViz(
105
- model1,
106
- [
107
- SpacePlot,
108
- StatePlot,
109
- get_resistant_susceptible_ratio,
110
- ],
111
- model_params=model_params,
112
- name="Virus Model",
113
- )
114
- page # noqa
@@ -1,96 +0,0 @@
1
- import math
2
-
3
- import networkx as nx
4
-
5
- import mesa
6
- from mesa import Model
7
- from mesa.examples.basic.virus_on_network.agents import State, VirusAgent
8
-
9
-
10
- def number_state(model, state):
11
- return sum(1 for a in model.grid.get_all_cell_contents() if a.state is state)
12
-
13
-
14
- def number_infected(model):
15
- return number_state(model, State.INFECTED)
16
-
17
-
18
- def number_susceptible(model):
19
- return number_state(model, State.SUSCEPTIBLE)
20
-
21
-
22
- def number_resistant(model):
23
- return number_state(model, State.RESISTANT)
24
-
25
-
26
- class VirusOnNetwork(Model):
27
- """A virus model with some number of agents."""
28
-
29
- def __init__(
30
- self,
31
- num_nodes=10,
32
- avg_node_degree=3,
33
- initial_outbreak_size=1,
34
- virus_spread_chance=0.4,
35
- virus_check_frequency=0.4,
36
- recovery_chance=0.3,
37
- gain_resistance_chance=0.5,
38
- seed=None,
39
- ):
40
- super().__init__(seed=seed)
41
- self.num_nodes = num_nodes
42
- prob = avg_node_degree / self.num_nodes
43
- self.G = nx.erdos_renyi_graph(n=self.num_nodes, p=prob)
44
- self.grid = mesa.space.NetworkGrid(self.G)
45
-
46
- self.initial_outbreak_size = (
47
- initial_outbreak_size if initial_outbreak_size <= num_nodes else num_nodes
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
-
54
- self.datacollector = mesa.DataCollector(
55
- {
56
- "Infected": number_infected,
57
- "Susceptible": number_susceptible,
58
- "Resistant": number_resistant,
59
- "R over S": self.resistant_susceptible_ratio,
60
- }
61
- )
62
-
63
- # Create agents
64
- for node in self.G.nodes():
65
- a = VirusAgent(
66
- self,
67
- State.SUSCEPTIBLE,
68
- self.virus_spread_chance,
69
- self.virus_check_frequency,
70
- self.recovery_chance,
71
- self.gain_resistance_chance,
72
- )
73
-
74
- # Add the agent to the node
75
- self.grid.place_agent(a, node)
76
-
77
- # Infect some nodes
78
- infected_nodes = self.random.sample(list(self.G), self.initial_outbreak_size)
79
- for a in self.grid.get_cell_list_contents(infected_nodes):
80
- a.state = State.INFECTED
81
-
82
- self.running = True
83
- self.datacollector.collect(self)
84
-
85
- def resistant_susceptible_ratio(self):
86
- try:
87
- return number_state(self, State.RESISTANT) / number_state(
88
- self, State.SUSCEPTIBLE
89
- )
90
- except ZeroDivisionError:
91
- return math.inf
92
-
93
- def step(self):
94
- self.agents.shuffle_do("step")
95
- # collect data
96
- self.datacollector.collect(self)