This exercise explores a simple matrix population model representing a metapopulation composed of two habitat patches (A and B). Each patch has two stages: juveniles and adults. Patches are connected by juvenile dispersal, and each patch has its own survival and fecundity parameters.
We will explore how changing demographic rates and dispersal affects the population dynamics of the system and draw connections to conservation and source–sink dynamics.
If you’re not confident using R, don’t worry: you can copy and paste the code blocks below into your R console or RStudio. Any lines you are asked to modify will be clearly marked.
Before starting, make sure you have the following packages loaded.
library(ggplot2)
library(tidyr)
library(dplyr)
Copy and paste the entire code block below without changing anything. This defines the model with starting values:
# PARAMETERS YOU CAN MODIFY LATER ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
f_A <- 2.0 # Fecundity in Patch A
sJ_A <- 0.3 # Juvenile survival in Patch A
sA_A <- 0.6 # Adult survival in Patch A
f_B <- 1.2 # Fecundity in Patch B
sJ_B <- 0.1 # Juvenile survival in Patch B
sA_B <- 0.4 # Adult survival in Patch B
d_AB <- 0.1 # Juvenile dispersal from A to B ← You will change this in Exercise 2
d_BA <- 0.1 # Juvenile dispersal from B to A ← You will change this in Exercise 3
# ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
# Initial population (J_A, A_A, J_B, A_B)
n0 <- matrix(c(50, 50, 50, 50), nrow = 4, byrow = FALSE)
# Projection matrix M
M <- matrix(c(
0, f_A, 0, 0,
sJ_A*(1 - d_AB), sA_A*(1 - d_AB), 0, 0,
0, 0, 0, f_B,
sJ_A*d_AB, sA_A*d_AB, sJ_B*(1 - d_BA), sA_B*(1 - d_BA)
), nrow = 4, byrow = TRUE)
# Simulation settings
timesteps <- 20
history <- matrix(NA, nrow = 4, ncol = timesteps)
history[, 1] <- n0
for (t in 2:timesteps) {
history[, t] <- M %*% history[, t - 1]
}
# Convert to long format for plotting
df <- data.frame(
Time = 0:(timesteps - 1),
Juveniles_A = history[1, ],
Adults_A = history[2, ],
Juveniles_B = history[3, ],
Adults_B = history[4, ]
)
df_long <- df %>%
pivot_longer(cols = -Time, names_to = "Stage_Patch", values_to = "Count") %>%
separate(Stage_Patch, into = c("Stage", "Patch"), sep = "_")
Paste this code to generate a plot of how population sizes change over time.
ggplot(df_long, aes(x = Time, y = Count + 1e-6, colour = Stage, linetype = Patch)) +
geom_line(linewidth = 1.2) +
theme_minimal() +
labs(
x = "Time",
y = "Population Size (log scale)",
colour = "Stage",
linetype = "Patch"
) +
scale_y_continuous(trans = "log10", limits = c(5, NA)) #sets a lower limit on the graph
Instructions:
Draw a life-cycle diagram of the model - the species is modelled with two stages (Juvenile, Adult), and in two patches (A and B). Run the model exactly as provided above.
Questions:
Instructions: Modify this single line in the earlier code block:
d_AB <- 0.1 # Try changing this to 0, 0.3, 0.5
Then re-run the whole model code and the plot code.
Questions:
Instructions: Modify this line:
d_BA <- 0 # Set to 0 for one-way dispersal, or try 0.3 for symmetry
Then re-run the model and plot.
Questions:
Instructions: Modify these two lines:
f_A <- 1.0 # Reduce fecundity in Patch A (was 2.0)
sJ_A <- 0.15 # Reduce juvenile survival in Patch A (was 0.3)
Then re-run the model and the plot.
Questions:
Use these questions to pull together what you’ve learned from the exercises above. Think about the broader patterns and lessons, not just individual plots.