Python PULP -阵容生成器的位置约束



我建立了一个NBA阵容生成器,可以根据每个球员的预测,优化9个位置的阵容(2个控球后卫,2个得分后卫,2个小前锋,2个大前锋,1个中锋)。

最初,为了处理可以打两个位置的球员,我设置了一个限制,阻止同一名球员在一个阵容中被选中两次,这是正确的。我遇到的问题是,偶尔当我构建多个阵容时,其中两个将是重复的,但程序认为它们是不同的。

Generator的版本1

例如,玩家a和玩家B都被选中,但他们都是双位置球员,他们共享相同的双位置(例如,他们都可以是PG或SG),因为生成器将交换他们,在阵容1中,玩家a被选为PG和B作为SG,在阵容2中,玩家a被选为SG和B作为PG。

我在第一个版本中约束位置的代码如下:

prob += (pulp.lpSum(self.positions['PG'][i] * players_lineup[i] for i in range(self.num_players)) == 2)
prob += (pulp.lpSum(self.positions['SG'][i] * players_lineup[i] for i in range(self.num_players)) == 2)
prob += (pulp.lpSum(self.positions['SF'][i] * players_lineup[i] for i in range(self.num_players)) == 2)
prob += (pulp.lpSum(self.positions['PF'][i] * players_lineup[i] for i in range(self.num_players)) == 2)
prob += (pulp.lpSum(self.positions['C'][i] * players_lineup[i] for i in range(self.num_players)) == 1)

因为程序将PG版本的玩家A和SG版本的玩家A视为独立的实体,它实际上已经改变了结果(尽管功能相同)。

生成器版本2

所以我创建了一个更新的版本,每个玩家都有一个位置1和一个位置2(如果玩家没有第二个位置,可以没有)。我在这里遇到的问题是,我现在可以生成一个符合以下示例约束的阵容,但该阵容在技术上是不正确的。首先,我将提供我的新约束,然后我将解释我的问题。

#Ensures that the lineup has at least 2 potential suitors for PG
prob += (pulp.lpSum(self.positions['PG'][i] * players_lineup[i] for i in range(self.num_players)) >= 2)
# Ensures that the lineup has no more than 2 players who can only play PG
prob += (pulp.lpSum(
self.positions['PG'][i] * self.dualPosition[i] * players_lineup[i] for i in range(self.num_players)) <=2)
#Ensures that the lineup has at least 2 potential suitors for SG
prob += (pulp.lpSum(self.positions['SG'][i] * players_lineup[i] for i in range(self.num_players)) >= 2)
# Ensures that the lineup has no more than 2 players who can only play SG
prob += (pulp.lpSum(
self.positions['SG'][i] * self.dualPosition[i] * players_lineup[i] for i in range(self.num_players)) <= 2)
#Ensures that the lineup has at least 2 potential suitors for SF
prob += (pulp.lpSum(self.positions['SF'][i] * players_lineup[i] for i in range(self.num_players)) >= 2)
# Ensures that the lineup has no more than 2 players who can only play SF
prob += (pulp.lpSum(
self.positions['SF'][i] * self.dualPosition[i] * players_lineup[i] for i in range(self.num_players)) <= 2)
#Ensures that the lineup has at least 2 potential suitors for PF
prob += (pulp.lpSum(self.positions['PF'][i] * players_lineup[i] for i in range(self.num_players)) >= 2)
# Ensures that the lineup has no more than 2 players who can only play PF
prob += (pulp.lpSum(
self.positions['PF'][i] * self.dualPosition[i] * players_lineup[i] for i in range(self.num_players)) <= 2)
#Ensures that the lineup has at least 1 potential suitor for C
prob += (pulp.lpSum(self.positions['C'][i] * players_lineup[i] for i in range(self.num_players)) >= 1)
# Ensures that the lineup has no more than 1 player who can only play C
prob += (pulp.lpSum(
self.positions['C'][i] * self.dualPosition[i] * players_lineup[i] for i in range(self.num_players)) <= 1)

我在这里面临的问题是,约束条件得到满足,但他们显然没有达到我想要他们哈哈!我发现正在构建如下的队列:

<表类="年代桌子">玩家Pos 1Pos 2tbody><PG没有BPG没有CPGSGDPGSGESG科幻小说F科幻小说PF<G/td>科幻小说PFHC没有我PGSG

我认为如果你重新表述你的问题,你会快乐得多。对于一个整数程序来说,用一组球员和一组位置对它进行双索引是很自然的。在你的约束条件中,事情会变得更加清晰,因为你可以将玩家或位置相加,从而更清楚地表达你的问题。我真的不清楚你们的许多模型项目是什么,比如positions[i]dualPositions[i]。这里有一个玩具模型,可以帮助你思考如何对这个坏男孩进行双索引…

注意,有几种方法可以处理"法律转让";一部分原因。下面是如何做到这一点的一个概念。

# hoops dream team
from pulp import *
salaries = {'bob'   : 100,
'steve' : 110,
'bernie': 105,
'eugene': 120,
'biff'  : 115, 
'reggie': 99,
'mike'  : 102}
positions = {'PG','FWD', 'CTR'}
legal_assignments = {   'bob'   : {'PG'},
'steve' : {'PG', 'FWD'},
'bernie': {'FWD', 'CTR'},
'eugene': {'FWD', 'PG'},
'biff'  : {'PG'},
'reggie': {'CTR', 'FWD'},
'mike'  : {'FWD'}}
legal_assignments_set = { (k,v) for k in legal_assignments.keys() for v in legal_assignments[k]}
prob = LpProblem("Team", LpMinimize)
assign = LpVariable.dicts("assignment", legal_assignments_set, cat="Binary")
#minimize cost of team
prob += sum(assign[player, pos] * salaries[player] for (player, pos) in legal_assignments_set)
# constraints...
# only assign each player once
for player in salaries.keys():
prob += sum(assign[player, pos] for pos in positions if (player, pos) in legal_assignments_set) <=1
# fill each position to 2 PG, 2 FWD, 1 CTR
prob += sum(assign[player, 'PG'] for player in salaries.keys() if (player, 'PG') in legal_assignments_set) == 2
prob += sum(assign[player, 'FWD'] for player in salaries.keys() if (player, 'FWD') in legal_assignments_set) == 2
prob += sum(assign[player, 'CTR'] for player in salaries.keys() if (player, 'CTR') in legal_assignments_set) == 1
prob.solve()
print('Status:', LpStatus[prob.status])
for v in prob.variables():
print(v.name, '=', v.varValue)

最新更新