【发布时间】:2020-10-03 23:23:45
【问题描述】:
问题
我正在使用 lpSolve 为一支梦幻棒球队寻找最佳阵容 - 一个背包问题,涉及在比赛给定的限制条件下,每个球员 PLAYERID 的价格 SALARY 和投影点 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,]
问题
如何编码这个新的约束?我一直在手动进行这些类型的调整,但如果有可用于自动化此过程的解决方案,我将不胜感激。谢谢!
【问题讨论】:
-
我不确定您将如何在 R 中编写此代码,但执行“非此即彼”类型约束的典型方法是将选择变量添加在一起:
x + x' <= 1 for all (x, x') in set of prohibited combos跨度> -
@AirSquid 是的,我有这样的逻辑来确保阵容中没有重复的球员(有些球员有多个位置的资格),但我还没有完全弄清楚如何翻译这就是我在这里需要的。我确信这是正确的思路——我只是还没有完全解决问题。
-
@Eric_Alan 上面的脚本是否为您运行?我收到以下错误。我认为这可能是因为您缩短了球员名单。在尝试求解器之前,我还必须更改一些约束,因为此数据框中只有三种玩家类型。警告消息:在 rbind(const.mat, const.dir.num, const.rhs) 中:结果的列数不是向量长度的倍数(arg 2)
-
删除重复播放器约束后,我能够运行代码。请参阅下面我提出的想法。由于 all.bin = TRUE,所以重复播放器约束无论如何都是多余的。
-
@windyvation 你是对的 - 如果没有
slate_players数据帧的所有 91 行(包括所有七种玩家类型),上述脚本将无法正常运行。重复球员约束在整个数据集中发挥作用,因为有少数球员有资格打多个位置,但只能出现在最优解中一次。
标签: r optimization constraints knapsack-problem lpsolve