问题描述
我正在从事幻想足球计划,但遇到了约束方面的问题。一个幻想团队由1QB,2RB,3WR,1TE,1DEF和1FLEX(可以是RB,WR或TE)组成
我的输出正在复制播放器。因此,例如,如果John Doe担任RB职位,我需要他不要担任FLEX职位。我不知道如何完成此约束。也许进行名称比较以确保名称互不相同?
任何建议将不胜感激!
以下是一些示例数据:
| position | displayName | Roster | Position | salary | points |
|----------+---------------------+----------+----------+--------+--------|
| RB | Christian McCaffrey | 15033483 | RB/FLEX | 10000 | 30.95 |
| WR | Michael Thomas | 15033799 | WR/FLEX | 9000 | 24.62 |
| QB | Lamar Jackson | 15033397 | QB | 8100 | 29.85 |
| RB | Dalvin Cook | 15033485 | RB/FLEX | 7900 | 21.62 |
# Set constraints
##################################################################
salaries = {}
points = {}
for pos in availables.position.unique():
available_pos = availables[availables.position == pos]
salary = list(available_pos[["displayName","salary"]].set_index("displayName").to_dict().values())[0]
point = list(available_pos[["displayName","points"]].set_index("displayName").to_dict().values())[0]
salaries[pos] = salary
points[pos] = point
pos_num_available = {
"QB": 1,"RB": 2,"WR": 3,"TE": 1,"FLEX": 1,"DST": 1
}
pos_flex = {
"QB": 0,"RB": 1,"WR": 1,"FLEX": 0,"DST": 0
}
pos_flex_available = 3
SALARY_CAP = 50000
_vars = {k: LpVariable.dict(k,v,cat="Binary") for k,v in points.items()}
##################################################################
# Problem Definition
##################################################################
prob = LpProblem("Fantasy",LpMaximize)
rewards = []
costs = []
position_constraints = []
for k,v in _vars.items():
costs += lpSum([salaries[k][i] * _vars[k][i] for i in v])
rewards += lpSum([points[k][i] * _vars[k][i] for i in v])
prob += lpSum([_vars[k][i] for i in v]) <= pos_num_available[k]
prob += lpSum([pos_flex[k] * _vars[k][i] for i in v]) <= pos_flex_available
prob += lpSum(rewards)
prob += lpSum(costs) <= SALARY_CAP
prob.solve()
解决方法
为了便于阅读,我已经整理了一些代码。结构完全相同,只是一些语法上的问题。
请考虑以下内容:
import pulp as pl
import pandas as pd
availables = pd.DataFrame(
[
["RB","Christian McCaffrey",15033483,"RB/FLEX",10000,30.95],["WR","Michael Thomas",15033799,"WR/FLEX",9000,24.62],["QB","Lamar Jackson",15033397,"QB",8100,29.85],["RB","Dalvin Cook",15033485,7900,21.62]
],columns=["position","displayName","Roster","Position","salary","points"]
)
##################################################################
# Set constraints
##################################################################
salaries = {}
points = {}
players = {}
for position in availables.position.unique():
available_for_position = availables[availables.position == position]
players[position] = list(available_for_position.Roster.values)
salaries[position] = {
player_roster: salary for player_roster,salary in
zip(players[position],available_for_position.salary.values)
}
points[position] = {
player_roster: _points for player_roster,_points in
zip(players[position],available_for_position.points.values)
}
positions_available = {
"QB": 1,"RB": 2,"WR": 3,"TE": 1,"FLEX": 1,"DST": 1
}
flexible_positions = ("RB","WR","TE")
SALARY_CAP = 50000
# Player variables['QB'][15033483] denotes whether Lamar Jackson is selected
variables = {position: pl.LpVariable.dict(position,players[position],cat="Binary")
for position in players}
##################################################################
# Problem Definition
##################################################################
prob = pl.LpProblem("Fantasy",pl.LpMaximize)
rewards = []
costs = []
number_of_selected_players = []
for position,players in variables.items():
for player,player_selected in players.items():
# If this player is selected,he will add salaries and points
costs += salaries[position][player] * player_selected
rewards += points[position][player] * player_selected
number_of_selected_players += player_selected
# Of this position,if it does not support FLEX,at most `positions_available`
# are supported. If it does support FLEX,increment that by
# `flexible_positions_available`
if position not in flexible_positions:
prob += pl.lpSum(players.values()) == positions_available[position]
else:
# We need at least `positions_available` players on this position and at
# most`positions_available + flexible_positions_available` players
prob += pl.lpSum(players.values()) >= positions_available[position]
prob += (pl.lpSum(players.values())
<= positions_available[position] + positions_available["FLEX"])
# In total,we need exactly `positions_available` players
prob += pl.lpSum(number_of_selected_players) == sum(positions_available.values())
prob += pl.lpSum(rewards)
prob += pl.lpSum(costs) <= SALARY_CAP
prob.solve()
您可以跟踪每个玩家是否被选中。然后,您最多允许positions_available
位该位置的玩家,除非它是“灵活”位置,否则您允许positions_available
至positions_available + positions_available['FLEX']
之间的位置。
因为您总共需要9名玩家,所以唯一的自由度是选择一个灵活的玩家来填补最后的灵活位置。