找出Pyomo模型不可行的原因

问题描述 投票:0回答:3

我得到了一个包含大量变量和约束的 pyomo 具体模型。

不知何故,我的模型中的一个变量违反了一个约束,这使得我的模型不可行:

WARNING: Loading a SolverResults object with a warning status into model=xxxx;
    message from solver=Model was proven to be infeasible.

有没有办法询问求解者,不可行的原因?

例如,假设我有一个名为

x
的变量,如果我定义以下 2 个约束,模型将是 ofc。不可行的。

const1:
    x >= 10

const2:
    x <= 5

我想要实现的目标是指出导致这种不可行性的约束和变量,以便我可以修复它。否则,对于我的大模型来说,很难找出导致这种不可行性的原因。

IN: write_some_comment
OUT: variable "x" cannot fulfill "const1" and "const2" at the same time.
variables constraints pyomo feasibility
3个回答
9
投票

许多求解器(包括IPOPT)都会在求解器终止时将变量的值返还给您,即使问题被发现不可行。到那时,您确实有一些选择。

pyomo.util.infeasible
中有贡献的代码可能会对您有所帮助。 https://github.com/Pyomo/pyomo/blob/master/pyomo/util/infeasible.py

用途:

from pyomo.util.infeasible import log_infeasible_constraints
...
SolverFactory('your_solver').solve(model)
...
log_infeasible_constraints(model)

2
投票

我不会相信求解器在报告“不可行”后加载到模型中的任何数字。我认为没有任何求解器能够保证这些数字的有效性。此外,除非一个包可以推测建模者的意图,否则不清楚它将如何列出不可行的约束。考虑 2 个约束:

C1:  x <= 5
C2:  x >= 10

X ∈ Reals, or Integers, ...

哪个是无效约束?这得看情况!重点是,根据求解器尝试的值来解开谜团似乎是一项不可能的任务。

一种可能的替代策略:使用您认为有效的解决方案加载模型,并测试约束的松弛度。这个“加载的解决方案”甚至可能是一个空的情况,其中所有内容都被清零(如果这在模型的上下文中有意义)。它也可以是通过单元测试代码尝试的一组已知可行的解决方案。

如果您可以构建您认为有效的解决方案(忘记最佳解决方案,只需一些有效的解决方案),您可以(1)加载这些值,(2)迭代模型中的约束,(3)评估约束并寻找负松弛,并且 (4) 用值和表达式报告罪魁祸首

一个例子:

import pyomo.environ as pe

test_null_case = True

m = pe.ConcreteModel('sour constraints')

# SETS
m.T = pe.Set(initialize=['foo', 'bar'])

# VARS
m.X = pe.Var(m.T)
m.Y = pe.Var()

# OBJ
m.obj = pe.Objective(expr = sum(m.X[t] for t in m.T) + m.Y)

# Constraints
m.C1 = pe.Constraint(expr=sum(m.X[t] for t in m.T) <= 5)
m.C2 = pe.Constraint(expr=sum(m.X[t] for t in m.T) >= 10)
m.C3 = pe.Constraint(expr=m.Y >= 7)
m.C4 = pe.Constraint(expr=m.Y <= sum(m.X[t] for t in m.T))

if test_null_case:
    # set values of all variables to a "known good" solution...
    m.X.set_values({'foo':1, 'bar':3})  # index:value
    m.Y.set_value(2)  # scalar
    for c in m.component_objects(ctype=pe.Constraint):
        if c.slack() < 0:  # constraint is not met
            print(f'Constraint {c.name} is not satisfied')
            c.display()  # show the evaluation of c
            c.pprint()   # show the construction of c
            print()
else:
    pass
    # instantiate solver & solve, etc...

报告:

Constraint C2 is not satisfied
C2 : Size=1
    Key  : Lower : Body : Upper
    None :  10.0 :    4 :  None
C2 : Size=1, Index=None, Active=True
    Key  : Lower : Body            : Upper : Active
    None :  10.0 : X[foo] + X[bar] :  +Inf :   True

Constraint C3 is not satisfied
C3 : Size=1
    Key  : Lower : Body : Upper
    None :   7.0 :    2 :  None
C3 : Size=1, Index=None, Active=True
    Key  : Lower : Body : Upper : Active
    None :   7.0 :    Y :  +Inf :   True

0
投票

Qi Chen 的解决方案对我不起作用,它没有在我的屏幕上打印任何内容。我进行了调试,发现您还必须使用至少

INFO
级别的记录器。

import logging
from pyomo.util.infeasible import log_infeasible_constraints

def log_pyomo_infeasible_constraints(model_instance):          
    # Create a logger object with DEBUG level
    logging_logger = logging.getLogger()
    logging_logger.setLevel(logging.DEBUG)
    # Create a console handler
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    # add the handler to the logger
    logging_logger.addHandler(ch)
    # Log the infeasible constraints of pyomo object
    print("Displaying Infeasible Constraints")
    log_infeasible_constraints(model_instance, log_expression=True,
                         log_variables=True, logger=logging_logger)
© www.soinside.com 2019 - 2024. All rights reserved.