Configurando un optimizador lineal con una restricción "o"
Tengo un gran optimizador lineal que estoy ejecutando y necesito ayuda para configurar las restricciones para obtener lo que quiero. Es difícil para mí expresarlo en palabras exactamente (de ahí el vago título posterior), así que he escrito un ejemplo, detalles:
Seleccione un total de 5 artículos, maximizando el valor y manteniendo el costo por debajo de 5k. Cada elemento tiene 2 "tipos". Están etiquetados comotype1
= A, B, C, D o E, ytype2
= X o Y. 4 elementos deben ser de tipo X, 1 debe ser de tipo YEl siguiente ejemplo funciona muy bien, pero quiero agregar dos restricciones más y no estoy realmente seguro de cómo hacerlo. Las otras dos restricciones:
Quiero que cada optimización tenga al menos 2 instancias detype1
. No me importa de qué tipo es múltiplo o si dos tipos diferentes son múltiplos (por ejemplo, 2 A y 2 C), por eso lo considero una restricción "o" (A> 2 OR B> 2 OR ...) ¿Es esto factible? Esto podría ser un poco más difícil: cualquiera que sea el "tipo Y" elegido, no quiero quetype1
para aparecer de nuevo. Digamos que el elemento Y estype1
= C, quiero que todos los demás elementos elegidos no sean C. Me imagino que tendré que agregar otra matriz ficticia que interactúatype1
ytype2
Ejemplo de resultado deseado:
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
EJEMPLO DE TRABAJO:
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
¡Gracias por tu ayuda