我正在尝试找到一种方法来将一些约束添加到线性程序中,以迫使解决方案具有一定程度的唯一性。我会尝试解释一下我的意思。以下面的例子为例,线性程序返回2个男性和1个女性组合的最大可能得分。
查看团队/成绩/代表列,但我们可以看到行与行之间存在大量重复。实际上Shana和Jason完全相同。
Name<-c("Jane","Brad","Harry","Shana","Debra","Jason")
Sex<-c("F","M","M","F","F","M")
Score<-c(25,50,36,40,39,62)
Team<-c("A","A","A","B","B","B")
Grade<-c(1,2,1,2,1,2)
Rep<-c("C","D","C","D","D","D")
df<-data.frame(Name,Sex,Score,Team,Grade,Rep)
df
Name Sex Score Team Grade Rep
1 Jane F 25 A 1 C
2 Brad M 50 A 2 D
3 Harry M 36 A 1 C
4 Shana F 40 B 2 D
5 Debra F 39 B 1 D
6 Jason M 62 B 2 D
library(Rglpk)
num <- length(df$Name)
obj<-df$Score
var.types<-rep("B",num)
matrix <- rbind(as.numeric(df$Sex == "M"),as.numeric(df$Sex == "F"))
direction <- c("==","==")
rhs<-c(2,1)
sol <- Rglpk_solve_LP(obj = obj, mat = matrix, dir = direction, rhs = rhs,types = var.types, max = TRUE)
df[sol$solution==1,]
Name Sex Score Team Grade Rep
2 Brad M 50 A 2 D
4 Shana F 40 B 2 D
6 Jason M 62 B 2 D
我想要解决的是如何限制最后三列中的随机性水平。例如,我希望在任何两行中不超过2列相同。因此,这意味着Shana行或Jason行将在模型中替换为替换。
我不确定这是否可以轻松添加到Rglpk模型中?感谢可以提供的任何帮助。
答案 0 :(得分:3)
这听起来像是在问你如何防止有一对“太相似”的人。从优化模型返回。一旦你确定了一对规则使得一对人过于相似&#34;,你可以简单地为每一对添加一个约束,限制你的解决方案只有这两个人中的一个。
例如,如果我们使用不超过2列相同的规则,我们可以轻松识别出要阻止的所有对:
pairs <- t(combn(nrow(df), 2))
(blocked <- pairs[rowSums(sapply(df[,c("Team", "Grade", "Rep")], function(x) {
x[pairs[,1]] == x[pairs[,2]]
})) >= 3,])
# [,1] [,2]
# [1,] 1 3
# [2,] 4 6
我们希望阻止对Jane / Harry和Shana / Jason。线性约束很容易做到这一点:
library(Rglpk)
num <- length(df$Name)
obj<-df$Score
var.types<-rep("B",num)
matrix <- rbind(as.numeric(df$Sex == "M"), as.numeric(df$Sex == "F"),
outer(blocked[,1], seq_len(num), "==") + outer(blocked[,2], seq_len(num), "=="))
direction <- rep(c("==", "<="), c(2, nrow(blocked)))
rhs<-c(2, 1, rep(1, nrow(blocked)))
sol <- Rglpk_solve_LP(obj = obj, mat = matrix, dir = direction, rhs = rhs,types = var.types, max = TRUE)
df[sol$solution==1,]
# Name Sex Score Team Grade Rep
# 2 Brad M 50 A 2 D
# 5 Debra F 39 B 1 D
# 6 Jason M 62 B 2 D
计算每一对被阻止的方法很有吸引力,因为我们可以有一个更复杂的规则来阻止对,因为我们不需要将规则编码到线性程序中。我们需要做的就是计算需要阻止的每一对。
答案 1 :(得分:1)
对于具有相同最后3列的每组行,我们构造一个约束,使得最多可以出现其中一行。如果a是这样一组行的指示符向量,那么约束将如下所示:
a'x <= 1
为此,将最后3列的行号拆分为向量列表s
,其中每个组件的组成部分是具有相同后3列的行的行号向量。只保留那些行号超过1的conponents s1
。在这种情况下,s1
的第一个成分是c(1,3),指的是Jane和Harry行,第二个成分是c(4,6),指的是Shana和Jason行。在此特定数据中,每个组中有2行,但在其他数据中,组中可能有2行以上。对于excl
的每个元素,s1
都有一行(约束)。
问题中的数据只有大小为2的组,但一般情况下,如果某些组中有k行,则需要k选择2个约束行,以确保如果成对完成,则只选择其中一个k,而这里的方法只需要整个组的一个约束行。例如,如果k = 10,则选择(10,2)= 45,因此使用1个约束代替45。
最后rbind excl
到matrix
给matrix2
并相应调整其他Rglpk_solve_LP
参数:
nr <- nrow(df)
s <- split(1:nr, df[4:6])
s1 <- s[lengths(s) > 1]
excl <-t(sapply(s1, "%in%", x = 1:nr)) + 0
matrix2 <- rbind(matrix, excl)
direction2 <- c(direction, rep("<=", nrow(excl)))
rhs2 <- c(rhs, rep(1, nrow(excl)))
sol2 <- Rglpk_solve_LP(obj = obj, mat = matrix2,
dir = direction2, rhs = rhs2, types = "B", max = TRUE)
df[ sol2$solution == 1, ]
,并提供:
Name Sex Score Team Grade Rep
2 Brad M 50 A 2 D
5 Debra F 39 B 1 D
6 Jason M 62 B 2 D