Ejemplo n.º 1
0
class ISuffix(ComponentMap, ICategorizedObject):
    """The interface for suffixes."""
    __slots__ = ()

    #
    # Implementations can choose to define these
    # properties as using __slots__, __dict__, or
    # by overriding the @property method
    #

    direction = _abstract_readonly_property(doc="The suffix direction")
    datatype = _abstract_readonly_property(doc="The suffix datatype")

    #
    # Interface
    #

    def __str__(self):
        return ICategorizedObject.__str__(self)
Ejemplo n.º 2
0
class IConstraint(ICategorizedObject):
    """The interface for constraints"""
    __slots__ = ()

    #
    # Implementations can choose to define these
    # properties as using __slots__, __dict__, or
    # by overriding the @property method
    #

    body = _abstract_readonly_property(
        doc="The body of the constraint")
    lb = _abstract_readonly_property(
        doc="The lower bound of the constraint")
    ub = _abstract_readonly_property(
        doc="The upper bound of the constraint")
    rhs = _abstract_readonly_property(
        doc="The right-hand side of the constraint")
    equality = _abstract_readonly_property(
        doc=("A boolean indicating whether this "
             "is an equality constraint"))

    _linear_canonical_form = _abstract_readonly_property(
        doc=("Indicates whether or not the class or "
             "instance provides the properties that "
             "define the linear canonical form of a "
             "constraint"))

    # temporary (for backwards compatibility)
    @property
    def lower(self):
        return self.lb
    @property
    def upper(self):
        return self.ub

    #
    # Interface
    #

    def __call__(self, exception=True):
        """Compute the value of the body of this constraint."""
        if exception and (self.body is None):
            raise ValueError("constraint body is None")
        elif self.body is None:
            return None
        return self.body(exception=exception)

    @property
    def lslack(self):
        """Lower slack (body - lb). Returns :const:`None` if
        a value for the body can not be computed."""
        # this method is written so that constraint
        # types that build the body expression on the
        # fly do not have to here
        body = self(exception=False)
        if body is None:
            return None
        lb = self.lb
        if lb is None:
            lb = _neg_inf
        else:
            lb = value(lb)
        return body - lb

    @property
    def uslack(self):
        """Upper slack (ub - body). Returns :const:`None` if
        a value for the body can not be computed."""
        # this method is written so that constraint
        # types that build the body expression on the
        # fly do not have to here
        body = self(exception=False)
        if body is None:
            return None
        ub = self.ub
        if ub is None:
            ub = _pos_inf
        else:
            ub = value(ub)
        return ub - body

    @property
    def slack(self):
        """min(lslack, uslack). Returns :const:`None` if a
        value for the body can not be computed."""
        # this method is written so that constraint
        # types that build the body expression on the
        # fly do not have to here
        body = self(exception=False)
        if body is None:
            return None
        return min(self.lslack, self.uslack)

    @property
    def expr(self):
        """Get the expression on this constraint."""
        body_expr = self.body
        if body_expr is None:
            return None
        if self.equality:
            return body_expr == self.rhs
        else:
            if self.lb is None:
                return body_expr <= self.ub
            elif self.ub is None:
                return self.lb <= body_expr
            return logical_expr.RangedExpression((self.lb, body_expr, self.ub), (False, False))

    @property
    def bounds(self):
        """The bounds of the constraint as a tuple (lb, ub)"""
        return (self.lb, self.ub)

    def has_lb(self):
        """Returns :const:`False` when the lower bound is
        :const:`None` or negative infinity"""
        lb = self.lb
        return (lb is not None) and \
            (value(lb) != float('-inf'))

    def has_ub(self):
        """Returns :const:`False` when the upper bound is
        :const:`None` or positive infinity"""
        ub = self.ub
        return (ub is not None) and \
            (value(ub) != float('inf'))