Determine whether segregation can be explained by individual motivations to avoid being a local minority. Agents will move around a two-dimensional space depending on whether they are a racial minority within their local neighborhood.
A population of agents will be generated; each agent will have a race (black or white) and a position in a 2-dimensional space.
Each agent will first calculate how far they are from each other agent in the 2D space. The agent will then identify all agents who reside within a set radius around them. These agents constitute the focal agent’s neighborhood.
The focal agent will then determine the race of all agents in their neighborhood. Finally, the agent will determine whether they are in the minority race in their neighborhood.
In this stage of the life cycle, the agent makes one decision: if the agent is not in the minority then they will stay where they are. If the agent is in the minority, they will move to a new random location.
The model will plot the position of agents before and after the movement phases
library(ggplot2)
#Population Size#
#The number of agents to generate
popSize<-1000
#Neighborhood Radius#
#How close an agent must be to be a neighbor
#smaller radius, fewer patches need to be homogenous for people to be happy
radius<-20
#Minority Threshold#
#The proportion of same-race neighbors below which an agent will decide to move
threshold<-.5
#maximum number of movement cycles that agents will go through
maxSteps <- 100
#Current Steps#
#create a variable to track completed movement cycles
steps <- 0
agentGenerate<-function(n){
#Assign each agent a random race
race<-sample(c("black","white"),n,replace=T)
#Assign each agent a random x-position
xPos<-runif(n,0,100)
#Assign each agent a random y-position
yPos<-runif(n,0,100)
#Generate the agents
agents<-data.frame(race,xPos,yPos)
#Output the agents
return(agents)
}
#Assess#
#Have the agents assess their neighborhood and decide whether they want to move
assess<-function(agents,radius,threshold){
#Computes the straight-line distance between each agent and all other agents
distances<-as.matrix(dist(agents[,2:3]))
moveDecision <-rep(NA, nrow(agents))
for(a in 1:nrow(agents)){
#Determine which agents are the focal agent's neighbors
neighbors<-distances[a,]<=radius
#Determine which agents are of the same race as the focal agent
sameRace<-agents$race[a] == agents$race
#have the agent determine the proportion of neghbors who are of the same race
assessment <- sum(sameRace & neighbors)/sum(neighbors)
#have the agent decide whether or not to move
moveDecision[a] <- assessment<threshold
}
#output the agent's movement decisions!
return(moveDecision)
}
#Move#
# a function to have agents move
move <- function(agents,moveDecision){
#loop one-by-one through agents
for(a in 1:nrow (agents)){
#if this particular agent bracket a decides to move, then...
if(moveDecision[a]==T){
#assign them a new random x and y position
#silly way to move, since its a random place in neighborhood
agents$xPos[a] <- runif(1,0,100)
agents$yPos[a] <- runif(1,0,100)
}
}
#output the agents with their (potential) new positions
return(agents)
}
#Generate the agents
agents<-agentGenerate(popSize)
#save the starting state of the agents dataframe
startAgents <- agents
while(maxSteps>steps){
#increment steps by 1
steps <- steps+1
#Assess#
#have the agents assess their neighborhood and decide whether to move
moveDecision <- assess(agents,radius,threshold)
#Move#
#have the agents move if they are dissatisfied with their current
#neighborhood
agents <- move(agents,moveDecision)
#if no one wants to move...
#break automatically stops any loop, end the loop
if(sum(moveDecision)==0){
break
}
}
#save the state of the agents data frame after they move
endAgents <- agents
t1plot <- ggplot(data=startAgents,
aes(x=xPos,
y=yPos,
color=race)) +
labs(x="", y="", color="Agent Race")+
geom_point(size=2.5)+
scale_color_manual(values=c("black", "white"),
labels=c("Black", "White"))+
theme(panel.background = element_rect(fill="grey"))
t2plot <- ggplot(data=endAgents,
aes(x=xPos,
y=yPos,
color=race)) +
labs(x="", y="", color="Agent Race")+
geom_point(size=2.5)+
scale_color_manual(values=c("black", "white"),
labels=c("Black", "White"))+
theme(panel.background = element_rect(fill="grey"))
Consistent with expectations, agents are initially not highly segregated:
t1plot
As long as individuals do not want to be the minority in their local neighborhood, the agents will have the desire to be in different local environments. So, after agents are allowed to move in accordance with their motivations, highly segregated neighborhoods do appear:
t2plot