设置具有“或”约束的线性优化器

时间:2018-05-12 21:18:18

标签: r dplyr mathematical-optimization lpsolve

我有一个很大的线性优化器我正在运行,需要一些帮助来设置约束以获得我想要的东西。我很难用文字表达(因此标题后的模糊),所以我写了一个例子,细节:

  1. 共选择5项,最大化价值并将成本保持在5k以下。
  2. 每个项目有2个“类型”。它们标记为type1 = A,B,C,D或E,type2 = X或Y.
  3. 4项必须是X型,1必须是Y型
  4. 以下示例效果很好,但我想再添加两个约束,我不确定如何做到这一点。另外两个限制因素:

    1. 我希望每次优化至少有2个type1个实例。我不关心哪种类型有多个或者如果两种不同的类型是倍数(例如2 A和2 C),这就是为什么我将其视为“或”约束(A> 2或B> 2或......)。这甚至可行吗?
    2. 这个可能有点困难:无论选择哪种“Y型”,我都不希望type1再次出现。所以说Y项是type1 = C,我希望每个其他选择的项目都不是C.我想我需要添加另一个虚拟矩阵交互type1type2
    3. 期望结果的示例:

         id type1 type2 value cost 
      10 10     B     X    19  865
      11 11     C     Y    19 1097 
      18 18     D     X    19 1005
      40 40     B     X    20  956
      45 45     A     X    20  980
      

      工作示例:

      library(lpSolve)
      library(dplyr)
      
      # setup df
        id <- 1:50
        type1 <- sample(c('A', 'B', 'C', 'D', 'E'), length(id), replace = T)
        type2 <- sample(c('X', 'X', 'X', 'Y'), length(id), replace = T)
        value <- round(runif(length(id), 0, 20),0)
        cost <- round(runif(length(id), 750, 1250),0)
      
        df <- data.frame(id, type1, type2, value, cost) %>% 
          mutate(total = 1)
      
      # Attach dummy vars
        type1Dummy <- as.data.frame.matrix(table(df$id, df$type1))
        type2Dummy <- as.data.frame.matrix(table(df$id, df$type2))
        df <- cbind(df, type1Dummy, type2Dummy)
      
      # constraints
        totalNum <- 5
        totalCost <- 5000
        totalX <- 4
        totalY <- 1
        rhs <- c(totalNum, totalCost, totalX, totalY)
      
      # Direction vector
        numDir <- '=='
        costDir <- '<='
        xDir <- '=='
        yDir <- '=='
        dir <- c(numDir, costDir, xDir, yDir)
      
      # Setup opt
        obj <- df$value
        mat <- t(data.frame(df$total, df$cost, df$X, df$Y))
      
      
      
      # Solver Setup
        sol <- lpSolve::lp("max",   
                           objective.in = obj,
                           const.mat  = mat,
                           const.dir  = dir,
                           const.rhs  = rhs,
                           all.bin    = T
        )
      
        df$selected <- sol$solution
        dfSolved <- df[df$selected == 1,]
        dfSolved
      

      感谢您的帮助!

0 个答案:

没有答案