常见警告/错误
警告
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
异常:
启动walker时,可用的帧数少于
pyomo.core.expr.visitor.RECURSION_LIMIT
。需要超过2 *
pyomo.core.expr.visitor.RECURSION_LIMIT
帧的回调。
(默认的)递归遍历器将捕获异常并以非递归模式从头开始重新启动遍历器,发出此警告。需要注意的是,遍历器在引发异常之前所做的任何部分工作都将丢失,可能会使遍历器处于不一致的状态。用户可以通过以下方式避免这种情况:
避免递归回调
重新设计系统以避免在可用堆栈帧较少时触发walker
直接调用
walk_expression_nonrecursive()
遍历方法
>>> 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的Set
或RangeSet
对象。这包括全局集合,如Reals
、Integers
、Binary
、NonNegativeReals
等,以及特定于模型的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