具有等式和不等式约束的R优化

问题描述 投票:11回答:3

我正在尝试查找函数的局部最小值,并且参数具有固定的总和。例如,

Fx = 10-5x1 + 2x2-x3

并且条件如下,

x1 + x2 + x3 = 15

((x1,x2,x3)> = 0

其中x1,x2和x3的总和具有已知值,并且都大于零。在R中,看起来像这样,

Fx = function(x) {10 - (5*x[1] + 2*x[2] + x[3])}
opt = optim(c(1,1,1), Fx, method = "L-BFGS-B", lower=c(0,0,0), upper=c(15,15,15))

我还尝试将不等式与constrOptim配合使用以强制求和。我仍然认为这可能是可行的解决方法,但是我无法使其有效。这是实际问题的简化示例,但是任何帮助将不胜感激。

r statistics mathematical-optimization minimization
3个回答
15
投票

在这种情况下,optim显然不起作用,因为您具有相等性约束。 constrOptim出于相同的原因也不会工作(我尝试将等式转换为两个不等式,即大于和小于15,但这不适用于constrOptim)。

但是,有一个专门用于解决此类问题的程序包,即Rsolnp

您可以通过以下方式使用它:

#specify your function
opt_func <- function(x) {
  10 - 5*x[1] + 2 * x[2] - x[3]
}

#specify the equality function. The number 15 (to which the function is equal)
#is specified as an additional argument
equal <- function(x) {
  x[1] + x[2] + x[3] 
}

#the optimiser - minimises by default
solnp(c(5,5,5), #starting values (random - obviously need to be positive and sum to 15)
      opt_func, #function to optimise
      eqfun=equal, #equality function 
      eqB=15,   #the equality constraint
      LB=c(0,0,0), #lower bound for parameters i.e. greater than zero
      UB=c(100,100,100)) #upper bound for parameters (I just chose 100 randomly)

输出:

> solnp(c(5,5,5),
+       opt_func,
+       eqfun=equal,
+       eqB=15,
+       LB=c(0,0,0),
+       UB=c(100,100,100))

Iter: 1 fn: -65.0000     Pars:  14.99999993134  0.00000002235  0.00000004632
Iter: 2 fn: -65.0000     Pars:  14.999999973563  0.000000005745  0.000000020692
solnp--> Completed in 2 iterations
$pars
[1] 1.500000e+01 5.745236e-09 2.069192e-08

$convergence
[1] 0

$values
[1] -10 -65 -65

$lagrange
     [,1]
[1,]   -5

$hessian
          [,1]      [,2]      [,3]
[1,] 121313076 121313076 121313076
[2,] 121313076 121313076 121313076
[3,] 121313076 121313076 121313076

$ineqx0
NULL

$nfuneval
[1] 126

$outer.iter
[1] 2

$elapsed
Time difference of 0.1770101 secs

$vscale
[1] 6.5e+01 1.0e-08 1.0e+00 1.0e+00 1.0e+00

所以得到的最佳值为:

$pars
[1] 1.500000e+01 5.745236e-09 2.069192e-08

这意味着第一个参数是15,其余零和零。这确实是函数的全局最小值,因为x2正在添加到函数中,并且5 * x1对结果的影响(负)比x3大得多。选择15、0、0是解决方案,并根据约束选择函数的全局最小值。

该功能很好用!


4
投票

这实际上是一个线性编程问题,因此自然的方法是使用线性编程求解器,例如lpSolve程序包。您需要提供一个目标函数和一个约束矩阵,求解器将完成其余工作:

library(lpSolve)
mod <- lp("min", c(-5, 2, -1), matrix(c(1, 1, 1), nrow=1), "=", 15)

然后,您可以访问最佳解和目标值(添加常数10,但未提供给求解器):

mod$solution
# [1] 15  0  0
mod$objval + 10
# [1] -65

[线性规划求解器应该比一般的非线性优化求解器快很多,并且应该不难返回精确的最优解(而不是可能会舍入误差的邻近点)。


0
投票

重写

fx = function(x) {10 - (5*x[1] + 2*x[2] + (15 - x[3] - x[2]))}

并添加其他约束条件

x[1] + x[2] <= 15

© www.soinside.com 2019 - 2024. All rights reserved.