如何在 R 中复制 excel 求解器
How to replicate excel solver in R
我使用 excel 求解器解决了一个优化问题,我正试图在 R 中复制它。
我找了很多包比如optim, ROI等等,但是好像都是只以一个vector为对象进行优化,并且允许变量取任意连续值。在我的例子中,我有一个也需要满足的约束矩阵,我的变量只能取二进制值。
这是我要解决的问题:
A-D是机器,1-3是任务,第一个矩阵的数字是用X机器做Y任务产生的值。约束是:A-D可以做且只能做一个任务(不能拆分);每个任务都可以工作,并且只能由一台机器工作。
这是我使用的代码:
par = rep(c(0,1),6)
mat <- matrix(c(9,10,11,4,5,10,1,3,5,7,5,4), nrow = 3)
fr <- function(x) {
y= matrix(x,nrow = 4)
sum(mat %*% y)
}
a = optim(par, fr)
一些问题:如何优化maximum,好像这个函数默认优化minimum?如何向其中添加约束?如何限制二进制变量?
您需要为 objective 函数构造一个向量和一个约束矩阵,最后使用 R LP 求解器之一求解:
library(lpSolve)
costs <- matrix(c(9, 10, 11, 4, 5, 10, 1, 3, 5, 7, 5, 4), nrow=3)
nr <- nrow(costs)
nc <- ncol(costs)
columns <- t(sapply(1:nc, function(x) rep(c(0, 1, 0), c(nr*(x-1), nr, nr*(nc-x)))))
rows <- t(sapply(1:nr, function(x) rep(rep(c(0, 1, 0), c(x-1, 1, nr-x)), nc)))
mod <- lp("max", as.vector(costs), rbind(columns, rows), "<=", rep(1, nr+nc), binary.vec=rep(TRUE, nr*nc))
现在您可以获取解决方案和 objective 函数:
mod$objval
# [1] 27
matrix(mod$solution, nrow=nr)
# [,1] [,2] [,3] [,4]
# [1,] 0 0 0 1
# [2,] 1 0 0 0
# [3,] 0 1 0 0
请注意,像 optim
这样的函数不太适合这个问题,因为它们不考虑约束矩阵,也因为它们不能限制为二进制变量值。
我使用 excel 求解器解决了一个优化问题,我正试图在 R 中复制它。
我找了很多包比如optim, ROI等等,但是好像都是只以一个vector为对象进行优化,并且允许变量取任意连续值。在我的例子中,我有一个也需要满足的约束矩阵,我的变量只能取二进制值。
这是我要解决的问题:
A-D是机器,1-3是任务,第一个矩阵的数字是用X机器做Y任务产生的值。约束是:A-D可以做且只能做一个任务(不能拆分);每个任务都可以工作,并且只能由一台机器工作。
这是我使用的代码:
par = rep(c(0,1),6)
mat <- matrix(c(9,10,11,4,5,10,1,3,5,7,5,4), nrow = 3)
fr <- function(x) {
y= matrix(x,nrow = 4)
sum(mat %*% y)
}
a = optim(par, fr)
一些问题:如何优化maximum,好像这个函数默认优化minimum?如何向其中添加约束?如何限制二进制变量?
您需要为 objective 函数构造一个向量和一个约束矩阵,最后使用 R LP 求解器之一求解:
library(lpSolve)
costs <- matrix(c(9, 10, 11, 4, 5, 10, 1, 3, 5, 7, 5, 4), nrow=3)
nr <- nrow(costs)
nc <- ncol(costs)
columns <- t(sapply(1:nc, function(x) rep(c(0, 1, 0), c(nr*(x-1), nr, nr*(nc-x)))))
rows <- t(sapply(1:nr, function(x) rep(rep(c(0, 1, 0), c(x-1, 1, nr-x)), nc)))
mod <- lp("max", as.vector(costs), rbind(columns, rows), "<=", rep(1, nr+nc), binary.vec=rep(TRUE, nr*nc))
现在您可以获取解决方案和 objective 函数:
mod$objval
# [1] 27
matrix(mod$solution, nrow=nr)
# [,1] [,2] [,3] [,4]
# [1,] 0 0 0 1
# [2,] 1 0 0 0
# [3,] 0 1 0 0
请注意,像 optim
这样的函数不太适合这个问题,因为它们不考虑约束矩阵,也因为它们不能限制为二进制变量值。