在 Pyomo 中复制模型克隆之间的后缀信息的有效方法

Effective way to copy Suffix information between model clones in Pyomo

假设我有一个使用 m2 = m.clone() 构建的 ConcreteModel m2。如果 m2 上有 Suffix 信息,例如 m2.ipopt_zL_out,我想将其复制回 m,最有效的方法是什么?

我可以做类似 m.ipopt_zL_out[m.var] = m2.ipopt_zL_out[ComponentUID(m.var).find_component_on(m2)] 的事情,但有人告诉我 ComponentUID 可能很昂贵。这是推荐的方法,还是有更好的方法?

我通常做的是在每个模型上创建从 ComponentUID 字符串到模型组件的前向和后向映射。为 Pyomo 对象创建映射是棘手的,通常不能使用标准 dict 来完成,因为像 Var 这样的东西是不可哈希的。有一个名为 ComponentMap 的 class,您可以使用它代替字典。还有一个名为 generate_cuid_names 的辅助函数,它可以高效地为模型批量生成所有 CUID 字符串,并且 returns 和 ComponentMap.

下面是一些示例代码:

# m1 and m2 are ConcreteModels

from pyomo.core.base.block import generate_cuid_names

# generate forward and reverse mappings for model 1
m1.obj_to_cuid = generate_cuid_names(m1)
m1.cuid_to_obj = dict((cuid, obj) for obj, cuid in m1.obj_to_cuid.items())

# generate forward and reverse mappings for model 2
m2.obj_to_cuid = generate_cuid_names(m2)
m2.cuid_to_obj = dict((cuid, obj) for obj, cuid in m2.obj_to_cuid.items())

# load model 2 suffix solution into model 1
m1.s.update((m1.cuid_to_obj[m2.obj_to_cuid[obj]], val)
            for obj, val in m2.s.items())

除了在这里和那里进行额外的字典查找(在 Python 中相对较快)之外,唯一慢的部分应该是 ComponentUID 字符串的初始生成,但这只是前期成本。

我还使用这种方法长期存储其他解决方案信息,或者通过网络将解决方案信息传输到相关模型。

请记住,generate_cuid_names 函数默认在块本地上下文中生成 CUID 字符串。这意味着如果您在模型的子块上调用它,父块标识符将不会出现在字符串中。这在某些情况下可能很有用,但该函数还有一个关键字,可让您更新现有的 ComponentMap(假设包含父块标识符)。在这种情况下,将生成完全限定的 CUID 字符串。有关详细信息,请参阅 pyomo/core/base/block.py 中的文档字符串。