【问题标题】:Using Python Pulp for binary optimization for multi-day player selection使用 Python Pulp 进行多日玩家选择的二进制优化
【发布时间】:2020-10-03 12:23:04
【问题描述】:

我正在努力解决使用纸浆的整数优化问题。我正在创建一个梦幻运动队——我需要在每个比赛日选择 11 名球员。 [为简单起见,假设只有 2 个比赛日]。另一个限制是我不能在 2 天内进行超过 3 次更改。换句话说,2天之间需要8名球员相同。我购买的播放器需要在 100 积分的预算内。

我有 2 个决策变量:即 2 天中每一天的选定团队。

    prob = LpProblem("Fantasy_Cricket", LpMaximize)
    player_names = list(squad.Player)
    player_gd1 = LpVariable.dicts("playerChosen1", player_names, 0, 1, cat='Integer')
    player_gd2 = LpVariable.dicts("playerChosen2", player_names, 0, 1, cat='Integer')

仅供参考:player_names 指的是所有可用玩家的列表。 目标函数是在 2 天内最大化预测得分(gd1 和 gd2 指的是比赛日 1 和比赛日 2)。这是所选球员 * 他的“价值”以及他的球队是否在给定日期比赛的函数。

    prob += lpSum([player_gd1[p]*squad[squad.Player==p]['Value'].sum()*squad[squad.Player==p]['gd1'].sum() + player_gd2[p]*squad[squad.Player==p]['Value'].sum()*squad[squad.Player==p]['gd2'].sum() for p in player_names])

约束设置如下:

    prob += lpSum([player_gd1[p]*squad[squad.Player==p]['Points'].sum() for p in player_names]) <=100
    prob += lpSum([player_gd2[p]*squad[squad.Player==p]['Points'].sum() for p in player_names]) <=100
    
    prob += lpSum([player_gd1[p] for p in player_names]) == 11
    prob += lpSum([player_gd2[p] for p in player_names]) == 11
    
    prob += lpSum([((player_gd1[p] + player_gd2[p]) ==2) for p in player_names]) >=8

前 4 个约束运行良好。这是导致“不可行”解决方案的第 5 个问题。基本上,我执行的规则是在 2 天内至少有 8 名玩家是共同的。

prob.solve()
print("Status:", LpStatus[prob.status]) 

状态:不可行

我是 Python 和 PuLP 的新手。任何人都可以帮忙吗?我错过了什么?

在此重申前 4 个约束工作正常。导致问题的是 5th 的引入(这是对多天选择的限制)。

提前致谢。

【问题讨论】:

  • 我认为这将涉及为游戏添加第二个索引和其他一些内容。但是让我们稍等一下……我在你的模型中没有看到任何可以激励交换球员的东西?你只为一支球队挑选球员,对吧?那支球队有一系列的比赛。每个玩家都有成本和价值。在您的模型中,什么会使团队选择与第 1 场比赛、第 2 场比赛、...、第 N 场比赛不同?此外,如果您编辑帖子并包含squad 数据框的一部分,那将非常有益。
  • @AirSquid,澄清一下:我每天最多可以更换 3 名玩家。我的球队是由多支球队组成的复合球队,因此在一天中累积积分的能力取决于特定球队是否真的在比赛。

标签: python optimization integer pulp


【解决方案1】:

你的最后一个约束:

prob += lpSum([((player_gd1[p] + player_gd2[p]) ==2) for p in player_names]) >=8

在纸浆中不是有效的约束。我可以看到你想要实现的目标,创建一个中间二进制变量((player_gd1[p] + player_gd2[p]) ==2),然后在所有玩家之间求和。如果你想这样做,你必须显式声明这个二进制变量,并找到一种方法,如果(且仅当)满足该条件时强制它取一个真值。

例如,您可以创建一组新变量:

player_swapped = LpVariable.dicts("player_swapped", player_names, 0, 1, cat='Integer')

然后有一组约束为:

for p in player_names:
    player_swapped[p] >= player_gd1[p] - player_gd2[p]
    player_swapped[p] >= player_gd2[p] - player_gd1[p]

然后,您可以设置游戏之间可以交换多少玩家的限制。

【讨论】:

  • 太棒了!谢谢你的及时回复。它绝对解决了这个问题。
  • 我很高兴它有帮助。如果您的问题得到解答,请考虑将我的答案标记为这样(小勾号)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-19
  • 2017-03-26
  • 2018-08-13
  • 1970-01-01
  • 1970-01-01
  • 2015-11-22
相关资源
最近更新 更多