用总和约束解决 R 中的简单二次优化

solve simple quadratic optimization in R with sum constraint

我想在 R 中解决一个非常简单的二次优化问题,其中一个约束是与向量和相关的等式约束。我尝试使用 quadprog 包,但我不知道如何让它工作。帮助函数不提供其中一个约束等于总和的示例。但也许 quadprog 不是正确的软件包...

我的问题如下。我想 shrink/expand 一个值向量,使得总和等于一个设定值,并且它们的值受 0 和最大值的约束。由于结果需要尽可能接近初始值,所以我想最小化残差平方和。下面我展示了一个玩具示例。很容易看出例如(5,5,6)在解space中但不是最优解。

x_start <- c(4,3,7)
tot <- 16

# Objective function that needs to be minimized
obj <- function(x){return((x-x_start)^2)}

# Subject to: 
# Sum constraint
con1 <- function(x) {return(sum(x)-tot)}

# Bounds 0 <= x <=6
x_max <- 6
x_min <- 0

R 中有许多包可用于此目的。查看 CRAN 上的优化任务视图:https://cran.r-project.org/web/views/Optimization.html

这里有两种可能。

1) CVXR我们可以使用CVXR进行凸优化

library(CVXR)

x_start <- c(4,3,7)
tot <- 16

x <- Variable(3)
objective <- Minimize(sum((x - x_start)^2))
constraints <- list(sum(x) == tot, x >= 0, x <= 6)
problem <- Problem(objective, constraints)
soln <- solve(problem)
xval <- soln$getValue(x)
xval
##          [,1]
## [1,] 5.500036
## [2,] 4.499964
## [3,] 6.000000

soln$value
## [1] 5.5

soln$status
## [1] "optimal"

2) limSolve 另一个可以做到这一点的包是 limSolve。这解决了在向量 x 上最小化 ||Ax-B||^2 的问题,满足 Ex = F 和 Gx >= H.

library(limSolve)
lsei(A = diag(3), B = x_start, 
  E = rep(1, 3), F = tot, 
  G = rbind(diag(3), -diag(3)), H = c(0, 0, 0, -6, -6, -6))

给予:

$X
[1] 5.5 4.5 6.0

$residualNorm
[1] 7.105427e-15

$solutionNorm
[1] 5.5

$IsError
[1] FALSE

$type
[1] "lsei"

尝试以矩阵和向量形式表达您的二次问题(即 objective 和约束)。对于 sum 约束,您可以使用向量之和与 1 向量的点积这一事实,因此约束矩阵上的相应行是 c(1,1,1) 并且该约束的 rhs 是 tot.

根据the documentationsolve.QP(Dmat, dvec, Amat, bvec, meq=0, factorized=FALSE)中的meq参数指定为等式约束的约束个数,

the first meq constraints are treated as equality constraints

因此将此参数更改为 1(或您需要的任意多个等式约束)并使 Amat 的第一列成为一个向量。