【问题标题】:lpSolve - "Must Not Be Together" Constraint?lpSolve - “不能在一起”约束?
【发布时间】: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' &lt;= 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


【解决方案1】:

我最终做的不是单个 MNBT 列,而是为每个单独的投手 SP 创建一个辅助列,以指示他可能不会出现在最佳解决方案中的哪些击球手。在这些列中,我为投手分配了一个值5,并为每个不能出现的击球手分配了1。然后约束变为这些列的总和为&lt;=5。逻辑是,最多5 击球手可能在同一阵容中面对任何单个投手,但如果同一投手出现在最佳解决方案中,那么他所面对的击球手都不会出现。

【讨论】:

    【解决方案2】:

    虽然这不会为您创建一组约束,但此示例是@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 中生成所有这些约束集。


    【讨论】:

    • 是的。这是我一直在寻找的解决方案(并在重复玩家约束中使用了一种变体),但还没有完全确定如何将“不能在一起”的玩家付诸实践。
    • @Eric_Alan 你是如何根据 windyvation 的响应来编写约束矩阵来限制击球手和投手的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多