You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PuLP优化器中限制球员变量仅出现一次

解决PuLP梦幻足球优化器中球员重复选中的问题

我正在跟着一篇教程制作PuLP优化器(感谢Branko Blagojevic的出色工作!),但教程存在一个问题:最终输出会重复选中同一球员(比如DeSean Jackson同时出现在FLEX和WR位置——这是规则不允许的,每个位置必须是唯一球员)。我的问题是:如何确保FLEX位置的球员与其他所有位置的球员不重复?我知道有类似问题,但它们的结构和我的不完全匹配。

我已尝试的方法

  • 曾考虑在设置奖励时,一旦球员被选入最优解就从_vars字典中删除该球员,代码如下:

    del _vars['__player__']
    

    但随后意识到优化求解并非像设置奖励那样的迭代过程,因此该方法无效。

  • 之后想到可以添加约束来确保每个球员仅出现一次,尝试的代码如下:

    # _vars 的定义方式
    _vars = {k: LpVariable.dict(k, v, cat="Binary") for k, v in points.items()}
    
    current = current.set_index(['displayName','position'])
    pairs = current.index   # 格式为 (name, pos) 的元组
    name_set = current.index.unique(0)
    
    
    # 设置奖励项
    for k, v in _vars.items():
        costs += pulp.lpSum([salaries[k][i] * _vars[k][i] for i in v])
        rewards += pulp.lpSum([points[k][i] * _vars[k][i] for i in v])
        prob += pulp.lpSum([_vars[k][i] for i in v]) <= pos_num_available[k]
    
    # 我认为正确的思路应该类似这样
    for name in name_set:
        prob += pulp.lpSum([_vars[n, p] for (n, p) in pairs if n == name]) <=1
    
    
    prob += pulp.lpSum(rewards)
    prob += pulp.lpSum(costs) <= SALARY_CAP
    

    但没能成功实现——我觉得需要调整pairs使其匹配_vars的结构?无论如何,我确信添加约束让每个球员仅出现一次是正确的思路,只是需要帮助完成该约束的编写。


正确的约束实现方案

你的思路完全正确:必须添加每个球员只能被选中一次的约束。之前的问题在于_vars的结构是按位置分组(键是位置字符串,比如'WR'、'FLEX'),而非(球员名, 位置)元组,所以_vars[n, p]的写法不匹配变量结构。

下面是可行的实现代码:

# 第一步:构建球员到所属位置的映射字典
player_pos_map = {}
# 遍历所有位置(比如WR、RB、FLEX等)
for position in points.keys():
    # 遍历当前位置下的所有球员
    for player_name in points[position].keys():
        if player_name not in player_pos_map:
            player_pos_map[player_name] = []
        # 记录该球员所属的位置(可能多个,比如WR和FLEX)
        player_pos_map[player_name].append(position)

# 第二步:添加每个球员只能被选中一次的约束
for player_name, positions in player_pos_map.items():
    # 收集该球员在所有可选位置中的二进制变量
    selected_vars = []
    for pos in positions:
        # 从对应位置的变量组中取出该球员的变量
        if player_name in _vars[pos]:
            selected_vars.append(_vars[pos][player_name])
    # 设置约束:该球员被选中的总次数 ≤1
    prob += pulp.lpSum(selected_vars) <= 1

代码说明

  1. 构建球员位置映射:先遍历所有位置和球员,记录每个球员可以被选入的所有位置(比如部分球员同时属于WR和FLEX池)。
  2. 添加唯一性约束:对每个球员,把他在各个位置对应的二进制变量求和,约束总和不超过1,这样就彻底避免了同一球员被重复选中到不同位置的情况。

把这段代码添加到你现有逻辑中(在设置完位置数量约束之后,目标函数之前即可),就能解决重复选人的问题。


内容的提问来源于stack exchange,提问作者bismo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 03:45:35