常见警告/错误

警告

W1001: 设置变量值不在域内

当设置Var值时(通过调用Var.set_value()或设置value属性),Pyomo将通过检查值是否在Var.domain中来验证传入的值。任何不在域中的值都会生成此警告:

>>> m = pyo.ConcreteModel()
>>> m.x = pyo.Var(domain=pyo.Integers)
>>> m.x = 0.5
WARNING (W1001): Setting Var 'x' to a value `0.5` (float) not in domain
     Integers.
     See also https://pyomo.readthedocs.io/en/stable/errors.html#w1001
>>> print(m.x.value)
0.5

用户可以通过使用以下设置值来绕过所有域验证:

>>> m.x.set_value(0.75, skip_validation=True)
>>> print(m.x.value)
0.75

W1002: 在范围外设置变量值

当设置Var值时(通过调用set_value()或设置value属性),Pyomo将通过检查该值是否在Var.bounds指定的范围内来验证传入的值。任何超出范围的值都会生成此警告:

>>> m = pyo.ConcreteModel()
>>> m.x = pyo.Var(domain=pyo.Integers, bounds=(1, 5))
>>> m.x = 0
WARNING (W1002): Setting Var 'x' to a numeric value `0` outside the bounds
    (1, 5).
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1002
>>> print(m.x.value)
0

用户可以通过使用以下设置值来绕过所有域验证:

>>> m.x.set_value(10, skip_validation=True)
>>> print(m.x.value)
10

W1003: 遍历表达式树时意外的递归错误

Pyomo 利用递归遍历器(StreamBasedExpressionVisitor)来遍历(walk)表达式树。对于大多数表达式,这个递归遍历器是最有效的。然而,Python 的递归深度限制相对较浅(通常为 1000 帧)。递归遍历器被设计为监控堆栈深度,并在达到堆栈限制之前干净地切换到非递归遍历器。然而,有两种(罕见的)情况,Python 堆栈限制仍然可能引发 RecursionError 异常:

  1. 启动walker时,可用的帧数少于pyomo.core.expr.visitor.RECURSION_LIMIT

  2. 需要超过2 * pyomo.core.expr.visitor.RECURSION_LIMIT 帧的回调。

(默认的)递归遍历器将捕获异常并以非递归模式从头开始重新启动遍历器,发出此警告。需要注意的是,遍历器在引发异常之前所做的任何部分工作都将丢失,可能会使遍历器处于不一致的状态。用户可以通过以下方式避免这种情况:

>>> import sys
>>> import pyomo.core.expr.visitor as visitor
>>> from pyomo.core.tests.unit.test_visitor import fill_stack
>>> expression_depth = visitor.StreamBasedExpressionVisitor(
...     exitNode=lambda node, data: max(data) + 1 if data else 1)
>>> m = pyo.ConcreteModel()
>>> m.x = pyo.Var()
>>> @m.Expression(range(35))
... def e(m, i):
...     return m.e[i-1] if i else m.x
>>> expression_depth.walk_expression(m.e[34])
36
>>> fill_stack(sys.getrecursionlimit() - visitor.get_stack_depth() - 30,
...            expression_depth.walk_expression,
...            m.e[34])
WARNING (W1003): Unexpected RecursionError walking an expression tree.
    See also https://pyomo.readthedocs.io/en/stable/errors.html#w1003
36
>>> fill_stack(sys.getrecursionlimit() - visitor.get_stack_depth() - 30,
...            expression_depth.walk_expression_nonrecursive,
...            m.e[34])
36

错误

E2001: 变量域必须是Pyomo集合的实例

变量域始终是Pyomo的SetRangeSet对象。这包括全局集合,如RealsIntegersBinaryNonNegativeReals等,以及特定于模型的Set实例。Var.domain设置器将尝试将分配的值转换为Pyomo的Set,任何失败都会导致此警告(以及转换器的异常):

>>> m = pyo.ConcreteModel()
>>> m.x = pyo.Var()
>>> m.x.domain = 5
Traceback (most recent call last):
   ...
TypeError: Cannot create a Set from data that does not support __contains__...
ERROR (E2001): 5 is not a valid domain. Variable domains must be an instance
    of a Pyomo Set or convertible to a Pyomo Set.
    See also https://pyomo.readthedocs.io/en/stable/errors.html#e2001