(Corresponds to commit 4bd8422107 in earlywarning repo)
For the individual-based simulation, the population dynamics are given by
\[\begin{align} \frac{dP(n,t)}{dt} &= b_{n-1} P(n-1,t) + d_{n+1}P(n+1,t) - (b_n+d_n) P(n,t), \\ b_n &= \frac{e K n^2}{n^2 + h^2}, \\ d_n &= e n + a, \end{align}\]
which is provided by the saddle_node_ibm model in populationdynamics.
For each of the warning signal statistics in question, we need to generate the distibution over all replicates and then over replicates which have been selected conditional on having experienced a crash.
We begin by running the simulation of the process for all replicates.
Load the required libraries
library(populationdynamics)
library(earlywarning)
library(reshape2) # data manipulation
library(data.table) # data manipulation
library(ggplot2) # graphics
library(snowfall) # parallel
theme_publish <- theme_set(theme_bw(12))
theme_publish <-
theme_update(legend.key=theme_blank(),
panel.grid.major=theme_blank(),panel.grid.minor=theme_blank(),
plot.background=theme_blank(), legend.title=theme_blank())
Conditional distribution
Then we fix a set of paramaters we will use for the simulation function. Since we will simulate 20,000 replicates with 50,000 pts a piece, we can save memory by performing the conditional selection on the ones that cross a threshold we go along and disgard the others. (We will create a null distribution in which we ignore this conditional selection later).
threshold <- 250
select_crashes <- function(n){
T<- 5000
n_pts <- n
pars = c(Xo = 500, e = 0.5, a = 180, K = 1000, h = 200,
i = 0, Da = 0, Dt = 0, p = 2)
sn <- saddle_node_ibm(pars, times=seq(0,T, length=n_pts), reps=1000)
d <- dim(sn$x1)
crashed <- which(sn$x1[d[1],] <= threshold)
# crashed <- which(sn$x1[d[1],]==0)
sn$x1[,crashed]
}
A few extra commands format the data into a table with columns of times, replicate id number, and population value at the given time.
sfInit(parallel=FALSE)
sfLibrary(populationdynamics)
sfExportAll()
examples <- sfLapply(1:20, function(i) select_crashes(50000))
dat <- melt(as.matrix(as.data.frame(examples, check.names=FALSE)))
names(dat) = c("time", "reps", "value")
levels(dat$reps) <- 1:length(levels(dat$reps)) # use numbers for reps
ggplot(subset(dat, reps %in% levels(dat$reps)[1:9])) + geom_line(aes(time, value)) + facet_wrap(~reps, scales="free")

Zoom in on the relevant area of data near the crash
require(plyr)
zoom <- ddply(dat, "reps", function(X){
tip <- min(which(X$value<threshold))
index <- max(tip-200,1):tip
data.frame(time=X$time[index], value=X$value[index])
})
ggplot(subset(zoom, reps %in% levels(zoom$reps)[1:9])) + geom_line(aes(time, value)) + facet_wrap(~reps, scales="free")

Compute model-based warning signals on all each of these.
dt <- data.table(subset(zoom, value>threshold))
var <- dt[, warningtrend(data.frame(time=time, value=value), window_var), by=reps]$V1
acor <- dt[, warningtrend(data.frame(time=time, value=value), window_autocorr), by=reps]$V1
dat <- melt(data.frame(Variance=var, Autocorrelation=acor))
Null distribution
To compare against the expected distribution of these statistics, we create another set of simulations without conditioning on having experienced a chance transition, on which we perform the identical analysis.
threshold <- 250
select_crashes <- function(n){
T<- 5000
n_pts <- n
pars = c(Xo = 500, e = 0.5, a = 180, K = 1000, h = 200,
i = 0, Da = 0, Dt = 0, p = 2)
sn <- saddle_node_ibm(pars, times=seq(0,T, length=n_pts), reps=500)
d <- dim(sn$x1)
sn$x1[1:501,]
}
sfExportAll()
examples <- sfLapply(1:10, function(i) select_crashes(50000))
nulldat <- melt(as.matrix(as.data.frame(examples, check.names=FALSE)))
nulldat <- melt(examples)
names(nulldat) = c("time", "reps", "value")
levels(nulldat$reps) <- 1:length(levels(dat$reps))
Zoom in on the relevant area of data near the crash
require(plyr)
nullzoom <- ddply(nulldat, "reps", function(X){
data.frame(time=X$time, value=X$value)
})
nulldt <- data.table(nullzoom)
nullvar <- nulldt[, warningtrend(data.frame(time=time, value=value), window_var), by=reps]$V1
nullacor <- nulldt[, warningtrend(data.frame(time=time, value=value), window_autocorr), by=reps]$V1
nulldat <- melt(data.frame(Variance=nullvar, Autocorrelation=nullacor))
ggplot(dat) + geom_histogram(aes(value, y=..density..), binwidth=0.3, alpha=.5) +
facet_wrap(~variable) + xlim(c(-1, 1)) +
geom_density(data=nulldat, aes(value), adjust=2) + xlab("Kendall's tau") + theme_bw()
