【问题标题】:Pulp Integer Programming Constraint ignoredPulp 整数编程约束被忽略
【发布时间】:2020-12-28 00:07:59
【问题描述】:

我正在尝试仅使用布尔变量解决 LpProblem,而 Pulp 似乎忽略了一些约束。提供有关该问题的一些背景信息:

我想为学校在尝试创建课堂小组时面临的问题找到最佳解决方案。在这种情况下,学生将获得一篇论文,最多可写 5 名其他学生,学校保证他们将与至少其中一名学生在一起。要了解我如何将此问题建模为整数规划问题,请参阅 this question

在该链接中,您将看到我的变量定义为 x_ij = 1 如果学生 i 将与学生 j 在一起,否则 x_i_j = 0。此外,在那个链接中,我询问了我在使用 Pulp 实现时遇到问题的约束:如果 x_i_j = 1 和 x_j_k = 1,则通过传递属性,x_i_k = 1。换句话说,如果学生 i 和学生 j 在一起,并且学生 j 和学生 k 在一起,那么学生 i 就自然会和学生 k 在一起。

我的目标是最大化在输入矩阵和变量矩阵之间执行 Hadamard 乘积时获得的矩阵的所有元素的总和。换句话说,我想尽可能多地考虑学生的要求。

我现在将提供一些有助于可视化问题的代码 sn-ps 和屏幕截图:

输入(只是一个样本:真实矩阵是 37x37)

输出

正如您在最后一张图片中看到的那样,x_27 = 1 和 x_37 = 1 但 x_23 = 0 这没有意义。

这是我定义变量的方式

def define_variables():
  variables = []
  for i in range(AMOUNT_OF_STUDENTS):
    row = []
    for j in range(AMOUNT_OF_STUDENTS):
      row.append(LpVariable(f"x_{i}_{j}", lowBound=0, upBound=1, cat='Integer'))
    variables.append(row)
  return variables

这是我定义传递约束的方式

    for i in range(len(variables)):
      for j in range(i, len(variables)):
        if i != j:
          problem += variables[i][j] == variables[j][i]   # Symmetry
        for k in range(j, len(variables)):
          if i < j < k < len(variables):
            problem += variables[i][j] + variables[j][k] - variables[i][k] <= 1 # Transitive
            problem += variables[i][j] + variables[i][k] - variables[j][k] <= 1
            problem += variables[j][k] + variables[i][k] - variables[i][j] <= 1

打印 LpProblem 时,我看到约束显然不起作用:

正如您在输出中看到的那样:x_2_7 = 1 和 x_3_7 = 1。因此,为了满足这个约束,x_2_3 也应该为 1,但正如您在输出中看到的那样,它也是 0。

对可能发生的事情有任何想法吗?我已经被困了好几天,这个问题似乎很好建模,当我只有 8 个学生(64 个变量)时它就起作用了。现在我有 37 名学生(1369 个变量),它的行为似乎很奇怪。求解器得出了一个解决方案,但它似乎忽略了一些约束。

非常感谢任何帮助!提前谢谢你。

【问题讨论】:

  • 另外,在你的解决方案x_27 != x_72。当你得到解决方案时,求解器的状态是什么?
  • 没注意到。另一个约束被忽略。你说的状态是什么意思?求解器说它找到了一个最佳解决方案。但是,在找到解决方案之前,它会在控制台中输出多次减少问题的行数和列数。我不知道这到底是什么意思。我假设它忽略了多余的约束/变量。

标签: python pulp


【解决方案1】:

约束正常工作。在下面找到分析: (从github交叉发布:https://github.com/coin-or/pulp/issues/377

import pulp as pl
import pytups as pt

path = 'debugSolution.txt'

# import model
_vars, prob = pl.LpProblem.from_json(path)

# get all variables with non-zero value
vars_value = pt.SuperDict(_vars).vfilter(pl.value)

# export the lp
prob.writeLP('debugSolution.lp')

# the constraint you show in the SO problem is:
# _C3833: - x_2_3 + x_2_7 + x_3_7 <= 1

'x_2_7' in vars_value
# True, so x_2_7 has value 1

'x_3_7' in vars_value
# False, so x_3_7 has value 0

'x_2_3' in vars_value
# False, so x_2_3 has value 0

所以-0 + 1 + 0 &lt;= 1 表示遵守约束。将x_3_7 的值带回某处肯定有问题,因为您认为在纸浆中它是 0 时是 1。

【讨论】:

【解决方案2】:

这称为集合分区问题,PuLP 在其文档here 中有一个示例。

本质上,您无需将变量建模为学生 A 是否与学生 B 同班的指标,而是定义一组学生和一组教室之间的映射。然后,您可以将您的学生偏好应用为约束或最大化目标的一部分。

【讨论】:

  • 感谢您的回答@foglerit,我将阅读您引用的文档并对我的代码进行必要的更改。尽管如此,奇怪的是,以我的方式 Pulp 忽略了某些约束,即使它们被正确定义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-22
  • 1970-01-01
  • 2016-11-04
  • 2015-01-02
相关资源
最近更新 更多