提问者:小点点

PYOMO:使用集合和参数定义数据集以解决优化问题


我试图将一些数据转化为最佳化问题的PYOMO模型。

materials = ['steel', 'alum', 'carbon', 'cheese']

每种材料都有两个特性-密度和导电性,其值定义如下。

density =   {   'steel' : 1.2,
            'alum'  : 0.8,
            'carbon': 1.8,
            'cheese': 0.7}

conductivity = {'steel' : 6.4,
               'alum'  : 3.1,
               'carbon': 4.4,
               'cheese': 0.3}

目标函数计算2块矩形板的重量,如下所示:

Objective function = Area_1 * thickness_1 * density_1 + Area_2 * thickness_2 * density_2

其中,面积_1、厚度_1和密度_1是板1的面积、厚度和密度。

每个板的面积和厚度是固定的。但是“密度”值取决于解算器为获得最佳结果而选择的材质。该模型还有一个定义如下的约束:

(conductivity_1/thickness_1) + (conductivity_2/thickness_2)  => 22

因此,当求解器为板选择密度值时,它还必须选择相同材料的导电率值。

如果有人能帮我解决这个问题,我将不胜感激。我也欢迎如果你有不同的想法来解决这个问题。谢谢你。


共1个答案

匿名用户

下面是一个我认为符合您所有问题的示例模型。

一旦你将第二个索引设置为3个板的板P={1,2,3},那么我们需要将我们的决策变量加倍索引,以表示材料m到板p.在这个例子中,4个材料,3个板。

这里还有许多其他的约束条件,但我添加的这些约束条件回答了您关于骨料导电性的问题。请注意,我还添加了一个约束,以确保为每个板指定1种且仅指定1种材质。根据模型中的其他约束条件,您可能需要/可能不需要此选项,但它可以很好地防止虚假答案。这也是使用pyomo中的function-rule组合的“for-every”约束样式的一个示例。

结果...一个铝和奶酪三明治...:)

# material selection model

import pyomo.environ as pyo

# data
materials = ['steel', 'alum', 'carbon', 'cheese']

density =   {   'steel' : 1.2,
                'alum'  : 0.8,
                'carbon': 1.8,
                'cheese': 0.7}

conductivity = {'steel' : 40.8,
                'alum'  : 30.1,
                'carbon': 42.4,
                'cheese': 15.3}

price =     {   'steel' : 2.3,
                'alum'  : 3.5,
                'carbon': 5.8,
                'cheese': 6.0}

                  # t     area
plate_dims = {  1: (10,   150), 
                2: (12.5, 200),
                3: (8,    125)}

mdl = pyo.ConcreteModel('material selector')

# SETS (used to index the decision variable and the parameters)
mdl.M = pyo.Set(initialize=materials)
mdl.P = pyo.Set(initialize=plate_dims.keys())

# VARIABLES
mdl.x = pyo.Var(mdl.M, mdl.P, domain=pyo.Binary)  # select material M for plate P

# PARAMETERS
mdl.density =       pyo.Param(mdl.M, initialize=density)
mdl.conductivity =  pyo.Param(mdl.M, initialize=conductivity)
mdl.price =         pyo.Param(mdl.M, initialize=price)
mdl.p_thickness =   pyo.Param(mdl.P, initialize= {k:v[0] for k,v in plate_dims.items()})
mdl.p_area =        pyo.Param(mdl.P, initialize= {k:v[1] for k,v in plate_dims.items()})

# OBJ (minimize total density)
mdl.obj = pyo.Objective(expr=sum(mdl.x[m, p] * mdl.p_thickness[p] 
                        * mdl.p_area[p] * mdl.density[m] 
                        for m in mdl.M for p in mdl.P))

# CONSTRAINTS
# minimum conductivity
mdl.c1 = pyo.Constraint(expr=sum(mdl.x[m, p] * mdl.conductivity[m]/mdl.p_thickness[p]
                        for m in mdl.M for p in mdl.P) >= 5.0)

# must populate all plates with 1 material
def c2(model, plate):
    return sum(mdl.x[m, plate] for m in mdl.M) == 1
mdl.c2 = pyo.Constraint(mdl.P, rule=c2)

# solve it
solver = pyo.SolverFactory('glpk')
result = solver.solve(mdl)
mdl.display()
Model material selector

  Variables:
    x : Size=12, Index=x_index
        Key           : Lower : Value : Upper : Fixed : Stale : Domain
          ('alum', 1) :     0 :   0.0 :     1 : False : False : Binary
          ('alum', 2) :     0 :   0.0 :     1 : False : False : Binary
          ('alum', 3) :     0 :   1.0 :     1 : False : False : Binary
        ('carbon', 1) :     0 :   0.0 :     1 : False : False : Binary
        ('carbon', 2) :     0 :   0.0 :     1 : False : False : Binary
        ('carbon', 3) :     0 :   0.0 :     1 : False : False : Binary
        ('cheese', 1) :     0 :   1.0 :     1 : False : False : Binary
        ('cheese', 2) :     0 :   1.0 :     1 : False : False : Binary
        ('cheese', 3) :     0 :   0.0 :     1 : False : False : Binary
         ('steel', 1) :     0 :   0.0 :     1 : False : False : Binary
         ('steel', 2) :     0 :   0.0 :     1 : False : False : Binary
         ('steel', 3) :     0 :   0.0 :     1 : False : False : Binary

  Objectives:
    obj : Size=1, Index=None, Active=True
        Key  : Active : Value
        None :   True : 3600.0

  Constraints:
    c1 : Size=1
        Key  : Lower : Body              : Upper
        None :   5.0 : 6.516500000000001 :  None
    c2 : Size=3
        Key : Lower : Body : Upper
          1 :   1.0 :  1.0 :   1.0
          2 :   1.0 :  1.0 :   1.0
          3 :   1.0 :  1.0 :   1.0