Nothing
# Functions for simulations and calculations involving Poisson processes.
hpp.event.times <- function(rate, num.events, num.sims=1, t0=0) {
# Simulate homogeneous Poisson process event times.
#
# Get the n consecutive event times of an homogeneous poisson process with given rate.
# Note: the rate parameter is often referred to as lambda.
#
# Params
# :rate: the rate at which events occur in the Poisson process, aka lambda
# :num.events: number of event times to simulate in each process
# :num.sims: number of simulated paths to create
# :t0: start time
#
# Returns:
# a numeric vector of length num.events if num.sims=1
# else, a num.events * num.sims matrix [num.events+1 is prepend.zero=T]
if(num.sims==1) {
return(t0 + cumsum(rexp(n=num.events, rate=rate)))
}
else {
x = matrix(rexp(n=num.events*num.sims, rate=rate), num.events)
return(t0 + apply(x, 2, cumsum))
}
}
hpp.sim <- function(rate, num.events, num.sims=1, t0=0, prepend.t0=T) {
# Simulate homogeneous Poisson process(es).
#
# Get the n consecutive event times of an homogeneous poisson process with given rate.
# Note: the rate parameter is often referred to as lambda.
#
# Params
# :rate: the rate at which events occur in the Poisson process, aka lambda
# :num.events: number of event times to simulate in each process
# :num.sims: number of simulated paths to create
# :t0: start time
# :prepend.t0: TRUE to include t0 at the start of the process
#
# Returns:
# a numeric vector of length num.events if num.sims=1
# else, a num.events * num.sims matrix [num.events+1 is prepend.zero=T]
if(num.sims==1) {
x = hpp.event.times(rate, num.events, num.sims=1, t0=t0)
if(prepend.t0)
return(c(t0, x))
else
return(x)
}
else {
x = hpp.event.times(rate, num.events, num.sims=num.sims, t0=t0)
if(prepend.t0)
return(rbind(rep(t0, num.sims), x))
else
return(x)
}
}
hpp.mean <- function(rate, t0=0, t1=1, num.points=100, maximum=NULL) {
# Calculate the expected value of an homogeneous Poisson process at points in time.
#
# Params
# :rate: the rate at which events occur in the Poisson process, aka lambda
# :t0: start time
# :t1: end time
# :num.points: number of points between t0 and t1 to use in estimating mean
# :maximum: the optional maximum value that the process should take
times = seq(t0, t1, length.out=num.points)
x = rate*times
if(is.null(maximum))
return(x)
else
return(pmin(x, maximum))
}
hpp.mean.event.times <- function(rate, num.events) {
# Calculate the expected event times of an homogeneous Poisson process.
#
# Params
# :rate: the rate at which events occur in the Poisson process, aka lambda
# :num.events: observe mean event times at this many points
return(seq(from=1/rate, length.out=num.events, by=1/rate))
}
hpp.plot <- function(rate, num.events, num.sims=100, t0=0, t1=NULL,
num.points=100, quantiles=c(0.025, 0.975), ...) {
# Plot num.events simulated homogeneous Poisson processes, plus
# the mean and quantiles
#
# Params
# :rate: the rate at which events occur in the Poisson process, aka lambda
# :num.events: number of event times to simulate in each process
# :num.sims: number of simulated paths to plot
# :t0: plot start time
# :t1: plot end time
# :num.points: number of points to use in estimating mean and quantile processes
# :quantiles: plot these quantile processes
x = hpp.sim(rate, num.events, num.sims)
if(is.null(t1))
t1 = 1.1*max(x)
plotprocesses(x, xlim=c(t0, t1), ...)
# Expected value process
x.bar = hpp.mean(rate, t0, t1, num.points, maximum=num.events)
lines(seq(t0, t1, length.out=num.points), x.bar, col='darkorange1', lwd=2)
# Quantile processes
x.q = t(apply(x, 1, function(x) quantile(x, probs=quantiles)))
plotprocesses(x.q, col='red', lwd=2, lty=3, add=T)
return(list(x=x, x.bar=x.bar, x.q=x.q))
}
nhpp.event.times <- function(rate, num.events, prob.func, num.sims=1, t0=0) {
# Simulate non-homogeneous Poisson process event times.
#
# Get the n consecutive event times of a non-homogeneous poisson process.
# Events are simulated using an homogeneous process with rate,
# and an event at time t is admitted with probability prob.func(t).
# This method, called 'thinning' by Lewis & Shedler (1978) is described in
# Simulation of Non-Homogeneous Poisson Processes by Thinning
# The rate parameter of an homogeneous process is often called lambda.
#
# Params
# :rate: the rate at which events occur in the equivalent homogeneous
# Poisson process, aka lambda
# :num.events: number of event times to simulate in each process
# :prob.func: function that takes time as sole argument and returns value between 0 and 1
# :num.sims: number of simulated paths to create
# :t0: the reference start time of all events
#
# Returns:
# a numeric vector of length num.events if num.sims=1
# else, a num.events * num.sims matrix [num.events+1 is prepend.zero=T]
n <- num.events
if(n<=0) return(c())
if(num.sims==1) {
# As a first attempt, take 2n homogeneous events
times = hpp.event.times(rate, 2*n, t0=t0)
# and accept each event with time-varying probability, determined by prob.func
prob.accept = prob.func(times)
rands = runif(2*n)
accept = rands < prob.accept
if(sum(accept) >= n) {
# We have enough events to accept
returnable = times[accept][1:n]
return(returnable)
}
else {
# We need more events
extra = hpp.event.times(rate, n-sum(accept), num.sims=1, t0=max(times))
returnable = c(times[accept], extra)
return(returnable)
}
}
else {
f = function(x) nhpp.event.times(rate, num.events, prob.func, num.sims=1, t0=t0)
return(sapply(1:num.sims, f))
}
}
nhpp.sim <- function(rate, num.events, prob.func, num.sims=1, t0=0, prepend.t0=T) {
# Simulate non-homogeneous Poisson process(es).
#
# Get the n consecutive event times of a non-homogeneous poisson process.
# Events are simulated using an homogeneous process with rate,
# and an event at time t is admitted with probability prob.func(t).
# This method, called 'thinning' by Lewis & Shedler (1978) is described in
# Simulation of Non-Homogeneous Poisson Processes by Thinning
# The rate parameter of an homogeneous process is often called lambda.
#
# Params
# :rate: the rate at which events occur in the equivalent homogeneous
# Poisson process, aka lambda
# :num.events: number of event times to simulate in each process
# :prob.func: function that takes time as sole argument and returns value between 0 and 1
# :num.sims: number of simulated paths to create
# :t0: the reference start time of all events
# :prepend.t0: T to include t0 at the start of the process
#
# Returns:
# a numeric vector of length num.events if num.sims=1
# else, a num.events * num.sims matrix [num.events+1 is prepend.zero=T]
if(num.sims==1) {
x = nhpp.event.times(rate, num.events, prob.func=prob.func, num.sims=1, t0=t0)
if(prepend.t0)
return(c(t0, x))
else
return(x)
}
else {
x = nhpp.event.times(rate, num.events, prob.func=prob.func, num.sims=num.sims, t0=t0)
if(prepend.t0)
return(rbind(rep(t0, num.sims), x))
else
return(x)
}
}
# A slower but easier to understand (e.g. non-recursive) version of nhpp.sim
nhpp.sim.slow <- function(rate, num.events, prob.func, num.sims=1, t0=0, prepend.t0=T) {
# Simulate a non-homogeneous Poisson process.
#
# Get the n consecutive event times of a non-homogeneous poisson process.
# Events are simulated using an homogeneous process with rate,
# and an event at time t is admitted with probability prob.func(t).
# This method, called 'thinning' by Lewis & Shedler (1978) is described in
# Simulation of Non-Homogeneous Poisson Processes by Thinning
# The rate parameter of an homogeneous process is often called lambda.
#
# Params
# :rate: the rate at which events occur in the equivalent homogeneous
# Poisson process, aka lambda
# :num.events: number of event times to simulate in each process
# :prob.func: function that takes time as sole argument and returns value between 0 and 1
# :num.sims: number of simulated paths to create
# :t0: the reference start time of all events
# :prepend.t0: T to include t0 at the start of the process
#
# Returns:
# a numeric vector of length num.events if num.sims=1
# else, a num.events * num.sims matrix
if(num.sims==1) {
i=0; t=t0
times = numeric(length=num.events)
while(i < num.events) {
tau = rexp(n=1, rate=rate)
t.new = t + tau
if(runif(1) < prob.func(t.new)) {
i = i + 1
times[i] = t.new
}
t = t.new
}
if(prepend.t0)
return(c(t0, times))
else
return(times)
}
else {
f = function(x) nhpp.sim.slow(rate, num.events, prob.func)
return(sapply(1:num.sims, f))
}
}
nhpp.mean <- function(rate, prob.func, t0=0, t1=1, num.points=100,
maximum=NULL) {
# Calculate the expected value of a non-homogeneous Poisson process at points in time.
#
# Params
# :rate: the rate at which events occur in the Poisson process, aka lambda
# :prob.func: function that takes time as sole argument and returns value between 0 and 1
# :t0: start time
# :t1: end time
# :num.points: number of points between t0 and t1 to use in estimating mean
# :maximum: the optional maximum value that the process should take
f <- function(x) rate * prob.func(x)
times = seq(t0, t1, length.out=num.points)
y = sapply(times, function(x) integrate(f, lower=0, upper=x)$value)
if(is.null(maximum))
return(y)
else
return(pmin(y, maximum))
}
nhpp.mean.event.times <- function(rate, num.events, prob.func, max.time=1000) {
# Calculate the expected event times of a non-homogeneous Poisson process.
#
# Params
# :rate: the rate at which events occur in the Poisson process, aka lambda
# :num.events: calculate the event times for this many events
# :prob.func: function that takes time as sole argument and returns value between 0 and 1
# :max.time: the maximum time needs to be specified to act as upper bound in the
# solver routine. I would like to remove the need to set this variable
# but for now I use the arbitrarily high value of 1000...
t0=0
times = c()
f <- function(x) rate * prob.func(x)
for(i in 1:num.events) {
t1 = uniroot(function(x) integrate(f, lower=t0, upper=x)$value - 1,
lower=t0, upper=max.time)$root
times = c(times, t1)
t0 = t1
}
return(times)
}
nhpp.plot <- function(rate, num.events, prob.func, num.sims=100,
t0=0, t1=NULL, num.points=100,
quantiles=c(0.025, 0.975), ...) {
# Plot num.events simulated homogeneous Poisson process, plus
# the mean and quantiles
# Params
# :rate: the rate at which events occur in the Poisson process, aka lambda
# :num.events: number of event times to simulate in each process
# :prob.func: function that takes time as sole argument and returns value between 0 and 1
# :num.sims: number of simulated paths to plot
# :t0: plot start time
# :t1: plot end time
# :num.points: number of points to use in estimating mean and quantile processes
# :quantiles: plot these quantile processes
x = nhpp.sim(rate, num.events, prob.func, num.sims)
if(is.null(t1))
t1 = 1.1*max(x)
plotprocesses(x, xlim=c(t0, t1), ...)
# Expected value process
x.bar = nhpp.mean(rate, prob.func, t0, t1, num.points, maximum=num.events)
lines(seq(t0, t1, length.out=num.points), x.bar, col='darkorange1', lwd=2)
# Quantile processes
x.q = t(apply(x, 1, function(x) quantile(x, probs=quantiles)))
plotprocesses(x.q, col='red', lwd=2, lty=3, add=T)
return(list(x=x, x.bar=x.bar, x.q=x.q))
}
# Inference
nhpp.lik <- function(x, T1, rate, prob.func) {
# TODO: explain
lambda.func = function(x) rate * prob.func(x)
expectation = integrate(lambda.func, lower=0, upper=T1)$value
return(sum(log(lambda.func(x))) - expectation)
}
hpp.lik <- function(x, T1, rate) {
# Get the likelihood of a rate parameter at a specific time for observed HPP event times.
# Params
# :x: a vector of HPP event times
# :T1: Calculate likelihood at this time
# :rate: the putative HPP event rate
return(nhpp.lik(x, T1, rate, prob.func=function(x) rep(1, length(x))))
}
hpp.mle <- function(x, T1) {
# Get the maximum-likelihood rate parameter for given HPP event times.
# Params
# :x: a vector of HPP event times
# :T1: Calculate MLE at this time
return(length(x) / T1)
}
nhpp.mle <- function(x, T1, prob.func, max.val) {
# TODO: explain
opt.f = function(z) nhpp.lik(x, T1, rate=z, prob.func=prob.func)
return(optimize(opt.f, interval=c(0, max.val), maximum=T)$maximum)
}
# Plotting
plotprocesses = function(x, y=NULL, xlab='t (years)', ylab='N', type='l', lty=2, col='cadetblue3', xlim=c(0, 1.1*max(x)),
lwd=0.5, add=F, ...) {
# TODO: explain
if(is.null(y))
y = 0:(dim(x)[1]-1)
matplot(x, y, xlab=xlab, ylab=ylab, type=type, lty=lty, col=col, xlim=xlim, lwd=lwd, add=add, ...)
}
# Object-oriented approach
setClass("PoissonProcessScenario",
representation(x="matrix", x.bar="numeric", x.bar.index="numeric", x.q="matrix"),
prototype(x=matrix(), x.bar=numeric(), x.bar.index=numeric(), x.q=matrix())
)
setMethod("plot" , "PoissonProcessScenario",
function(x, plot.mean=T, plot.quantiles=T, ...) {
# Plot simulated processes
plotprocesses(x@x, ...)
# Plot mean process
if(plot.mean)
lines(x@x.bar.index, x@x.bar, col='darkorange1', lwd=2)
# Plot quantile processes
if(plot.quantiles)
plotprocesses(x@x.q, col='red', lwd=2, lty=3, add=T)
}
)
setMethod ("show", "PoissonProcessScenario",
function(object) {
cat(dim(object@x), "\n")
cat("\n")
}
)
hpp.scenario <- function(rate, num.events, num.sims=100, t0=0, t1=NULL,
num.points=100, quantiles=c(0.025, 0.975), ...) {
# Simulate an homogeneous Poisson process scenario, with sample paths,
# expected value process, and quantile processes.
#
# Params
# :rate: the rate at which events occur in the Poisson process, aka lambda
# :num.events: number of event times to simulate in each process
# :num.sims: number of simulated paths to plot
# :t0: start time of processes
# :t1: end time of mean process, inferred automiatically when NULL (default)
# :num.points: number of points to use in estimating mean process
# :quantiles: calculate these quantile processes
# Simulated processes
x = hpp.sim(rate, num.events, num.sims, t0=t0, ...)
if(is.null(t1))
t1 = 1.1*max(x)
# Expected value process
x.bar = hpp.mean(rate, t0=t0, t1=t1, num.points=num.points, maximum=num.events)
# Quantile processes
x.q = t(apply(x, 1, function(x) quantile(x, probs=quantiles)))
return(
new("PoissonProcessScenario", x=x, x.bar=x.bar,
x.bar.index=seq(t0, t1, length.out=num.points), x.q=x.q)
)
}
nhpp.scenario <- function(rate, num.events, prob.func, num.sims=100, t0=0, t1=NULL,
num.points=100, quantiles=c(0.025, 0.975), ...) {
# Simulate a non-homogeneous Poisson process scenario, with sample paths,
# expected value process, and quantile processes.
#
# Params
# :rate: the rate at which events occur in the Poisson process, aka lambda
# :num.events: number of event times to simulate in each process
# :num.sims: number of simulated paths to plot
# :t0: start time of processes
# :t1: end time of mean process, inferred automiatically when NULL (default)
# :num.points: number of points to use in estimating mean process
# :quantiles: calculate these quantile processes
# Simulated processes
x = nhpp.sim(rate, num.events, prob.func, num.sims=num.sims, t0=t0, ...)
if(is.null(t1))
t1 = 1.1*max(x)
# Expected value process
x.bar = nhpp.mean(rate, prob.func, t0=t0, t1=t1, num.points=num.points, maximum=num.events)
# Quantile processes
x.q = t(apply(x, 1, function(x) quantile(x, probs=quantiles)))
return(
new("PoissonProcessScenario", x=x, x.bar=x.bar,
x.bar.index=seq(t0, t1, length.out=num.points), x.q=x.q)
)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.