【问题标题】:Pulp writing proper constraints to produce feasible solutionPulp 编写适当的约束以产生可行的解决方案
【发布时间】:2019-11-17 19:14:11
【问题描述】:

我正在尝试对特定数量的固定装置选择 15 名球员进行建模。我的 LpProblem 包含 2 个二进制变量 player 和 fixture。

choices = LpVariable.dicts(
            "Choices", (fixtures, constraints["player"]), 0, 1, LpBinary)

我想使用此约束来限制为一组固定装置选择的球员数量(这很糟糕 - 它计算所有选择而不是使用的球员数量):

prob += lpSum([choices[f][p] for f in fixtures for p in constraints["player"]]
                      ) <= player_count + len(fixtures) - 1, "Transfers limit"

我还设置了一个约束,为每场比赛挑选 15 名球员:

for fixture in fixtures:
            prob += lpSum([choices[fixture][p]
                           for p in constraints["player"]]) == player_count, str(fixture) + " Total of " + str(player_count) + " players"

我的目标是选择 15 个和少量的从夹具到夹具的更改,但由于某种原因,这些限制会产生不可行的问题。例如,如果我搜索fixtures = [0,1,2],当我将传输限制设置为 45 (15*3) 时,问题变得可行。我不确定如何制定传输限制约束来实现我的目标。

例子:

players = [1, 2, 3, 4, 5, 6]
fixtures = [1, 2, 3]

prob = LpProblem(
    "Fantasy football selection", LpMaximize)

choices = LpVariable.dicts(
    "Players", (fixtures, players), 0, 1, LpBinary)

# objective function
prob += lpSum([predict_score(f, p) * choices[f][p]
               for p in players for f in fixtures]), "Total predicted score"

# constraints
for f in fixtures:
    # total players for each fixture
    prob += lpSum([choices[f][p] for p in players]) == 2, ""
    if f != fixtures[0]:
        # max of 1 change between fixtures
        prob += lpSum([1 if choices[f-1][p] != choices[f]
                       [p] else 0 for p in players]) <= 2, ""

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

【问题讨论】:

  • 你能提供一个minimal reproducible example吗?另外,您能否就您正在努力实施的约束提供更清晰的解释 - 我阅读了文本,但仍然不清楚缺少的约束打算做什么。
  • 嘿,我添加了一个简单的示例,我正在努力实现的约束是“夹具之间最多 1 次更改”,例如它会产生不可行的解决方案。我猜这是因为变量相互依赖,它可能是一个非线性方程。
  • 您通常不能按照您所指示的方式使用if 语句 - 但是会有一种方法来制定您想要的约束......您只需要考虑哪些操作二进制变量需要 /constraints。还有predict_score() 函数是什么?
  • 返回一个整数表示玩家得分
  • 我在下面发布的答案尝试。请注意,对于完整的minimal reproducible example,您应该真正执行任何必需的导入,并提供任何此类功能的最小实现。例如,请参阅 dummy predict_score() 我的答案。

标签: python pulp integer-programming


【解决方案1】:

我建议引入额外的二进制变量,这些变量可用于跟踪图片f 和夹具f-1 之间是否发生了变化。然后,您可以对允许的更改数量施加限制。

在下面的示例代码中,如果您注释掉最后一个约束,您会发现实现了更高的目标,但代价是更多的更改。另请注意,我为目标函数中的非零 changes 变量添加了一个微小的惩罚 - 这是在未进行更改时强制它们为零 - 此方法不需要这个小惩罚,但可能让您更轻松地了解正在发生的事情。

没有最后一个约束应该得到118的客观值,但只有109的值。

from pulp import *
import random

players = [1, 2, 3, 4, 5]
fixtures = [1, 2, 3, 4]
random.seed(42)

score_dict ={(f, p):random.randint(0,20) for f in fixtures for p in players}

def predict_score(f,p):
    return score_dict[(f,p)]

prob = LpProblem(
    "Fantasy football selection", LpMaximize)

# Does fixture f include player p
choices = LpVariable.dicts(
    "choices", (fixtures, players), 0, 1, LpBinary)

changes = LpVariable.dicts(
    "changes", (fixtures[1:], players), 0, 1, LpBinary)

# objective function
prob += lpSum([predict_score(f, p) * choices[f][p]
               for p in players for f in fixtures]
              ) - lpSum([[changes[f][p] for f in fixtures[1:]] for p in players])/1.0e15, "Total predicted score"

# constraints
for f in fixtures:
    # Two players for each fixture
    prob += lpSum([choices[f][p] for p in players]) == 2, ""

    if f != fixtures[0]:
        for p in players:
            # Assign change constraints, force to one if player
            # is subbed in or out
            prob += changes[f][p] >= (choices[f][p] - choices[f-1][p])
            prob += changes[f][p] >= (choices[f-1][p] - choices[f][p])

        # Enforce only one sub-in + one sub-out per fixture (i.e. at most one change)
        # prob += lpSum([changes[f][p] for p in players]) <= 2

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

print("Objective Value: ", prob.objective.value())

choices_soln = [[choices[f][p].value() for p in players] for f in fixtures]
print("choices_soln")
print(choices_soln)

changes_soln = [[changes[f][p].value() for p in players] for f in fixtures[1:]]
print("changes_soln")
print(changes_soln)

【讨论】:

    猜你喜欢
    • 2016-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多