腌制Pyomo表达式时如何解决“递归错误”

时间:2019-08-21 17:10:23

标签: python pickle pyomo

我以前对Pyomo模型进行酸洗没有遇到麻烦,但是现在在尝试对表达式进行酸洗时会出现递归错误。

有趣的是,在下面的示例中,可以通过两种方法避免该错误:

  • 通过从参数中删除“可变”标志
  • 通过将集合的大小减小到非常小的值,例如范围(0,10)

...但是我不知道为什么这些方法可以解决错误,对于我想腌制的实际优化模型,它们也不可行。

以下示例仅通过对单个表达式的酸洗产生错误。 (我正在使用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以外的其他方式保存模型?

在此先感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

一种解决方法是使用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)

文档here