Source code for pyomo.contrib.preprocessing.plugins.deactivate_trivial_constraints

# -*- coding: utf-8 -*-

#  ___________________________________________________________________________
#  Pyomo: Python Optimization Modeling Objects
#  Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
#  Under the terms of Contract DE-NA0003525 with National Technology and 
#  Engineering Solutions of Sandia, LLC, the U.S. Government retains certain 
#  rights in this software.
#  This software is distributed under the 3-clause BSD License.
#  ___________________________________________________________________________

"""Transformation to deactivate trivial constraints."""
import logging

from pyomo.common.collections import ComponentSet
from pyomo.common.config import (ConfigBlock, ConfigValue, NonNegativeFloat,
from pyomo.core.base.constraint import Constraint
from pyomo.core.base.plugin import TransformationFactory
from pyomo.core.expr.numvalue import value
from pyomo.core.plugins.transform.hierarchy import IsomorphicTransformation

logger = logging.getLogger('pyomo.contrib.preprocessing')

[docs]@TransformationFactory.register( 'contrib.deactivate_trivial_constraints', doc="Deactivate trivial constraints.") class TrivialConstraintDeactivator(IsomorphicTransformation): """Deactivates trivial constraints. Trivial constraints take form :math:`k_1 = k_2` or :math:`k_1 \\leq k_2`, where :math:`k_1` and :math:`k_2` are constants. These constraints typically arise when variables are fixed. Keyword arguments below are specified for the ``apply_to`` and ``create_using`` functions. """ CONFIG = ConfigBlock("TrivialConstraintDeactivator") CONFIG.declare("tmp", ConfigValue( default=False, domain=bool, description="True to store a set of transformed constraints for future" " reversion of the transformation." )) CONFIG.declare("ignore_infeasible", ConfigValue( default=False, domain=bool, description="True to skip over trivial constraints that are " "infeasible instead of raising a ValueError." )) CONFIG.declare("return_trivial", ConfigValue( default=[], description="a list to which the deactivated trivial" "constraints are appended (side effect)" )) CONFIG.declare("tolerance", ConfigValue( default=1E-13, domain=NonNegativeFloat, description="tolerance on constraint violations" )) __doc__ = add_docstring_list(__doc__, CONFIG) def _apply_to(self, instance, **kwargs): config = self.CONFIG(kwargs) if config.tmp and not hasattr(instance, '_tmp_trivial_deactivated_constrs'): instance._tmp_trivial_deactivated_constrs = ComponentSet() elif config.tmp: logger.warning( 'Deactivating trivial constraints on the block {} for which ' 'trivial constraints were previously deactivated. ' 'Reversion will affect all deactivated constraints.'.format( # Trivial constraints are those that do not contain any variables, ie. # the polynomial degree is 0 trivial_constraints = ( constr for constr in instance.component_data_objects( ctype=Constraint, active=True, descend_into=True) if constr.body.polynomial_degree() == 0) for constr in trivial_constraints: # We need to check each constraint to sure that it is not violated. constr_lb = value( constr.lower) if constr.has_lb() else float('-inf') constr_ub = value( constr.upper) if constr.has_ub() else float('inf') constr_value = value(constr.body) # Check if the lower bound is violated outside a given tolerance if (constr_value + config.tolerance <= constr_lb): if config.ignore_infeasible: continue else: raise ValueError( 'Trivial constraint {} violates LB {} ≤ BODY {}.' .format(, constr_lb, constr_value)) # Check if the upper bound is violated outside a given tolerance if (constr_value >= constr_ub + config.tolerance): if config.ignore_infeasible: continue else: raise ValueError( 'Trivial constraint {} violates BODY {} ≤ UB {}.' .format(, constr_value, constr_ub)) # Constraint is not infeasible. Deactivate it. if config.tmp: instance._tmp_trivial_deactivated_constrs.add(constr) config.return_trivial.append(constr) constr.deactivate()
[docs] def revert(self, instance): """Revert constraints deactivated by the transformation. Args: instance: the model instance on which trivial constraints were earlier deactivated. """ for constr in instance._tmp_trivial_deactivated_constrs: constr.activate() del instance._tmp_trivial_deactivated_constrs