我不熟悉求解器(优化),我想找到最大化非线性函数的x1和x2的最佳值。
a1 = 0.000176
b1 = 26.51410219
a2 = 0.0000403
b2 = 158.4966186
max
fn = (b1*(1-exp(-a1*x1))+(b2*(1-exp(-a2*x2)))
Subject to
x1 + x2 <=20000
x1 <=15000
x2 >= 9000
如果我要在excel中这样做(我想在这种情况下使用R),我得到以下值; fn = 152,x1 = 5695,x2 = 14305。 我查看了quadprog软件包,但是我无法正常工作。 我真的很感激你能提供的任何帮助。
答案 0 :(得分:2)
我认为你需要另一个关闭表达式才能最大化。目前还不清楚你是否想要fn或fn2:
fn = function(x1,x2){ (b1*(1-exp(-a1*x1))) + (b2*(1-exp(-a2*x2))) }
fn2 = function(x1,x2){ (b1*(1-exp(-a1*x1)) + (b2*(1-exp(-a2*x2)))) }
施加约束的一种方法是在边界处减去大值:
optim(par=list(10000, 10000), fn=function(x){
# starting values inside constraint boundaries
( b1*(1-exp(-a1*x[1]))+(b2*(1-exp(-a2*x[2]))) -
200000*( ( x[1]+x[2])> 20000) -
200000*(x[1]>15000) -
200000*(x[2] < 9000) )},
control=list(fnscale=-1) # to make max
)
#---------
$par
[1] 2215.306 17784.694
$value
[1] 89.65546
$counts
function gradient
197 NA
$convergence
[1] 0
$message
NULL
> 2215.306 + 17784.694
[1] 20000
你可以看到fn2
我建议的R方法优于Excel结果:
> fn2( x1 = 5695 , x2 = 14305)
[1] 86.22543
> fn2(2215.306 , 17784.694)
[1] 89.65546
也可以对敏感度进行图形检查,将值设置在边界之外会抑制图中的外观:
vals <- outer(X=seq(5000,20000,by=1000), Y=seq(5000,20000,by=1000), FUN=function(x,y) ( b1*(1-exp(-a1*x))+(b2*(1-exp(-a2*y))) ) )
constr1 <- outer(X=seq(5000,20000,by=1000), Y=seq(5000,20000,by=1000), FUN=function(x,y) ( x+y >20000 ) )
constr2 <- outer(X=seq(5000,20000,by=1000), Y=seq(5000,20000,by=1000), FUN=function(x,y) ( x >15000 ) )
constr3 <- outer(X=seq(5000,20000,by=1000), Y=seq(5000,20000,by=1000), FUN=function(x,y) ( y < 9000 ) )
vals[constr1] <- NA
vals[constr2] <- NA
vals[constr3] <- NA
persp(x=seq(5000,20000,by=1000), y=seq(5000,20000,by=1000),z=vals,ticktype="detailed", las=3,ylab="",theta=-45)
答案 1 :(得分:0)
使用constrOptim可以获得类似的结果,但是约束应该具有Ax&gt; = b的形式。
fn = function(x){
(26.51410219*(1-exp(-0.000176*x[1]))) + (158.4966186*(1-exp(-0.0000403*x[2])))
}
将约束重写为
x1 +x2 <=20000 --> -x1 –x2 >= -20000
x1 <= 15000 --> -x1 >= -15000
x2 >= 9000
A = matrix(c(-1,-1,-1,0,0,1),nrow=3,byrow=T)
b = c(-20000,-15000,9000)
constrOptim(c(5000,10000),fn,NULL,A,b,control=list(fnscale=-1))
$par
[1] 2275.632 17724.367
$value
[1] 89.65666