For this part, we’ll be using Nicky Case’s agent-based modeling simulator, the Emoji Simulator. When you make your write-ups with this, you can include screenshots for your plots and as your model “code”.
During the 1960s the economist Thomas Schelling researched segregation and racial preferences, and showed individuals can have only relatively mild preferences for the same type and yet these subtle preferences can lead to societal segregation.
The rules for this model are simple: each person is happy if at least a certain percentage of their neighbors are the same type as them. If a person is happy, they stay in their current location. If they are unhappy, they move to a randomly chosen new location. This continues until all the people are happy (or possibly forever).
Start by doing the following:
For each problem, include the written answer to the problem, a
screenshot of the model behavior, and the “code” (a screenshot or
listing of the rules and model/environment setup).
Problem 1A) From the blank model, code up a version of the Schelling model with the following rules:
Code the model, supposing that each animal will move if less than 2 (25%) of its neighbors to be the same as it. Run the model a few times. What behavior do you observe?
Problem 1B) Adjust the number of neighbors required to be the same. How does the model behavior vary as this number varies from 1 to 8?
Problem 1C) Now try out adjusting the balance between empty cells and animals. How does the model behavior change as the density of whales and foxes increases or decreases? Do you always observe separation between the two types? Why do you think this is?
Problem 1D) Lastly, let’s illustrate the importance of being careful about how we specify our rules. Re-run problems 1A - 1C with a slightly different rule: each type of animal wants no more than Y of its neighbors to be the opposite type. In other words, if there are more than 6 (75%) neighbors of the other type, it will move. Does this change the behavior of the model? If so, how does the behavior change? Why do you think this is?
Start with a blank model and build a model of your choosing! In your write-up, document the model you built, including:
If you’re relatively new to Python, or you don’t know how to build loops and/or functions in Python, here are some tutorials to get started with:
Finally, we’ll be using a few modules/packages for Python in this
class, such as numpy
, scipy
, and
matplotlib
. To get familiar with those, here’s a quick
cheatsheet that covers many of the packages we’ll need (also useful
as a reference even if you’ve used them before!).
Next we will work with a simple agent based model of swarming flying insects (e.g. gnats) in python, adapted from Sayama’s PyCX library. This model illustrates much of the types of structures we will use throughout the class for our models.
In particular, many of the models we use will be built on three main functions:
With these three basic functions and a for loop, we can build a ton of different models, as we will see over the semester! In any case, the code for the model is here: Swarming Agent-Based Model.
Problem 1A: Understanding the model) Read through
the model code. In the section labeled “Define our Agents”, look at the
class definition given there. We haven’t covered classes in python yet,
but the agent
class here defines the properties that agents
have (under __init__
) and the actions they can take (the
other functions defined there). Based on this, list the properties and
actions for the agents in this model, and say what you think each
property or action means/does (include this in your homework
writeup).
Problem 1B: Running the model) Run the model for 30 timesteps (the default that’s already set) and observe the behavior of the swarm. Include the plot of the swarm at the final timestep in your writeup.
Problem 1C: Expanding the swarm) In the model, each
insect in the swarm is started at a random position in the unit square
(the box from 0 to 1 in x and y). Adjust the code in the
initialize
function to make the swarm start off in a random
position in a box with side-length 10 (i.e. a 10x10 box, or put another
way, random x-axis and y-axis values between 0 and 10). Run the model
for 30 steps again (possibly a few times to see what it does
consistently). Then try the model with a 100x100 box. Include plots of
the swarm at the final time step for the length 10 box and the length
100 box.
Do the swarms behave the same for each initial swarm size? Does the swarm appear to converge back to a swarm of the same size at the end of all three simulations (length 1, 10, 100), or does the final swarm size appear to change depending on the initial size? Include your answers in your writeup.
Problem 1D: Measuring swarm size) One way to track the swarm size is to calculate the variance (a measure of spread of a distribution) of the positions of all the agents. Let’s plot the variance over time for our model. We’ll do that like this:
vars
to the global
line in our three functions (i.e. it should read
global agents, vars
)var
command from numpy
. Add this line to
the end of the initialize
function:
vars = [np.var([a.x for a in agents])]
. This will be a list
we will use to store the variance at each time step.update
function:
vars.append(np.var([a.x for a in agents]))
. This will add
the new variance each time we update the model.Finally, edit the model so that you run it for 100 time steps (instead of 30), and add this code after you’ve run the model:
plt.figure()
plt.plot(range(101),vars)
If running 100 time steps takes too long, you may want to comment out
the lines for observe()
and the display/sleep commands so
that it doesn’t generate a plot at each step as it runs.
Generate plots of the variance over time for 100 time steps with initial swarm locations in boxes of length 1, 10, and 100. Include all three plots in your writeup. How does the swarm size change over time? How does it change as you adjust the size of the initial swarm? Include your answers in your writeup.
Next, let’s code up the Chaos Game in Python. This will give us some practice coding from scratch—building functions, using for loops, and using if statements. We’ll code it up step by step, and then put it all together.
First, let’s import some of the libraries we need (you may need to install these libraries first!):
from math import * # useful math functions
import numpy as np # useful array objects
# (also a core scientific computing library)
import matplotlib.pyplot as plt # nice plotting commands
from random import random, randint # random number generation functions
Problem 2A: Functions) Write a function called
midpoint
that takes in two tuples of the form
(x,y)
as inputs, and returns their midpoint as a new tuple.
We can calculate the midpoint of two points \((x_1, y_1)\) and \((x_2,y_2)\) like this: \[ midpoint = \left(\frac{1}{2}(x_1 + x_2) \, ,\,
\frac{1}{2}(y_1 + y_2) \right)\] We will use this function later
to calculate add new points as we draw the chaos game. Add this function
to the beginning of your script.
Problem 2B: Setup) Next, let’s setup some of what we need for the Chaos Game:
corner
that contains three tuples,
each with the coordinates of one vertex on your equilateral triangle. In
case you’ve forgotten your Pythagorean theorem from way back when,
here’s a set of coordinates you can use: \((0,0)\), \((1,0)\), and \((0.5, \sqrt{3}/2)\) (python uses the
function sqrt
for square roots).N = 1000
np.zeros
function. We will use these to store all the x and
y coordinates we will plot on the Chaos Game. You can make these arrays
like this: x = np.zeros(N)
.Problem 2C: Starting position) Now we have
everything we need, and we can start the Chaos Game! Choose a random
starting position for your x and y coordinates, and store this starting
position in your x
and y
arrays as the first
entry. (Remember that Python indexes from zero so you’ll store these in
x[0]
and y[0]
!) To choose the random location,
you can use the random()
function. (This will pick a random
value between 0 and 1, which works out since those are the maximum size
for the triangle we’re using. If you picked a different size triangle,
be sure to adjust the range for your random draw!)
Problem 2D: For loops) Now that we have our starting
position, we need to choose the rest of our 1000 points. For this, we’ll
use a loop. Write a loop that iterates from 1
to
N
. On each iteration of the loop, you should:
corner
x
and y
listRemember that for Python, spacing is important! Make sure you indent each line in the for loop the same amount, or you’ll run into trouble.
Problem 2E: Plot the results!) Okay, we should have a nice Chaos Game going now! We can plot our results like this:
plt.figure()
plt.scatter(x, y) # plot our chaos game points
plt.scatter((0,1,0.5),(0,0,sqrt(3)/2),color='red') # plot the triangle vertices
plt.show()
When you put all this code together, you should get something that looks roughly like this! Include your final plot and your code when you turn in your lab.
If you have time and interest, try changing the Chaos Game! A few things you can try:
If you want to try some pre-worked out ideas, there are some nice examples on Wolfram Mathworld. If you try a few different things, what do you notice? Are there particular configurations that work or don’t work? Why do you think this is?
What are you considering for your final project? Give an idea or two (definitely not final, just want you to start thinking about possibilities!)