PuLP优化求解仅返回唯一值:梦幻足球阵容球员排重约束实现
解决方案
你只需要按球员姓名对数据集分组,为每个球员添加「所有对应实例的选中变量之和≤1」的约束即可,修改方案如下:
完整修改后代码
import pandas as pd import pulp print('--- (1/4) 定义问题 ---') # 读取csv raw_data = pd.read_csv('./csv/fantasypros.csv') # 对位置做独热编码 encoded = pd.get_dummies(raw_data['Pos. Parent']) raw_data = raw_data.join(encoded) 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 = {} # 新增:存储每个球员对应的所有决策变量 player_var_map = {} # 遍历球员生成决策变量 for i, player in raw_data.iterrows(): var_name = 'x' + str(i) decision_var = pulp.LpVariable(var_name, cat='Binary') total_points[decision_var] = player["FPTS"] cost[decision_var] = player["salary"] 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 # 新增:把当前决策变量加入对应球员的变量列表 player_name = player["Player"] if player_name not in player_var_map: player_var_map[player_name] = [] player_var_map[player_name].append(decision_var) # 定义目标函数:最大化总得分 objective_function = pulp.LpAffineExpression(total_points) model += objective_function # 薪资帽约束 total_cost = pulp.LpAffineExpression(cost) model += (total_cost <= 135) print('--- (2/4) 定义约束 ---') # 新增:同一球员最多选中1个实例的约束 for player_name, vars in player_var_map.items(): model += (pulp.lpSum(vars) <= 1, f"single_{player_name}_constraint") # 位置约束 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) 求解问题 ---') model.solve() print('--- (4/4) 格式化结果 ---') raw_data["is_drafted"] = 0.0 for var in model.variables(): raw_data.loc[int(var.name[1:]), 'is_drafted'] = 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("总薪资消耗:{}".format(my_team["Point Cost"].sum())) print("预期总得分:{}".format(my_team["FPTS"].sum().round(1))) print('--- 执行完成 ---')
核心修改说明
- 新增
player_var_map字典,按球员姓名存储所有同名人的决策变量 - 遍历所有球员分组,添加约束:每组内的决策变量求和不超过1,确保同一个球员最多只能有一个实例被选入阵容
- 原有逻辑全部保留,不会影响位置、薪资、阵容人数等原有约束的生效
内容的提问来源于stack exchange,提问作者python_noob_5
相关产品推荐
相关产品推荐

