为lpSolve约束创建交互虚拟变量

时间:2018-06-08 04:22:41

标签: r mathematical-optimization linear-programming lpsolve

我有一个线性编程模型,我正在尝试优化,需要一些帮助来设置约束以获得我想要的东西。高级:我想只在他们的“类型”与另一个项目的特定“类型”“冲突”时才选择项目。通过示例进行更深入的解释:

  1. 共选择6项,最大化价值并将成本保持在17k以下。
  2. 每个项目有3个“类型”。它们标记为type1 = X或Y,type2type3 = A,B或C.出于本示例的目的,我标记为type2 = A2 ,B2,C2和type3 = A3,B3,C3。
  3. 4项必须是X型,2必须是Y型。
  4. 我试图设置的具体约束是,无论Type3选择的'Y'变量最终是什么('A3','B3','C3'),Type2 'X'变量的s与该字母不匹配。例如。如果Y是'B3',则X可以是'A2'或'C2'。如果一个Y是'C3'而另一个是'A3',则所有X必须是'B2'。可接受的解决方案的两个例子:

       id type1   type2 type3 value cost 
     3  3     Y     C2    A3   28   240
    10 10     X     B2    C3   30   327
    11 11     Y     A2    C3   28   350
    18 18     X     B2    C3   29   372
    40 40     X     B2    B3   29   338
    45 45     X     B2    A3   29   277
    
       id type1   type2 type3 value cost 
     3  3     Y     C2    C3   28   240
    10 10     X     B2    C3   30   327
    11 11     Y     A2    C3   28   350
    18 18     X     B2    C3   29   372
    40 40     X     B2    B3   29   338
    45 45     X     A2    A3   29   277
    

    我的当前代码仅在两个Y不同type3时才有效。为此,我添加了一个交互向量Y_3X_2,如果type3与Y匹配则会获得值为10000,如果type2与X匹配,则其值为1.每个向量约束为<= 100000,因此只能选择这些Y中的一个或多个X. 我正在寻求帮助,让两个Y都相同type3

    工作示例

    library(dplyr)
    library(lpSolve)
    
    id <- 1:50
    value <- round(runif(length(id), 10, 30),0)
    cost <- round(runif(length(id), 200, 400),0)
    type1 <- sample(c(rep('X', 3), 'Y'), length(id), replace = T)
    type2 <- sample(c('A2', 'B2', 'C2'), length(id), replace = T)
    type3 <- sample(c('A3', 'B3', 'C3'), length(id), replace = T)
    
    df <- data.frame(id, value, cost, type1, type2, type3) %>% 
      mutate(selected = 1)
    
    # Attach dummy vars
    type1Dummy <- as.data.frame.matrix(table(df$id, df$type1))
    type2Dummy <- as.data.frame.matrix(table(df$id, df$type2))
    type3Dummy <- as.data.frame.matrix(table(df$id, df$type3))
    df <- cbind(df, type1Dummy, type2Dummy, type3Dummy) 
    
    # Interaction dummy vars
    YA3XA2 <- ifelse(df$Y + df$A3 == 2, 10000,
                     ifelse(df$X + df$A2 == 2, 1,
                            0))
    YB3XB2 <- ifelse(df$Y + df$B3 == 2, 10000,
                     ifelse(df$X + df$B2 == 2, 1,
                            0))
    YC3XC2 <- ifelse(df$Y + df$C3 == 2, 10000,
                     ifelse(df$X + df$C2 == 2, 1,
                            0))
    
    df <- cbind(df, YA3XA2, YB3XB2, YC3XC2)
    
    # constraints
    totalNum <- 6
    totalCost <- 17000
    totalX <- 4
    totalY <- 2
    intConXYA <- 10000
    intConXYB <- 10000
    intConXYC <- 10000
    rhs <- c(totalNum, totalCost, totalX, totalY, intConXYA, intConXYB, intConXYC)
    
    # Direction vector
    numDir <- '=='
    costDir <- '<='
    xDir <- '=='
    yDir <- '=='
    intConA <- '<='
    intConB <- '<='
    intConC <- '<='
    dir <- c(numDir, costDir, xDir, yDir, intConA, intConB, intConC)
    
    # Setup opt
    obj <- df$value
    mat <- t(data.frame(df$selected, df$cost, df$X, df$Y, df$YA3XA2, df$YB3XB2, df$YC3XC2))
    
    
    # Solver Setup
    sol <- lpSolve::lp("max",   
                       objective.in = obj,
                       const.mat    = mat,
                       const.dir    = dir,
                       const.rhs    = rhs,
                       all.bin      = T
    )
    
    df$solver <- sol$solution
    dfSolved <- df[df$solver == 1,]
    dfSolved
    

    代码演练:

    • 使用ID,值,费用,类型1/2/3
    • 创建数据框
    • 创建虚拟变量。这些是告诉优化器所必需的 只选择4 X和2 Y,以及设置交互 虚拟变量。
    • Type1Dummy将创建2列。 Df $ X == 1如果Type1 =='X',则df $ Y == 1如果Type2 =='Y'。
    • Type2Dummy将创建3列。 Df $ A2 == 1如果type2 =='A2'等,
    • Type3Dummy将创建3个类似于Type2Dummy
    • 的列
    • 使用虚拟变量。创建3个交互虚拟 变量,YA3XA2基本上读作:if type1 =='Y'&amp; type3 == 'A3'| type1 =='X'&amp; type2 =='A2'THEN赋值,否则为0. 如果type1 =='Y',则要分配的值为10000,如果为1,则分配的值为10000 type1 =='X'。
    • 分配右手约束。注意到的约束 交互假人是10000.这意味着EITHER 1 Y可以 为特定类型3选择或可以选择任何数量的X. 特定的Y2,但它们永远不会被选中。如果Y是 然后选择总和为10000,并且不能选择任何其他内容。
    • 我的问题,上述约束工作“太正确”了。它成功地阻止了某些类型3的Y. 某些类型2的X,但它也意味着我不能拥有2个Y. 相同的类型3。如果我将约束提高到20000则允许 2 Y是相同类型3,但它也允许1 Y和3 X type2(sum = 10004,&lt; 20000)。

0 个答案:

没有答案