问题描述
我正在努力解决使用纸浆的整数优化问题。我正在创建一支幻想运动队-在每个游戏日我需要选择11名球员。 [为简单起见,假设仅2个游戏日]。另一个限制是我在两天内所做的更改不能超过3个。换句话说,两天之内必须有8位玩家相同。我购买的玩家的预算不得超过100个积分。
我有2个决策变量:即2天之内的选定团队。
prob = LpProblem("Fantasy_Cricket",LpMaximize)
player_names = list(squad.Player)
player_gd1 = LpVariable.dicts("playerChosen1",player_names,1,cat='Integer')
player_gd2 = LpVariable.dicts("playerChosen2",cat='Integer')
仅供参考:player_names
是指所有可用球员的列表。
目标函数是在两天内最大化预测分数(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
前四个约束工作正常。这是导致“不可行”解决方案的第五个原因。基本上,我要执行一个规则,即在两天内至少有8位玩家是相同的。
prob.solve()
print("Status:",LpStatus[prob.status])
状态:不可行
我是Python和PuLP的新手。有人可以帮忙吗?我想念什么?
在此重申,前4个约束工作正常。正是第五种方法的引入(这是对多日选择的限制),导致出现问题。
谢谢。
解决方法
您的最后一个约束:
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,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]
然后您可以设置游戏之间可以交换多少玩家的限制。