Week 11
Lecture in a nutshell
(Continued from Week 10)
- Model 2. Logistic growth of prey + Type I functional response
- Model equations:
\(\begin{align}\frac {dN}{dt} = rN(1-\frac{N}{K})-aNP\end{align}\\\)\(\begin{align}\frac {dP}{dt} = eaNP-dP\end{align}\)
- The equilibrium points \((N^{*}, P^{*})\):
- \(E_{0} = (0, 0)\)
- \(E_{N} = (K, 0)\)
- \(E_{NP} = (\frac{d}{ea}, \frac{r}{a}(1-\frac{d}{eak}))\)
- Local stability analysis:
- \(E_{0}\)
- \(J_{E_{0}} = \begin{vmatrix}r & 0 \\ 0 & -d\end{vmatrix}\)
- \(\lambda's = r\) and \(-d\) (one positive and one negative)
- Unstable
- \(E_{N}\)
- \(J_{E_{N}} = \begin{vmatrix}-r & -aK \\ 0 & eaK-d\end{vmatrix}\)
- \(\lambda's = -r\) and \(eaK-d\)
- Stable if \(eaK < d~(K < \frac{d}{ea})\)
- \(E_{NP}\)
- \(J_{E_{NP}} = \begin{vmatrix}-\frac{rd}{eaK} & -\frac{d}{e} \\ eaP^{*} & 0\end{vmatrix}\)
- Characteristic equation: \(\lambda^{2} - (\frac{rd}{eaK})\lambda + adP^{*} = 0\)
- \(\lambda_{1} + \lambda_{2} = -\frac{rd}{eaK} < 0~\&~\lambda_{1}\lambda_{2} = adP^{*} > 0\)
- Stable if \(P^{*} > 0\) (feasibility) and \(K > \frac{d}{ea}\)
- \(E_{0}\)
- Model equations:
- Model 3. Exponential growth of prey + Type II functional response
- Model equations:
\(\begin{align}\frac {dN}{dt} = rN-(\frac{aN}{1+ahN})P\end{align}\\\)\(\begin{align}\frac {dP}{dt} = e(\frac{aN}{1+ahN})P-dP\end{align}\)
- Internal equilibrium is unstable (oscillations with increasing amplitude)
- Model equations:
- Model 4. Logistic growth of prey + Type II functional response
- Model equations:
\(\begin{align}\frac {dN}{dt} = rN(1-\frac{N}{K})-(\frac{aN}{1+ahN})P\end{align}\\\)\(\begin{align}\frac {dP}{dt} = e(\frac{aN}{1+ahN})P-dP\end{align}\)
- The equilibrium points \((N^{*}, P^{*})\):
- \(E_{0} = (0, 0)\)
- \(E_{N} = (K, 0)\)
- \(E_{NP} = (\frac{d}{a(e-dh)}, \frac{r}{a}(1-\frac{d}{a(e-dh)k})(1+ah\frac{d}{a(e-dh)}))\)
- Local stability analysis:
- \(E_{0}\)
- \(J_{E_{0}} = \begin{vmatrix}r & 0 \\ 0 & -d\end{vmatrix}\)
- \(\lambda's = r\) and \(-d\)
- Unstable
- \(E_{N}\)
- \(J_{E_{N}} = \begin{vmatrix}-r & \frac{-aK}{1+ahK} \\ 0 & \frac{eaK}{1+ahK}-d\end{vmatrix}\)
- \(\lambda's = -r\) and \(\frac{eaK}{1+ahK}-d\)
- Stable if \((K < \frac{d}{a(e-dh)})\)
- \(E_{NP}\)
- \(J_{E_{NP}} = \begin{vmatrix}N^{*}(\frac{-r}{K}+\frac{a^{2}hP^{*}}{(1+ahN^{*})^{2}}) & -\frac{aN^{*}}{1+ahN^{*}} \\ \frac{eaP^{*}}{(1+ahN^{*})^{2}} & 0\end{vmatrix}\)
- Characteristic equation: \(\lambda^{2} - N^{*}(\frac{-r}{K}+\frac{a^{2}hP^{*}}{(1+ahN^{*})^{2}})\lambda + \frac{ea^{2}N^{*}P^{*}}{(1+ahN^{*})^{3}} = 0\)
- If feasible (\(N^{*}, P^{*} > 0\)), \(E_{NP}\) is stable if \(\frac{-r}{K}+\frac{a^{2}hP^{*}}{(1+ahN^{*})^{2}} < 0\) (or \(N^{*} > \frac{-1+ahk}{2ah}\))
- Paradox of enrichment: increasing the carrying capacity K of prey will destabilize the system
- Poincaré–Bendixson theorem: the trajectory must exhibit sustained periodic motion in a bounded 2D state-space if there is no equilibrium within.
- \(E_{0}\)
- Model equations:
Lab demonstration
Similar to what we’ve done in the previous class, in this lab we are going to analyze the Rosenzweig–MacArthur predator–prey model:
Please simulate the model using the parameter set (N = 5, P = 2, r = 1.0, K = 5.0, a = 1.3, h = 0.9, e = 0.6, d = 0.5) and plot the population trajectories of predator and prey as well as show their population dynamics in the state-space diagram.
What will happen if you add a perturbation to the system (i.e., change the initial conditions)? Try out different values of N and P and visualize the differences in the state-space diagram. Also compare the results of the Rosenzweig–MacArthur model and the original Lotka-Volterra model. What do you find regarding the final equilibrium cycles?
library(tidyverse)
library(deSolve)
### Model specification
<- function(times, state, parms) {
RM_predation_model with(as.list(c(state, parms)), {
= r*N*(1-(N/K))-(a*N/(1+a*h*N))*P
dN_dt = e*(a*N/(1+a*h*N))*P-d*P
dP_dt return(list(c(dN_dt, dP_dt)))
})
}
### Model parameters
<- seq(0, 200, by = 0.01)
times <- c(N = 5, P = 2)
state <- c(r = 1.0, K = 5.0, a = 1.3, h = 0.9, e = 0.6, d = 0.5)
parms
### Model application
<- ode(func = RM_predation_model, times = times, y = state, parms = parms)
pop_size
### Visualize the population dynamics
# (1) population trajectories
%>%
pop_size as.data.frame() %>%
pivot_longer(cols = -time, names_to = "species", values_to = "N") %>%
ggplot(aes(x = time, y = N, color = species)) +
geom_line(size = 1.5) +
theme_classic(base_size = 12) +
labs(x = "Time", y = "Population size") +
scale_x_continuous(limits = c(0, 200.5), expand = c(0, 0)) +
scale_y_continuous(limits = c(0, max(pop_size[, -1])*1.2), expand = c(0, 0)) +
scale_color_brewer(name = NULL, palette = "Set1", labels = c("Prey", "Predator"), direction = -1)
# (2) state-space diagram
%>%
pop_size as.data.frame() %>%
ggplot(aes(x = N, y = P)) +
geom_path() +
geom_vline(xintercept = with(as.list(parms), d/(e*a-a*d*h)), color = "#E41A1C", size = 1) +
geom_function(data = data.frame(x = seq(0, 5, 0.01)), aes(x = x), fun = function(n){with(as.list(parms), r*(1+a*h*n)*(1-n/K)/a)}, inherit.aes = F, color = "#377EB8", size = 1) +
geom_point(aes(x = tail(N, 1), y = tail(P, 1)), size = 2) +
theme_classic(base_size = 14) +
theme(axis.line.x = element_line(color = "#E41A1C", size = 1),
axis.line.y = element_line(color = "#377EB8", size = 1)) +
labs(x = "Prey", y = "Predator") +
scale_x_continuous(limits = c(0, max(pop_size[, "N"]*1.05)), expand = c(0, 0)) +
scale_y_continuous(limits = c(0, max(pop_size[, "P"]*1.05)), expand = c(0, 0))
Special topic: time-scale separation
Time-scale separation is a useful technique to reduce the dimension of the model system, where some state variables are assumed to operate at a much shorter time scale (i.e., fast variables) compared with the others (i.e., slow variables). The fast variables will adjust rapidly to their new equilibria in response to a slight change in the slow variables, such that the slow variables can be viewed as “constants” from the perspective of fast variables.
Here, we are going to use the Lotka-Volterra model with logistic prey growth to demonstrate time-scale separation:
We will treat prey as a fast variable and predator as a slow variable. First, we find the quasi-equilibrium \(N^{\wedge}\) of prey by setting the prey equation to zero:
And then we plug \(N^{\wedge}\) into predator equation:
What do you see in the above equation? It is actually a logistic growth model! So under time-scale separation, predator will exhibit logistic population growth. We will show this shortly in the code below.
One simple way to achieve time-scale separation in this model is to increase the prey growth rate so that prey will grow much faster than predator, mimicking the shorter generation time of prey relative to that of predator.
library(tidyverse)
library(deSolve)
<- function(times, state, parms) {
Prey_logistic_model with(as.list(c(state, parms)), {
= r*N*(1-(N/K))-a*N*P
dN_dt = e*a*N*P-d*P
dP_dt return(list(c(dN_dt, dP_dt)))
})
}
<- seq(0, 100, by = 0.01)
times <- c(N = 40, P = 20)
state <- c(r = 40.0, K = 60, a = 0.1, e = 0.1, d = 0.5) # r is chosen to be sufficiently large for time-scale separation
parms
<- ode(func = Prey_logistic_model, times = times, y = state, parms = parms)
pop_size
# population trajectories
%>%
pop_size as.data.frame() %>%
pivot_longer(cols = -time, names_to = "species", values_to = "N") %>%
ggplot(aes(x = time, y = N, color = species)) +
geom_line(size = 1.5) +
theme_classic(base_size = 12) +
labs(x = "Time", y = "Population size") +
scale_x_continuous(limits = c(0, 100.5), expand = c(0, 0)) +
scale_y_continuous(limits = c(0, max(pop_size[, -1])*1.2), expand = c(0, 0)) +
scale_color_brewer(name = NULL, palette = "Set1", labels = c("Prey", "Predator"), direction = -1)
# state-space diagram
%>%
pop_size as.data.frame() %>%
ggplot(aes(x = N, y = P)) +
geom_point(color = "grey60", size = 3, shape = 21) +
geom_vline(xintercept = with(as.list(parms), d/(e*a)), color = "#E41A1C", size = 1) +
geom_abline(slope = with(as.list(parms), -r/(a*K)),
intercept = with(as.list(parms), r/a),
color = "#377EB8", size = 1) +
geom_point(aes(x = with(as.list(parms), d/(e*a)),
y = with(as.list(parms), -r/(a*K)*d/(e*a) + r/a)),
size = 4) +
theme_classic(base_size = 14) +
theme(axis.line.x = element_line(color = "#E41A1C", size = 1),
axis.line.y = element_line(color = "#377EB8", size = 1)) + labs(x = "Prey", y = "Predator") +
scale_y_continuous(limits = c(NA, 100))
If we solve for the new predator growth equation derived under time-scale separation using the same parameter set and visualize the population trajectory, we will get almost exactly the same predator growth pattern as that in the original model.
<- function(times, state, parms) {
Time_scale_logistic with(as.list(c(state, parms)), {
= (e*a*K-d)*P*(1-((e*a*K*(a/r))/(e*a*K-d))*P)
dP_dt return(list(c(dP_dt)))
})
}
<- seq(0, 100, by = 0.1)
times <- c(N = 40, P = 20)
state <- c(P = 20)
state_timescale <- c(r = 40.0, K = 60, a = 0.1, e = 0.1, d = 0.5) # r is chosen to be sufficiently large for time-scale separation
parms
<- ode(func = Prey_logistic_model, times = times, y = state, parms = parms)
pop_size_original <- ode(func = Time_scale_logistic, times = times, y = state_timescale, parms = parms)
pop_size_timescale
# plot the two predator population trajectories in the same figure
%>%
pop_size_timescale as.data.frame() %>%
mutate(P_original = pop_size_original[, "P"]) %>%
rename(P_timescale = P) %>%
pivot_longer(cols = -time, names_to = "model", values_to = "n") %>%
ggplot(aes(x = time, y = n, color = model)) +
geom_point(size = 2.5, alpha = 0.8, shape = 21) +
theme_classic(base_size = 14) +
labs(x = "Time", y = "Population size") +
scale_x_continuous(limits = c(0, 100.5), expand = c(0, 0)) +
scale_y_continuous(limits = c(0, max(pop_size_timescale[, -1])*1.2), expand = c(0, 0)) +
scale_color_brewer(name = NULL, palette = "Set2", labels = c("Original", "Time-scale"))
When you gradually shift r from small to large values, you can see that the population dynamics of predator and prey change quite dramatically. Some interesting patterns will arise!
Additional readings
No additional readings this week.
Assignments
No assignments this week.