首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python PuLP优化问题对于幻想足球,如何添加一定的条件约束?

Python PuLP优化问题对于幻想足球,如何添加一定的条件约束?
EN

Stack Overflow用户
提问于 2020-09-28 00:44:29
回答 1查看 1.2K关注 0票数 0

这是我目前第一次在python中使用PuLP库。潜入这个图书馆的目的是在巨蟒中做一个幻想的足球解说员。我已经成功地做了求解,但不知道如何添加一些约束,我需要。

我有一个excel表400名球员,我如何预测他们发挥,我想找到最佳组合的9名球员给出特定的限制。excel表持有,球员名称,球员投影,团队成员是启动,对手球员面对,和位置。下面是熊猫的头像。

代码语言:javascript
复制
              Name  Projection Position Team  Salary Opponent
0             Jets    3.528576      DST  NYJ    2000      IND
1           Texans    7.936528      DST  HOU    2100      PIT
2         Panthers    4.219883      DST  CAR    2200      LAC
3          Raiders    0.904948      DST  LVR    2300       NE

我成功完成的限制:最多选择9名球员,只有1名QB,3-4位WR,1-2位TE,1位DST和2-3位RB。

代码语言:javascript
复制
raw_data = pd.read_csv(file_name,engine="python",index_col=False, header=0, delimiter=",", quoting = 3)

#create new columns that has binary numbers if player == a specific position
raw_data["RB"] = (raw_data["Position"] == 'RB').astype(float)
raw_data["WR"] = (raw_data["Position"] == 'WR').astype(float)
raw_data["QB"] = (raw_data["Position"] == 'QB').astype(float)
raw_data["TE"] = (raw_data["Position"] == 'TE').astype(float)
raw_data["DST"] = (raw_data["Position"] == 'DST').astype(float)
raw_data["Salary"] = raw_data["Salary"].astype(float)

total_points = {}
cost = {}
QBs = {}
RBs = {}
WRs = {}
TEs = {}
DST = {}
number_of_players = {}

# i = row index, player = player attributes
for i, player in raw_data.iterrows():
    var_name = 'x' + str(i) # Create variable name
    decision_var = pulp.LpVariable(var_name, cat='Binary') # Initialize Variables

    total_points[decision_var] = player["Projection"] # Create Projection Dictionary
    cost[decision_var] = player["Salary"] # Create Cost Dictionary
    
    # Create Dictionary for Player Types
    QBs[decision_var] = player["QB"]
    RBs[decision_var] = player["RB"]
    WRs[decision_var] = player["WR"]
    TEs[decision_var] = player["TE"]
    DST[decision_var] = player["DST"]
    number_of_players[decision_var] = 1.0

QB_constraint = pulp.LpAffineExpression(QBs)
RB_constraint = pulp.LpAffineExpression(RBs)
WR_constraint = pulp.LpAffineExpression(WRs)
TE_constraint = pulp.LpAffineExpression(TEs)
DST_constraint = pulp.LpAffineExpression(DST)
total_players = pulp.LpAffineExpression(number_of_players)

model += (QB_constraint == 1)
model += (RB_constraint <= 3)
model += (RB_constraint >= 2)
model += (WR_constraint <= 4)
model += (WR_constraint >= 3)
model += (TE_constraint <= 2)
model += (TE_constraint >= 1)
model += (DST_constraint == 1)
model += (total_players == 9)

我试图添加的限制因素,并无法弄清楚如何:让2名球员被选中在同一支球队与QB,对手的DST不能是任何一个9的球队,有1名对手是QB的球队。知道我会怎么做吗?这些数据在我的excel文件中,但我不知道如何将这些约束添加到模型中?

我一直在查看文档中的案例,我找不到根据模型选择来更改最优输出的任何示例。如果选择一个四分卫,就会影响被选中的8名球员中的其他人。

感谢任何人为我提供的任何帮助

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-28 05:22:47

这正是我的专长!通常,如果您希望约束取决于对特定变量(e.x )的选择。选择哪一个QB变量),您将需要为每个可能的选择设置一个新的约束,以某种聪明的方式确保该约束只在该变量被选中时才能执行。

  1. Stack至少在你的QB中使用n播放器:您将对玩家池中的每个QB都有一个新的约束。约束将如下所示:

代码语言:javascript
复制
[sum of other players on the same team as QB] + -n*[QB] >= 0

这样,如果优化器选择QB,它还必须选择QB的团队中的n其他球员,以满足这样的要求:当您从该团队的其他球员的数量中减去n时,结果是非负的。当没有选择QB时,这个方程什么也不做,因为QB变量有唯一的负系数。请注意,这种方法还允许您堆叠一个特定的位置(Ex )。一个QB堆栈),通过操作玩家在该等式的左边出现的内容。您还可以将其调整为强制DST堆栈。

  1. 不要将任何球员与你的DST堆叠在一起:这与上面的相似之处在于,我们对每支球队都有一个等式,但是说“这些球员名单中没有一个”而不是“至少有n个这样的球员”会稍微改变一下数学。

代码语言:javascript
复制
[sum of players facing DST] + 8*[DST] <= 8

在这个方程中,如果优化器选择DST,左侧已经是8,所以在对方队伍中添加任何球员都会使方程超出极限。如果DST没有被选中,这个等式没有影响,因为我们不会选择超过8个非DST玩家。

  1. 将你的QB与对方球队中至少一名球员堆叠在一起:这基本上和1一样,但是我们选择了n=1,用QB的对手而不是队友

来填充剩下的等式

代码语言:javascript
复制
[sum of players on the team facing QB] + -1*[QB] >= 0

同样,如果QB被选中,我们还必须选择这个等式中的其他参与者之一来平衡它,并保持总非负。如果没有选择QB,这个方程就什么也不做了,因为所有其他参与者都有正系数。

在使用纸浆实现这些变量方面,我发现使用LpVariables.dicts创建变量非常有帮助,这样您就可以多次遍历播放机列表,每次访问相同的变量:

代码语言:javascript
复制
player_ids = raw_data.index
player_vars = pulp.LpVariable.dicts('player', player_ids, cat = 'Binary')

然后很容易使用列表理解来创建您的名册约束和目标,例如:

代码语言:javascript
复制
prob = pulp.LpProblem("DFS Optimizer", pulp.LpMaximize)
#Objective
prob += pulp.lpSum([raw_data['Projection'][i]*player_vars[i] for i in player_ids]),
##Total Salary:
prib += pulp.lpSum([raw_data['Salary'][i]*player_vars[i] for i in player_ids]) <= 50000,
##Exactly 9 players:
prob += pulp.lpSum([player_vars[i] for i in player_ids]) == 9,
##2-3 RBs:
prob += pulp.lpSum([player_vars[i] for i in player_ids if raw_data['Position'][i] == 'RB']) >= 2,
prob += pulp.lpSum([player_vars[i] for i in player_ids if raw_data['Position'][i] == 'RB']) <= 3,

你可能可以从那里推断出如何做所有你已经做过的事情。现在是QB堆叠:

代码语言:javascript
复制
###Stack QB with 2 teammates
for qbid in player_ids:
    if raw_data['Position'][qbid] == 'QB':
        prob += pulp.lpSum([player_vars[i] for i in player_ids if 
                           (raw_data['Team'][i] == raw_data['Team'][qbid] and 
                            raw_data['Position'][i] in ('WR', 'RB', 'TE'))] + 
                           [-2*player_vars[qbid]]) >= 0,
###Don't stack with opposing DST:
for dstid in player_ids:
    if raw_data['Position'][dstid] == 'DST':
        prob += pulp.lpSum([player_vars[i] for i in player_ids if
                            raw_data['Team'][i] == raw_data['Opponent'][dstid]] +
                           [8*player_vars[dstid]]) <= 8,
###Stack QB with 1 opposing player:
for qbid in player_ids:
    if raw_data['Position'][qbid] == 'QB':
        prob += pulp.lpSum([player_vars[i] for i in player_ids if
                            raw_data['Team'][i] == raw_data['Opponent'][qbid]] +
                           [-1*player_vars[qbid]]) >= 0,

一旦你得到这一点,并能够生成一个单一的阵容与任何堆叠规则,这是真正的乐趣,当你开始尝试生成几行进入一个GPP。你怎么确保他们都不一样?如果你想让你的两个阵容中至少有3个不同的球员呢?你如何为你的球员设定最小/最高暴露量?我希望这一切都有帮助,我知道这是一个很长的阅读。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64094589

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档