Nothing
vcov_hessian <- function(object){
rankings <- object$rankings
weights <- object$weights
adherence <- object$adherence
ranker <- object$ranker
if (!is.null(adherence)){
a <- adherence[ranker]
wa <- rowsum(weights, ranker)[,1]
} else a <- NULL
gamma <- object$gamma
normal <- object$normal
# attributes
items <- colnames(rankings)
N <- ncol(rankings) # total number of objects
nr <- nrow(rankings) # number of rankings
# items ranked from last to 1st place
R <- t(apply(rankings, 1L, order, decreasing = TRUE))
mode(R) <-"integer"
# sizes of selected sets
set <- apply(rankings, 1L, function(x){
last <- which(x == max(x))
ind <- which(x > 0L)
# exclude untied last place
if (length(last) == 1L) ind <- setdiff(ind, last)
list(size = tabulate(x[ind])[x[ind]], item_id = ind)
})
item_id <- unlist(lapply(set, `[[`, "item_id"))
S <- lapply(set, `[[`, "size")
ns <- lengths(S)
w <- rep.int(weights, ns)
if (!is.null(object$adherence)) ranker_id <- rep.int(ranker, ns)
S <- unlist(S)
rm(set)
# sufficient statistics
# for delta d, (number of sets with cardinality d)/cardinality
d <- sort(unique(S))
D <- length(d)
B <- unname(rowsum(w, S)[,1L])
B <- B/d
# from now only only need weight/size per set, so replace S with this
S <- w/S
rm(w)
# for alpha
A <- numeric(N)
item <- sort(unique(item_id))
if (is.null(adherence)){
# sum over all sets st object i is in selected set weight/size
A[item] <- unname(rowsum(S, item_id)[,1L])
} else {
# now (adherence * weight)/size
A[item] <- unname(rowsum(adherence[ranker_id]*S, item_id)[,1L])
}
if (!is.null(object$normal)){
# compute inverse of variance covariance matrix (used in score function)
K <- solve(object$normal$invSigma)
Rinv <- solve(chol(K))
Kinv <- Rinv %*% t(Rinv)
} else Rinv <- Kinv <- NULL
# unique rows with >= 1 element for logical matrix
# case where p is fixed
uniquerow <- function(M){
len <- ncol(M)
if (len == 1L) return(1L)
pattern <- M[,1L]
max_exp <- .Machine$double.digits
for (k in seq_len(len - 1L)){
# N.B. can't use integer here, can get integer overflow
pattern <- 2*pattern + M[,k]
if (k == len - 1L ||
k %% max_exp == (max_exp - 1L)){
pattern <- match(pattern, unique(pattern))
max_exp <- .Machine$double.digits - ceiling(log2(max(pattern)))
}
}
as.integer(pattern)
}
# max number of objects in set
nc <- max(rowSums(rankings > 0L))
# create W so cols are potential set sizes and value > 0 indicates ranking
# aggregate common sets
# - incorporate ranking weights by weighted count vs simple tabulate
W <- G <- list() # weight (currently rep count); group of rankings
P <- logical(nc) # set sizes present in rankings
minrank <- rep.int(1L, nr)
for (i in seq_len(nc)){
p <- (nc - i + 1L)
set <- rankings >= minrank
r <- which(rowSums(set) == p)
P[p] <- p != 1L && length(r)
if (!P[p]) next
g <- uniquerow(set[r, , drop = FALSE])
if (!is.null(adherence)){ # combine within ranker (adherence may change)
x <- ranker[r]/log10(max(ranker[r]) + 1L) + g
g <- match(x, x)
}
W[[p]] <- as.vector(unname(rowsum(weights[r], g)))
G[[p]] <- r[!duplicated(g)]
minrank[r] <- minrank[r] + 1L
}
P <- which(P)
# objective for computing vcov minus the full log-posterior
obj_full <- function(par){
alpha <- exp(par[1L:N])
delta <- exp(par[((N + 1L):(N + D))[-D]])
adherence <- exp(par[-(1L:(N + D - 1L))])
if (length(adherence)){
# update adherence per ranking
a[1L:nr] <- adherence[ranker]
}
# assign to parent environment so can use further quantities in score
assign("fit", PlackettLuce:::expectation("all", alpha, c(1.0, delta),
a, N, d, P, R, G, W),
envir = parent.env(environment()))
# update A
if (!length(adherence)){
A[item] <- unname(rowsum(S, item_id)[,1L])
} else {
A[item] <- unname(rowsum(adherence[ranker_id]*S, item_id)[,1L])
}
- PlackettLuce:::logp_full(alpha, delta, adherence,
normal$mu, Rinv, gamma$shape, gamma$rate,
wa, A, B, fit$theta)
}
gr_full <- function(par) {
alpha <- exp(par[1L:N])
delta <- exp(par[((N + 1L):(N + D))[-D]])
adherence <- exp(par[-(1L:(N + D - 1L))])
if (!is.null(gamma)){
norm <- normalization(alpha, c(1.0, delta),
adherence[ranker], d, P, R, G, W)
# update Z
Z <- unname(rowsum(S*log(alpha[item_id]), ranker_id)[,1L])
} else Z <- NULL
-PlackettLuce:::score_full(alpha, delta, adherence, ranker,
normal$mu, Rinv, gamma$shape, gamma$rate,
wa, A, B, Z,
fit$expA, fit$expB, norm$score) *
c(alpha, delta, adherence)[-c(1L, D)]
}
# cannot compute hessian with our gradient function as it relies on
# objective function being called immediately prior (as in optimisaton)
alpha <- object$coefficients[seq_len(N)]
delta <- object$coefficients[((N + 1L):(N + D))[-D]]
par <- c(log(alpha), log(delta))
if (!is.null(adherence)) {
par <- c(par, log(adherence))
}
H <- stats:::optimHess(par, obj_full)
p <- length(object$coefficients)
if (is.null(normal)) {
V <- matrix(0, p, p)
V[-1L, -1L] <- solve(H[-1,-1])[seq_len(p - 1L), seq_len(p - 1L)]
} else {
V <- solve(H)
M <- diag(nrow(V))
M[1L:N, 1L] <- M[1L:N, 1L] - 1L
V <- (M %*% V %*% t(M))[seq_len(p), seq_len(p)]
}
V
}
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.