使用R优化最小订单数量

rno*_*erg 1 r mathematical-optimization

我是优化的新手,我需要在一个简单的场景中实现它:

有一家汽车制造商可以生产5种型号的汽车/货车.与可以生产的每种型号相关联的是需要的劳动时间和所需的数量的钢,以及通过销售这样的汽车/厢式车获得的利润.制造商目前拥有固定数量的钢材和人工,应该以优化总利润的方式使用.

这是我挂断的部分 - 每辆车也有最低订货量.在生产/销售该模型变得经济可行之前,公司必须制造一定数量的每种型号.optim()如果不是最终条件,这将很容易发送,因为`lower = ...'参数可以给出一个具有最小订单数量的向量,但是它不会将0视为一个选项.有人可以帮我解决这个问题,考虑到最低订单,但仍然允许订单为0?以下是我组织相关信息/约束的方法:

Dorian <- data.frame(Model = c('SmCar', 'MdCar', 'LgCar', 'MdVan', 'LgVan'),
                   SteelReq = c(1.5,3,5,6,8), LabReq=c(30,25,40,45,55),
                   MinProd = c(1000,1000,1000,200,200),
                   Profit = c(2000,2500,3000,5500,7000))

Materials <- data.frame(Steel=6500,Labor=65000)

NetProfit<-function(x) {
  x[1]->SmCar
  x[2]->MdCar
  x[3]->LgCar
  x[4]->MdVan
  x[5]->LgVan
  np<-sum(Dorian$Profit*c(SmCar,MdCar,LgCar,MdVan,LgVan))
  np
}
LowerVec <- Dorian$MinProd #Or 0, how would I add this option?
UpperVec <- apply(rbind(Materials$Labor/Dorian$LabReq, 
                   Materials$Steel/Dorian$SteelReq),2,min)
# Attempt at using optim()
optim(c(0,0,0,0,0),NetProfit,lower=LowerVec, upper=UpperVec)
Run Code Online (Sandbox Code Playgroud)

最后,我想用已知分布的随机变量替换参数,例如Profit和LabReq(需要人工),并将其包装到一个函数中,该函数将Steel和Labor作为输入以及随机变量的参数.我想多次模拟然后找到给出Profit和Labor Required的特定参数的平均解决方案,所以理想情况下这个优化也会很快,以便我可以执行模拟.在此先感谢您的帮助!

flo*_*del 6

如果您不熟悉线性规划,请从这里开始:http://en.wikipedia.org/wiki/Linear_programming

另请参阅关于混合整数编程的部分http://en.wikipedia.org/wiki/Mixed_integer_programming#Integer_unknowns.当你试图解决的变量不是全部连续的时候,还包括布尔值或整数.


对于所有方面,您的问题是混合整数编程(确切地说,整数编程),因为您正在尝试求解整数:为每个模型生成的车辆数量.

已知有解决这些问题的算法,幸运的是,它们已经包含在R包中.Rglpk是其中之一,我将告诉你如何制定你的问题,以便你可以使用它的Rglpk_solve_LP功能.


让你x1, x2, x3, x4, x5成为你要解决的变量:为每个模型生产的车辆数量.

你的目标是:

Profit = 2000 x1 + 2500 x2 + 3000 x3 + 5500 x4 + 7000 x5.

你的钢约束是:

1.5 x1 + 3 x2 + 5, x3 + 6 x4 + 8 x5 <= 6500

你的劳工约束是:

30 x1 + 25 x2 + 40 x3 + 45 x4 + 55 x5 <= 65000

现在是困难的部分:建模最低生产要求.让我们以第一个为例:最低生产要求要求至少生产x11000辆汽车(x1 >= 1000)或根本不生产汽车(x1 = 0).为了模拟该需求,我们将引入一个布尔变量z1.通过布尔值,我的意思是z1只能取两个值:01.该要求可以建模如下:

1000 z1 <= x1 <= 9999999 z1

为什么这样做?考虑两个可能的值z1:

  1. 如果z1 = 0,然后x1被迫0
  2. 如果z1 = 1那时x1被迫大于1000(最低生产要求)并小于9999999,我选择任意大数字.

对每个模型重复此操作,您将不得不引入类似的布尔变量(z2, z3, z4, z5).最后,解算器不仅会解决问题x1, x2, x3, x4, x5而且会解决问题z1, z2, z3, z4, z5.


将所有这些付诸实践,这是解决问题的代码.我们要解决这个向量x = (x1, x2, x3, x4, x5, z1, z2, z3, z4, z5)

library(Rglpk)

num.models <- nrow(Dorian)

# only x1, x2, x3, x4, x5 contribute to the total profit
objective  <- c(Dorian$Profit, rep(0, num.models))

constraints.mat <- rbind(
    c(Dorian$SteelReq, rep(0, num.models)),                    # total steel used
    c(Dorian$LabReq,   rep(0, num.models)),                    # total labor used
    cbind(-diag(num.models), +diag(Dorian$MinProd)),           # MinProd_i * z_i
    cbind(+diag(num.models), -diag(rep(9999999, num.models)))) # x_i - 9999999 x_i

constraints.dir <- c("<=",
                     "<=",
                     rep("<=", num.models),
                     rep("<=", num.models))

constraints.rhs <- c(Materials$Steel,
                     Materials$Labor,
                     rep(0, num.models),
                     rep(0, num.models))

var.types <- c(rep("I", num.models),  # x1, x2, x3, x4, x5 are integers
               rep("B", num.models))  # z1, z2, z3, z4, z5 are booleans

Rglpk_solve_LP(obj   = objective,
               mat   = constraints.mat,
               dir   = constraints.dir,
               rhs   = constraints.rhs,
               types = var.types,
               max   = TRUE)

# $optimum
# [1] 6408000
#
# $solution
# [1] 1000    0    0  202  471    1    0    0    1    1
#
# $status
# [1] 0
Run Code Online (Sandbox Code Playgroud)

因此,最佳解决方案是创建每个模型的(1000,0,0,202,471)车辆,总利润为6,408,000.