Beispiel #1
0
 def __init__(self, x, y, z, constr_id=None):
     Expression = cvxtypes.expression()
     self.x = Expression.cast_to_const(x)
     self.y = Expression.cast_to_const(y)
     self.z = Expression.cast_to_const(z)
     super(ExpCone, self).__init__([self.x, self.y, self.z],
                                   constr_id)
Beispiel #2
0
 def __init__(self,
              x,
              axis: Optional[int] = None,
              keepdims: bool = False) -> None:
     if isinstance(axis, cvxtypes.expression()):
         raise ValueError(min.__EXPR_AXIS_ERROR__)
     super(min, self).__init__(x, axis=axis, keepdims=keepdims)
Beispiel #3
0
    def __init__(self, x, p, max_denom: int = 1024) -> None:
        self._p_orig = p
        # NB: It is important that the exponent is an attribute, not
        # an argument. This prevents parametrized exponents from being replaced
        # with their logs in Dgp2Dcp.
        self.p = cvxtypes.expression().cast_to_const(p)
        if not (isinstance(self.p, cvxtypes.constant())
                or isinstance(self.p, cvxtypes.parameter())):
            raise ValueError(
                "The exponent `p` must be either a Constant or "
                "a Parameter; received ", type(p))
        self.max_denom = max_denom

        self.p_rational = None
        if isinstance(self.p, cvxtypes.constant()):
            # Compute a rational approximation to p, for DCP (DGP doesn't need
            # an approximation).

            if not isinstance(self._p_orig, cvxtypes.expression()):
                # converting to a CVXPY Constant loses the dtype (eg, int),
                # so fetch the original exponent when possible
                p = self._p_orig
            else:
                p = self.p.value
            # how we convert p to a rational depends on the branch of the function
            if p > 1:
                p, w = pow_high(p, max_denom)
            elif 0 < p < 1:
                p, w = pow_mid(p, max_denom)
            elif p < 0:
                p, w = pow_neg(p, max_denom)

            # note: if, after making the rational approximation, p ends up
            # being 0 or 1, we default to using the 0 or 1 behavior of the
            # atom, which affects the curvature, domain, etc... maybe
            # unexpected behavior to the user if they put in 1.00001?
            if p == 1:
                # in case p is a fraction equivalent to 1
                p = 1
                w = None
            if p == 0:
                p = 0
                w = None

            self.p_rational, self.w = p, w
            self.approx_error = float(abs(self.p_rational - p))
        super(power, self).__init__(x)
Beispiel #4
0
 def __init__(self, x, y, z, constr_id=None) -> None:
     Expression = cvxtypes.expression()
     self.x = Expression.cast_to_const(x)
     self.y = Expression.cast_to_const(y)
     self.z = Expression.cast_to_const(z)
     xs, ys, zs = self.x.shape, self.y.shape, self.z.shape
     if xs != ys or xs != zs:
         msg = (
             "All arguments must have the same shapes. Provided arguments have"
             "shapes %s" % str((xs, ys, zs)))
         raise ValueError(msg)
     super(ExpCone, self).__init__([self.x, self.y, self.z], constr_id)
Beispiel #5
0
 def __init__(self, t, X, axis=0, constr_id=None):
     t = cvxtypes.expression().cast_to_const(t)
     if len(t.shape) >= 2 or not t.is_real():
         raise ValueError("Invalid first argument.")
     # Check t has one entry per cone.
     if (len(X.shape) <= 1 and t.size > 1) or \
        (len(X.shape) == 2 and t.size != X.shape[1-axis]) or \
        (len(X.shape) == 1 and axis == 1):
         raise ValueError(
             "Argument dimensions %s and %s, with axis=%i, are incompatible."
             % (t.shape, X.shape, axis))
     self.axis = axis
     if len(t.shape) == 0:
         t = t.flatten()
     super(SOC, self).__init__([t, X], constr_id)
Beispiel #6
0
    def _domain(self):
        """Returns constraints describing the domain of the node.
        """
        if not isinstance(self._p_orig, cvxtypes.expression()):
            p = self._p_orig
        else:
            p = self.p.value

        if p is None:
            raise ValueError("Cannot compute domain of parametrized power when "
                             "parameter value is unspecified.")
        elif (p < 1 and not p == 0) or (p > 1 and not is_power2(p)):
            return [self.args[0] >= 0]
        else:
            return []
Beispiel #7
0
 def __init__(self,
              expre,
              vec,
              ineq_form: bool = False,
              constr_id=None) -> None:
     Expression = cvxtypes.expression()
     if isinstance(vec, set):
         vec = list(vec)
     vec = Expression.cast_to_const(vec).flatten()
     if not expre.is_affine():
         msg = """
         Provided Expression must be affine, but had curvature %s.
         """ % expre.curvature
         raise ValueError(msg)
     # Note: we use the term "expre" rather than "expr" since
     # "expr" is already a property used by all Constraint classes.
     self.expre = expre
     self.vec = vec
     self._ineq_form = ineq_form
     super(FiniteSet, self).__init__([expre, vec], constr_id)
Beispiel #8
0
 def __init__(self, x, y, z, alpha, constr_id=None) -> None:
     Expression = cvxtypes.expression()
     self.x = Expression.cast_to_const(x)
     self.y = Expression.cast_to_const(y)
     self.z = Expression.cast_to_const(z)
     for val in [self.x, self.y, self.z]:
         if not (val.is_affine() and val.is_real()):
             raise ValueError('All arguments must be affine and real.')
     alpha = Expression.cast_to_const(alpha)
     if alpha.is_scalar():
         alpha = cvxtypes.promote()(alpha, self.x.shape)
     self.alpha = alpha
     if np.any(self.alpha.value <= 0) or np.any(self.alpha.value >= 1):
         msg = "Argument alpha must have entries in the open interval (0, 1)."
         raise ValueError(msg)
     arg_shapes = [self.x.shape, self.y.shape, self.z.shape, self.alpha.shape]
     if any(arg_shapes[0] != s for s in arg_shapes[1:]):
         msg = ("All arguments must have the same shapes. Provided arguments have"
                "shapes %s" % str(arg_shapes))
         raise ValueError(msg)
     super(PowCone3D, self).__init__([self.x, self.y, self.z],
                                     constr_id)
Beispiel #9
0
 def __init__(self, W, z, alpha, axis: int = 0, constr_id=None) -> None:
     Expression = cvxtypes.expression()
     W = Expression.cast_to_const(W)
     if not (W.is_real() and W.is_affine()):
         msg = "Invalid first argument; W must be affine and real."
         raise ValueError(msg)
     z = Expression.cast_to_const(z)
     if z.ndim > 1 or not (z.is_real() and z.is_affine()):
         msg = ("Invalid second argument. z must be affine, real, "
                "and have at most one z.ndim <= 1.")
         raise ValueError(msg)
     # Check z has one entry per cone.
     if (W.ndim <= 1 and z.size > 1) or \
        (W.ndim == 2 and z.size != W.shape[1-axis]) or \
        (W.ndim == 1 and axis == 1):
         raise ValueError(
             "Argument dimensions %s and %s, with axis=%i, are incompatible."
             % (W.shape, z.shape, axis))
     if W.ndim == 2 and W.shape[axis] <= 1:
         msg = "PowConeND requires left-hand-side to have at least two terms."
         raise ValueError(msg)
     alpha = Expression.cast_to_const(alpha)
     if alpha.shape != W.shape:
         raise ValueError("Argument dimensions %s and %s are not equal." %
                          (W.shape, alpha.shape))
     if np.any(alpha.value <= 0):
         raise ValueError("Argument alpha must be entry-wise positive.")
     if np.any(
             np.abs(1 - np.sum(alpha.value, axis=axis)) > PowConeND._TOL_):
         raise ValueError("Argument alpha must sum to 1 along axis %s." %
                          axis)
     self.W = W
     self.z = z
     self.alpha = alpha
     self.axis = axis
     if z.ndim == 0:
         z = z.flatten()
     super(PowConeND, self).__init__([W, z], constr_id)
Beispiel #10
0
    def __init__(self,
                 x,
                 p: Optional[List[int]] = None,
                 max_denom: int = 1024) -> None:
        """ Implementation details of geo_mean.

        Attributes
        ----------

        w_dyad : tuple of ``Fractions`` whose denominators are all a power of two
            The dyadic completion of ``w``, which is used internally to form the
            inequalities representing the geometric mean.

        tree : ``dict``
            keyed by dyadic tuples, whose values are Sequences of children.
            The children are also dyadic tuples.
            This represents the graph that needs to be formed to represent the
            weighted geometric mean.

        cone_lb : int
            A known lower bound (which is not always tight) on the number of cones
            needed to represent this geometric mean.

        cone_num_over : int
            The number of cones beyond the lower bound that this geometric mean used.
            If 0, we know that it used the minimum possible number of cones.
            Since cone_lb is not always tight, it may be using the minimum number of cones even if
            cone_num_over is not 0.

        cone_num : int
            The number of second order cones used to form this geometric mean

        """
        if p is not None and hasattr(p, '__getitem__'):
            p = np.array(p)
            idxs = p > 0
            Expression = cvxtypes.expression()
            x = Expression.cast_to_const(x)[idxs]
            p = p[idxs]
        super(geo_mean, self).__init__(x)

        x = self.args[0]
        if x.is_vector():
            n = 1 if x.ndim == 0 else max(x.shape)
        else:
            raise ValueError('x must be a row or column vector.')

        if p is None:
            p = [1] * n
        self.p = p

        if len(p) != n:
            raise ValueError('x and p must have the same number of elements.')

        if any(v < 0 for v in p) or sum(p) <= 0:
            raise ValueError('powers must be nonnegative and not all zero.')

        self.w, self.w_dyad = fracify(p, max_denom)
        self.approx_error = approx_error(p, self.w)

        self.tree = decompose(self.w_dyad)

        # known lower bound on number of cones needed to represent w_dyad
        self.cone_lb = lower_bound(self.w_dyad)

        # number of cones used past known lower bound
        self.cone_num_over = over_bound(self.w_dyad, self.tree)

        # number of cones used
        self.cone_num = self.cone_lb + self.cone_num_over