非线性规划—R实现

非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学八大分支之一,20世纪50年代初,库哈(H.W.Kuhn) 和托克 (A.W.Tucker) 提出了非线性规划的基本定理,为非线性规划奠定了理论基础。这一方法在工业、交通运输、经济管理和军事等方面有广泛的应用,特别是在“最优设计”方面,它提供了数学基础和计算方法,因此有重要的实用价值。

一、非线性规划概述

1.非线性规划的标准型

对实际规划问题作定量分析,必须建立数学模型。建立数学模型首先要选定适当的目标变量和决策变量,并建立起目标变量与决策变量之间的函数关系,称之为目标函数。然后将各种限制条件加以抽象,得出决策变量应满足的一些等式或不等式,称之为约束条件。非线性规划问题的一般数学模型可表述为求未知量\(X=(\)\(x_1\),\(x_2\),\(...\),\(x_n\)),使满足约束条件:

\[g_i(X)\geq0\ \ \ i=1,2,...,m \]

\[h_j(X)=0\ \ j=1,2,...p\ \]

并使目标函数\(f(\)\(x_1\),\(x_2\),\(...\),\(x_n\))达到最小值(或最大值),其中\(f\)\(g_i\)\(h_j\)都是定义在\(n\)维向量空间\(R_n\)的某子集\(D\)(定义域)上的实值函数,且至少有一个是非线性函数。
上述模型可简记为:

\[min \ \ \ f(X)\\\ \ \ s.t. \begin{cases} g_i(X)\leq0\ \ \ i=1,2,...,m \\ h_j(X)=0\ \ j=1,2,...p\ \\X_L\leq\ X \leq\ X_U \end{cases} \]

其中\(X=(\)\(x_1\),\(x_2\),\(...\),\(x_n\))属于定义域\(D\),符号\(min\)表示“求最小值”,符号\(s.t.\)表示“受约束于”。这是本文采用的非线性规划的标准型,为了和软件要求的一致,但与运筹学中常用的非线性规划标准型不一致,运筹学标准型一般要求不等式约束"\(\geq\)"。
定义域\(D\) 中满足约束条件的点称为问题的可行解。全体可行解所成的集合称为问题的可行集。对于一个可行解\(x^*\),如果存在\(x^*\)的一个邻域,使目标函数在\(x^*\)处的值\(f(x^*)\)优于 (指不大于或不小于)该邻域中任何其他可行解处的函数值,则称\(x^*\)为问题的局部最优解(简称局部解)。如果\(f(x^*)\)优于一切可行解处的目标函数值,则称x*为问题的整体最优解(简称整体解)。非线性规划问题要求给出整体解,而现有解法大多只是求出局部解,不过在许多实际场景下这个局部解也是整体解。

2.非线性规划求解方法

无约束法

指寻求\(n\)元实函数\(f\)在整个\(n\)维向量空间\(R_n\)上的最优值点的方法。这类方法的意义在于:虽然实用规划问题大多是有约束的,但许多约束最优化方法可将有约束问题转化为若干无约束问题来求解。无约束最优化方法大多是逐次一维搜索的迭代算法。这类迭代算法可分为两类: 一类需要用目标函数的导函数,称为解析法。另一类不涉及导数,只用到函数值,称为直接法。
这些迭代算法的基本思想是:在一个近似点处选定一个有利搜索方向,沿这个方向进行一维寻查,得出新的近似点。然后对新点施行同样手续,如此反复迭代,直到满足预定的精度要求为止。根据搜索方向的取法不同,可以有各种算法。属于解析型的算法有:①梯度法:又称最速下降法。这是早期的解析法,收敛速度较慢。②牛顿法:收敛速度快,但不稳定,计算也较困难。③共轭梯度法:收敛较快,效果较好。④变尺度法:这是一类效率较高的方法。其中达维登-弗莱彻-鲍威尔变尺度法,简称 DFP法,是最常用的方法。属于直接型的算法有交替方向法(又称坐标轮换法)、模式搜索法、旋转方向法、鲍威尔共轭方向法和单纯形加速法等。

约束法

常用的约束最优化方法有4种:①拉格朗日乘子法:它是将原问题转化为求拉格朗日函数的驻点。②制约函数法:又称系列无约束最小化方法,简称SUMT法。它又分两类,一类叫惩罚函数法,或称外点法;另一类叫障碍函数法,或称内点法。它们都是将原问题转化为一系列无约束问题来求解。③可行方向法:这是一类通过逐次选取可行下降方向去逼近最优点的迭代算法。如佐坦迪克法、弗兰克-沃尔夫法、投影梯度法和简约梯度法都属于此类算法。④近似型算法:这类算法包括序贯线性规划法和序贯二次规划法。前者将原问题化为一系列线性规划问题求解,后者将原问题化为一系列二次规划问题求解。

二、非线性规划求解—R实现

下面循序渐进给出非线性规划求解的实例,分无约束、只带有不等式约束、带有等式约束的非线性规划来求解。

0. R语言包nloptr加载

R语言常用的处理非线性规划的包为“nloptr”,这个包要求手工计算目标函数和约束函数的梯度。
!!!注意这个包采用的非线性规划的标准型:目标函数要求\(min\),不等式约束要求“$\leq$”。

install.packages("nloptr")
library(nloptr)

1. 无约束非线性规划

无约束规划中没有约束条件,只需要对目标函数取极值。
例1 求函数\(f(x)=12x-3x^4-2x^6\)的极大值。

1.1 R求解程序

!!!R语言的nloptr包默认求解的是极小值,因此若要求最大值只需加个负号就行。

library(nloptr)                                  #加载nloptr非线性规划包
eval_f = function(x){
  return(list('objective'=-(12*x-3*x^4-2*x^6),   #输入目标函数
              'gradient'=-c(12-12*x^3-12*x^5)))  #一阶导数要手动算一下
}
res1 = nloptr(x0 = c(0),  #给x赋一个初值,优化算法会不断迭代
              eval_f = eval_f,
              lb = c(-Inf),  #下界是负无穷
              ub = c(Inf),   #上界是正无穷
               opts = list('algorithm'='NLOPT_LD_MMA',"xtol_rel"=1.0e-8))
1.2 计算结果
res1$solution
[1] 0.8376198                #解x=0.8376198
res1$objective
[1] -7.883946                #目标函数值f(x)=-7.883946,但题中要求的是极大值,所以原问题的极大值为7.883946

2. 只有不等式约束的非线性规划

例2 求下面非线性规划的解。

\[min\ \ z=-x_1-2x_2+0.5x_1^2+0.5x_2^2 \\\ \ \ s.t. \begin{cases} 2x_1+3x_2\leq6\\ x_1+4x_2\leq5\\0\leq\ x_1\ ,0\leq\ x_2 \end{cases} \]

2.1 R求解程序
library(nloptr) 
eval_f = function(x){
  return(list('objective'=-x[1]-2*x[2]+0.5*x[1]^2+0.5*x[2]^2,
              'gradient'=c(-1+x[1],-2+x[2])))
}
eval_g = function(x){
  return(list('constraints' = c(2*x[1]+3*x[2]-6,x[1]+4*x[2]-5),
              'jacobian' = rbind(c(2,3),c(1,4))))
}
res2=nloptr(x0 = c(0,0),
            eval_f = eval_f,
            lb = c(0,0),
            ub = c(Inf,Inf),
            eval_g_ineq = eval_g,
             opts = list('algorithm'='NLOPT_LD_MMA',"xtol_rel"=1.0e-8))
2.2 计算结果
res2$solution  
[1] 0.7646988 1.0588253       #解x1=0.7646988,x2=1.0588253
res2$objective
[1] -2.029412                 #目标函数值z=-2.029412

3. 约束条件含等式的非线性规划

例3 求下面非线性规划的解。

\[min \ \ \ z=x_1^2+x_2^2+8\\\ \ \ s.t. \begin{cases} x_1^2-x_2\geq0\\ \ -x_1+x_2^2+2=0\ \\0\leq\ x_1 ,0 \leq\ x_2 \end{cases} \]

3.1 R求解程序
library(nloptr) 
eval_f = function(x){
  return(list('objective'=x[1]^2 + x[2]^2 + 8,
              'gradient'=c(2*x[1],2*x[2])))
}
eval_g = function(x){
  return(list('constraints' = c(x[2]-x[1]^2),
              'jacobian' = rbind(c(-2*x[1],1))))
}
eval_h = function(x){
  return(list('constraints' = c(-x[1]-x[2]^2+2),
              'jacobian' = rbind(c(-1,-2*x[2]))))
}

local_opts <- list( "algorithm" = "NLOPT_LD_MMA",
                    "xtol_rel" = 1.0e-7 )
opts <- list( "algorithm" = "NLOPT_LD_AUGLAG",
              "xtol_rel" = 1.0e-7,
              "maxeval" = 1000,
              "local_opts" = local_opts )
res3 = nloptr(x0 = c(0,0),
              eval_f = eval_f,
              lb = c(0,0),
              ub = c(Inf,Inf),
              eval_g_ineq = eval_g,
              eval_g_eq = eval_h,
              opts=opts)
3.2 计算结果
res3$solution
[1] 2 0                      #解x1=2,x2=0
res3$objective
[1] 12                       #目标函数值z=12

总结

在经营管理、工程设计、科学研究、军事指挥等方面普遍地存在着最优化问题。例如:如何在现有人力、物力、财力条件下合理安排产品生产,以取得最高的利润;如何设计某种产品,在满足规格、性能要求的前提下,达到最低的成本;如何确定一个自动控制系统的某些参数,使系统的工作状态最佳;如何分配一个动力系统中各电站的负荷,在保证一定指标要求的前提下,使总耗费最小;如何安排库存储量,既能保证供应,又使储存费用最低;如何组织货源,既能满足顾客需要,又使资金周转最快等。对于静态的最优化问题,当目标函数或约束条件出现未知量的非线性函数,且不便于线性化,或勉强线性化后会招致较大误差时,就可应用非线性规划的方法去处理。

原创文献

R语言-运筹学非线性规划实例

posted @ 2022-04-30 18:00  郝hai  阅读(1787)  评论(0编辑  收藏  举报