def is_dcp(self, dpp: bool = False) -> bool: if dpp: with scopes.dpp_scope(): args_ok = all(arg.is_affine() for arg in self.args) exps_ok = not isinstance(self.alpha, cvxtypes.parameter()) return args_ok and exps_ok return all(arg.is_affine() for arg in self.args)
def is_dcp(self, dpp: bool = False) -> bool: """A power cone constraint is DCP if each argument is affine. """ if dpp: with scopes.dpp_scope(): args_ok = self.args[0].is_affine() and self.args[1].is_affine() exps_ok = not isinstance(self.alpha, cvxtypes.parameter()) return args_ok and exps_ok return True
def is_log_log_constant(self): """Is the expression log-log constant, ie, elementwise positive? """ if not self.is_constant(): return False if isinstance(self, (cvxtypes.constant(), cvxtypes.parameter())): return self.is_pos() else: return self.value is not None and np.all(self.value > 0)
def validate_arguments(self) -> None: """Raises an error if the arguments are invalid. """ super(gmatmul, self).validate_arguments() if not self.A.is_constant(): raise ValueError("gmatmul(A, X) requires that A be constant.") if self.A.parameters() and not isinstance(self.A, cvxtypes.parameter()): raise ValueError( "gmatmul(A, X) requires that A be a Constant or a Parameter.") if not self.args[0].is_pos(): raise ValueError("gmatmul(A, X) requires that X be positive.")
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)