#' \item 'M' : list of moments of order 1,2,3: will be computed if not provided.
#' \item 'X,Y' : input/output, mandatory if moments not given
#' \item 'exact': use exact formulas when available?
+#' \item weights Weights on moments when minimizing sum of squares
#' }
#'
#' @return An object 'op' of class OptimParams, initialized so that \code{op$run(x0)}
M <- computeMoments(optargs$X,optargs$Y)
}
- # TODO: field?!
- exactComp <<- optargs$exact
- if (is.null(exactComp))
- exactComp <<- FALSE
+ weights <- optargs$weights
+ if (is.null(weights))
+ weights <- rep(1, K)
# Build and return optimization algorithm object
methods::new("OptimParams", "li"=link, "M1"=as.double(M[[1]]),
- "M2"=as.double(M[[2]]), "M3"=as.double(M[[3]]), "K"=as.integer(K))
+ "M2"=as.double(M[[2]]), "M3"=as.double(M[[3]]),
+ "weights"=weights, "K"=as.integer(K))
}
# Encapsulated optimization for p (proportions), β and b (regression parameters)
# @field M1 Estimated first-order moment
# @field M2 Estimated second-order moment (flattened)
# @field M3 Estimated third-order moment (flattened)
+# @field weights Vector of moments' weights
# @field K Number of populations
# @field d Number of dimensions
#
M1 = "numeric", #order-1 moment (vector size d)
M2 = "numeric", #M2 easier to process as a vector
M3 = "numeric", #M3 easier to process as a vector
+ weights = "numeric", #weights on moments
# Dimensions
K = "integer",
d = "integer"
β3 <- apply(β, 2, function(col) col %o% col %o% col)
return(
- sum( ( β %*% (p * .G(li,1,λ,b)) - M1 )^2 ) +
- sum( ( β2 %*% (p * .G(li,2,λ,b)) - M2 )^2 ) +
- sum( ( β3 %*% (p * .G(li,3,λ,b)) - M3 )^2 ) )
+ weights[1] * sum( ( β %*% (p * .G(li,1,λ,b)) - M1 )^2 ) +
+ weights[2] * sum( ( β2 %*% (p * .G(li,2,λ,b)) - M2 )^2 ) +
+ weights[3] * sum( ( β3 %*% (p * .G(li,3,λ,b)) - M3 )^2 ) )
},
grad_f = function(x)
km1 = 1:(K-1)
grad <- #gradient on p
- t( sweep(as.matrix(β [,km1]), 2, G1[km1], '*') - G1[K] * β [,K] ) %*% F1 +
- t( sweep(as.matrix(β2[,km1]), 2, G2[km1], '*') - G2[K] * β2[,K] ) %*% F2 +
- t( sweep(as.matrix(β3[,km1]), 2, G3[km1], '*') - G3[K] * β3[,K] ) %*% F3
+ weights[1] * t( sweep(as.matrix(β [,km1]), 2, G1[km1], '*') - G1[K] * β [,K] ) %*% F1 +
+ weights[2] * t( sweep(as.matrix(β2[,km1]), 2, G2[km1], '*') - G2[K] * β2[,K] ) %*% F2 +
+ weights[3] * t( sweep(as.matrix(β3[,km1]), 2, G3[km1], '*') - G3[K] * β3[,K] ) %*% F3
grad_β <- matrix(nrow=d, ncol=K)
for (i in 1:d)
dβ3_right[block,] <- dβ3_right[block,] + β2
dβ3 <- dβ3_left + sweep(dβ3_right, 2, p * G3, '*')
- grad_β[i,] <- t(dβ) %*% F1 + t(dβ2) %*% F2 + t(dβ3) %*% F3
+ grad_β[i,] <-
+ weights[1] * t(dβ) %*% F1 +
+ weights[2] * t(dβ2) %*% F2 +
+ weights[3] * t(dβ3) %*% F3
}
grad <- c(grad, as.double(grad_β))
grad = c(grad, #gradient on b
- t( sweep(β, 2, p * G2, '*') ) %*% F1 +
- t( sweep(β2, 2, p * G3, '*') ) %*% F2 +
- t( sweep(β3, 2, p * G4, '*') ) %*% F3 )
+ weights[1] * t( sweep(β, 2, p * G2, '*') ) %*% F1 +
+ weights[2] * t( sweep(β2, 2, p * G3, '*') ) %*% F2 +
+ weights[3] * t( sweep(β3, 2, p * G4, '*') ) %*% F3 )
grad
},
{
"Run optimization from x0 with solver..."
- if (!is.numeric(x0) || any(is.na(x0)) || length(x0) != (d+2)*K-1
- || any(x0[1:(K-1)] < 0) || sum(x0[1:(K-1)]) > 1)
- {
- stop("x0: numeric vector, no NA, length (d+2)*K-1, sum(x0[1:(K-1) >= 0]) <= 1")
- }
-
- op_res = constrOptim( x0, .self$f, .self$grad_f,
+ if (!is.list(x0))
+ stop("x0: list")
+ if (is.null(x0$β))
+ stop("At least x0$β must be provided")
+ if (!is.matrix(x0$β) || any(is.na(x0$β)) || ncol(x0$β) != K)
+ stop("x0$β: matrix, no NA, ncol == K")
+ if (is.null(x0$p))
+ x0$p = rep(1/K, K-1)
+ else if (length(x0$p) != K-1 || sum(x0$p) > 1)
+ stop("x0$p should contain positive integers and sum to < 1")
+ # Next test = heuristic to detect missing b (when matrix is called "beta")
+ if (is.null(x0$b) || all(x0$b == x0$β))
+ x0$b = rep(0, K)
+ else if (any(is.na(x0$b)))
+ stop("x0$b cannot have missing values")
+
+ op_res = constrOptim( linArgs(x0), .self$f, .self$grad_f,
ui=cbind(
rbind( rep(-1,K-1), diag(K-1) ),
matrix(0, nrow=K, ncol=(d+1)*K) ),
# link="probit"; order=2; λ=c(531.8099,586.8893,523.5816); b=c(-118.512674,-3.488020,2.109969)
# Switch to pracma package for that (but it seems slow...)
+ exactComp <- FALSE #TODO: global, or argument...
+
if (exactComp && link == "probit")
{
# Use exact computations