Source code for idaes.core.base.var_like_expression

#################################################################################
# The Institute for the Design of Advanced Energy Systems Integrated Platform
# Framework (IDAES IP) was produced under the DOE Institute for the
# Design of Advanced Energy Systems (IDAES), and is copyright (c) 2018-2021
# 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.md and LICENSE.md for full copyright and
# license information.
#################################################################################

"""
Creating a Component derived from Pyomo's Expression to use in cases
where an Expression could be mistaken for a Var.
"""

import pyomo.environ as pyo
from pyomo.core.base.expression import _GeneralExpressionData
from pyomo.core.base.component import ModelComponentFactory
from pyomo.core.base.indexed_component import (
    UnindexedComponent_set,
)
from pyomo.core.base.disable_methods import disable_methods


# Author: Andrew Lee
[docs]class _GeneralVarLikeExpressionData(_GeneralExpressionData): """ An object derived from _GeneralExpressionData which implements methods for common APIs on Vars. Constructor Arguments: expr: The Pyomo expression stored in this expression. component: The Expression object that owns this data. Public Class Attributes: expr: The expression owned by this data. Private class attributes: _component: The expression component. """ # Define methods for common APIs on Vars in case user mistakes # an Expression for a Var
[docs] def set_value(self, value, force=False): """ Overload set_value method to provide meaningful error if user attempts to set the value of the Expression. In order to support changing the expression (and setting it originally), if self._expr is None or force=True, the value of the expression will be updated, otherwise a TypeError will be raised. Args: value: value to set for _expr force: force updating of _expr if True (default = False) Returns: None Raises: TypeError if _expr is not None and force=False """ if self._expr is None or force: super().set_value(value) else: raise TypeError( f"{self.name} is an Expression and does not have a value " f"which can be set." )
@property def value(self): raise TypeError( f"{self.name} is an Expression and does not have a value " f"attribute. Use the 'value()' method instead." ) @value.setter def value(self, expr): raise TypeError( "%s is an Expression and does not have a value which can be set." % (self.name) ) def setlb(self, val=None): raise TypeError( "%s is an Expression and can not have bounds. " "Use an inequality Constraint instead." % (self.name) ) def setub(self, val=None): raise TypeError( "%s is an Expression and can not have bounds. " "Use an inequality Constraint instead." % (self.name) ) def fix(self, val=None): raise TypeError( "%s is an Expression and can not be fixed. " "Use an equality Constraint instead." % (self.name) ) def unfix(self): raise TypeError("%s is an Expression and can not be unfixed." % (self.name))
[docs]@ModelComponentFactory.register( "Named expressions that can be used in places of variables." ) class VarLikeExpression(pyo.Expression): """ A shared var-like expression container, which may be defined over a index. Constructor Arguments: initialize: A Pyomo expression or dictionary of expressions used to initialize this object. expr: A synonym for initialize. rule: A rule function used to initialize this object. """ _ComponentDataClass = _GeneralVarLikeExpressionData NoConstraint = (1000,) Skip = (1000,) def __new__(cls, *args, **kwds): if cls is not VarLikeExpression: return super(VarLikeExpression, cls).__new__(cls) if not args or (args[0] is UnindexedComponent_set and len(args) == 1): return super(VarLikeExpression, cls).__new__( AbstractSimpleVarLikeExpression ) else: return super(VarLikeExpression, cls).__new__(IndexedVarLikeExpression)
[docs]class SimpleVarLikeExpression(_GeneralVarLikeExpressionData, VarLikeExpression): def __init__(self, *args, **kwds): _GeneralVarLikeExpressionData.__init__(self, expr=None, component=self) VarLikeExpression.__init__(self, *args, **kwds) # # From Pyomo: Leaving this method for backward compatibility reasons. # (probably should be removed) # Note: Doesn't seem to work without it #
[docs] def add(self, index, expr): """Add an expression with a given index.""" if index is not None: raise KeyError( "SimpleExpression object '%s' does not accept " "index values other than None. Invalid value: %s" % (self.name, index) ) if (type(expr) is tuple) and (expr == pyo.Expression.Skip): raise ValueError( "Expression.Skip can not be assigned " "to an Expression that is not indexed: %s" % (self.name) ) self.set_value(expr) return self
@disable_methods({"set_value", "is_constant", "is_fixed", "expr"}) class AbstractSimpleVarLikeExpression(SimpleVarLikeExpression): pass
[docs]class IndexedVarLikeExpression(VarLikeExpression): # # From Pyomo: Leaving this method for backward compatibility reasons # Note: It allows adding members outside of self._index. # This has always been the case. Not sure there is # any reason to maintain a reference to a separate # index set if we allow this. #
[docs] def add(self, index, expr): """Add an expression with a given index.""" if (type(expr) is tuple) and (expr == pyo.Expression.Skip): return None cdata = _GeneralVarLikeExpressionData(expr, component=self) self._data[index] = cdata return cdata
# Define methods for common APIs on Vars in case user mistakes # an Expression for a Var def setlb(self, val=None): raise TypeError( "%s is an Expression and can not have bounds. " "Use inequality Constraints instead." % (self.name) ) def setub(self, val=None): raise TypeError( "%s is an Expression and can not have bounds. " "Use inequality Constraints instead." % (self.name) ) def fix(self, val=None): raise TypeError( "%s is an Expression and can not be fixed. " "Use equality Constraints instead." % (self.name) ) def unfix(self): raise TypeError("%s is an Expression and can not be unfixed." % (self.name))