惩罚权重 - 优化

时间:2021-03-08 13:13:08

标签: r optimization

我是 R 和优化的新手。我试图优化分为 3 个区域的 5 个月小麦收获期的总收入。我想引入两个约束:

-在每个时间步我只允许在一个区域收获

-开放区域的收获率 (HR) 在 0.1 到 0.5 之间(当然,另外两个区域的收获率为 0)

因此,我想要一种优化,1. 找到要开放的区域,2. 为其分配一个 HR,从而在每个时间步最大化收入。

到目前为止,我已经能够引入带有随机惩罚参数的惩罚函数。但是,它仅适用于很短的时间段(例如,5 或 10 个月)。当我将时间增加到 15 个月或更长时间时,就会为某些时间步长打开两个或三个补丁。 我如何才能确保每月只打开一个补丁并在更长的时间内开放?

我在这里粘贴一个玩具示例。任何建议将不胜感激!


r=3
c=10

biomass = matrix (runif(r*c , 50, 100), r, c)

price = matrix(runif(r*c, 5, 10), r, c)

yield = matrix(NA, r, c)
revenues = yield
value = rep(NA, c)


crop = function(HR){
  
  HR = matrix(HR, r, c) 
  
  for (i in 1:c){  
  
    if (i<c){
    yield[,i] = biomass[,i] * HR[,i]
    revenues[,i] = yield[,i] * price[,i]
    biomass[,i+1] = biomass[,i] - yield[,i]
    value[i] = sum(revenues[,i])
    
    }else{
    yield[,i] = biomass[,i] * HR[,i]
    revenues[,i] = yield[,i] * price[,i]
    value[i] = sum(revenues[,i])
    output=sum(value)
    
    }
   } 
  return(output)
}



penalty <- function(HR) {  
  
  HR1 <- matrix(HR, r, c)
  
  penaltyfun = 12000 * ((HR1[1,]*HR1[3,])^2 + (HR1[1,]*HR1[2,])^2 + (HR1[2,]*HR1[3,])^2)
  
  mainfun <- crop(HR1-penaltyfun)
  
  return(mainfun)
}


HR= matrix(0.1, r, c)
test  = optim(par=as.vector(HR), fn=penalty, lower=0, upper=0.5,
              control = list(fnscale = -1),
              method = 'L-BFGS-B')

options(max.print=100000)
matrix(test$par, r, c)

1 个答案:

答案 0 :(得分:1)

这不是您要找的功能

当你拿着锤子时,一切都开始看起来像钉子。

根据您告诉我们的内容和您的代码,您正在解决这个问题:

  • 您有一系列三元组(生物量1、生物量2、生物量3
  • 以及一系列类似的价格(price1, price2, price3)
  • 根据这些,您可以计算出收入i = 生物量i * 收获率 * 价格i
  • 您的目标是最大限度地提高整个系列的收入。

观察 1:除非您引入其他限制,否则没有理由让收获率小于最大收获面积。1

观察 2:由于收获量与后续生物量或价格无关,您将获得 maximum_total_revenue = sum(max_revenue(step))

观察 3: 由于您一次只能从一个田地中收获,您只需寻找 max(revenue1,income2、收入3),无需进一步优化。

观察 1、2 和 3 的结果:不要使用 optim,这是一种矫枉过正。只需查看时间序列,计算最大值并将它们相加即可。

如果你坚持:

可能是,您发布的案例只是一个可供学习的示例。在这种情况下,可能需要使用 optim for。在您的情况下,optim 函数最大化了作物(HR1,HR2,HR3) - 惩罚(HR1,HR2,HR3)。

观察 1:由于您的 HR < 1,您实际上是在通过平方项来射击自己,因为在这种情况下 (HR1[1,]*HR1[3,])^2 < (HR1[1,]*HR1[3,])2由于如果超过一个 HR 不为零,您正试图获得尽可能大的惩罚,您可能不想这样做。

观察 2: 将惩罚计算为 crop(HR1-penaltyfun) 有点奇怪。问题是你突然计算出一些负的作物率,而在试图计算它时事情会崩溃。我不太确定为什么会发生这种情况,因为我不太了解 optim 的内部。所以我建议惩罚为crop(HR1) - penaltyfun。从外行人的角度来看,这更有意义 - 我们不会单独惩罚作物产量和收入,我们只是增加了打破限制的惩罚。

所以我们需要做的最后一件事是确保惩罚足够大,以阻止优化器一次收获两个补丁。这什么时候可以发生?
如果H1 * H2 * penalty_constant / columns < revenue(H1) + revenue(H2)。例如。如果违反规则时给定步骤的收入大于遵守规则时的收入。3

如何打击这种公然违反规则的行为?
通过调整penalty_constant。您希望常量足够大以保证 “只有一个收割机” 策略,但又不会大到让优化器陷入恐慌:​​“收割是可怕的,我宁愿不收割因为惩罚是如此之大”

penalty <- function(HR) {
 HR1 <- matrix(HR, r, c)      
  penaltyfun = 100 * c * ((HR1[1,]*HR1[3,]) + (HR1[1,]*HR1[2,]) + (HR1[2,]*HR1[3,]))      
  mainfun <- crop(HR1) - sum(penaltyfun)
  return(mainfun)
}

这个对我来说效果很好。不过,它可能仍然需要一些调整。特别是如果您想为每个非零结果值获得不同于 HR_max 的结果。


1将需要非线性约束 - 因为否则 HR 将是 0 或 0.5,具体取决于是否值得收获。
2 0.52 = 0.25 < 0.5
3 优化器告诉我们类似的事情:你确定你不想为了这一天偷邻居的收割机吗?奖励是值得的。