Lotka-Volterra’s Predator–Prey Model
Overview
This document focuses on illustrating the Lotka-Volterra’s model, originally developed by Alfred J. Lotka (1925) and Vito Volterra (1926), to describe the dynamics of biological systems where two species interact: one as a predator and the other as prey.
The dynamics of the model are represented by the following set of first-order, nonlinear differential equations:
\[ \begin{aligned} \frac{dx}{dt} & = \alpha x - \beta xy \\ \frac{dy}{dt} & = - \gamma y + \delta xy \end{aligned} \]
where:
- \(x\) and \(y\) are the populations of the prey and predator, respectively;
- \(\alpha\) and \(\delta\) are the prey per capita growth rate and the effect of the presence of prey on the predator’s growth rate, respectively;
- \(\beta\) and \(\gamma\) are the effect of the presence of predators on the prey death rate and predator’s per capita death rate, respectively.
Setting up the environment
Numerical solution of the equations
Code
lotka_volterra <- function(
x = 0.9,
y = 1.8,
alpha = 2 / 3,
beta = 4 / 3,
gamma = 1,
delta = 1,
from = 0,
to = 100,
by = 0.01
) {
checkmate::assert_number(x, lower = 0)
checkmate::assert_number(y, lower = 0)
checkmate::assert_number(alpha)
checkmate::assert_number(beta)
checkmate::assert_number(gamma)
checkmate::assert_number(delta)
checkmate::assert_number(from, lower = 0)
checkmate::assert_number(to, lower = from)
checkmate::assert_number(by, lower = 0)
fun <- function (t, y, parms) {
list2env(as.list(y), envir = environment())
list2env(as.list(parms), envir = environment())
list(
c(
dx = (alpha * x) - (beta * x * y), # Prey
dp = (- gamma * y) + (delta * x * y) # Predator
)
)
}
initial_values <- c(x = x, y = y)
parameters <- list(alpha = alpha, beta = beta, gamma = gamma, delta = delta)
time <- seq(from = from, to = to, by = by)
data <-
deSolve::ode(
y = initial_values,
times = time,
func = fun,
parms = parameters
) |>
dplyr::as_tibble() |>
dplyr::mutate(dplyr::across(dplyr::everything(), ~ as.numeric(.x)))
list(
data = data,
initial_values = as.list(initial_values),
parameters = parameters
) |>
invisible()
}
Code
lotka_volterra() |> magrittr::extract2("data")
#> # A tibble: 10,001 × 3
#> time x y
#> <dbl> <dbl> <dbl>
#> 1 0 0.9 1.8
#> 2 0.01 0.885 1.80
#> 3 0.02 0.869 1.80
#> 4 0.03 0.855 1.79
#> 5 0.04 0.840 1.79
#> 6 0.05 0.826 1.79
#> # ℹ 9,995 more rows
Plotting population dynamics
Code
plot_pop_dynamics <- function(
x = 0.9,
y = 1.8,
alpha = 2 / 3,
beta = 4 / 3,
gamma = 1,
delta = 1,
from = 0,
to = 100,
by = 0.01
) {
checkmate::assert_number(x, lower = 0)
checkmate::assert_number(y, lower = 0)
checkmate::assert_number(alpha)
checkmate::assert_number(beta)
checkmate::assert_number(gamma)
checkmate::assert_number(delta)
checkmate::assert_number(from, lower = 0)
checkmate::assert_number(to, lower = from)
checkmate::assert_number(by, lower = 0)
lotka_volterra(x, y, alpha, beta, gamma, delta, from, to, by) |>
list2env(envir = environment())
plot <-
data |>
ggplot2::ggplot(ggplot2::aes(x = time)) +
ggplot2::geom_line(
ggplot2::aes(y = x, color = "Prey"),
linewidth = 0.75
) +
ggplot2::geom_line(
ggplot2::aes(y = y, color = "Predator"),
linetype = "dashed",
linewidth = 0.75
) +
ggplot2::labs(
title = "Lotka-Volterra's Model Population Dynamics",
subtitle = latex2exp::TeX(
paste0(
"$X_0$ = ", initial_values$x, " | ",
"$Y_0$ = ", initial_values$y, " | ",
"$\\alpha$ = ", round(parameters$alpha, 2), " | ",
"$\\beta$ = ", round(parameters$beta, 2), " | ",
"$\\gamma$ = ", round(parameters$gamma, 2), " | ",
"$\\delta$ = ", round(parameters$delta, 2)
),
),
x = "Time",
y = "Population",
color = ggplot2::element_blank()
) +
ggplot2::scale_color_manual(
breaks = c("Prey", "Predator"),
values = c("blue", "red")
)
print(plot)
invisible()
}
Code
plot_pop_dynamics()
Phase space visualization
Code
plot_phase_space <- function(
x = 0.9,
y = 1:5,
alpha = 2 / 3,
beta = 4 / 3,
gamma = 1,
delta = 1,
from = 0,
to = 100,
by = 0.01
) {
checkmate::assert_number(x, lower = 0)
checkmate::assert_numeric(y, lower = 0)
checkmate::assert_number(alpha)
checkmate::assert_number(beta)
checkmate::assert_number(gamma)
checkmate::assert_number(delta)
checkmate::assert_number(from, lower = 0)
checkmate::assert_number(to, lower = from)
checkmate::assert_number(by, lower = 0)
plot <-ggplot2::ggplot()
for (i in y) {
data_i <-
lotka_volterra(x, i, alpha, beta, gamma, delta, from, to, by) |>
magrittr::extract2("data") |>
dplyr::mutate(color = as.character(i))
plot <-
plot +
ggplot2::geom_path(
data = data_i,
ggplot2::aes(x = x, y = y, color = color),
linewidth = 0.75
)
}
colors <- gg_color_hue(length(y))
names(colors) <- as.character(y)
plot <-
plot +
ggplot2::labs(
title = "Lotka-Volterra's Model Phase-Space",
subtitle = latex2exp::TeX(
paste0(
"$X_0$ = ", x, " | ",
"$\\alpha$ = ", round(alpha, 2), " | ",
"$\\beta$ = ", round(beta, 2), " | ",
"$\\gamma$ = ", round(gamma, 2), " | ",
"$\\delta$ = ", round(delta, 2)
),
),
x = "Prey",
y = "Predator"
) +
scale_color_manual(name = latex2exp::TeX("$Y_0$"), values = colors)
print(plot)
invisible()
}
Code
plot_phase_space()
References
Lotka, A. J. (1925). Elements of physical biology. Williams & Wilkins Company. http://archive.org/details/elementsofphysic017171mbp
Volterra, V. (1926). Fluctuations in the abundance of a species considered mathematically. Nature, 118(2972), 558–560. https://doi.org/10.1038/118558a0