lpSolve - "Must Not Be Together" 约束?
lpSolve - "Must Not Be Together" Constraint?
问题
我正在使用 lpSolve 寻找梦幻棒球队的最佳阵容 - 一个背包问题,涉及价格 SALARY
和给定范围内每个球员 PLAYERID
的预计得分 DK
比赛的限制。
当前代码运行良好,但我想补充一个我不太明白的约束。新的限制是阵容中没有任何球员面对同一阵容中的一名投手 SP
。
到目前为止我有什么
我创建了一个名为 MNBT
(不得在一起)的专栏,其中定义了对方投手的 PLAYERID
不得与每个球员在同一阵容中找到,但我被困在那里。 data.frame slate_players
的前 20 行如下(如果需要,我可以提供此特定比赛的所有 91 行):
PLAYERID POS TEAM OPP SALARY DK TEAM_O MNBT
1 37584 SP LAD OAK 10000 18.42 0SP 13170
2 11292 SP TEX HOU 9300 18.41 0SP 1452665
3 1452665 SP HOU TEX 7400 15.22 0SP 11292
4 11168 SP BAL BOS 6900 9.06 0SP 13502
5 13170 SP OAK LAD 6800 6.06 0SP 37584
6 13502 SP BOS BAL 6700 13.52 0SP 11168
7 2038873 SP KCR DET 6600 18.45 0SP 34649
8 34649 SP DET KCR 6500 7.46 0SP 2038873
9 11446 C KCR DET 5300 7.55 KCR 34649
10 1054004 C LAD OAK 5000 8.25 LAD 13170
11 15541 C BOS BAL 4500 7.08 BOS 11168
12 1252110 C OAK LAD 4100 5.07 OAK 37584
13 22667 C BAL BOS 3400 7.09 BAL 13502
14 10290 C TEX HOU 2900 4.08 TEX 1452665
15 13171 C DET KCR 2800 5.45 DET 2038873
16 17552 C HOU TEX 2600 4.47 HOU 11292
17 36727 1B LAD OAK 5800 9.09 LAD 13170
18 17648 1B LAD OAK 5400 8.57 LAD 13170
19 17887 1B OAK LAD 4900 7.30 OAK 37584
20 17851 1B KCR DET 4400 7.24 KCR 34649
[...]
当前 lpSolve 代码
# count the unique players and teams on the slate
unique_teams = unique(slate_players$TEAM_O)
unique_players = unique(slate_players$PLAYERID)
# define the objective for the solver
obj = slate_players$DK
# create a constraint matrix for the solver
con = rbind(t(model.matrix(~ POS + 0, slate_players)), #Positions
t(model.matrix(~ PLAYERID + 0, slate_players)), #DupPlayers
t(model.matrix(~ TEAM_O + 0, slate_players)), #SameTeam
rep(1,nrow(slate_players)), #TotPlayers
slate_players$SALARY) #MaxSalary
# set the direction for each of the constraints
dir = c("==", #1B
"==", #2B
"==", #3B
"==", #C
"==", #OF
"==", #SP
"==", #SS
rep('<=',length(unique_players)), #DupPlayers
rep('<=',length(unique_teams)), #SameTeam
"==", #TotPlayers
"<=") #MaxSalary
# set the limits for the right-hand side of the constraints
rhs = c(1, #1B
1, #2B
1, #3B
1, #C
3, #OF
2, #SP
1, #SS
rep(1,length(unique_players)), #DupPlayers
rep(5,length(unique_teams)), #SameTeam
10, #TotPlayers
50000) #MaxSalary
# find the optimal solution using the solver
result = lp("max", obj, con, dir, rhs, all.bin = TRUE)
# create a table for the players that are in optimal solution
solindex = which(result$solution==1)
optsolution = slate_players[solindex,]
问题
如何编写这个新约束?我一直在手动进行这些类型的调整,但如果有一种解决方案可以自动执行此过程,我将不胜感激。谢谢!
虽然这不会为您创建约束集,但此示例是@AirSquid 提到的可能有帮助的约束之一。
在上面的例子中,第 6 位玩家 (13502) 无法对战第 13 位玩家 (22667)。
加入约束条件:
c(0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0)
添加到路线:
"<="
添加到右侧:
1
下一个技巧是如何在 R.Cheerio 中生成所有这些约束集。
我最终做的,而不是单个 MNBT
列,是为每个单独的投手创建一个辅助列 SP
以指示他可能不会出现在最佳解决方案中的哪些击球手。在这些列中,我为投手分配了 5
的值,为每个他不能出现的击球手分配了 1
的值。然后约束变成了这些列中每一列的总和将是 <=
5
。逻辑是最多 5
名击球手可能在同一阵容中面对任何单个投手,但如果同一投手出现在最佳解决方案中,他所面对的击球手中有 none 将是。
问题
我正在使用 lpSolve 寻找梦幻棒球队的最佳阵容 - 一个背包问题,涉及价格 SALARY
和给定范围内每个球员 PLAYERID
的预计得分 DK
比赛的限制。
当前代码运行良好,但我想补充一个我不太明白的约束。新的限制是阵容中没有任何球员面对同一阵容中的一名投手 SP
。
到目前为止我有什么
我创建了一个名为 MNBT
(不得在一起)的专栏,其中定义了对方投手的 PLAYERID
不得与每个球员在同一阵容中找到,但我被困在那里。 data.frame slate_players
的前 20 行如下(如果需要,我可以提供此特定比赛的所有 91 行):
PLAYERID POS TEAM OPP SALARY DK TEAM_O MNBT
1 37584 SP LAD OAK 10000 18.42 0SP 13170
2 11292 SP TEX HOU 9300 18.41 0SP 1452665
3 1452665 SP HOU TEX 7400 15.22 0SP 11292
4 11168 SP BAL BOS 6900 9.06 0SP 13502
5 13170 SP OAK LAD 6800 6.06 0SP 37584
6 13502 SP BOS BAL 6700 13.52 0SP 11168
7 2038873 SP KCR DET 6600 18.45 0SP 34649
8 34649 SP DET KCR 6500 7.46 0SP 2038873
9 11446 C KCR DET 5300 7.55 KCR 34649
10 1054004 C LAD OAK 5000 8.25 LAD 13170
11 15541 C BOS BAL 4500 7.08 BOS 11168
12 1252110 C OAK LAD 4100 5.07 OAK 37584
13 22667 C BAL BOS 3400 7.09 BAL 13502
14 10290 C TEX HOU 2900 4.08 TEX 1452665
15 13171 C DET KCR 2800 5.45 DET 2038873
16 17552 C HOU TEX 2600 4.47 HOU 11292
17 36727 1B LAD OAK 5800 9.09 LAD 13170
18 17648 1B LAD OAK 5400 8.57 LAD 13170
19 17887 1B OAK LAD 4900 7.30 OAK 37584
20 17851 1B KCR DET 4400 7.24 KCR 34649
[...]
当前 lpSolve 代码
# count the unique players and teams on the slate
unique_teams = unique(slate_players$TEAM_O)
unique_players = unique(slate_players$PLAYERID)
# define the objective for the solver
obj = slate_players$DK
# create a constraint matrix for the solver
con = rbind(t(model.matrix(~ POS + 0, slate_players)), #Positions
t(model.matrix(~ PLAYERID + 0, slate_players)), #DupPlayers
t(model.matrix(~ TEAM_O + 0, slate_players)), #SameTeam
rep(1,nrow(slate_players)), #TotPlayers
slate_players$SALARY) #MaxSalary
# set the direction for each of the constraints
dir = c("==", #1B
"==", #2B
"==", #3B
"==", #C
"==", #OF
"==", #SP
"==", #SS
rep('<=',length(unique_players)), #DupPlayers
rep('<=',length(unique_teams)), #SameTeam
"==", #TotPlayers
"<=") #MaxSalary
# set the limits for the right-hand side of the constraints
rhs = c(1, #1B
1, #2B
1, #3B
1, #C
3, #OF
2, #SP
1, #SS
rep(1,length(unique_players)), #DupPlayers
rep(5,length(unique_teams)), #SameTeam
10, #TotPlayers
50000) #MaxSalary
# find the optimal solution using the solver
result = lp("max", obj, con, dir, rhs, all.bin = TRUE)
# create a table for the players that are in optimal solution
solindex = which(result$solution==1)
optsolution = slate_players[solindex,]
问题
如何编写这个新约束?我一直在手动进行这些类型的调整,但如果有一种解决方案可以自动执行此过程,我将不胜感激。谢谢!
虽然这不会为您创建约束集,但此示例是@AirSquid 提到的可能有帮助的约束之一。
在上面的例子中,第 6 位玩家 (13502) 无法对战第 13 位玩家 (22667)。
加入约束条件:
c(0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0)
添加到路线:
"<="
添加到右侧:
1
下一个技巧是如何在 R.Cheerio 中生成所有这些约束集。
我最终做的,而不是单个 MNBT
列,是为每个单独的投手创建一个辅助列 SP
以指示他可能不会出现在最佳解决方案中的哪些击球手。在这些列中,我为投手分配了 5
的值,为每个他不能出现的击球手分配了 1
的值。然后约束变成了这些列中每一列的总和将是 <=
5
。逻辑是最多 5
名击球手可能在同一阵容中面对任何单个投手,但如果同一投手出现在最佳解决方案中,他所面对的击球手中有 none 将是。