Skip to content

Commit ec4541a

Browse files
committed
- Add sugarcape_g1mt that is consistent with complexity tutorial
- Include interactive version with single run, batch run and server options - Update .gitignore to ignore IDE environment files
1 parent 0a63142 commit ec4541a

File tree

10 files changed

+961
-0
lines changed

10 files changed

+961
-0
lines changed

.gitignore

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,24 @@ docs/_build/
5555

5656
# PyBuilder
5757
target/
58+
59+
# Jupyter and iPython notebook checkpoints
60+
*.ipynb_checkpoints
61+
62+
# Spyder app workspace config file
63+
.spyderworkspace
64+
65+
# PyCharm environment files
66+
.idea/
67+
68+
# VSCode environment files
69+
.vscode/
70+
*.code-workspace
71+
72+
# Apple OSX
73+
*.DS_Store
74+
75+
# mypy
76+
.mypy_cache/
77+
.dmypy.json
78+
dmypy.json

examples/sugarscape_g1mt/Readme.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Sugarscape Constant Growback Model with Traders
2+
3+
## Summary
4+
5+
This is Epstein & Axtell's Sugarscape model with Traders, a detailed description is in Chapter four of
6+
*Growing Artificial Societies: Social Science from the Bottom Up.* (1996)
7+
8+
This code generally matches the code in the Complexity Explorer Tutorial, but in `.py` instead of `.ipynb` format.
9+
10+
### Agents:
11+
12+
- **Sugar**: Sugar agents grow back at one unit per time step and can be harvested and traded by the trader agents. Sugar
13+
is unequally distributed across the landscape with sugar hills in the upper left and lower right of the space.
14+
(green if you do the interactive run)
15+
- **Spice**: Spice agents grow back at one unit per time step and can be harvested and traded by the trader agents. Spice
16+
is unequally distributed across the landscape with spice hills in the upper right and lower left of the space.
17+
(yellow if you do the interactive run)
18+
- **Traders**: Trader agents have the following attributes: (1) metabolism for sugar, (2) metabolism for spice, (3) vision,
19+
(4) initial sugar endowment and (5) initial spice endowment. The traverse the landscape harvesting sugar and spice and
20+
trading with other agents. If they run out of sugar or spice then they are removed from the model.
21+
22+
The trader agents traverse the landscape according to rule **M**:
23+
- Look out as far as vision permits in the four principal lattice directions and identify the unoccupied site(s).
24+
- Considering only unoccupied sites find the nearest position that produces the most welfare using the Cobb-Douglas function.
25+
- Move to the new position
26+
- Collect all the resources (sugar and spice) at that location
27+
(Epstein and Axtell, 1996, p. 99)
28+
29+
The traders trade according to rule **T**:
30+
- Agents and potential trade partner compute their marginal rates of substitution (MRS), if they are equal *end*.
31+
- Exchange resources, with spice flowing from the agent with the higher MRS to the agent with the lower MRS and sugar
32+
flowing the opposite direction.
33+
- The price (p) is calculated by taking the geometric mean of the agents' MRS.
34+
- If p > 1 then p units of spice are traded for 1 unit of sugar; if p < 1 then 1/p units of sugar for 1 unit of spice
35+
- The trade occurs if it will (a) make both agent better off (increases MRS) and (b) does not cause the agents' MRS to
36+
cross over one another otherwise *end*.
37+
- This process then repeats until an *end* condition is met.
38+
(Epstein and Axtell, 1996, p. 105)
39+
40+
The model demonstrates several Mesa concepts and features:
41+
- MultiGrid
42+
- Multiple agent types (traders, sugar, spice)
43+
- Dynamically removing agents from the grid and schedule when they die
44+
- Data Collection at the model and agent level
45+
- Batchrunner (i.e. parameter sweeps)
46+
47+
## Installation
48+
49+
To install the dependencies use pip and the requirements.txt in this directory. e.g.
50+
51+
```
52+
$ pip install -r requirements.txt
53+
```
54+
55+
## How to Run
56+
57+
To run the model a single instance of the model:
58+
59+
```
60+
$ python run.py -s
61+
```
62+
63+
To run the model with BatchRunner:
64+
65+
```
66+
$ python run.py
67+
```
68+
69+
To run the model interactively:
70+
71+
```
72+
$ mesa runserver
73+
```
74+
75+
Then open your browser to [http://127.0.0.1:8521/](http://127.0.0.1:8521/) and press Reset, then Run.
76+
77+
## Files
78+
79+
* ``sugarscape_g1mt/trader_agents.py``: Defines the Trader agent class.
80+
* ``sugarscape_g1mt/resource_agents.py``: Defines the Sugar and Spice agent classes.
81+
* ``sugarscape_g1mt/model.py``: Manages the Sugarscape Constant Growback with Traders model.
82+
* ``sugarscape_g1mt/sugar_map.txt``: Provides sugar and spice landscape in raster type format.
83+
* ``server.py``: Sets up and launches and interactive visualization server.
84+
* ``run.py``: Runs Server, Single Run or Batch Run with data collection and basic analysis.
85+
86+
## Additional Resources
87+
88+
- [Growing Artificial Societies](https://mitpress.mit.edu/9780262550253/growing-artificial-societies/)
89+
- [Complexity Explorer Sugarscape with Traders Tutorial](https://www.complexityexplorer.org/courses/172-agent-based-models-with-python-an-introduction-to-mesa)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
jupyter
2+
mesa
3+
numpy
4+
matplotlib
5+
networkx

examples/sugarscape_g1mt/run.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import sys
2+
import pandas as pd
3+
import matplotlib.pyplot as plt
4+
import networkx as nx
5+
import mesa
6+
from sugarscape_g1mt.model import SugarscapeG1mt
7+
from sugarscape_g1mt.server import server
8+
9+
10+
# Analysis
11+
def assess_results(results, single_agent):
12+
# Make dataframe of results
13+
results_df = pd.DataFrame(results)
14+
# Plot and show mean price
15+
plt.scatter(results_df["Step"], results_df["Price"], s=0.75)
16+
plt.show()
17+
18+
if single_agent is not None:
19+
plt.plot(results_df["Step"], results_df["Trader"])
20+
plt.show()
21+
else:
22+
n = max(results_df["RunID"])
23+
# Plot number of Traders
24+
for i in range(n):
25+
results_explore = results_df[results_df["RunId"] == i]
26+
plt.plot(results_explore["Step"], results_explore["Trader"])
27+
plt.show()
28+
29+
if single_agent is not None:
30+
results_df = single_agent
31+
32+
# Show Trade Networks
33+
# create graph object
34+
print("Making Network")
35+
G = nx.Graph()
36+
trade = results_df.dropna(subset=["Trade Network"])
37+
# add agent keys to make initial node set
38+
G.add_nodes_from(list(trade["AgentID"].unique()))
39+
40+
# create edge list
41+
for idx, row in trade.iterrows():
42+
if len(row["Trade Network"]) > 0:
43+
for agent in row["Trade Network"]:
44+
G.add_edge(row["AgentID"], agent)
45+
46+
# Get Basic Network Statistics
47+
print("Node Connectivity {}".format(nx.node_connectivity(G)))
48+
print("Average Clustering {}".format(nx.average_clustering(G)))
49+
print("Global Efficiency {}".format(nx.global_efficiency(G)))
50+
51+
# Plot histogram of degree distribution
52+
degree_sequence = sorted((d for n, d in G.degree()), reverse=True)
53+
degree_sequence = [d for n, d in G.degree()]
54+
plt.hist(degree_sequence)
55+
plt.show()
56+
57+
# Plot network
58+
nx.draw(G)
59+
plt.show()
60+
61+
62+
# Run the model
63+
64+
args = sys.argv[1:]
65+
66+
67+
if args[0] == "runserver":
68+
server.launch()
69+
70+
elif "s" in args[0] or "Single" in args[0]:
71+
print("Running Single Model")
72+
# instantiate the model
73+
model = SugarscapeG1mt()
74+
# run the model
75+
model.run_model()
76+
# Get results
77+
model_results = model.datacollector.get_model_vars_dataframe()
78+
# Convert to make similar to batch_run_results
79+
model_results["Step"] = model_results.index
80+
agent_results = model.datacollector.get_agent_vars_dataframe()
81+
agent_results = agent_results.reset_index()
82+
# assess the results
83+
assess_results(model_results, agent_results)
84+
85+
else:
86+
print("Conducting a Batch Run")
87+
# Batch Run
88+
params = {
89+
"width": 50,
90+
"height": 50,
91+
"vision_min": range(1, 3),
92+
"metabolism_max": [3, 5],
93+
}
94+
95+
results_batch = mesa.batch_run(
96+
SugarscapeG1mt,
97+
parameters=params,
98+
iterations=1,
99+
number_processes=1,
100+
data_collection_period=1,
101+
display_progress=True,
102+
)
103+
104+
assess_results(results_batch, None)

examples/sugarscape_g1mt/sugarscape_g1mt/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)