与线性规划不同的是,非线性规划要求目标函数或约束条件中含有非线性函数。相应的求解这类问题就要用到非线性规划的方法。约束条件或者目标函数的放宽使得规划模型更具普适性,但也增加了问题求解的难度。对于简单的非线性规划问题,R语言中stat包即可求解。在这里我们给大家介绍R语言中求解非线性规划更为专业的Rdonlp2包。
Rdonlp2在求解非线性规划问题上功能十分强大,用户可自行安装并查阅帮助文档:
library(Rdonlp2)
Rdonlp2包的核心函数为 donlp2,可以快速求解非线性规划的最值。其用法如下:
donlp2(par,fn,
par.upper=rep(+Inf,length(par)),
par.lower=rep(+Inf,length(par)),
A=NULL,
lin.upper=rep(+Inf,length(par)),
lin.lower=rep(-Inf,length(par)),
nlin=list(),
nlin.upper=rep(+Inf,length(nlin)),
nlin.lower=rep(-Inf,length(nlin)),
control=donlp2.control(),
control.fun=function(lst){return(TRUE)},
env=.GlobalEnv,
name="Rdonlp2"
)
对该函数众多参数进行解释:
par : 初始迭代向量
fn : 连续型函数
par.upper、par.lower : 自变量的上下限
A:线性约束矩阵
lin.upper、lin.lower : 线性约束条件的上下界
nlin : 非线性约束条件函数列表
nlin.upper、nlin.lower : 非线性约束条件的上下界
其余参数可忽略。
用Rdonlp2包编写非线性规划计算命令:
library(Rdonlp2)
p=c(0,0) #迭代初始值
par.l=c(-100,100);par.u=c(100,100)#自变量定义域约束
fn=function(x){
exp(x[1])*(4*x[1]^2+2*x[2]^2+4*x[1]*x[2]+2*x[2]+1)
} #目标函数
A=matrix(c(1,1,3,-1),2,byrow=TRUE)
lin.l=c(2,1);lin.u=c(+Inf,3) #线性约束
nlcon1=function(x){
-x[1]*x[2]
} #非线性约束
donlp2(p,fn,par.u,par.l,A,lin.l=lin.l,lin.u=lin.u,
nlin=list(nlcon1))
$message
[1] "KT-conditions satisfied, no further correction computed"
$par
[1] 33.66667 100.00000
$gradf
[1] 1.625065e+19 2.243635e+17
相应运行结果包括中间过程、算法参数、运行时间等数据,这里就不全部列出。
再看一例利用Rdonlp2包求解二元rastrigin函数最小值的问题。该函数因为有众多极值点而仅有一个最值点对各类优化算法有一定的欺骗性,但用其来测试各类优化算法效果显著。该二元rastrigin函数为:
先作出该函数的三维图像:
a<-5
x<-seq(-a,a,0.01)
y<-seq(-a,a,0.01)
f<-function(x,y){
x^2-10*sin(2*pi*x)+y^2-10*cos(2*pi*y)+20
}
z<-outer(x,y,f)
image(x,y,z,col=heat.colors(24))
library(rgl)
zorder<-rank(z)
persp3d(x,y,z,col=rainbow(as.integer(max(zorder)))[zorder])
fn<-function(x){
f<-sum(x^2*cos(2*pi*x)+10)
}
par<-c(-500,500)
ret<-donlp2(par,fn)
ret$f
[1] 20
ret$par
[1] -2.654965e-06 2.654965e-06
由输出结果可知该函数最小值为20 。所以Rdonlp2求解非线性规划也是非常方便的。当然了,还有很多更为一般的非线性规划问题是Rdonlp2包也不能解决的,这时候可能会向遗传算法、模拟退火这些启发式算法求助啦。这里且不作讨论。
在许多实际问题中,衡量一个方案的好坏标准往往不止一个,例如制造一枚导弹,既要射程远又要最省燃料,还得精度高。这一类问题就不是单一的目标规划问题了,我们称之为多目标规划问题。
求解多目标规划问题通常有主要目标法、分层序列法和线性加权求和法等方法。其中主要目标法通过确定一个主要目标,将多目标优化问题转化为线性或非线性规划问题;分层序列法是将目标中多个目标按照其重要程度排一个次序而逐步求解的过程;线性加权法则是对各目标赋予一个权数,加权求和得到一个新的目标函数而进行求解的过程。
R语言中多目标规划问题的求解通常用goalprog包,其核心函数为llgp:
llgp(coefficient,targets,achievements,maxiter=1000,verbose=FALSE)
其中coefficient为约束系数矩阵,targets为系数矩阵约束向量,achievements是包含objective、priority、p、n的目标函数,其中objective表示第几对偏差变量,priority表示该偏差变量的优先级,p和n分别为正负偏差变量的权系数。
看一道多目标规划问题计算实例:(该题来自钱颂迪《运筹学》教材4.4节例5)
llgp函数计算过程如下:
library(goalprog)
coefficients<-matrix(c(1,1,5,1,1,0,3,1),4)
targets<-c(10,4,56,12)
achievements<-data.frame(objective=1:4,priority=c(1,1,3,4),
p=c(2,3,0,1),n=c(0,0,1,0))
soln<-llgp(coefficients,targets,achievements)
soln$converged
[1] TRUE
soln$out
Decision variables
X
X1 4.000000e+00
X2 6.000000e+00
Summary of objectives
Objective Over Under Target
G1 1.000000e+01 0.000000e+00 0.000000e+00 1.000000e+01
G2 4.000000e+00 0.000000e+00 0.000000e+00 4.000000e+00
G3 3.800000e+01 0.000000e+00 1.800000e+01 5.600000e+01
G4 1.000000e+01 0.000000e+00 2.000000e+00 1.200000e+01
Achievement function
A
P1 0.000000e+00
P2 0.000000e+00
P3 1.800000e+01
P4 0.000000e+00
由输出的结果我们可以看到x1、x2最优值分别为4和6。
由该例我们可以看出,R语言求解多目标规划问题只需按照函数格式将规划的目标函数、约束条件套入格式即可,过程非常简单。
参考文献:
魏太云.R软件与最优化[C]//中国r语言会议.2008.