从输出变量中提取数据

Extract data from an output variable

我正在尝试找出一个 post 处理代码来从 PYOMO 中的索引变量的输出中提取数据。变量的输出如下。

x : Size=24, Index=x_index
    Key                  : Lower : Value                  : Upper : Fixed : Stale : Domain
      ('alum', 'Face 1') :     0 :                    0.0 :     1 : False : False : Binary
      ('alum', 'Face 2') :     0 :                    0.0 :     1 : False : False : Binary
      ('alum', 'Face 3') :     0 :                    0.0 :     1 : False : False : Binary
      ('alum', 'Face 4') :     0 :                    0.0 :     1 : False : False : Binary
      ('alum', 'Face 5') :     0 :                    0.0 :     1 : False : False : Binary
      ('alum', 'Face 6') :     0 :                    0.0 :     1 : False : False : Binary
    ('copper', 'Face 1') :     0 :                    1.0 :     1 : False : False : Binary
    ('copper', 'Face 2') :     0 : 1.1025499604398013e-08 :     1 : False : False : Binary
    ('copper', 'Face 3') :     0 :     0.7535049595290465 :     1 : False : False : Binary
    ('copper', 'Face 4') :     0 : 1.0003766762453678e-08 :     1 : False : False : Binary
    ('copper', 'Face 5') :     0 : 1.0265826814190929e-08 :     1 : False : False : Binary
    ('copper', 'Face 6') :     0 :                    1.0 :     1 : False : False : Binary
     ('steel', 'Face 1') :     0 :                    0.0 :     1 : False : False : Binary
     ('steel', 'Face 2') :     0 :                    0.0 :     1 : False : False : Binary
     ('steel', 'Face 3') :     0 :                    0.0 :     1 : False : False : Binary
     ('steel', 'Face 4') :     0 :                    0.0 :     1 : False : False : Binary
     ('steel', 'Face 5') :     0 :                    0.0 :     1 : False : False : Binary
     ('steel', 'Face 6') :     0 :                    0.0 :     1 : False : False : Binary
      ('zinc', 'Face 1') :     0 : 1.0461836921235404e-08 :     1 : False : False : Binary
      ('zinc', 'Face 2') :     0 :                    1.0 :     1 : False : False : Binary
      ('zinc', 'Face 3') :     0 :    0.24649506011873923 :     1 : False : False : Binary
      ('zinc', 'Face 4') :     0 :                    1.0 :     1 : False : False : Binary
      ('zinc', 'Face 5') :     0 :                    1.0 :     1 : False : False : Binary
      ('zinc', 'Face 6') :     0 :  9.618909950291308e-09 :     1 : False : False : Binary

预期的输出是一个字典,如下所示

selected_materials = {'Face 1':'copper',
                      'Face 2':'zinc',
                      'Face 3':'copper',
                      'Face 4':'zinc',
                      'Face 5':'zinc',
                      'Face 6':'copper' }

想法是为每张脸选择一张material。选择标准是在输出变量 'x' 中为每个键(material、面的组合)获得的最大值。例如。对于 Face 1,在 4 materials 中比较该值,并选择具有最高值的值。

我的尝试:

我创建了一个代码来找到 material 中单个面孔的最高值,如下所示。

max([pyo.value(mdl.x[m, 'Face 1']) for m in materials])

其中 m 是如下所示的列表(在算法的初始步骤中定义)

materials = ['steel', 'alum', 'copper', 'zinc']

但是找到与最高值对应的 material 似乎具有挑战性。如果有人有想法,请帮助我。

如果你能给我一些更好的主意,我将不胜感激。

有几种方法可以做到这一点。我要做的第一件事是将变量中的值提取到一个普通的旧 python 数据结构中,这使得它更容易使用。您可能可以实施以下示例的几个变体,具体取决于您对理解的熟悉程度等。

import pyomo.environ as pyo
from collections import defaultdict
from operator import itemgetter

matls = ['steel', 'wood']

faces = ['Face 1', 'Face 2']

some_values = { ('steel', 'Face 1') : 1,
                ('wood', 'Face 1')  : 2.2,
                ('steel', 'Face 2') : 3.5,
                ('wood', 'Face 2')  : 1.1}

# PYOMO MODEL

m = pyo.ConcreteModel()

# Sets
m.M = pyo.Set(initialize=matls)
m.F = pyo.Set(initialize=faces)

# Variables

# Initializing just for the purposes of sorting later....normally NOT needed
m.X = pyo.Var(m.M, m.F, domain=pyo.NonNegativeReals, initialize=some_values)


m.pprint()

# let's pull the values out into a list of tuples.
# this isn't totally necessary, but it is pretty clear, and good staring place
res = [ (face, matl, m.X[matl, face].value) for face in m.F for matl in m.M]

for item in res:
    print(item)

# ok... let's gather the results by face and then get the max.  (you could also sort the results or whatever...

choices = defaultdict(list)
for face, matl, score in res:
    choices[face].append( (matl, score) )

# pick the max
for face in choices:
    matl, score = max(choices[face], key=itemgetter(1)) 
    print(f'for face {face} the best material is: {matl} with score {score:.2f}')

产量:

1 Var Declarations
    X : Size=4, Index=X_index
        Key                 : Lower : Value : Upper : Fixed : Stale : Domain
        ('steel', 'Face 1') :     0 :     1 :  None : False : False : NonNegativeReals
        ('steel', 'Face 2') :     0 :   3.5 :  None : False : False : NonNegativeReals
         ('wood', 'Face 1') :     0 :   2.2 :  None : False : False : NonNegativeReals
         ('wood', 'Face 2') :     0 :   1.1 :  None : False : False : NonNegativeReals

4 Declarations: M F X_index X
('Face 1', 'steel', 1)
('Face 1', 'wood', 2.2)
('Face 2', 'steel', 3.5)
('Face 2', 'wood', 1.1)
for face Face 1 the best material is: wood with score 2.20
for face Face 2 the best material is: steel with score 3.50