R语言中优化函数

线性规划: lpSolve 包 中的lp函数,linprog包中的 solveLP函数

无约束或区间约束的优化问题可以利用stat包中的optim()optimize函数:

https://blog.csdn.net/shen19920619/article/details/55094994
https://segmentfault.com/a/1190000011761522

optim函数的例子

#求解局部最优值
f <- function(x) (x[1]^2 + x[2] - 11)^2 + (x[1] + x[2]^2 - 7)^2
optim(par=初值,fn,method=c(),lower=下界,upper=上界)$par
#这个函数需要提供初值,只能实现最小化,可以处理高维
optimize(f, interval, lower = min(interval), upper = max(interval),maximum = FALSE,tol = 误差精度)
#这个函数需要提供区间

result=optim(c(0.2,0.3),f)

线性约束的二次规划问题的求解可以利用quadprog包:

https://blog.csdn.net/littlely_ll/article/details/53946628

二次规划的一般形式:

在这里插入图片描述

solve.QP()函数

solve.QP()是该函数只解决严格的凸二次规划问题,求极小值。

solve.QP(Dmat, dvec, Amat, bvec, meq=0, factorized=FALSE) 
函数参数: 
- Dmat: 为Hessian矩阵 
- dvec: 为向量,和Dmat相对应 
- Amat: 约束的系数矩阵,默认约束为“≥” 
- bvec: 为向量,和Amat相对应 
- meq: 表示从哪一行开始Amat矩阵中的约束是等式,默认为0 
VALUE: 
- solution: 二次规划问题中向量的取值 
- value: 标量,二次规划目标函数的取值 
- unconstrained.solution: 没有约束条件下向量的取值

例子:

在这里插入图片描述
代码如下:

D <- matrix(c(1,0,0,2),nr=2)
d <- c(3,1)
A <- t(matrix(c(1,-1,2,1,2,-1),nr=3))##函数表达式中为A^T,而在程序中需要输入A。
b0 <- c(2,1,-4)
solve.QP(Dmat = D,dvec = d, Amat = A,bvec = b0)

$solution
[1] 2.0 1.5

$value
[1] -3.25

$unconstrained.solution
[1] 3.0 0.5

$iterations
[1] 2 0

$Lagrangian
[1] 0 1 0

$iact
[1] 2

在约束条件下,x=2.0,y=1.5x=2.0,y=1.5,目标函数最小值为-3.25;在无约束条件下x=3.0,y=0.5x=3.0,y=0.5。

线性约束的二次规划问题也可以利用osqp

这个是OXFORD大学随后提供的优化包。
安装:

install.packages("remotes")
remotes::install_github("r-lib/remotes#103")
remotes::install_git("git://github.com/OxfordControl/osqp-r",submodules = TRUE)

例子:

在这里插入图片描述

library(osqp)
library(Matrix)

# Define problem data
P <- Matrix(c(4., 1.,
              1., 2.), 2, 2, sparse = TRUE)
q <- c(1., 1.)
A <- Matrix(c(1., 1., 0.,
              1., 0., 1.), 3, 2, sparse = TRUE)
l <- c(1., 0., 0.)
u <- c(1., 0.7, 0.7)

# Change alpha parameter and setup workspace
settings <- osqpSettings(alpha = 1.0)
model <- osqp(P, q, A, l, u, settings)

# Solve problem
res <- model$Solve()

来源参考:https://osqp.org/docs/examples/setup-and-solve.html

非线性优化函数nloptr

nloptr是一个在R中用于非线性优化的包。它提供了一种寻找目标函数的最小值或最大值的方法。nloptr包中的函数可以通过设置不同的参数来使用不同的优化算法。

以下是nloptr包中最常用的函数:

  • nloptr:这是nloptr包中最重要的函数,用于执行非线性优化。它接受初始值、目标函数、约束条件等参数,并返回优化结果。

  • nloptrx:这个函数提供了一个更灵活的接口,可以用于更复杂的优化问题,包括非线性约束和不等式约束。

  • auglag:这个函数可以用于求解带有约束的非线性优化问题,使用增广拉格朗日方法进行求解。

  • slsqp:这个函数是一个特定的优化算法,用于求解带有约束的非线性优化问题。

实例


library(nloptr)

# 定义目标函数
objective <- function(x) {
  return(x^2 + 5*sin(x))
}

# 设置初始值
x0 <- 1

# 进行优化
result <- nloptr(x0 = x0, eval_f = objective, opts = list("algorithm" = "NLOPT_LN_COBYLA"))

# Call:
#   
#   nloptr(x0 = x0, eval_f = objective, opts = list(algorithm = "NLOPT_LN_COBYLA"))
# 
# 
# 
# Minimization using NLopt version 2.7.1 
# 
# NLopt solver status: 4 ( NLOPT_XTOL_REACHED: Optimization stopped 
#                          because xtol_rel or xtol_abs (above) was reached. )
# 
# Number of Iterations....: 24 
# Termination conditions:  relative x-tolerance = 1e-04 (DEFAULT) 
# Number of inequality constraints:  0 
# Number of equality constraints:    0 
# Optimal value of objective function:  -3.24639426722972 
# Optimal value of controls: -1.110552









# 定义目标函数
objective <- function(x) {
  return((x[1]-2)^2 + (x[2]-3)^2)
}

# 设置初始值
x0 <- c(0, 0)

# 进行优化
result <- nloptr(x0 = x0, eval_f = objective, opts = list("algorithm" = "NLOPT_LN_COBYLA"))

# Call:
#   
#   nloptr(x0 = x0, eval_f = objective, opts = list(algorithm = "NLOPT_LN_COBYLA"))
# 
# 
# 
# Minimization using NLopt version 2.7.1 
# 
# NLopt solver status: 4 ( NLOPT_XTOL_REACHED: Optimization stopped 
#                          because xtol_rel or xtol_abs (above) was reached. )
# 
# Number of Iterations....: 39 
# Termination conditions:  relative x-tolerance = 1e-04 (DEFAULT) 
# Number of inequality constraints:  0 
# Number of equality constraints:    0 
# Optimal value of objective function:  1.26010111855728e-08 
# Optimal value of controls: 1.999952 3.000101

利用Rdonlp2包求解非线性约束约束的非线性优化问题

安装代码:

install.packages("Rdonlp2", repos="http://R-Forge.R-project.org")

注意在使用donlp2时upper和lower成对出现,缺省一个就会报错。

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 = donlp2Control(),
    control.fun = function(lst){return(TRUE)},
    env = .GlobalEnv, 
    name = NULL)

使用可参考:
https://blog.csdn.net/qq_27755195/article/details/51458659

安装Rdonlp2包不成功的解决方法

使用命令按章Rdonlp2时提示如下信息:

WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
Package which is only available in source form, and may need
  compilation of C/C++/Fortran: ‘Rdonlp2’
  These will not be installed

表明缺少Rtools,需要下载安装并配置环境变量,然后重启R,下载地址为:https://cran.r-project.org/bin/windows/Rtools/,
具体操作可参考:https://www.cnblogs.com/liugh/p/9937489.html
安装完Rtools还不能正常安装Rdonlp2的话,就从这里https://r-forge.r-project.org/R/?group_id=156下载后本地安装。

非线性约束的非线性优化Rsolnp包

solnp函数

功能:

solnp函数,用于求解光滑的非线性约束非线性优化问题,返回目标函数的局部极小值。

形式:

solnp(pars, fun, eqfun = NULL, eqB = NULL, ineqfun = NULL, ineqLB = NULL,
ineqUB = NULL, LB = NULL, UB = NULL, control = list(), …)

参数:

  • pars: 初值。
  • fun: 目标函数,返回值是一个常数。
  • eqfun: (可选) 返回等式约束的值,多个等式约束返回一个vector.
  • eqB: (可选) 等式约束的约束值,和eqfun的返回结果相一致。
  • ineqfun: (可选) 不等式约束,多个返回由表达式结果组成的向量。
  • ineqLB: (可选) 不等式约束的下界约束,维数和ineqfun返回结果一致。
  • ineqUB:(可选) 不等式约束的上界约束,维数和ineqfun返回结果一致。
  • LB: (可选)优化变量的下界向量。
  • UB: (可选)优化变量的上界向量。
  • control: (可选) 优化器的控制参数。

注意,有些时候在R上进行优化也需要制定一个较大的上下界,以避免函数出错。

control参数:

  • rho: 对跑出可行域的目标函数进行的惩罚权重(默认 1).This is used as a penalty weighting scaler for infeasibility in the augmented objective function.
    The higher its value the more the weighting to bring the solution into the feasible region (default 1). However, very high values might lead to numerical ill conditioning or significantly slow down convergence.
  • outer.iter: 最大的major iterations (默认 400).
  • inner.iter: 最大的minor iterations (默认 800).
  • delta: Relative step size in forward difference evaluation (default 1.0e-7).
  • tol: 精度(默认 1e-8).
  • trace:目标函数值和优化变量在每个major iteration中输出的次数(默认 1).

函数返回值:

  • pars: 优化变量的结果。
  • convergenc: 是否优化成功的指标,0表示优化成功,1或2表示没有优化成功。
  • values: 优化迭代过程中的目标函数值组成的向量,最后一个值是最终的优化结果。
  • lagrange: Lagrange乘子组成的向量。
  • hessian: 最优解时的hessian矩阵。
  • ineqx0: 取得最优解时的,不等式约束的松弛变量(slack variables)。
  • nfuneval: The number of function evaluations.
  • elapsed: 优化所耗费的时间。

例子:

在这里插入图片描述

代码:

library(pacman)
p_load(Rsolnp)

fn1=function(x)
{
  z=x[1]^2*sin(x[2])+x[2]^2*cos(x[1])
  return(z)
}
eqn1=function(x){
  z1=x[1]*x[2]
}
ineqn1=function(x){
  z1=x[1]+x[2]
  z2=3*x[1]-x[2]
  z3=sin(x[1])*cos(x[2])
  return(c(z1,z2,z3))
}
x0 = c(10,10)
powell=solnp(x0, fun = fn1, eqfun = eqn1, eqB = c(2),
             ineqfun = ineqn1,ineqLB = c(2,1,-Inf),
             ineqUB = c(Inf,3,3),LB = c(-100,-100), UB = c(100,100))

结果:

> powell
$pars
[1] 1.403075 1.425440

$convergence
[1] 0

$values
 [1] -138.309264  -40.714718   -5.028974    2.438729    2.315228    2.295481
 [7]    2.295413    2.285524    2.287054    2.287053    2.287053

$lagrange
              [,1]
[1,]  5.424216e-01
[2,] -9.412557e-13
[3,] -7.857526e-13
[4,]  3.065161e-12

$hessian
             [,1]         [,2]        [,3]        [,4]        [,5]
[1,]  0.988384217  0.003371369 -0.02097895 -0.51309600 -0.52773026
[2,]  0.003371369  0.156623138 -0.20311846 -0.05872235  0.35866137
[3,] -0.020978952 -0.203118459  0.90354377 -0.99230133 -0.87784508
[4,] -0.513096002 -0.058722354 -0.99230133  5.80401809 -0.06335659
[5,] -0.527730257  0.358661374 -0.87784508 -0.06335659  1.77786334

$ineqx0
[1] 2.8285155 2.7837853 0.1428122

$nfuneval
[1] 236

$outer.iter
[1] 10

$elapsed
Time difference of 0.04886913 secs

$vscale
[1] 2.28705348 0.00000001 1.00000000 1.00000000 1.00000000 1.00000000
[7] 1.00000000

gosolnp函数

功能:

当目标函数不光滑或者有很多极小值点时,很难判断全局最优解,并且结果往往依赖于初值的选取。该函数可以随机地设置许多初值来运行求解器,以解决前述的问题。

函数形式:

c

参数:

  • pars: 初值。
  • fixed: 需要保持固定而不能随机生成的pars索引。
  • fun: 目标函数,返回值是一个常数。
  • eqfun: (可选) 返回等式约束的值,多个等式约束返回一个vector.
  • eqB: (可选) 等式约束的约束值,和eqfun的返回结果相一致。
  • ineqfun: (可选) 不等式约束,多个返回由表达式结果组成的向量。
  • ineqLB: (可选) 不等式约束的下界约束,维数和ineqfun返回结果一致。
  • ineqUB:(可选) 不等式约束的上界约束,维数和ineqfun返回结果一致。
  • LB: 优化变量的下界向量,该函数是不可选的!
  • UB: 优化变量的上界向量,该函数是不可选的!
  • control: (可选) 优化器的控制参数和solnp函数一致。
  • distr: 一个和优化参数相同维数的向量,表示每个元素产生时服从的分布。 1:uniform, 2: truncated nromal, 3: normal.
  • distr.opt: 当参数产生不服从uniform时,需要设置分布的参数mean和sd.
    -** n.restarts**: 重启求解器的次数。
  • n.sim: 在每一重启求解器时随机参数的个数。注意,如果不等约束存在时,往往会被拒绝。当不等约束的区间比较宽时,这个参数才会用到。
  • cluster: 如果你想用并行计算的话,这里会启动并行池,但是一定要记得关闭并行池!!
  • rseed: (可选) 用初始化随机数产生的种子,不设置时就用系统时间作为种子。

函数返回值:

  • pars: 优化变量的结果。
  • convergenc: 是否优化成功的指标,0表示优化成功,1或2表示没有优化成功。
  • values: 优化迭代过程中的目标函数值组成的向量,最后一个值是最终的优化结果。
  • lagrange: Lagrange乘子组成的向量。
  • hessian: 最优解时的hessian矩阵。
  • ineqx0: 取得最优解时的,不等式约束的松弛变量(slack variables)。
  • nfuneval: The number of function evaluations.
  • elapsed: 优化所耗费的时间。
  • start.pars: 用来重启求解器的参数。

代码:

library(pacman)
p_load(Rsolnp)

fn1=function(x)
{
  z=x[1]^2*sin(x[2])+x[2]^2*cos(x[1])
  return(z)
}
eqn1=function(x){
  z1=x[1]*x[2]
}
ineqn1=function(x){
  z1=x[1]+x[2]
  z2=3*x[1]-x[2]
  z3=sin(x[1])*cos(x[2])
  return(c(z1,z2,z3))
}

res=gosolnp(pars = NULL, fixed = NULL, fun=fn1, eqfun = eqn1, eqB = c(2), 
        ineqfun = ineqn1,ineqLB = c(2,1,-Inf), ineqUB = c(Inf,3,3), LB = c(-100,-100), UB = c(100,100), 
        distr = c(1, 1), distr.opt = list(), n.restarts = 10, n.sim = 20000,cluster = NULL, 
        rseed = NULL,control = list(inner.iter=20))

结果:

> res
$pars
[1] 1.403075 1.425440

$convergence
[1] 0

$values
 [1] -6100.911889  -537.602906   158.772954   246.463384   -48.645892    -7.284604     2.431605     2.317129     2.295495
[10]     2.286594     2.286974     2.287053     2.287053     2.287053

$lagrange
              [,1]
[1,]  5.424216e-01
[2,] -7.233024e-13
[3,]  2.581390e-13
[4,]  3.923091e-12

$hessian
            [,1]        [,2]        [,3]      [,4]        [,5]
[1,]  0.91620341  0.18268745 -0.08606492 -1.102502 -0.46314376
[2,]  0.18268745  0.24258774  0.09443442 -1.041828  0.02485526
[3,] -0.08606492  0.09443442  0.87122932 -2.169818 -0.89204316
[4,] -1.10250227 -1.04182752 -2.16981847 12.382395  1.35653707
[5,] -0.46314376  0.02485526 -0.89204316  1.356537  1.84242189

$ineqx0
[1] 2.8285155 2.7837853 0.1428122

$nfuneval
[1] 344

$outer.iter
[1] 13

$elapsed
Time difference of 0.05988693 secs

$vscale
[1] 2.28705348 0.00000001 1.00000000 1.00000000 1.00000000 1.00000000 1.00000000

$start.pars
[1] 28.34000 82.92805

$rseed
[1] 1580362550
  • 8
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值