
Compute invasion fitness from competition/impact tensors and growth predictions
Source:R/compute_invasion_fitness.R
compute_invasion_fitness.Rd
Aggregates the site- and species-specific impact tensor to quantify the total competitive penalty experienced by each invader at each site, then computes several invasion-fitness formulations by subtracting competition penalties from predicted growth.
Arguments
- I_raw
3D numeric array
[invader, resident, site]
fromassemble_matrices()
, orNULL
if you passpressure_inv_site
instead.- pressure_inv_site
numeric matrix
[invader, site]
(sum over residents), optional alternative toI_raw
.- r_mat
numeric matrix
[invader, site]
of invader growth on the response scale, orNULL
if you passpredictions
.- predictions
data.frame or
NULL
. Long table with columnsspecies
,site_id
,pred
. Used to buildr_mat
ifr_mat
isNULL
.- a_ij
numeric matrix
[invader, resident]
of competition coefficients; required only forlambda_rel
or forlambda_logis
whenlogistic_on = "rel"
.- Nstar
numeric matrix
[resident, site]
of resident abundances; required forlambda_rel
and forlambda_logis
whenlogistic_on = "rel"
.- logistic_on
character. Use
"raw"
(default) to apply the logistic cap toC_raw
; use"rel"
to apply it toA %*% N_rel
.- k
numeric. Logistic steepness parameter (default
1
).- x0
numeric or
NULL
. Logistic midpoint. IfNULL
, set tomedian(C_target, na.rm = TRUE)
.- prefer
"logis"
|"rel"
|"raw"
|"scaled"
. Which fitness to return as$lambda
(default"logis"
).
Value
A list with components:
C_raw
[invader, site]
: total penalty summed over residents.r_mat
[invader, site]
: invader growth matrix.lambda_raw
,lambda_scaled
,lambda_rel
,lambda_logis
: fitness variants.lambda
: the selected fitness (perprefer
).meta
: data about inputs, dimensions, and chosen options.
Details
Let \(I_{i j s}\) be the per-pair impact at site \(s\) (e.g., from
assemble_matrices()
), with invader \(i\), resident \(j\). The total
competition penalty at each invader-site is
$$C_{i s} = \sum_{j} I_{i j s}.$$
Given a matrix of invader growth predictions \(r_{i s}\), we compute:
Raw: \(\lambda^{raw}_{i s} = r_{i s} - C_{i s}\).
Scaled: \(\lambda^{scaled}_{i s} = r_{i s} - C_{i s}/J\) \,(where \(J\) is the number of residents).
Relative-abundance: \(\lambda^{rel}_{i s} = r_{i s} - (A N^{rel})_{i s}\), where \(A = [a_{i j}]\) and \(N^{rel}_{j s} = N_{j s} / \sum_{j'} N_{j' s}\).
Logistic-capped: \(\lambda^{logis}_{i s} = r_{i s} - \frac{1}{1 + \exp\{-k\, (C^{*}_{i s} - x_{0})\}}\), with \(C^{*}_{i s}\) taken as either \(C_{i s}\) (raw) or \((A N^{rel})_{i s}\) (relative), selected via
logistic_on = "raw"
or"rel"
.
Examples
# --- Minimal, fully simulated example (base R only) ------------------------
set.seed(123)
# IDs
invaders <- paste0("sp", 1:3) # 3 invaders
residents <- paste0("r", 1:4) # 4 residents
sites <- paste0("s", 1:5) # 5 sites
# Competition coefficients a_ij (invader × resident), e.g. from a Gaussian of
# synthetic distances. Values in (0,1].
n_i <- length(invaders); n_j <- length(residents); n_s <- length(sites)
d_ij <- matrix(runif(n_i * n_j), nrow = n_i,
dimnames = list(invaders, residents))
sigma <- 0.4
a_ij <- exp(-(d_ij^2) / (2 * sigma^2))
# Resident abundances per site Nstar (resident × site), positive numbers
Nstar <- matrix(rexp(n_j * n_s, rate = 1), nrow = n_j,
dimnames = list(residents, sites))
# Build a simple impact tensor I_raw [invader, resident, site]:
# I_ijs = a_ij * Nstar[j, s]
I_raw <- array(NA_real_, dim = c(n_i, n_j, n_s),
dimnames = list(invaders, residents, sites))
for (s in seq_along(sites)) {
I_raw[, , s] <- a_ij * rep(Nstar[, s], each = n_i)
}
# Predicted growth on the response scale r_mat [invader, site]
r_mat <- matrix(rexp(n_i * n_s, rate = 1), nrow = n_i,
dimnames = list(invaders, sites))
# Compute invasion fitness (logistic cap applied to relative pressure A %*% N_rel)
fit <- compute_invasion_fitness(
I_raw = I_raw,
r_mat = r_mat,
a_ij = a_ij,
Nstar = Nstar,
logistic_on = "rel",
k = 1,
x0 = NULL,
prefer = "logis"
)
# Inspect the final fitness matrix [invader × site]
dim(fit$lambda); range(fit$lambda, na.rm = TRUE)
#> [1] 3 5
#> [1] -0.4682323 2.1860024
# Alternative variants:
# fit_raw <- compute_invasion_fitness(I_raw = I_raw, r_mat = r_mat, prefer = "raw")
# fit_scaled <- compute_invasion_fitness(I_raw = I_raw, r_mat = r_mat, prefer = "scaled")