用总和约束解决 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 documentation,solve.QP(Dmat, dvec, Amat, bvec, meq=0, factorized=FALSE)
中的meq
参数指定为等式约束的约束个数,
the first meq
constraints are treated as equality constraints
因此将此参数更改为 1(或您需要的任意多个等式约束)并使 Amat
的第一列成为一个向量。
我想在 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 documentation,solve.QP(Dmat, dvec, Amat, bvec, meq=0, factorized=FALSE)
中的meq
参数指定为等式约束的约束个数,
the first
meq
constraints are treated as equality constraints
因此将此参数更改为 1(或您需要的任意多个等式约束)并使 Amat
的第一列成为一个向量。