Example #1
0
    def __init__(self, x, p, max_denom=1024):
        p_old = p

        # 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, self.w = p, w

        self.approx_error = float(abs(self.p - p_old))

        super(power, self).__init__(x)
Example #2
0
    def __init__(self, x, p, max_denom=1024):
        p_old = p

        # 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, self.w = p, w

        self.approx_error = float(abs(self.p - p_old))

        super(power, self).__init__(x)
Example #3
0
def transform_norm_p(expr):
    p = expr.p
    x = only_arg(expr)
    t = epi_var(expr, "norm_p", size=(1,1))

    if p == float("inf"):
        return t, [expression.leq_constraint(x, t),
                   expression.leq_constraint(expression.negate(x), t)]

    if p == 1:
        return transform_expr(expression.sum_entries(expression.abs_val(x)))

    if p == 2:
        return t, [expression.soc_constraint(t, x)]

    r = epi_var(expr, "norm_p_r", size=dims(x))
    t1 = expression.multiply(expression.ones(*dims(x)), t)

    if p < 0:
        p, _ = power_tools.pow_neg(p)
        p = Fraction(p)
        constrs = gm_constrs(t1, [x, r], (-p/(1-p), 1/(1-p)))
    elif 0 < p < 1:
        p, _ = power_tools.pow_mid(p)
        p = Fraction(p)
        constrs = gm_constrs(r, [x, t1], (p, 1-p))
    elif p > 1:
        abs_x, constrs = transform_expr(expression.abs_val(x))
        p, _ = power_tools.pow_high(p)
        p = Fraction(p)
        constrs += gm_constrs(abs_x, [r, t1], (1/p, 1-1/p))

    constrs.append(expression.eq_constraint(expression.sum_entries(r), t))
    return t, constrs
Example #4
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)
Example #5
0
 def __init__(self, x, p=2, axis=None, keepdims=False, max_denom=1024):
     if p < 0:
         # TODO(akshayka): Why do we accept p < 0?
         self.p, _ = pow_neg(p, max_denom)
     elif 0 < p < 1:
         self.p, _ = pow_mid(p, max_denom)
     elif p > 1:
         self.p, _ = pow_high(p, max_denom)
     elif p == 1:
         raise ValueError('Use the norm1 class to instantiate a one norm.')
     elif p == 'inf' or p == 'Inf' or p == np.inf:
         raise ValueError('Use the norm_inf class to instantiate an '
                          'infinity norm.')
     else:
         raise ValueError('Invalid p: {}'.format(p))
     self.approx_error = float(abs(self.p - p))
     super(Pnorm, self).__init__(x, axis=axis, keepdims=keepdims)
Example #6
0
def transform_norm_p(expr):
    p = expr.p
    x = only_arg(expr)
    t = epi_var(expr, "norm_p")

    if p == float("inf"):
        return t, [
            expression.leq_constraint(x, t),
            expression.leq_constraint(expression.negate(x), t)
        ]

    if p == 1:
        return transform_expr(expression.sum_entries(expression.abs_val(x)))

    if p == 2:
        if not expr.has_axis:
            return t, [
                expression.soc_constraint(t, expression.reshape(x, 1, dim(x)))
            ]
        if expr.axis == 0:
            return t, [
                expression.soc_constraint(expression.reshape(t, dim(x, 1), 1),
                                          expression.transpose(x))
            ]
        if expr.axis == 1:
            return t, [expression.soc_constraint(t, x)]

    r = epi_var(expr, "norm_p_r", size=dims(x))
    t1 = expression.multiply(expression.ones(*dims(x)), t)

    if p < 0:
        p, _ = power_tools.pow_neg(p)
        p = Fraction(p)
        constrs = gm_constrs(t1, [x, r], (-p / (1 - p), 1 / (1 - p)))
    elif 0 < p < 1:
        p, _ = power_tools.pow_mid(p)
        p = Fraction(p)
        constrs = gm_constrs(r, [x, t1], (p, 1 - p))
    elif p > 1:
        abs_x, constrs = transform_expr(expression.abs_val(x))
        p, _ = power_tools.pow_high(p)
        p = Fraction(p)
        constrs += gm_constrs(abs_x, [r, t1], (1 / p, 1 - 1 / p))

    constrs.append(expression.eq_constraint(expression.sum_entries(r), t))
    return t, constrs
Example #7
0
    def __init__(self, x, p=2, axis=None, max_denom=1024):
        p_old = p
        if p in ('inf', 'Inf', np.inf):
            self.p = np.inf
        elif p < 0:
            self.p, _ = pow_neg(p, max_denom)
        elif 0 < p < 1:
            self.p, _ = pow_mid(p, max_denom)
        elif p > 1:
            self.p, _ = pow_high(p, max_denom)
        elif p == 1:
            self.p = 1
        else:
            raise ValueError('Invalid p: {}'.format(p))

        super(pnorm, self).__init__(x, axis=axis)

        if self.p == np.inf:
            self.approx_error = 0
        else:
            self.approx_error = float(abs(self.p - p_old))
Example #8
0
    def __init__(self, x, p=2, axis=None, max_denom=1024):
        p_old = p
        if p in ('inf', 'Inf', np.inf):
            self.p = np.inf
        elif p < 0:
            self.p, _ = pow_neg(p, max_denom)
        elif 0 < p < 1:
            self.p, _ = pow_mid(p, max_denom)
        elif p > 1:
            self.p, _ = pow_high(p, max_denom)
        elif p == 1:
            self.p = 1
        else:
            raise ValueError('Invalid p: {}'.format(p))

        super(pnorm, self).__init__(x, axis=axis)

        if self.p == np.inf:
            self.approx_error = 0
        else:
            self.approx_error = float(abs(self.p - p_old))
Example #9
0
def transform_power(expr):
    p = expr.p

    if p == 1:
        return only_arg(expr)

    one = expression.scalar_constant(1, size=dims(expr))
    if p == 0:
        return one, []

    t = epi_var(expr, "power")
    x = only_arg(expr)

    if p < 0:
        p, w = power_tools.pow_neg(p)
        constrs = gm_constrs(one, [x, t], w)
    if 0 < p < 1:
        p, w = power_tools.pow_mid(p)
        constrs = gm_constrs(t, [x, one], w)
    if p > 1:
        p, w = power_tools.pow_high(p)
        constrs = gm_constrs(x, [t, one], w)

    return t, constrs
Example #10
0
def transform_power(expr):
    p = expr.p

    if p == 1:
        return only_arg(expr)

    one = expression.scalar_constant(1, size=dims(expr))
    if p == 0:
        return one, []

    t = epi_var(expr, "power")
    x = only_arg(expr)

    if p < 0:
        p, w = power_tools.pow_neg(p)
        constrs = gm_constrs(one, [x, t], w)
    if 0 < p < 1:
        p, w = power_tools.pow_mid(p)
        constrs = gm_constrs(t, [x, one], w)
    if p > 1:
        p, w = power_tools.pow_high(p)
        constrs = gm_constrs(x, [t, one], w)

    return t, constrs