Python约束优化问题

问题描述

我正在从事幻想足球计划,但遇到了约束方面的问题。一个幻想团队由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_availablepositions_available + positions_available['FLEX']之间的位置。

因为您总共需要9名玩家,所以唯一的自由度是选择一个灵活的玩家来填补最后的灵活位置。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...