首页 > 解决方案 > 如何根据纸浆python中先前变量的值分配后续变量?

问题描述

我正在使用纸浆库解决 python 中的优化问题。我有一个 5X5 矩阵作为优化问题的决策变量 (x(i,j))。这些决策变量可以取 1 到 10 之间的整数值。我需要帮助来编写我无法在纸浆中定义的 2 个约束的代码:

  1. 如果 x(i,j) 的值为 1,则 k >j 的 x(i,k)=1(此约束意味着在任何行中,如果决策变量的值为 1,则所有后续元素的值在那一行也是1)

  2. 如果 x(i,j) 的值不是 1,并且 x(i,k) 的值不是 1,那么 x(i,j) 不应该等于 x(i,k)(这个约束意味着在任何没有 2 个元素的行(值不等于 1)可以相等

我还附上了满足这两个约束的示例 x 矩阵的屏幕截图。任何帮助表示赞赏。提前致谢。 在此处输入图像描述

标签: pythonoptimizationpulpmixed-integer-programming

解决方案


基于@Erwin Kalvelagen 的评论,如果选择决策变量作为二元变量:

y(i,j,k) == 1,当且仅当元素(i, j)具有值k

然后您的第二个约束非常简单(假设set_I并且已被声明为适当的列表):set_Jset_K

for i in set_I:
    for k in set_K:
        if k==1:
            continue
        model += lpSum([y[i, j, k] for j in set_J]) <= 1

换句话说,对于每一行i,所有可能的数字k(除了1)它们最多可以出现在每一行的一列中。

第一个约束更有趣一些,我相信它可以通过很多不同的方式来完成。这是一种方法——我们要禁止所有左边1至少有一个的数字(除了 ) 。1所以我们可以设置约束如下:

for i in set_I:
    for j in set_J:
        if j == 1:
            continue # no constraint for 1st column
        for k in set_K:
            if k==1:
                continue # no constraint on 1s
            prev_cols = [item for item in set_J if item < j]
            model += y[i, j, k] <= 1 - 0.25*lpSum([y[i, item, 1] for item in prev_cols])

您可能需要将一些1' 更改为0',具体取决于您设置索引/集的方式。要理解最后一个约束,请考虑两种情况:

i) 前面的列都没有1s。这种约束将使它们变得y[i,j,k] <= 1无效(y无论如何都是二进制变量)。

ii) 任何先前的列中都有1s - 约束将变为y[i,j,k] <= 0.75(或0.5, 0.25, 或者0如果有 2、3 或 4 个先前的)。与二进制变量一样,唯一可行的值y小于。因此,对于左侧有 a 的列,所有非值都将被禁止。1011


推荐阅读