首页 > 解决方案 > 使用 lpSolve 和 for 循环解决 r 中的最大化问题?

问题描述

我是 r 新手,正在努力解决以下最大化问题。

考虑以下数据框:

cars week1 week2 week3 week4 week5 week6 week7 week8 week9 week10 breakevenCoverage audi 20 20 21 21 20 19 22 22 22 22 0.71 tesla 12 12 12 12 12 12 12 12 12 12 0.74 bmw 12 12 12 12 12 13 13 13 13 13 0.73 toyota 1 1 1 1 1 1 1 1 0 0 0.71 honda 6 6 7 7 7 7 7 8 8 8 0.71

假设这代表汽车租赁公司在 10 周内可供出租的汽车数量。我们需要为汽车投保,但只能购买 10 周的保险(即承保的汽车数量不能每周变化)。根据我们选择投保的汽车数量,我们可以相当容易地确定车队的总覆盖范围。例如,如果我们在 10 周内覆盖 18 辆奥迪,车队的总覆盖率为 18 x 10 / (20+20+21+21+20+19+22+22+22+22) = 86.1% .

现在考虑为额外的汽车投保的增量保险。例如,如果我们覆盖第 19 辆奥迪,它覆盖了整整 10 周的汽车(因为每周至少有 19 辆汽车),因此增量覆盖率为 100%。如果我承保第 20 辆奥迪,则保险涵盖 10 周中的 9 周(除第 6 周外),因此增量承保率为 90%。如果我承保第 21 辆奥迪,则保险承保 10 周中的 6 周的汽车(因为在第 1、2、5、6 周内出租的汽车少于 21 辆),因此增量承保率为 60%。

对于每辆车,我正在尝试确定要确保的最大汽车数量,以使将汽车添加到保单中的增量覆盖范围 >= 该汽车的给定盈亏平衡覆盖范围。

我是这样思考问题的:

目标:最大化numCarsToInsure,其中

约束:incrCoverage >= breakevenCoverage,在incrCoverage哪里

for i = 1 to 10 if week[i] >= numCarsToInsure then Covered = Covered + 1 incrCoverage = Covered / 10

(作为求解的一部分,应针对 numCarsToInsure 的每个值评估上述循环)

对于 audi,numCarsToInsure 应为 20,其中 incrCoverage 为 90%。如果 NumCarsToInsure 为 21,则 incrCoverage 降至 60%,即 <breakevenCoverage 的 71%。对于 tesla,numCarsToInsure 应为 12,其中 incrCoverage 为 100%。如果 numCarsToInsure 为 13,则 incrCoverage 降至 0%,即 <breakevenCoverage 的 74%。等等。

lpSolve 是正确的方法吗?如果是这样,如何使用 lp() 函数对 for 循环进行建模?

另一种方法是从 numCarsToInsure = 0 开始,求解 incrCoverage,与 breakevenCoverage 进行比较,然后继续递增 numCarsToInsure 并求解,直到 incrCoverage 低于 breakevenCoverage。但我希望 r 具有某种优雅的求解功能,可以做到这一点而不是手工制作。

如果我能弄清楚如何解决给定的观察结果,我就可以找出整个数据框,但是解决整个数据框的代码会非常有帮助。

谢谢!!

标签: r

解决方案


感谢您提出您的问题。我认为您不需要任何形式的优化来执行此最大化。当然不是 lpSolve 或 optim。在您等于或超过盈亏平衡保险范围之前,您只为额外的汽车投保(整数,而不是汽车的一部分)。为此,一个while循环就足够了:

# reproducible dataset - best practice is to use dput(yourData) to generate this
dat <- data.frame(
  cars = structure(c(1L, 4L, 2L, 5L, 3L), .Label = c("audi", "bmw", "honda", 
                                                     "tesla", "toyota"), class = "factor"),
  week1 = c(20L, 12L, 12L, 1L, 6L),
  week2 = c(20L, 12L, 12L, 1L, 6L),
  week3 = c(21L, 12L, 12L, 1L, 7L),
  week4 = c(21L, 12L, 12L, 1L, 7L),
  week5 = c(20L, 12L, 12L, 1L, 7L),
  week6 = c(19L, 12L, 13L, 1L, 7L),
  week7 = c(22L, 12L, 13L, 1L, 7L),
  week8 = c(22L, 12L, 13L, 1L, 8L),
  week9 = c(22L, 12L, 13L, 0L, 8L),
  week10 = c(22L, 12L, 13L, 0L, 8L),
  breakevenCoverage = c(0.71, 0.74, 0.73, 0.71, 0.71),
  stringsAsFactors = FALSE)

# I like to initialize all my empty objects 
dat[,"covered"] <- 0 # initialize the column we will fill with results
dat[,"coveredPercent"] <- 0
coveredPercent <- 0

for(i in 1:nrow(rawdat)){ # for each car
  covered = 0 # start at zero
  coveredPercent = 0
  while(coveredPercent < rawdat[i, "breakevenCoverage"]){
    covered <- covered + 1 
    coveredPercent <- covered*10/sum(dat[i, 2:11])
  }
  dat[i, "covered"] <- covered
  dat[i, "coveredPercent"] <- coveredPercent
}
dat

显示结果:

    #cars week1 week2 week3 week4 week5 week6 week7 week8 week9 week10 breakevenCoverage covered coveredPercent
#1   audi    20    20    21    21    20    19    22    22    22     22              0.71      15      0.7177033
#2  tesla    12    12    12    12    12    12    12    12    12     12              0.74       9      0.7500000
#3    bmw    12    12    12    12    12    13    13    13    13     13              0.73      10      0.8000000
#4 toyota     1     1     1     1     1     1     1     1     0      0              0.71       1      1.2500000
#5  honda     6     6     7     7     7     7     7     8     8      8              0.71       6      0.8450704

如果您有任何问题,请告诉我。


推荐阅读