【问题标题】:how to add a set of SOS1 constraint in pyomo如何在 pyomo 中添加一组 SOS1 约束
【发布时间】:2021-01-13 23:19:22
【问题描述】:

我正在解决一个优化问题,我需要为每个产品分配一个纸箱类型,并确定应该使用多少个相应类型的纸箱。每个产品只能分配到一种纸箱类型。一个特定类型的纸箱可以容纳多少个特定产品是已知的。

我创建了如下决策变量:

import pyomo.environ as pyo
model = pyo.ConcreteModel(name="Pack_size_optim")
model.dv_prod_carton = pyo.Var(prod, cartons, within=pyo.NonNegativeIntegers)

prod, cartons 是具有独特产品和纸箱类型的列表

现在,对于我的问题,我想要的是决策变量:对于所有纸箱类型的每种产品都应该是一组 SOS 1,即对于每种产品,只有一种纸箱类型应该具有 > 0 的值。

我正在尝试类似下面的方法,但它不起作用:

for i in prod:    
    pyo.SOSConstraint(var = [model.dv_prod_carton[i, j] for j in cartons], sos = 1)

我认为上面 pyo.SOSConstraint 函数中的 var 参数应该是一个“IndexedVar”,但我有一个变量列表。

任何人都可以帮助我实现上述目标。谢谢。

【问题讨论】:

    标签: linear-programming pyomo mixed-integer-programming


    【解决方案1】:

    你在这里走错了路。您不需要(也不应该使用)此处的特殊有序集。

    公平披露:我从未使用过它们,也许其他人对它们为什么适合这里有意见。但是在您的情况下,您将有多个产品纸箱分配,所以我看不出您将如何适应它。

    你只需要做两件事...

    1. 声明一个二元决策变量,由 2 个集合索引:产品、容器,以表示将产品 p 放入容器 c 的决定。这将是您模型的基础
    2. 设置一个约束,对每个产品的所有容器求和,并将其设置为

    ...然后根据需要进行任何其他约束/obj

    【讨论】:

    • 按照我设置问题的方式,我正在确定每种产品的正确纸箱数量。假设我有 1 个产品 - P1 和 3 个纸箱类型 - C1、C2、C3,它们可以容纳 5、6、7 个单位的 P1。我设置问题的方法是确定正确的数量(以及相应的纸箱类型)纸箱 reqd。所以,例如输出可能看起来像 P1 -> C1 = 0,P1 -> C2 = 0,P1 -> C3 = 5。这样我可以识别纸箱类型 (C3) 和纸箱数量,我都了解您的解决方案,但是我会需要额外的决策变量来获得正确数量的纸箱,即 5 (C3)。
    • 是的。我完全同意,这是解决此类问题的标准方法。您需要一个二元决策变量来表示使用 C3 的决策,类似于 use[p, c] 和第二个整数变量来表示数量,索引类似,qty[p, c]
    • 明白。但是,prods 的数量很大,并且独特的纸箱类型的集合也很大。在您的方法中,我将通过 p、c 制作 2 个决策变量矩阵。如果我需要将这两个决策变量相乘,那么我需要对二进制整数变量的乘积进行线性化。这将需要引入更多的辅助变量。通过将相关的决策变量集声明为 SOS1 集,我们可以避免生成二进制变量,从而减少变量的数量。而且我也想学习如何在 pyomo 中声明 SOS1 :) 感谢您的投入
    • 一切正常。一些注意事项......上面制作的矩阵非常稀疏,这是一种非常标准的方法。不需要变量的乘法......它是线性的。祝你好运!
    【解决方案2】:

    (至少)有四种方法可以对此建模:

    我能够通过明确指定 .ref 和 .sosno 来使 SOS1 变量工作。我相信有更好的方法,但至少这似乎有效:

    # SOS1 test with concrete model
    
    import pyomo.environ as pyo
    
    model = pyo.ConcreteModel()
    
    model.x = pyo.Var([1,2], domain=pyo.PositiveReals, bounds=(0,1))
    
    model.OBJ = pyo.Objective(expr = model.x[1] + model.x[2],sense=pyo.maximize)
    
    # don't exactly know how to get these approaches to work
    #pyomo.core.kernel.sos.sos1([model.x[1],model.x[2]])
    #pyo.SOSConstraint(var = [model.x[1], model.x[2]], sos = 1)
    #model.sos_constraint = pyo.SOSConstraint(var = model.x, sos = 1)
    #Message: Solver does not support SOS level 1 constraints 
    
    model.sosno = pyo.Suffix(direction=pyo.Suffix.EXPORT)
    model.ref = pyo.Suffix(direction=pyo.Suffix.EXPORT)
    
    # Add entry for each index of model.x
    model.sosno.set_value(model.x, 1)
    model.ref[model.x[1]] = 1
    model.ref[model.x[2]] = 2
    
    # if SOS1 works correctly solution should have one of x[1],x[2] nonzero
    # indeed we see with Cplex:
    # 'Objective': {'OBJ': {'Value': 1.0}}, 'Variable': {'x[1]': {'Value': 1.0}}
    

    这有点像你在 AMPL 中所做的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-15
      • 1970-01-01
      • 2021-04-25
      • 2018-05-29
      • 2018-07-09
      • 1970-01-01
      相关资源
      最近更新 更多