Skip to contents

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.

Usage

compute_invasion_fitness(
  I_raw = NULL,
  pressure_inv_site = NULL,
  r_mat = NULL,
  predictions = NULL,
  a_ij = NULL,
  Nstar = NULL,
  logistic_on = c("raw", "rel"),
  k = 1,
  x0 = NULL,
  prefer = c("logis", "rel", "raw", "scaled")
)

Arguments

I_raw

3D numeric array [invader, resident, site] from assemble_matrices(), or NULL if you pass pressure_inv_site instead.

pressure_inv_site

numeric matrix [invader, site] (sum over residents), optional alternative to I_raw.

r_mat

numeric matrix [invader, site] of invader growth on the response scale, or NULL if you pass predictions.

predictions

data.frame or NULL. Long table with columns species, site_id, pred. Used to build r_mat if r_mat is NULL.

a_ij

numeric matrix [invader, resident] of competition coefficients; required only for lambda_rel or for lambda_logis when logistic_on = "rel".

Nstar

numeric matrix [resident, site] of resident abundances; required for lambda_rel and for lambda_logis when logistic_on = "rel".

logistic_on

character. Use "raw" (default) to apply the logistic cap to C_raw; use "rel" to apply it to A %*% N_rel.

k

numeric. Logistic steepness parameter (default 1).

x0

numeric or NULL. Logistic midpoint. If NULL, set to median(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 (per prefer).

  • 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")