【问题标题】:R optimization with equality and inequality constraints具有等式和不等式约束的 R 优化
【发布时间】:2015-08-10 05:23:51
【问题描述】:

我试图找到一个函数的局部最小值,并且参数有一个固定的总和。例如,

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 中使用不等式来强制固定总和。我仍然认为这可能是一个合理的解决方法,但我无法让它发挥作用。这是实际问题的简化示例,但非常感谢任何帮助。

【问题讨论】:

  • 重写 fx = function(x) {10 - (5*x[1] + 2*x[2] + (15 - x[3] - x[2]))} 并添加x[1] + x[2] 的附加约束

标签: r statistics mathematical-optimization minimization


【解决方案1】:

在这种情况下,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的选择是函数根据约束条件的解和全局最小值。

这个功能很好用!

【讨论】:

  • 关于您对使用 constrOptim 的评论,您可以使用例如:opt = constrOptim(c(5, 5, 5), Fx, ui=rbind(diag(c(1, 1, 1)), c(1, 1, 1), -c(1, 1, 1)), ci=c(0, 0, 0, 15-1e-4, -15-1e-4), method='Nelder-Mead', control=list(reltol=1e-10))
【解决方案2】:

这实际上是一个线性规划问题,因此一种自然的方法是使用线性规划求解器,例如 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

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

【讨论】:

  • 不错的一个!当 OP 说:“这是真正问题的简化示例”时,我认为实际问题可能是非线性的。因此,为了确保我建议了一种非线性方法(即使速度较慢,它仍然有效)。如果速度是一个问题,提供梯度(在这种情况下很简单)会使它更快。无论如何,我不是说不好,你添加这个答案真的很好,绝对有帮助。
  • 你能看看这个问题吗? stackoverflow.com/questions/68280857/r-x-probs-outside-0-1 谢谢!
【解决方案3】:

重写

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

并添加额外的约束

x[1] + x[2] &lt;= 15

【讨论】:

    【解决方案4】:

    除了使用外部库,您可以稍微不同地定义问题:

    x1 + x2 + x3 = 15 等价于1/15 (x1+x2+x3) = 1,我将其表示为y1+y2+y3=1

    所以x1 等于y1 的 15 倍。

    现在,您可以将 y 定义为 softmax 函数的输出 - 这可以确保 y 是非负数并且总和为 1。所以 y = softmax(z)

    为了得到完整的转换,我们可以这样写:

    softmax.15 = function(z) {
      y = exp(z)/sum(exp(z))
      x = 15*y
      return(x)
    }
    

    现在您可以使用新变量对问题进行无约束优化:

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

    这会输出最优的z,所以只需记住对输出再次进行转换以获得最优的x

    softmax.15(opt$par)
    # [1] 1.500000e+01 2.445345e-08 1.147868e-08
    

    【讨论】:

      猜你喜欢
      • 2015-10-08
      • 1970-01-01
      • 1970-01-01
      • 2019-05-23
      • 2018-07-24
      • 2018-03-15
      • 1970-01-01
      • 2016-07-19
      • 1970-01-01
      相关资源
      最近更新 更多