在 PuLP 优化解决方案中仅包含唯一值 [英] Include Only Unique Values in a PuLP Optimization Solution

查看:34
本文介绍了在 PuLP 优化解决方案中仅包含唯一值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这篇文章是从 这个问题.

我的目标是在给定一组约束的情况下生成最佳的梦幻足球阵容.由于梦幻足球联赛的性质,我的库存中可能多次拥有同一名球员,尽管我只能在我的阵容中使用该球员的一个实例.我使用 PuLP 创建了一个优化问题来生成阵容,但我需要添加一个约束以确保该球员不会多次出现在该阵容中.

My goal is to generate an optimal fantasy football lineup given a set of constraints. Due to the nature of the fantasy football league, it is possible that I have the same player multiple times in my inventory, although I can only play one instance of that player in my lineup. I have created an optimization problem using PuLP to generate the lineup, but I need to add a constraint to ensure that a player does not appear in that lineup more than once.

以下是我当前的模型.任何有关如何确保我的解决方案中没有重复播放器的建议表示赞赏!

Below is my current model. Any suggestions on how to ensure no duplicate players in my solution are appreciated!

import pandas as pd
import pulp

print('--- (1/4) Defining the problem ---')

# Read csv
raw_data = pd.read_csv('./csv/fantasypros.csv')

# create new columns that has binary numbers if player == a specific position
encoded = pd.get_dummies(raw_data['Pos. Parent'])  # <-- One-Hote Encoding
raw_data = raw_data.join(encoded)  # <-- joining it to the raw_data table

raw_data["salary"] = raw_data["Point Cost"].astype(float)

model = pulp.LpProblem("NFTdraft", pulp.LpMaximize)

total_points = {}
cost = {}
qb = {}
rb = {}
wr = {}
te = {}
k = {}
dst = {}
dk = {}
num_players = {}

vars_list = []

# 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["FPTS"]  # Create FPTS Dictionary
    cost[decision_var] = player["salary"]  # Create Cost Dictionary

    # Create Dictionary for Player Types
    qb[decision_var] = player["QB"]
    rb[decision_var] = player["RB"]
    wr[decision_var] = player["WR"]
    te[decision_var] = player["TE"]
    k[decision_var] = player["K"]
    dst[decision_var] = player["DST"]
    dk[decision_var] = player["DK"]
    num_players[decision_var] = 1.0

objective_function = pulp.LpAffineExpression(total_points)
model += objective_function

total_cost = pulp.LpAffineExpression(cost)
model += (total_cost <= 135)

print('--- (2/4) Defining the constraints ---')
QB_constraint = pulp.LpAffineExpression(qb)
RB_constraint = pulp.LpAffineExpression(rb)
WR_constraint = pulp.LpAffineExpression(wr)
TE_constraint = pulp.LpAffineExpression(te)
K_constraint = pulp.LpAffineExpression(k)
DST_constraint = pulp.LpAffineExpression(dst)
DK_constraint = pulp.LpAffineExpression(dk)
total_players = pulp.LpAffineExpression(num_players)

model += (QB_constraint >= 1)
model += (QB_constraint <= 2)
model += (RB_constraint <= 8)
model += (WR_constraint <= 8)
model += (TE_constraint <= 8)
model += (K_constraint <= 1)
model += (DST_constraint <= 1)
model += (DK_constraint <= 2)
model += (total_players == 10)

print('--- (3/4) Solving the problem ---')
model.solve()

print('--- (4/4) Formatting the results ---')
raw_data["is_drafted"] = 0.0

for var in model.variables():
    raw_data.loc[int(var.name[1:]), 'is_drafted'] = var.varValue  # <--- CHANGED HERE

my_team = raw_data[raw_data["is_drafted"] == 1.0]
my_team = my_team[["Asset Name", "Player", "Pos. Parent", "Rarity", "Point Cost", "FPTS"]]

print(my_team)
print("Total used amount of salary cap: {}".format(my_team["Point Cost"].sum()))
print("Projected points: {}".format(my_team["FPTS"].sum().round(1)))
print('--- Completed ---')

推荐答案

要将限制设置为仅允许单人玩家(来自重复玩家的数据框),您需要设置类似于其他限制的内容.在这里,我们将只对 "Player" 进行单热编码,然后遍历它以创建限制,即每个 "Player" 必须有 1 个或更少> 姓名.

To set the restriction to only allow single player (from your dataframe of duplicate players) you'll need to setup something similar to the other restrictions). Here we'll just one-hot encode on "Player", then loop through that to create the restriction that you have to have 1 or less of each "Player" name.

import pandas as pd
import pulp

print('--- (1/4) Defining the problem ---')

# Read csv
raw_data = pd.read_csv('./csv/fantasypros.csv').drop_duplicates().reset_index(drop=True)

# create new columns that has binary numbers if player == a specific position
encoded = pd.get_dummies(raw_data['Pos. Parent']) #<-- One-Hote Encoding 
raw_data = raw_data.join(encoded) #<-- joining it to the raw_data table

# Will be used to create the constraint of not using same player name in lineup
encoded = pd.get_dummies(raw_data['Player']) #<-- One-Hote Encoding 
raw_data = raw_data.join(encoded) #<-- joining it to the raw_data table


raw_data["salary"] = raw_data["Point Cost"].astype(float)

model = pulp.LpProblem("NFTdraft", pulp.LpMaximize)

total_points = {}
cost = {}
qb = {}
rb = {}
wr = {}
te = {}
k = {}
dst = {}
dk = {}
num_players = {}

# Here I created a list of all the possible players in the dataframe
# This is used later to construct the dictionary of players, then
# to add each of those into the model
players_list = list(raw_data['Player'].unique())
players_list.sort()

pLAYER_dict = {}
for player in players_list:
    pLAYER_dict[player] ={}

vars_list = []

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

    total_points[decision_var] = player["FPTS"]  # Create FPTS Dictionary
    cost[decision_var] = player["salary"]  # Create Cost Dictionary

    # Create Dictionary for Player Types
    qb[decision_var] = player["QB"]
    rb[decision_var] = player["RB"]
    wr[decision_var] = player["WR"]
    te[decision_var] = player["TE"]
    k[decision_var] = player["K"]
    dst[decision_var] = player["DST"]
    dk[decision_var] = player["DK"]
    num_players[decision_var] = 1.0
    
    # Here is where I store each value for each player name for the player
    for key, v in PLAYER_dict.items():
        PLAYER_dict[key].update({decision_var:player[key]})


objective_function = pulp.LpAffineExpression(total_points)
model += objective_function

total_cost = pulp.LpAffineExpression(cost)
model += (total_cost <= 135)

print('--- (2/4) Defining the constraints ---')
QB_constraint = pulp.LpAffineExpression(qb)
RB_constraint = pulp.LpAffineExpression(rb)
WR_constraint = pulp.LpAffineExpression(wr)
TE_constraint = pulp.LpAffineExpression(te)
K_constraint = pulp.LpAffineExpression(k)
DST_constraint = pulp.LpAffineExpression(dst)
DK_constraint = pulp.LpAffineExpression(dk)
total_players = pulp.LpAffineExpression(num_players)

model += (QB_constraint >= 1)
model += (QB_constraint <= 2)
model += (RB_constraint <= 8)
model += (WR_constraint <= 8)
model += (TE_constraint <= 8)
model += (K_constraint <= 1)
model += (DST_constraint <= 1)
model += (DK_constraint <= 2)
model += (total_players == 10)

for k1, v1 in PLAYER_dict.items():
    player_constraint = pulp.LpAffineExpression(v1)
    model += (player_constraint <= 1)

print('--- (3/4) Solving the problem ---')
model.solve()

print('--- (4/4) Formatting the results ---')
raw_data["is_drafted"] = 0.0

for var in model.variables():
    raw_data.loc[int(var.name[1:]), 'is_drafted'] = var.varValue     # <--- CHANGED HERE
    
my_team = raw_data[raw_data["is_drafted"] == 1.0]
my_team = my_team[["Asset Name", "Player", "Pos. Parent", "Rarity", "Point Cost", "FPTS"]]

print(my_team)
print("Total used amount of salary cap: {}".format(my_team["Point Cost"].sum()))
print("Projected points: {}".format(my_team["FPTS"].sum().round(1)))
print('--- Completed ---')

输出:

              Asset Name               Player  ... Point Cost    FPTS
59         Arizona WR #1      DeAndre Hopkins  ...         19  20.301
375       Carolina RB #1  Christian McCaffrey  ...         20  26.500
582     Cincinnati WR #3           Tyler Boyd  ...         10  13.000
803         Denver RB #2     Javonte Williams  ...          8  11.100
1011     Green Bay WR #4         Randall Cobb  ...          5   8.800
1170  Indianapolis QB #2          Jacob Eason  ...          5  11.400
1301   Kansas City QB #1   Patrick Mahomes II  ...         20  23.900
1349   Kansas City WR #1          Tyreek Hill  ...         20  21.100
1658     Minnesota RB #1          Dalvin Cook  ...         20  22.500
2729    Washington WR #2        Curtis Samuel  ...          8  11.700

[10 rows x 6 columns]
Total used amount of salary cap: 135
Projected points: 170.3
--- Completed ---

这篇关于在 PuLP 优化解决方案中仅包含唯一值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆