我正在尝试在R中执行约束优化。我已经查看了这些帖子以及其他几个帖子:
function constrained optimization in R
上面的第一篇文章非常有帮助,但我仍然无法正确回答问题。
我的功能是:
Fd <- 224 * d1 + 84 * d2 + d1 * d2 - 2 * d1^2 - d2^2
我的约束是:3 * d1 + d2 = 280
首先,我使用无约束的穷举搜索然后进行约束穷举搜索找到正确的答案:
my.data <- expand.grid(x1 = seq(0, 200, 1), x2 = seq(0, 200, 1))
head(my.data)
dim(my.data)
d1 <- my.data[,1]
d2 <- my.data[,2]
Fd <- 224 * d1 + 84 * d2 + d1 * d2 - 2 * d1^2 - d2^2
new.data <- data.frame(Fd = Fd, d1 = d1, d2 = d2)
head(new.data)
# identify values of d1 and d2 that maximize Fd without the constraint
new.data[new.data$Fd == max(new.data$Fd),]
# **This is the correct answer**
# Fd d1 d2
# 6157 11872 76 80
# Impose constraint
new.data <- new.data[(3 * new.data$d1 + new.data$d2) == 280, ]
# identify values of d1 and d2 that maximize Fd with the constraint
new.data[new.data$Fd == max(new.data$Fd),]
# **This is the correct answer**
# Fd d1 d2
# 14743 11774 69 73
现在使用optim
找到无约束的最大值。这很有效。
Fd <- function(betas) {
b1 = betas[1]
b2 = betas[2]
(224 * b1 + 84 * b2 + b1 * b2 - 2 * b1^2 - b2^2)
}
# unconstrained
optim(c(60, 100), Fd, control=list(fnscale=-1), method = "BFGS", hessian = TRUE)
# $par
# [1] 75.99999 79.99995
现在使用constrOptim
找到受限制的最大值。这不起作用。
b1.lower.bound <- c(0, 280)
b1.upper.bound <- c(93.33333, 0)
b2.lower.bound <- c(93.33333, 0)
b2.upper.bound <- c(0, 280)
theta = c(60,100) # starting values
ui = rbind(c(280,0), c(0,93.33333)) # range of allowable values
theta %*% ui # obtain ci as -1 * theta %*% ui
# [,1] [,2]
# [1,] 16800 9333.333
constrOptim(c(60,100), Fd, NULL, ui = rbind(c(280,0), c(0,93.33333)), ci = c(-16800, -9333.333), control=list(fnscale=-1))
# $par
# [1] 75.99951 80.00798
我尝试使用ui
和ci
,但似乎无论我使用什么值,我都会得到与无约束optim
相同的答案。
感谢您的任何建议。
答案 0 :(得分:1)
这里我已经实施了G.格洛腾迪克的建议,它似乎回到了正确的答案。虽然,理想情况下我想学习如何使用约束优化获得正确的答案。我在这里使用了布伦特方法,因为只有一个变量。请注意,我必须在optim
语句中提供上限和下限。
# Find maxima using optim and substitution. First remove b2
#
# 3 * b1 + b2 = 280
#
# b2 = (280 - 3 * b1)
Fd <- function(betas) {
b1 = betas[1]
(224 * b1 + 84 * (280 - 3 * b1) + b1 * (280 - 3 * b1) - 2 * b1^2 - (280 - 3 * b1)^2)
}
optim(c(60), Fd, method = "Brent", lower = 0, upper = 93.33333, control=list(fnscale=-1))
# $par
# [1] 69
# Now remove b1
#
# 3 * b1 + b2 = 280
#
# b1 = ((280 - b2) / 3)
Fd <- function(betas) {
b2 = betas[1]
(224 * ((280 - b2) / 3) + 84 * b2 + ((280 - b2) / 3) * b2 - 2 * ((280 - b2) / 3)^2 - b2^2)
}
optim(c(100), Fd, method = "Brent", lower = 0, upper = 280, control=list(fnscale=-1))
# $par
# [1] 73
答案 1 :(得分:1)
constrOptim()
使用线性不等式约束,并按ui %*% param - ci >= 0
定义可行区域。如果约束为3 * d1 + d2 <= 280
,则ui
为c(-3, -1)
,ci
为-280
。
Fd <- function(betas) {
b1 = betas[1]
b2 = betas[2]
(224 * b1 + 84 * b2 + b1 * b2 - 2 * b1^2 - b2^2)
}
theta = c(59.999,100) # because of needing " ui %*% inital_par - ci > 0 "
ui = c(-3, -1)
ci = -280 # those ui & ci mean " -3*par[1] + -1*par[2] + 280 >= 0 "
constrOptim(theta, Fd, NULL, ui = ui, ci = ci, control=list(fnscale=-1))
# $par
# [1] 69.00002 72.99993
如果您不想要不平等而不是平等约束,那么最好使用Rsolnp
或alabama
包。他们可以使用不等式和/或相等约束(参见Constrained Optimization library for equality and inequality constraints)。
library(Rsolnp); library(alabama);
Fd2 <- function(betas) { # -1 * Fd
b1 = betas[1]
b2 = betas[2]
-1 * (224 * b1 + 84 * b2 + b1 * b2 - 2 * b1^2 - b2^2)
}
eqFd <- function(betas) { # the equality constraint
b1 = betas[1]
b2 = betas[2]
(3 * b1 + b2 -280)
}
solnp(pars = c(60, 100), fun = Fd2, eqfun = eqFd, eqB = 0)
auglag(par = c(60, 100), fn = Fd2, heq = eqFd)