我有一个线性编程模型,我正在尝试优化,需要一些帮助来设置约束以获得我想要的东西。高级:我想只在他们的“类型”与另一个项目的特定“类型”“冲突”时才选择项目。通过示例进行更深入的解释:
type1
= X或Y,type2
和type3
= A,B或C.出于本示例的目的,我标记为type2
= A2 ,B2,C2和type3
= A3,B3,C3。我试图设置的具体约束是,无论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
代码演练: