首页 > 解决方案 > 腌制 Pyomo 表达式时如何修复“递归错误”

问题描述

我以前没有遇到过酸洗 Pyomo 模型的问题,但现在尝试酸洗表达式时会引发递归错误。

有趣的是,可以通过以下几种方式避免以下示例中的错误:

...但我不知道为什么这些会修复错误,对于我试图腌制的实际优化模型,它们也不是可行的解决方案。

以下示例仅从单个表达式的酸洗中生成错误。(我正在使用 pyomo=5.6.2、cloudpickle=0.6.1 和 python=3.7.4)

import cloudpickle
import pyomo.environ as pyo

test_model = pyo.ConcreteModel()

# A set is added.
set_elements = list(range(0, 500))
test_model.my_set = pyo.Set(initialize=set_elements)

# A parameter is added.
param_values = dict()
for e in set_elements:
    param_values[e] = 1
test_model.my_param = pyo.Param(test_model.my_set, initialize=param_values, mutable=True)

# An expression is added.
def calculation_rule(mdl):
    return sum(mdl.my_param[e] for e in mdl.my_set)
test_model.calculation_expr = pyo.Expression(rule=calculation_rule)

# We attempt to pickle the expression.
pickle_str = cloudpickle.dumps(test_model.calculation_expr)

上述代码的最后一行引发了以下异常:

PicklingError: Could not pickle object as excessively deep recursion required.

问题:我是否需要修改表达式的编写方式才能腌制模型,还是应该使用 Cloudpickle 以外的其他方式保存模型?

提前感谢您的帮助!

标签: pythonpicklepyomo

解决方案


一种解决方法是使用 Pyomo 的quicksum而不是 Python 的sum. 它导致更紧凑的表达式树,并且似乎解决了您看到的递归问题:

# An expression is added.
def calculation_rule(mdl):
    return pyo.quicksum(mdl.my_param[e] for e in mdl.my_set)
test_model.calculation_expr = pyo.Expression(rule=calculation_rule)

文档在这里


推荐阅读