Nothing
#
log_g<-function(gam){ base::log(2)+stats::pnorm(-abs(gam),log=TRUE)+0.5*gam^2 }
L.fn<-function(p0){ stats::uniroot(function(gam) exp(log_g(gam))-(1-p0), c(-1000,0))$root }
U.fn<-function(p0){ stats::uniroot(function(gam) exp(log_g(gam))-p0, c(0,1000))$root }
p.fn<-function(p0,gam){ (p0-as.numeric(gam<0))/exp(log_g(gam))+as.numeric(gam<0)}
A.fn<-function(p0,gam){ temp.p = p.fn(p0,gam); return((1-2*temp.p)/(temp.p*(1-temp.p))) }
B.fn<-function(p0,gam){ temp.p = p.fn(p0,gam); return((2)/(temp.p*(1-temp.p))) }
C.fn<-function(p0,gam){ temp.p = p.fn(p0,gam); return((as.numeric(gam>0)-temp.p)^(-1)) }
# Internal helper: validate bounds and fall back to R reference if needed.
.gamma_bounds_ok_basic <- function(L, U) {
if (!is.numeric(L) || !is.numeric(U) || length(L) != 1L || length(U) != 1L) return(FALSE)
if (!is.finite(L) || !is.finite(U)) return(FALSE)
if (L >= U) return(FALSE)
# Gamma bounds should always straddle 0 for p0 in (0, 1).
if (L > 0 || U < 0) return(FALSE)
TRUE
}
.gamma_bounds_ok_cpp <- function(L, U, p0, tol_log = 1e-4) {
if (!.gamma_bounds_ok_basic(L, U)) return(FALSE)
log_target_L <- base::log1p(-p0)
log_target_U <- base::log(p0)
if (!is.finite(log_target_L) || !is.finite(log_target_U)) return(FALSE)
# Validate against the defining equations on the log scale:
# g_gamma(L) = 1 - p0, g_gamma(U) = p0
logL <- log_g(L)
logU <- log_g(U)
if (!is.finite(logL) || !is.finite(logU)) return(FALSE)
(abs(logL - log_target_L) <= tol_log) && (abs(logU - log_target_U) <= tol_log)
}
.gamma_bounds_ref <- function(p0) {
c(L = L.fn(p0), U = U.fn(p0))
}
.gamma_bounds <- function(p0) {
stopifnot(is.numeric(p0), length(p0) == 1L, is.finite(p0), p0 > 0, p0 < 1)
out_cpp <- try(get_gamma_bounds_cpp(p0), silent = TRUE)
if (!inherits(out_cpp, "try-error") && length(out_cpp) == 2L) {
if (is.null(names(out_cpp))) names(out_cpp) <- c("L", "U")
if (.gamma_bounds_ok_cpp(out_cpp[1], out_cpp[2], p0)) return(out_cpp)
}
out_ref <- try(.gamma_bounds_ref(p0), silent = TRUE)
if (!inherits(out_ref, "try-error") && .gamma_bounds_ok_basic(out_ref[1], out_ref[2])) {
return(out_ref)
}
stop("Unable to compute valid gamma bounds for p0 = ", p0)
}
#
CheckLossFn = function(p0,diff){diff*p0 - diff*as.numeric(diff<0)}
#
dlm_df = function(y, model, df, dim.df, s.priors = list(l0=1,S0=10), just.lik=FALSE){
### Gets the Time Series Length / Replicate number
y = check_ts(y)
TT = nrow(y)
### Gets the State Parameter dimension and Prior Distribution Parameters
m0 = model$m0
C0 = model$C0
l0 = s.priors$l0
S0 = s.priors$S0
n = length(m0)
### Constructs F and G
FF = model$FF
GG = model$GG
### Variable Saving
### Posterior Distribution
m = matrix(0,TT,n)
C = array(0,c(TT,n,n))
### Predictive State Distribution
a = matrix(0,TT,n)
R = array(0,dim = c(TT,n,n))
P = array(0,dim = c(TT,n,n))
W = array(0,dim = c(TT,n,n))
### One-Step Ahead Forecast
f = matrix(0,TT,1)
Q = array(0,c(TT,1,1))
inv.Q = array(0,c(TT,1,1))
### Regression Variables
e = matrix(0,TT,1)
A = array(0,c(TT,n,1))
### Sample Variance
S = vector("numeric",TT)
l = vector("numeric",TT)
# Prior Dim Check
m0 = matrix(m0,n,1)
C0 = matrix(C0,n,n)
### Discount Factor Blocking
df.mat = make_df_mat(df,dim.df,n)
### First Update
### One-step state forecast
a[1,] = GG[,,1] %*% m0
P[1,,] = GG[,,1] %*% C0 %*% t(GG[,,1])
W[1,,] = df.mat * P[1,,]
R[1,,] = P[1,,] + W[1,,]
### One-step ahead forecast
f[1,] = t(FF[,1]) %*% a[1,]
Q[1,,] = as.matrix(1 + t(FF[,1]) %*% R[1,,] %*% FF[,1],1,1)
inv.Q[1,,] = chol2inv(chol(Q[1,,]))
### Auxilary Variables
e[1,] = as.matrix(y[1,] - f[1,],1,1)
A[1,,] = R[1,,] %*% FF[,1] %*% inv.Q[1,,]
### Variance update
l[1] = l0 + 1
S[1] = l0 * S0 / l[1] + (t(e[1,]) %*% inv.Q[1,,] %*% e[1,] / l[1])
### Posterior Distribution
m[1,] = a[1,] + as.matrix(A[1,,],n,1) %*% e[1,]
C[1,,] = R[1,,] - as.matrix(A[1,,],n,1) %*% Q[1,,] %*% t(A[1,,])
C[1,,] = (C[1,,] + t(C[1,,]))/2
for(i in 2:TT){
### One-step state forecast
a[i,] = GG[,,i] %*% m[i-1,]
P[i,,] = GG[,,i] %*% C[i-1,,] %*% t(GG[,,i])
W[i,,] = df.mat * P[i,,]
R[i,,] = P[i,,] + W[i,,]
### One-step ahead forecast
f[i,] = t(FF[,i]) %*% a[i,]
Q[i,,] = matrix(1 + t(FF[,i])%*% R[i,,]%*% FF[,i],1,1)
inv.Q[i,,] = chol2inv(chol(Q[i,,]))
### Auxilary Variables
e[i,] = as.matrix(y[i,] - f[i,],1,1)
A[i,,] = as.matrix(R[i,,] %*% FF[,i] %*% inv.Q[i,,],n,1)
### Variance update
l[i] = l[i-1] + 1
S[i] = l[i-1] * S[i-1] / l[i] + (t(e[i,]) %*% inv.Q[i,,] %*% e[i,] / l[i])
### Posterior Distribution
m[i,] = a[i,] + as.matrix(A[i,,],n,1) %*% e[i,]
C[i,,] = R[i,,] - as.matrix(A[i,,],n,1) %*% Q[i,,] %*% t(as.matrix(A[i,,],n,1))
C[i,,] = (C[i,,] + t(C[i,,]))/2
}
### Adjust By Variance
R[1,,] = S0 * R[1,,]
Q[1,,] = S0 * Q[1,,]
C[1,,] = S[1] * C[1,,]
for(i in 2:TT){
R[i,,] = S[i-1] * R[i,,]
Q[i,,] = S[i-1] * Q[i,,]
C[i,,] = S[i] * C[i,,]
}
# Calculate Log-Likelihood
det.Q = log(abs(Q[1,,])) ; llik = lgamma((l0+1)/2)-lgamma(l0/2)-log(pi*l0)/2-det.Q/2-(l0+1)*log(1+t(e[1,])%*%inv.Q[1,,]%*%e[1,]/l0)/2
for(t in 2:TT){
det.Q = log(abs(Q[t,,]))
llik = llik + lgamma((l[t-1]+1)/2)-lgamma(l[t-1]/2)-log(pi*l[t-1])/2-det.Q/2-(l[t-1]+1)*log(1+t(e[t,])%*%inv.Q[t,,]%*%e[t,]/l[t-1])/2
}
if(just.lik){
return(list(llik = llik))
}
## SMOOTHING
### Initializes recursive relations
sa = matrix(0,TT,n)
sR = array(0, dim = c(TT,n,n))
### Runs the recursive equations
sa[TT,] = m[TT,]
sR[TT,,] = C[TT,,]
for(k in 1:(TT-1)){
### Computes the Auxilary recursion Variable B
B = C[TT-k,,] %*% t(GG[,,i]) %*% solve(R[TT-k+1,,])
sa[TT-k,] = m[TT-k,] + B %*% (sa[TT-k+1,] - a[TT-k+1,])
sR[TT-k,,] = C[TT-k,,] + B %*% (sR[TT-k+1,,] - R[TT-k+1,,]) %*% t(B)
}
### Adjusts the variance update
for(k in 1:TT){
sR[TT-k,,] = S[TT] * sR[TT-k,,] / S[TT-k]
}
return(list(fm = m, fC = C, m = sa, C = sR,model = model, s = S, n = l))
}
#
make_df_mat = function(df,dim.df,n){
if(sum(dim.df)!=n){ stop("sum of component dimensions given in dim.df does not match m0") }
if(length(df)!=length(dim.df)){ stop("length of component discount factors does not match length of component dimensions") }
dfs = rep(df,dim.df)
n.dfs = length(dim.df)
ind.dfs = c(0,sapply(1:length(dim.df),function(x){sum(dim.df[1:x])}),n)
df.mat = matrix(0,n,n)
for(j in 1:n.dfs){
df.mat[(ind.dfs[j]+1):ind.dfs[(j+1)],(ind.dfs[j]+1):ind.dfs[(j+1)]] = (1-dfs[ind.dfs[(j+1)]])/dfs[ind.dfs[(j+1)]]
}
return(df.mat)
}
#
check_mod = function(model){
if(!is.exdqlm(model)){
stop("Model must be an 'exdqlm' object. To create an 'exdqlm', use functions as.exdqlm(), seasMod(), or polytrendMod().")
}
## check all dimensions
# m0
if(!is.vector(model$m0)){
if(nrow(model$m0) != 1 & ncol(model$m0) != 1){
stop("m0 must be a vector, or a matrix with 1 column or 1 row")
}
}
model$m0 = as.matrix(c(model$m0))
p = nrow(model$m0)
# C0
model$C0 = as.matrix(model$C0)
if(p != dim(model$C0)[1] & p != dim(model$C0)[2]){
stop("C0 must be a square matrix matching the dimension of m0")
}
if(!all.equal(model$C0, t(model$C0)) | !all(eigen(model$C0)$values >= 0)){
stop("C0 must be a covariance matrix")
}
# FF
if(!is.vector(model$FF)){
if(nrow(model$FF) != p & ncol(model$FF) != p){
stop("FF must be a vector of length matching the dimension of m0, or a matrix with number of rows matching the dimension of m0")
}
if(ncol(model$FF) == p){
model$FF = t(model$FF)
}
}else{
if(length(model$FF) != p){
stop("FF must be a vector of length matching the dimension of m0, or a matrix with number of rows matching the dimension of m0")
}else{
model$FF = matrix(model$FF,p,1)
}
}
# GG
if(is.null(dim(model$GG)[3])){
model$GG = as.matrix(model$GG)
}else{
if(is.na(dim(model$GG)[3])){
model$GG = as.matrix(model$GG)
}else{
model$GG = as.array(model$GG)
}
}
if(p != dim(model$GG)[1] & p != dim(model$GG)[2]){
stop("GG must be a square matrix matching the dimension of m0, or an array with first two dimensions matching the dimension of m0")
}
return(model)
}
#
check_logics = function(gam.init,sig.init,fix.gamma,fix.sigma,dqlm.ind){
retval <- NULL
retval$gam.init = gam.init
retval$fix.gamma = fix.gamma
retval$dqlm.ind = dqlm.ind
if(dqlm.ind){
if(gam.init!=0 | !fix.gamma){
retval$gam.init <- gam.init <- 0
retval$fix.gamma <- fix.gamma <- TRUE
}
}else{
if(gam.init==0 && fix.gamma==TRUE){
retval$dqlm.ind = TRUE
}
}
if(fix.gamma & is.na(gam.init)){ stop("when fix.gamma = TRUE, gam.init must be specified") }
if(fix.sigma & is.na(sig.init)){ stop("when fix.sigma = TRUE, sig.init must be specified") }
return(retval)
}
#
check_ts = function(dat){
dat = as.matrix(dat)
if(all(dim(dat)>1)){
stop("data must be univariate time-series")
}
if(dim(dat)[1]<dim(dat)[2]){
dat = t(dat)
}
return(invisible(dat))
}
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.