# -*- coding: UTF-8 -*-
##############################################################################
# Institute for the Design of Advanced Energy Systems Process Systems
# Engineering Framework (IDAES PSE Framework) Copyright (c) 2018, by the
# software owners: The Regents of the University of California, through
# Lawrence Berkeley National Laboratory, National Technology & Engineering
# Solutions of Sandia, LLC, Carnegie Mellon University, West Virginia
# University Research Corporation, et al. All rights reserved.
#
# Please see the files COPYRIGHT.txt and LICENSE.txt for full copyright and
# license information, respectively. Both files are also available online
# at the URL "https://github.com/IDAES/idaes".
##############################################################################
"""Debugging utility functions."""
from __future__ import division, print_function
import logging
from pyomo.environ import Block, Constraint, Var, value
from pyomo.gdp import Disjunct
logger = logging.getLogger('idaes.debug')
[docs]def display_infeasible_constraints(m, tol=1E-6):
"""Print the infeasible constraints in the model.
Uses the current model state. Prints to standard out.
Args:
m (Block): Pyomo block or model to check
tol (float): feasibility tolerance
"""
for constr in m.component_data_objects(
ctype=Constraint, active=True, descend_into=True):
# constraint is an equality
if constr.equality:
if abs(value(constr.lower) - value(constr.body)) >= tol:
print('{}: {} ≠ {}'.format(
constr.name, value(constr.body), value(constr.lower)))
continue
if constr.lower is not None:
if value(constr.lower) - value(constr.body) >= tol:
print('{}: {} < {}'.format(
constr.name, value(constr.body), value(constr.lower)))
continue
if constr.upper is not None:
if value(constr.body) - value(constr.upper) >= tol:
print('{}: {} > {}'.format(
constr.name, value(constr.body), value(constr.upper)))
continue
[docs]def display_infeasible_bounds(m, tol=1E-6):
"""Print the infeasible variable bounds in the model.
Args:
m (Block): Pyomo block or model to check
tol (float): feasibility tolerance
"""
for var in m.component_data_objects(
ctype=Var, descend_into=True):
if var.lb is not None:
if value(var.lb) - value(var) >= tol:
print('{}: {} < {}'.format(
var.name, value(var), value(var.lb)))
continue
if var.ub is not None:
if value(var) - value(var.ub) >= tol:
print('{}: {} > {}'.format(
var.name, value(var), value(var.ub)))
continue
[docs]def log_disjunct_values(m, integer_tolerance=1E-3, logger=logger,
selected_only=False):
"""Display logical value of model disjuncts.
Args:
integer_tolerance (float): tolerance on integrality test.
logger: logger to use for output. Otherwise, default debug module
logger is used.
selected_only: only log the selected disjuncts
"""
for disj in m.component_data_objects(
ctype=(Block, Disjunct),
descend_into=(Block, Disjunct)):
try:
if abs(value(disj.indicator_var) - 1) <= integer_tolerance:
logger.info("%s: True" % disj.name)
elif abs(value(disj.indicator_var)) <= integer_tolerance:
if not selected_only:
logger.info("%s: False" % disj.name)
else:
logger.warn("%s has non-integer indicator variable value: %s"
% (disj.name, value(disj.indicator_var)))
except AttributeError:
pass