【发布时间】:2021-08-25 00:51:37
【问题描述】:
我第一次涉足 PuLP(通常是 Python)来运行梦幻足球游戏的优化问题。
我下面的代码运行成功,但输出的是一个空的DataFrame。
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
raw_data["QB"] = (raw_data["Pos. Parent"] == "QB").astype(float)
raw_data["RB"] = (raw_data["Pos. Parent"] == "RB").astype(float)
raw_data["WR"] = (raw_data["Pos. Parent"] == "WR").astype(float)
raw_data["TE"] = (raw_data["Pos. Parent"] == "TE").astype(float)
raw_data["K"] = (raw_data["Pos. Parent"] == "K").astype(float)
raw_data["DST"] = (raw_data["Pos. Parent"] == "DEF").astype(float)
raw_data["DK"] = (raw_data["Pos. Parent"] == "DK").astype(float)
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 = []
# 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
vars.append(decision_var)
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.iloc[int(var.name[1:]), 10] = var.varValue
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 ---')
预期结果是模型建议在给定约束条件下提供最预期结果的十名球员的阵容。
我不确定这是否有帮助,但下面是我解决问题并尝试格式化结果时 Python 控制台中的输出。
At line 2 NAME MODEL
At line 3 ROWS
At line 15 COLUMNS
At line 35896 RHS
At line 35907 BOUNDS
At line 38668 ENDATA
Problem MODEL has 10 rows, 2760 columns and 8324 elements
Coin0008I MODEL read with 0 errors
Continuous objective value is 193.829 - 0.01 seconds
Cgl0003I 2 fixed, 0 tightened bounds, 0 strengthened rows, 0 substitutions
Cgl0003I 2 fixed, 6 tightened bounds, 0 strengthened rows, 0 substitutions
Cgl0003I 0 fixed, 1 tightened bounds, 0 strengthened rows, 0 substitutions
Cgl0004I processed model has 7 rows, 266 columns (266 integer (58 of which binary)) and 773 elements
Cutoff increment increased from 1e-05 to 0.000999
Cbc0012I Integer solution of -192.1 found by DiveCoefficient after 0 iterations and 0 nodes (0.05 seconds)
Cbc0038I Full problem 7 rows 266 columns, reduced to 2 rows 3 columns
Cbc0012I Integer solution of -192.574 found by DiveCoefficient after 10 iterations and 0 nodes (0.08 seconds)
Cbc0031I 2 added rows had average density of 7.5
Cbc0013I At root node, 2 cuts changed objective from -193.82941 to -192.574 in 4 passes
Cbc0014I Cut generator 0 (Probing) - 0 row cuts average 0.0 elements, 3 column cuts (3 active) in 0.003 seconds - new frequency is 1
Cbc0014I Cut generator 1 (Gomory) - 6 row cuts average 9.0 elements, 0 column cuts (0 active) in 0.003 seconds - new frequency is 1
Cbc0014I Cut generator 2 (Knapsack) - 0 row cuts average 0.0 elements, 0 column cuts (0 active) in 0.002 seconds - new frequency is -100
Cbc0014I Cut generator 3 (Clique) - 0 row cuts average 0.0 elements, 0 column cuts (0 active) in 0.000 seconds - new frequency is -100
Cbc0014I Cut generator 4 (MixedIntegerRounding2) - 1 row cuts average 7.0 elements, 0 column cuts (0 active) in 0.000 seconds - new frequency is 1
Cbc0014I Cut generator 5 (FlowCover) - 0 row cuts average 0.0 elements, 0 column cuts (0 active) in 0.001 seconds - new frequency is -100
Cbc0014I Cut generator 6 (TwoMirCuts) - 5 row cuts average 8.0 elements, 0 column cuts (0 active) in 0.000 seconds - new frequency is -100
Cbc0001I Search completed - best objective -192.574, took 10 iterations and 0 nodes (0.08 seconds)
Cbc0035I Maximum depth 0, 60 variables fixed on reduced cost
Cuts at root node changed objective from -193.829 to -192.574
Probing was tried 4 times and created 3 cuts of which 0 were active after adding rounds of cuts (0.003 seconds)
Gomory was tried 4 times and created 6 cuts of which 0 were active after adding rounds of cuts (0.003 seconds)
Knapsack was tried 4 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.002 seconds)
Clique was tried 4 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
MixedIntegerRounding2 was tried 4 times and created 1 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
FlowCover was tried 4 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.001 seconds)
TwoMirCuts was tried 4 times and created 5 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Result - Optimal solution found
Objective value: 192.57400000
Enumerated nodes: 0
Total iterations: 10
Time (CPU seconds): 0.08
Time (Wallclock seconds): 0.12
Option for printingOptions changed from normal to all
Total time (CPU seconds): 0.10 (Wallclock seconds): 0.14
--- (4/4) Formatting the results ---
Empty DataFrame
Columns: [Asset Name, Player, Pos. Parent, Rarity, Point Cost, FPTS]
Index: []
Total used amount of salary cap: 0
Projected points: 0.0
--- Completed ---
提前感谢您就如何让我的最佳 10 人阵容填充 DataFrame 提供任何建议。
编辑 - 根据@chitown88 的要求,这里是CSV 的链接。
【问题讨论】:
-
@python_noob5,分享/发布 Fantasypros.csv 文件,我可以为您提供帮助。
-
@chitown88 感谢您的回复。我会给你的答案一个镜头。我还在帖子底部添加了指向 CSV 的链接。
-
更新:成功了,谢谢!如果您不介意的话,现在我有另一个问题 - 由于游戏的设置方式,我的“库存”中可能会出现重复的玩家,但我只能使用每个阵容中的一个。这个模型吐出 6 次最佳球员的阵容...我如何添加一个约束,每个阵容包含十个唯一的球员姓名(不重复)?
-
好问题。没有把握。我现在试试看能不能解决。我会尽快回复你
-
我为您找到了解决方案。创建一个新帖子(因为这是一个新问题),我会在那里为您发布。当你发布它时告诉我(可以把链接放在这里)
标签: python dataframe optimization pulp