std_model_params_names <- c("alpha", "beta", "rho", "kappa")
#' Wrapper to compute total area under exponential trawl function.
#'
#' @param rho Exponential trawl parameter (should be non-negative).
#'
#' @return Total area under exponential trawl function (1/rho).
#'
#' @examples
#' ComputeAExp(1) # should be 1.0
#' ComputeAExp(0.2) # should be 5.0.
#' @export
ComputeAExp <- function(rho){
if(rho < 0) stop ('rho should be non-negative.')
return(1 / rho)
}
#' Wrapper to compute difference area between \code{t1} and \code{t2}
#' under exponential trawl function.
#'
#' @param rho Exponential trawl parameter (should be non-negative).
#' @param t1 First timestamp.
#' @param t2 Second timestamp.
#' @return Difference area between \code{t1} and \code{t2}
#' under exponential trawl function.
#'
#' @examples
#' ComputeB3Exp(1, t1 = 3, t2 = 5)
#' ComputeB3Exp(0.2, t1 = 7, t2 = 3)
#'
#' @export
ComputeB3Exp <- function(rho, t1, t2){
if(rho < 0) stop('rho should be non-negative.')
if(t2 > t1){
return((1 - exp(rho * (t1-t2)))/rho)
}else{
if(t2 == t1){
return(0.0)
}else{
return((1 - exp(rho * (t2 - t1)))/rho)
}
}
}
#' Wrapper to compute difference area between \code{t2} and \code{t1}
#' under exponential trawl function.
#'
#' @param rho Exponential trawl parameter (should be non-negative).
#' @param t1 First timestamp.
#' @param t2 Second timestamp.
#' @return Difference area between \code{t1} and \code{t2}
#' under exponential trawl function. Relies on ComputeB3Exp.
#'
#' @examples
#' ComputeB1Exp(1, t1 = 3, t2 = 5)
#' ComputeB1Exp(0.2, t1 = 7, t2 = 3)
#'
#' @export
ComputeB1Exp <- function(rho, t1, t2){
if(rho < 0) stop('rho should be non-negative.')
# Compute A_t_1 \ A_t_2
return(ComputeB3Exp(rho, t2, t1))
}
#' Wrapper to compute intersection area between \code{t1} and \code{t2}
#' under exponential trawl function.
#'
#' @param rho Exponential trawl parameter (should be non-negative).
#' @param t1 First timestamp.
#' @param t2 Second timestamp.
#' @return Intersection area between \code{t1} and \code{t2}
#' under exponential trawl function.
#'
#' @examples
#' ComputeBInterExp(1, t1 = 3, t2 = 5)
#' ComputeBInterExp(0.2, t1 = 7, t2 = 3)
#'
#' @export
ComputeBInterExp <- function(rho, t1, t2){
if(rho < 0) stop('rho should be non-negative.')
if(t1 > t2){
return(exp(rho * (t2-t1))/rho)
}else{
if(t1 == t2){
return(1/rho)
}else{
return(exp(rho * (t1-t2))/rho)
}
}
}
#' Computes inverse of g from the marginal transform method (vectorised version).
#' That is from GPD(offset_shape, offset_scale) to GPD(alpha, beta+kappa).
#'
#' @param z Data distributed as GPD(offset_shape, offset_scale).
#' @param alpha Shape parameter of output data.
#' @param beta Part of scale parameter of output data (beta + kappa).
#' Should be positive.
#' @param kappa Part of scale parameter of output data.
#' Should be positive.
#' @param offset_scale Scale parameter of input data.
#' Should be positive.
#' @param offset_shape Shape parameter of input data.
#'
#' @return GPD(alpha, beta+kappa)-distributed data from
#' GPD(offset_shape, offset_scale)-distributed input data.
TrfInverseG <- function(z, alpha, beta, kappa, offset_scale, offset_shape){
# From GPD(alpha, beta+kappa) to GPD(offset_shape, offset_scale)
if(beta <= 0) stop('beta should be positive.')
if(kappa <= 0) stop('kappa should be positive.')
if(offset_scale <= 0) stop('offset_scale should be positive.')
res <- (offset_scale)*((1+sign(alpha)*z/(beta+kappa))^{alpha/offset_shape}-1)
return(res)
}
#' Computes g from the marginal transform method (vectorised version).
#' That is from GPD(alpha, beta+kappa) to GPD(offset_shape, offset_scale).
#'
#' @param x Data distributed as GPD(offset_shape, offset_scale).
#' @param alpha Shape parameter of output data.
#' @param beta Part of scale parameter of output data (beta + kappa).
#' Should be positive.
#' @param kappa Part of scale parameter of output data.
#' Should be positive.
#' @param offset_scale Scale parameter of input data.
#' Should be positive.
#' @param offset_shape Shape parameter of input data.
#'
#' @return GPD(offset_shape, offset_scale)-distributed data from
#' GPD(alpha, beta+kappa)-distributed data input data.
TrfG <- function(x, alpha, beta, kappa, offset_scale, offset_shape){
# From GPD(offset_shape, offset_scale) to GPD(alpha, beta+kappa)
if(beta <= 0) stop('beta should be positive.')
if(kappa <= 0) stop('kappa should be positive.')
if(offset_scale <= 0) stop('offset_scale should be positive.')
res <- sign(alpha)*(beta+kappa)*((1+sign(offset_shape)*x/(offset_scale))^{offset_shape/alpha}-1)
return(res)
}
#' Computes predefined transformed scale parameter.
#'
#' @param alpha Shape parameter of output data.
#' @param beta Part of scale parameter of output data (beta + kappa).
#' Should be positive.
#' @param kappa Part of scale parameter of output data.
#' Should be positive.
#' @param offset_shape Shape parameter of input data.
#'
#' @return Transformed scale parameter given original data parameters.
TrfFindOffsetScale <- function(alpha, beta, kappa, offset_shape){
if(beta <= 0) stop('beta should be positive.')
if(kappa <= 0) stop('kappa should be positive.')
return(1+kappa)
}
#' Computes the probability density function of Generalised Pareto Distribution at x,
#' with shape parameter alpha and scale parameter beta.
#'
#' @param x value at which the pdf is evaluated.
#' @param alpha Shape parameter.
#' @param beta Scale parameter, should be positive.
#'
#' @return GPD pdf function evaluated at x with shape and scale parameters respectively alpha and beta.
#' @examples dlgpd(2.34, alpha = 1, beta = 2)
#'
#' @export
#'
dlgpd <- function(x, alpha, beta){
if(beta <= 0) stop('beta should be positive.')
return(abs(alpha)/beta*max(0,(1+sign(alpha)*x/beta))^{-alpha-1.0})
}
#' Computes the cumulative distribution function of Generalised Pareto
#' Distribution at x, with shape parameter alpha and scale parameter beta.
#'
#' @param x value at which the pdf is evaluated.
#' @param alpha Shape parameter.
#' @param beta Scale parameter, should be positive.
#' @param lower.tail logical; if TRUE (default), probabilities are \code{P[X <=
#' x]} otherwise, \code{P[X > x]}.
#' @return GPD CDF function evaluated at x with shape and scale parameters
#' respectively alpha and beta.
#' @examples plgpd(2.34, alpha = 1, beta = 2)
#'
#' @export
plgpd <- function(x, alpha, beta, lower.tail=T){
res <- max(1-(1+x/beta),0)^{-alpha}
if(lower.tail){
return(res)
}else{
return(1-res)
}
}
#' Computes determinant of Jacobian of Marginal Transform (MT) method.
#'
#' @param z GPD(offset_shape, offset_scale)-distributed data.
#' @param alpha Shape parameter of output data.
#' @param beta Part of scale parameter of output data (beta + kappa).
#' Should be positive.
#' @param kappa Part of scale parameter of output data.
#' Should be positive.
#' @param offset_scale Scale parameter of input data.
#' Should be positive.
#' @param offset_shape Shape parameter of input data.
#' @return Transformed scale parameter given original data parameters.
TrfJacobian <- function(z, alpha, beta, kappa, offset_scale, offset_shape){
# TODO check whether it is numerically stable by division of pdfs
inv_g_z <- TrfInverseG(z = z, alpha = alpha, beta = beta, kappa = kappa, offset_scale = offset_scale, offset_shape = offset_shape)
res <- dlgpd(x = z, alpha = alpha, beta = beta+kappa) / dlgpd(x = inv_g_z, alpha = offset_shape, beta = offset_scale)
return(res)
}
# Case 0-0
#' Computes partial part of latent trawl pairwise likelihood with \code{(x,y) = (0,0)}.
#'
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#'
#' @return Partial part of latent trawl pairwise likelihood with \code{(x,y) = (0,0)}.
PairwiseZeroZero1 <- function(alpha, beta, kappa){
return(-2 * (1 + kappa / beta)^{-alpha})
}
#' Computes second part of latent trawl pairwise likelihood with \code{(x,y) = (0,0)}.
#'
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B1 Difference area between times \code{t1} and \code{t2}.
#' @param B2 Intersection area between times \code{t1} and \code{t2}.
#' @param B3 Difference area between times \code{t2} and \code{t1}.
#'
#' @return Second part of latent trawl pairwise likelihood with \code{(x,y) = (0,0)}.
PairwiseZeroZero2 <- function(alpha, beta, kappa, B1, B2, B3){
A <- B1 + B2
temp = (1 + 2 * kappa / beta)^{-alpha * B2 / A}
return((1 + kappa / beta)^{-alpha * ( 2 * B1) / A} * temp)
}
#' Computes latent trawl pairwise likelihood with \code{(x,y) = (0,0)} for Exponential
#' Trawl funciton.
#'
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B1 Difference area between times \code{t1} and \code{t2}.
#' @param B2 Intersection area between times \code{t1} and \code{t2}.
#' @param B3 Difference area between times \code{t2} and \code{t1}.
#' @param transformation Boolean to use the Marginal Transform (MT) method.
#' @param n.moments Number of moments achieved by transformed GPD marginals, if used.
#'
#' @return Second part of latent trawl pairwise likelihood with \code{(x,y) = (0,0)}.
#' @examples
#' PairwiseZeroZero(alpha = 3.2, beta = 2, kappa = 3, B1=0.3, B2=0.7, B3=0.3)
#'
#' @export
PairwiseZeroZero <- function(alpha, beta, kappa, B1, B2, B3, transformation=F, n.moments=0){
if(transformation){
alpha <- n.moments+1
beta <- 1
}
temp <- PairwiseZeroZero1(alpha, beta, kappa)
temp <- temp + PairwiseZeroZero2(alpha = alpha, beta = beta, kappa = kappa, B1 = B1, B2 = B2, B3 = B3)
return(1 + temp)
}
# Case 1-0
# TODO Remove dependency on rho
#' Computes first part of latent trawl pairwise likelihood with \code{(x,0)} where \code{x} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param trawlA Total trawl set measure / area under trawl function.
#'
#' @return first part of latent trawl pairwise likelihood with \code{(x,0)} where \code{x} positive.
PairwiseOneZero1 <- function(x1, alpha, beta, kappa, trawlA){
return(alpha / beta * (1 + (kappa + x1) / beta)^{-alpha - 1})
}
#' Computes partial part of second term in latent trawl pairwise likelihood with \code{(x,0)} where \code{x} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B1 Difference area between \code{t2} and \code{t1} (in this order).
#' @param trawlA Total trawl set measure / area under trawl function.
#'
#' @return Partial part of second term in latent trawl pairwise likelihood with \code{(x,0)} where \code{x} positive.
PairwiseOneZero21 <- function(x1, alpha, beta, kappa, B1, trawlA){
return( 1 / beta* (1 + (kappa + x1) / beta)^{-alpha * B1 / trawlA - 1})
}
#' Computes partial part of second term in latent trawl pairwise likelihood with \code{(x,0)} where \code{x} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B2 Intersection area between \code{t1} and \code{t2}.
#' @param trawlA Total trawl set measure / area under trawl function.
#'
#' @return Partial part of second term in latent trawl pairwise likelihood with \code{(x,0)} where \code{x} positive.
PairwiseOneZero22<- function(x1, alpha, beta, kappa, B2, trawlA ){
return((1 + (2*kappa + x1) / beta)^{-alpha * B2 / trawlA - 1})
}
#' Computes partial part of second term in latent trawl pairwise likelihood with \code{(x,0)} where \code{x} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B3 Difference area between \code{t1} and \code{t2} (in this order).
#' @param trawlA Total trawl set measure / area under trawl function.
#'
#' @return Partial part of second term in latent trawl pairwise likelihood with \code{(x,0)} where \code{x} positive.
PairwiseOneZero23 <- function(x1, alpha, beta, kappa, B3, trawlA){
return((1 + kappa / beta)^{-alpha * B3 / trawlA})
}
#' Computes partial part of second term in latent trawl pairwise likelihood with \code{(x,0)} where \code{x} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B1 Difference area between \code{t1} and \code{t2} (in this order).
#' @param trawlA Total trawl set measure / area under trawl function.
#'
#' @return Partial part of second term in latent trawl pairwise likelihood with \code{(x,0)} where \code{x} positive.
PairwiseOneZero24 <- function(x1, alpha, beta, kappa, B1, trawlA){
return(-alpha * (1 + (kappa + x1) / beta) - alpha* B1/trawlA * kappa / beta)
}
#' Computes second term in latent trawl pairwise likelihood with \code{(x,0)}
#' where \code{x} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B1 Difference area between \code{t1} and \code{t2} (in this order).
#' @param B2 intersection area between \code{t1} and \code{t2} (in this order).
#' @param B3 Difference area between \code{t2} and \code{t1} (in this order).
#' @param trawlA Total trawl set measure / area under trawl function.
#'
#' @return Second term in latent trawl pairwise likelihood with \code{(x,0)}
#' where \code{x} positive.
PairwiseOneZero2 <- function(x1, alpha, beta, kappa, B1, B2, B3, trawlA){
temp <- PairwiseOneZero21(x1, alpha, beta, kappa, B1, trawlA)
temp <- temp * PairwiseOneZero22(x1, alpha, beta, kappa, B2, trawlA)
temp <- temp * PairwiseOneZero23(x1, alpha, beta, kappa, B3, trawlA)
temp <- temp * PairwiseOneZero24(x1, alpha, beta, kappa, B1, trawlA)
return(temp)
}
#' Computes term in latent trawl pairwise likelihood with \code{(x,0)} where \code{x} positive
#' with exponential trawl function.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B1 Difference area between \code{t1} and \code{t2} (in this order).
#' @param B2 intersection area between \code{t1} and \code{t2} (in this order).
#' @param B3 Difference area between \code{t2} and \code{t1} (in this order).
#' @param transformation Boolean to use the Marginal Transform (MT) method.
#' @param n.moments Number of moments achieved by transformed GPD marginals, if used.
#'
#' @return Second term in latent trawl pairwise likelihood with \code{(x,0)} where \code{x} positive
#' with exponential trawl function.
#' @examples
#' PairwiseOneZero(x1=0.5, alpha=0.3, beta=2, kappa=3, B1=0.3, B2=0.7, B3=0.3)
#'
#' @export
PairwiseOneZero <- function(x1, alpha, beta, kappa, B1, B2, B3, transformation=F, n.moments=4){
# Marginal Transformation
if(transformation){
offset_shape <- n.moments + 1
offset_scale <- TrfFindOffsetScale(alpha = alpha, beta = beta, kappa = kappa, offset_shape = offset_shape)
inv_x <- TrfInverseG(x1, alpha = alpha, beta = beta, kappa = kappa, offset_scale = offset_scale, offset_shape = offset_shape)
jacobian <- TrfJacobian(z = x1, alpha = alpha, beta = beta, kappa = kappa, offset_scale = offset_scale, offset_shape = offset_shape)
new_x <- inv_x
}else{
new_x <- x1
}
if(transformation){
temp <- PairwiseOneZero1(x1 = new_x, alpha=offset_shape, beta=1, kappa = kappa, trawlA = B1+B2)
temp <- temp + PairwiseOneZero2(new_x, alpha=offset_shape, beta=1, kappa, trawlA = B1+B2, B1, B2, B3)
temp <- temp * jacobian
}else{
temp <- PairwiseOneZero1(x1 = new_x, alpha = alpha, beta = beta, kappa = kappa, trawlA = B1+B2)
temp <- temp + PairwiseOneZero2(new_x, alpha, beta, kappa, trawlA = B1+B2, B1 = B1, B2 = B2, B3 = B3)
}
if(temp == 0.0 || is.na(temp) || is.nan(temp)){
temp <- 1.0
}
return(temp)
}
# Example
# Case 1-1
#' Computes frst part of first term in latent trawl pairwise likelihood with \code{(x,x)} where \code{x} positive and \code{y} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param x2 Positive value corresponding to \code{t2}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B1 Difference area between \code{t1} and \code{t2} (in this order).
#' @param trawlA Total trawl set measure / area under trawl function.
#'
#' @return Frst part of first term in latent trawl pairwise likelihood with \code{(x,x)} where \code{x} positive and \code{y} positive.
PairwiseOneOne11 <- function(x1, x2, alpha, beta, kappa, B1, trawlA){
return(1/beta^2 * (1+(kappa+x1)/beta)^{-alpha * B1 / trawlA-1})
}
#' Computes second part of first term in latent trawl pairwise likelihood with \code{(x,x)} where \code{x} positive and \code{y} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param x2 Positive value corresponding to \code{t2}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B2 Intersection area between \code{t1} and \code{t2} (in this order).
#' @param trawlA Total trawl set measure / area under trawl function.
#'
#' @return Second part of first term in latent trawl pairwise likelihood with \code{(x,x)} where \code{x} positive and \code{y} positive.
PairwiseOneOne12 <- function(x1, x2, alpha, beta, kappa, B2, trawlA){
return((1+(2*kappa+x1+x2)/beta)^{-alpha*B2/trawlA-2})
}
#' Computes third part of first term in latent trawl pairwise likelihood with \code{(x,x)} where \code{x} positive and \code{y} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param x2 Positive value corresponding to \code{t2}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B3 Difference area between \code{t2} and \code{t1} (in this order).
#' @param trawlA Total trawl set measure / area under trawl function.
#'
#' @return Second part of first term in latent trawl pairwise likelihood with \code{(x,x)} where \code{x} positive and \code{y} positive.
PairwiseOneOne13 <- function(x1, x2, alpha, beta, kappa, B3, trawlA){
return((1+(kappa+x2)/beta)^{-alpha*B3/trawlA-1})
}
#' Computes first term in latent trawl pairwise likelihood with \code{(x,x)} where \code{x} positive and \code{y} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param x2 Positive value corresponding to \code{t2}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B1 Difference area between \code{t1} and \code{t2} (in this order).
#' @param B2 Intersection area between \code{t1} and \code{t2} (in this order).
#' @param B3 Difference area between \code{t2} and \code{t1} (in this order).
#'
#' @return First term in latent trawl pairwise likelihood with \code{(x,x)} where \code{x} positive and \code{y} positive.
PairwiseOneOne1 <- function(x1, x2, alpha, beta, kappa, B1, B2, B3){
temp <- PairwiseOneOne11(x1 = x1, x2 = x2, alpha = alpha, beta = beta,
kappa = kappa, B1 = B1, trawlA = B1+B2)
temp <- temp * PairwiseOneOne12(x1 = x1, x2 = x2, alpha = alpha, beta = beta,
kappa = kappa, B2 = B2, trawlA = B1+B2)
temp <- temp * PairwiseOneOne13(x1 = x1, x2 = x2, alpha = alpha, beta = beta,
kappa = kappa, B3 = B3, trawlA = B1+B2)
return(temp)
}
#' Computes second term in latent trawl pairwise likelihood with \code{(x,x)}
#' where \code{x} positive and \code{y} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param x2 Positive value corresponding to \code{t2}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B1 Difference area between \code{t1} and \code{t2} (in this order).
#' @param B2 Intersection area between \code{t1} and \code{t2} (in this order).
#'
#' @return Second term in latent trawl pairwise likelihood with \code{(x,x)}
#' where \code{x} positive and \code{y} positive.
PairwiseOneOne21 <- function(x1, x2, alpha, beta, kappa, B1, B2){
return(alpha^2/(B1+B2)^2*B1*B2*(1+(2*kappa+x1+x2)/beta)*
((1+(kappa+x2)/beta) + (1+(kappa+x2)/beta)))
}
#' Computes second term in latent trawl pairwise likelihood with \code{(x,x)}
#' where \code{x} positive and \code{y} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param x2 Positive value corresponding to \code{t2}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B2 Intersection area between \code{t1} and \code{t2} (in this order).
#' @param trawlA Total trawl set measure / area under trawl function.
#'
#' @return Second term in latent trawl pairwise likelihood with \code{(x,x)}
#' where \code{x} positive and \code{y} positive.
PairwiseOneOne23 <- function(x1, x2, alpha, beta, kappa, B2, trawlA){
temp <- -alpha*B2/trawlA * (-alpha*B2/trawlA - 1)
temp <- temp*(1+(kappa+x1)/beta)*(1+(kappa+x2)/beta)
return(temp)
}
#' Computes second term in latent trawl pairwise likelihood with \code{(x,x)}
#' where \code{x} positive and \code{y} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param x2 Positive value corresponding to \code{t2}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B2 Intersection area between \code{t1} and \code{t2} (in this order).
#' @param B3 Difference area between \code{t2} and \code{t1} (in this order).
#'
#' @return Second term in latent trawl pairwise likelihood with \code{(x,x)}
#' where \code{x} positive and \code{y} positive.
PairwiseOneOne24 <- function(x1, x2, alpha, beta, kappa, B2, B3){
return((alpha * B3/(B2+B3) * (1+(2*kappa+x1+x2)/beta))^2)
}
#' Computes second term in latent trawl pairwise likelihood with \code{(x,x)}
#' where \code{x} positive and \code{y} positive.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param x2 Positive value corresponding to \code{t2}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B1 Difference area between \code{t1} and \code{t2} (in this order).
#' @param B2 Intersection area between \code{t1} and \code{t2} (in this order).
#' @param B3 Difference area between \code{t2} and \code{t1} (in this order).
#'
#' @return Second term in latent trawl pairwise likelihood with \code{(x,x)}
#' where \code{x} positive and \code{y} positive.
PairwiseOneOne2 <- function(x1, x2, alpha, beta, kappa, B1, B2, B3){
temp <- PairwiseOneOne21(x1 = x1, x2 = x2, alpha = alpha,
beta = beta, kappa = kappa, B1 = B1, B2 = B2)
# temp <- temp + PairwiseOneOne22(x1 = x1, x2 = x2, alpha = alpha,
# beta = beta, kappa = kappa, B1 = B1,
# B3 = B3)
temp <- temp + PairwiseOneOne23(x1 = x1, x2 = x2, alpha = alpha,
beta = beta, kappa = kappa, B2 = B2,
trawlA = B1+B3)
temp <- temp + PairwiseOneOne24(x1 = x1, x2 = x2, alpha = alpha,
beta = beta, kappa = kappa, B2 = B2,
B3 = B3)
return(temp)
}
#' Computes latent trawl pairwise likelihood with \code{(x,x)} where \code{x}
#' and \code{y} positive with exponential trawl function.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param x2 Positive value corresponding to \code{t2}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B1 Difference area between \code{t1} and \code{t2} (in this order).
#' @param B2 Intersection area between \code{t1} and \code{t2} (in this order).
#' @param B3 Difference area between \code{t2} and \code{t1} (in this order).
#' @param transformation Boolean to use the Marginal Transform (MT) method.
#' @param n.moments Number of moments achieved by transformed GPD marginals, if
#' used.
#'
#' @return Latent trawl pairwise likelihood with \code{(x,x)} where \code{x} positive
#' and \code{y} positive.
#' @examples PairwiseOneOne(x1=0.5, x2=0.3, alpha=2, beta=3, B1 = 0.3, B2 = 0.7,
#' B3 = 0.3, kappa=3.5)
#'
#' @export
PairwiseOneOne <- function(x1, x2, alpha, beta, kappa, B1, B2, B3, transformation=F, n.moments=4){
# Marginal Transformation
if(transformation){
offset_shape <- n.moments + 1
offset_scale <- TrfFindOffsetScale(alpha = alpha, beta = beta, kappa = kappa, offset_shape = offset_shape)
inv_x1 <- TrfInverseG(z = x1, alpha = alpha, beta = beta, kappa = kappa,
offset_scale = offset_scale, offset_shape = offset_shape)
inv_x2 <- TrfInverseG(z = x2, alpha = alpha, beta = beta, kappa = kappa,
offset_scale = offset_scale, offset_shape = offset_shape)
new_x1 <- inv_x1
new_x2 <- inv_x2
jacobian1 <- TrfJacobian(z = x1, alpha = alpha, beta = beta, kappa = kappa,
offset_scale = offset_scale, offset_shape = offset_shape)
jacobian2 <- TrfJacobian(z = x2, alpha = alpha, beta = beta, kappa = kappa,
offset_scale = offset_scale, offset_shape = offset_shape)
temp <- jacobian1 * jacobian2
#temp <- 1.0
#temp <- 1/temp
}else{
new_x1 <- x1
new_x2 <- x2
temp <- 1.0
}
if(temp == 0.0 || is.na(temp) || is.nan(temp)){
temp <- .Machine$double.eps
}
if(transformation){
temp <- temp * PairwiseOneOne1(x1 = new_x1, x2 = new_x2,
alpha = offset_shape, beta = 1, kappa = kappa, B1 = B1, B2 = B2, B3 = B3)
temp <- temp * PairwiseOneOne2(x1 = new_x1, x2 = new_x2,
alpha = offset_shape, beta = 1, kappa = kappa, B1 = B1, B2 = B2, B3 = B3)
}else{
temp <- temp * PairwiseOneOne1(x1 = new_x1, x2 = new_x2,
alpha = alpha, beta = beta, kappa = kappa, B1 = B1, B2 = B2, B3 = B3)
temp <- temp * PairwiseOneOne2(x1 = new_x1, x2 = new_x2,
alpha = alpha, beta = beta, kappa = kappa, B1 = B1, B2 = B2, B3 = B3)
}
return(temp)
}
#' Computes correct latent trawl SINGLE pairwise likelihood depending on the
#' values of \code{(x1,x2)} with exponential trawl function.
#'
#' @param x1 Positive value corresponding to \code{t1}.
#' @param x2 Positive value corresponding to \code{t2}.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param B1 Difference area between \code{t1} and \code{t2} (in this order).
#' @param B2 Intersection area between \code{t1} and \code{t2} (in this order).
#' @param B3 Difference area between \code{t2} and \code{t1} (in this order).
#' @param transformation Boolean to use the Marginal Transform (MT) method.
#' @param n.moments Number of finite moments for transformed marginals.
#'
#' @return SINGLE latent trawl pairwise likelihood depending on \code{(x1,x2)}.
#' @examples
#' SinglePairPL(x1=0.5, x2= 0.3, alpha=0.3, beta=2, kappa=3, B1=0.3, B2=0.7, B3=0.3, FALSE)
#' SinglePairPL(x1=2.0, x2=1.0, alpha=-2, beta=3., kappa=3, B1=0.3, B2=0.7, B3=0.3, TRUE)
#'
#' @export
SinglePairPL <- function(x1, x2, alpha, beta, kappa, B1, B2, B3, transformation=F, n.moments=0){
# TODO check whether t1 should be smaller than t2 or not
#print(x1)
if(x1 < .Machine$double.eps){
if(x2 < .Machine$double.eps){
return(PairwiseZeroZero(alpha = alpha, beta = beta, kappa = kappa, B1 = B1, B2 = B2, B3 = B3))
}else{
return(PairwiseOneZero(x2, alpha, beta, kappa, B1 = B1, B2 = B2, B3 = B3, transformation, n.moments = n.moments))
}
}else{
if(x2 < .Machine$double.eps){
return(PairwiseOneZero(x1, alpha, beta, kappa, B1 = B1, B2 = B2, B3 = B3, transformation, n.moments = n.moments))
}else{
return(PairwiseOneOne(x1, x2, alpha, beta, kappa, B1 = B1, B2 = B2, B3 = B3, transformation, n.moments = n.moments))
}
}
}
#' Computes latent trawl FULL pairwise likelihood depending with exponential
#' trawl function.
#'
#' @param times Vector of timestamps.
#' @param values Vector of target values.
#' @param alpha Shape parameter. Should be positive.
#' @param beta Latent Gamma scale parameter. Should be positive.
#' @param kappa Exceedance probability parameter. Should be positive.
#' @param rho Trawl parameter(s). For \code{trawl.function="exp"}, it should be
#' positive.
#' @param delta Maximum depth of pairwise likelihood blocks. Should be positive
#' natural integer.
#' @param trawl.function Type of trawl function that should be used. Default NA.
#' @param logscale Boolean to use logscale (log-likelihood). Default \code{T}.
#' @param transformation Boolean to use the Marginal Transform (MT) method.
#'
#' @return Full latent trawl pairwise likelihood.
#' @examples \donttest{FullPL(times=1:10, values = seq(from=0.1, to=5, by=0.5), alpha=0.3,
#' beta=2, kappa=3, rho=0.2, delta=2, T, F, "exp")}
#'
#' @export
FullPL <- function(times, values, alpha, beta, kappa, rho, delta, logscale=T, transformation=F, trawl.function="exp"){
ok_ind <- which(!is.na(values))
values <- values[ok_ind]
times <- times[ok_ind]
k <- length(values)
temp <- 0.0
upper <- pmin(1:(k-1)+delta, k)
lower <- 2:k
for(i in 1:(k-1)){
ind <- (lower[i]):(upper[i])
m <- 0
for(j in ind){
if(trawl.function == "exp"){
B1 <- ComputeB1Exp(rho = rho, t1 = times[i], t2 = times[j])
B2 <- ComputeBInterExp(rho = rho, t1 = times[i], t2 = times[j])
B3 <- ComputeB3Exp(rho = rho, t1 = times[i], t2 = times[j])
}else{
stop(paste("trawl.function", trawl.function, "not yet implemented."))
}
warnon <- SinglePairPL(values[i], values[j],
alpha = alpha,
beta = beta,
kappa = kappa,
B1 = B1, B2 = B2, B3 = B3,
transformation=transformation)
if(!is.na(warnon) & !is.nan(warnon)){
if(warnon > 1e-12){
# log the result
temp <- temp + log(warnon)
}else{
if(warnon >= 0.0){
temp <- temp + log(warnon)
}
}
}
}
}
if(logscale){
return(temp)
}else{
return(exp(temp))
}
}
#' Wrapper for FullPL using a list for parameters in the exponential trawl case.
#' @param times Vector of timestamps.
#' @param values Vector of target values.
#' @param delta Maximum depth of pairwise likelihood blocks. Should be positive
#' natural integer.
#' @param params List of parameters.
#' @param logscale Boolean to use logscale (log-likelihood). Default \code{T}.
#' @param transformation Boolean to use the Marginal Transform (MT) method.
#'
#' @return Pairwise Likelihood as per FullPL using a list of parameters instead.
#' @examples ParamsListFullPL(c(1,2,3,4,5), c(0, 2.3, .3, 0, 5), delta=2,
#' params=list("alpha"=2,"beta"=3,"kappa"=1.5, "rho"=0.2), TRUE, FALSE)
#'
#' @export
ParamsListFullPL <- function(times, values, delta, params, logscale=T, transformation=F){
# TODO add general model parameter names
# TODO add trawl.function
if(prod(std_model_params_names %in% names(params)) != 1) stop('Essential parameters missing.')
return(FullPL(times, values,
alpha = (params["alpha"][[1]]),
beta = (params["beta"][[1]]),
kappa = params["kappa"][[1]],
rho = params["rho"][[1]],
delta = delta,
logscale = T,
transformation = transformation))
}
#' Computes univariate latent trawl FULL pairwise likelihood depending with
#' exponential trawl function with the option to fix some parameter values.
#'
#' @param times Vector of timestamps.
#' @param values Vector of target values.
#' @param delta Maximum depth of pairwise likelihood blocks. Should be positive
#' natural integer.
#' @param fixed_names Vector of literal names of parameters to keep fixed.
#' @param fixed_params Vector of numerical values of fixed parameters.
#' @param params List of parameters.
#' @param model_vars_names Vector of all parameters names in the model.
#' @param logscale Boolean to use logscale (log-likelihood). Default \code{T}.
#' @param transformation Boolean to use the Marginal Transform (MT) method.
#'
#' @return FULL latent trawl pairwise likelihood with some (or none) parameters
#' fixed.
#' @examples times <- c(1,2,3,4,5)
#' values <- c(2,0,3,4,0)
#' delta <- 2
#' fixed_names <- c("alpha", "beta")
#' fixed_params <- c(2.0, 3.4)
#' params <- c(0.1, 4.3)
#' model_vars_names <- c("alpha", "beta", "rho", "kappa")
#' UnivariateFullPL(times, values, delta, fixed_names, fixed_params,
#' params, model_vars_names, TRUE, FALSE)
#'
#' @export
UnivariateFullPL <- function(times, values, delta, fixed_names, fixed_params, params, model_vars_names, logscale=T, transformation=F){
if(length(fixed_names) > length(model_vars_names)) stop('Too many fixed parameters compared to number of model params.')
if(length(fixed_params) + length(params) != length(model_vars_names)) stop('Wrong number of params compared to model specs.')
if(length(fixed_params) != length(fixed_names)) stop('fixed_params and fixed_names should have same length.')
opti_params <- !(model_vars_names %in% fixed_names)
opti_params_names <- model_vars_names[opti_params]
params_all <- rep(0, length(model_vars_names))
params_all[opti_params] <- params
if(length(fixed_params) > 0){
params_all[!opti_params] <- fixed_params
}
params_list <- list()
params_list[fixed_names] <- fixed_params
#params_list[opti_params_names] <- params
for(i in 1:length(fixed_names)){
params_list[fixed_names[i]] <- fixed_params[i]
}
params_list[opti_params_names] <- params
return(ParamsListFullPL(times = times,
values = values,
delta = delta,
params = params_list,
logscale = logscale,
transformation = transformation))
}
#' Computes Generalised Pareto (log-)likelihood on non-zero exceedances under
#' independence.
#'
#' @param values Vector of target values.
#' @param fixed_names Vector of literal names of parameters to keep fixed.
#' @param fixed_params Vector of numerical values of fixed parameters.
#' @param params List of parameters.
#' @param model_vars_names Vector of all parameters names in the model.
#' @param logscale Logical; Default (\code{TRUE}) is to use logscale (log-likelihood).
#' @param transformation Boolean to use the Marginal Transform (MT) method.
#' @param n.moments Number of moments the transformed variables should have
#' using the Marginal Transform (MT) method.
#'
#' @return Generalised Pareto (log-)likelihood on non-zero exceedances under
#' independence.
#' @examples times <- c(1,2,3,4,5)
#' values <- c(2,0,3,4,0)
#' delta <- 2
#' fixed_names <- c("alpha", "kappa")
#' params <- c(3.4, 0.1)
#' fixed_params <- c(2.0, 4.3)
#' model_vars_names <- c("alpha", "beta", "rho", "kappa")
#' MarginalGPDLikelihood(values, fixed_names, fixed_params, params, model_vars_names)
#'
#' @export
MarginalGPDLikelihood <- function(values, fixed_names, fixed_params, params, model_vars_names, logscale=T, transformation=F, n.moments=4){
if(length(fixed_names) > length(model_vars_names)) stop('Too many fixed parameters compared to number of model params.')
if(length(fixed_params) + length(params) != length(model_vars_names)) stop('Wrong number of params compared to model specs.')
if(length(fixed_params) != length(fixed_names)) stop('fixed_params and fixed_names should have same length.')
opti_params <- !(model_vars_names %in% fixed_names)
opti_params_names <- model_vars_names[opti_params]
params_all <- rep(0, length(model_vars_names))
params_all[opti_params] <- params
if(length(fixed_params) > 0){
params_all[!opti_params] <- fixed_params
}
if(transformation){
if(length(params_all) < 3) stop('Marginal GPD with transformation requires 3 parameters: alpha, beta and kappa.')
print(params_all)
lik <- vapply(values,
function(x){
temp_alpha <- params_all[1]
temp_beta <- params_all[2]
temp_kappa <- params_all[3]
offset_shape <- n.moments + 1
offset_scale <- TrfFindOffsetScale(alpha = temp_alpha, beta = temp_beta,
kappa = temp_kappa, offset_shape = offset_shape)
inv_x1 <- TrfInverseG(x, alpha = temp_alpha, beta = temp_beta, kappa = temp_kappa,
offset_scale = offset_scale, offset_shape = offset_shape)
jacobian1 <- TrfJacobian(z = x, alpha = temp_alpha, beta = temp_beta, kappa = temp_kappa,
offset_scale = offset_scale, offset_shape = offset_shape)
temp <- jacobian1
return(dlgpd(x = inv_x1, alpha = offset_shape, beta = offset_scale+temp_kappa)*jacobian1)
},
1.0)
}else{
lik <- vapply(values, function(x){return(dlgpd(x = x, alpha = params_all[1], beta = (params_all[2]+params_all[3])))}, 1.0)
}
if(logscale){
return(sum(log(lik[lik > 0.0])))
}else{
return(prod(lik))
}
}
#' Simplified marginal (GPD) log-likelihood function under independence in the
#' exponential trawl case.
#'
#' @param values Exceedance values.
#' @param params (at least) 2-d vector for GPD parameters
#'
#' @return Log-likelihood of GPD distribued variables (i.e. non-zero exceedances).
#' @examples MarginalSimpleLik(c(2.0, 0.3, 6.15, 0, 0.31), c(2.1, 1.17, 0.52, 4.17)) # for GPD(2.1, 1.17)
#'
#' @export
MarginalSimpleLik <- function(values, params){
alpha <- params[1]
beta_kappa <- params[2]
lik <- alpha / beta_kappa * (1+sign(alpha) * values / beta_kappa)^{-alpha-1}
return(sum(log(lik[lik>0])))
}
#' Generalised Pareto likelihood maximisation using L-BFGS-B optimisation
#' routine.
#'
#' @param values Exceedance values.
#' @param initial_guess (at least 2-d) Vector for GPD parameters starting
#' values.
#' @param lower Vector of lower bounds limits for optimisation procedure.
#' Default \code{c(0.1, 0.1)}.
#' @param upper Vector of upper bounds limits for optimisation procedure.
#' Default \code{c(20, 20)}.
#'
#' @return Parameters of Log-likelihood maximisation of GPD distribued variables
#' (i.e. non-zero exceedances).
#' @examples GPDFit(c(2.0, 0.3, 6.15, 0, 0.31), c(2.1, 1.17, 0.52, 4.17))
#'
#' @export
GPDFit <- function(values, initial_guess, lower=c(0.1, 0.1), upper=c(20, 20)){
fn_to_optim <- function(x){return(-MarginalSimpleLik(values = values, params = x))}
ff <- stats::optim(fn_to_optim, par = initial_guess, method = "L-BFGS-B", lower = lower, upper = upper)
return(ff$par)
}
#' Method of moments (MoM) on a one or multiple exceedance timeseries for the
#' latent trawl model using marginal GPD properties and probability of exceedance.
#'
#' @param values_array Matrix of exceedance timeseries
#'
#' @return Parameters given by a second-order method of moments as well as standard deviation across
#' timeseries for each individual parameter.
#' @examples
#' exceed1 <- c(0.1, 0, 0.2, 0, 0, 0, 0.6, 1.5)
#' exceed2 <- c(0, 0.3, 5.2, 0, 0, 3.0, 0, 2.2)
#' val_array <- cbind(exceed1, exceed2)
#' MoMGPD(val_array)
#'
#' @export
MoMGPD <- function(values_array){
# workds under the assumption that alpha > 2
# values_array contains the time series with first axis as time and second as # of time series
requireNamespace("stats", quietly = T)
n_dim <- length(values_array[1,])
n_values <- length(values_array[,1])
alphas_mom <- rep(0, n_dim)
betas_mom <- rep(0, n_dim)
kappas_mom <- rep(0, n_dim)
for(index in 1:n_dim){
var_mom <- stats::var(values_array[,index][values_array[,index]>0])
mean_mom <- mean(values_array[,index][values_array[,index]>0])
p_mom <- length(values_array[,index][values_array[,index]>0])/n_values
alphas_mom[index] <- 2*var_mom/(var_mom-mean_mom^2)
betas_mom[index] <- mean_mom*(alphas_mom[index]-1)
kappas_mom[index] <- betas_mom[index] * (1.0 - p_mom^{1/alphas_mom[index]})
betas_mom[index] <- betas_mom[index] - kappas_mom[index]
}
return(list(alpha=alphas_mom, beta=betas_mom, kappa=kappas_mom,
mean_alpha=mean(alphas_mom), mean_beta=mean(betas_mom), mean_kappa=mean(kappas_mom),
sd_alpha=stats::sd(alphas_mom), sd_beta=stats::sd(betas_mom), sd_kappa=stats::sd(kappas_mom)))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.