使用 Python Pulp 进行多日播放器选择的二进制优化

Using Python Pulp for binary optimization for multi-day player selection

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

我有 2 个决策变量:即 selected 团队每天 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 指的是所有可用玩家的列表。 objective 函数是最大化这 2 天的预测分数(gd1 和 gd2 指的是比赛日 1 和比赛日 2)。这是球员 selected * 他的 'Value' 以及他的球队是否在某一天比赛的函数。

    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 个约束工作正常。这是导致 'infeasible' 解决方案的第 5 个。基本上,我正在执行一个规则,即在这 2 天内至少有 8 个玩家是共同的。

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

Status: Infeasible

我是 Python 和 PuLP 的新手。谁能帮忙?我错过了什么?

在此重申前 4 个约束条件运行良好。引起问题的是第 5 次(这是对多天 selection 的限制)。

提前致谢。

你的最后一个约束:

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

在 PuLP 中不是有效约束。我可以看到您要实现的目标,即创建一个中间二进制变量 ((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]

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