Example #1
0
    def _grad(self, values):
        """Gives the (sub/super)gradient of the atom w.r.t. each argument.

        Matrix expressions are vectorized, so the gradient is a matrix.

        Args:
            values: A list of numeric values for the arguments.

        Returns:
            A list of SciPy CSC sparse matrices or None.
        """
        rows = self.args[0].size[0]*self.args[0].size[1]
        cols = self.size[0]*self.size[1]
        if self.p == 0:
            # All zeros.
            return [sp.csc_matrix((rows, cols), dtype='float64')]
        # Outside domain or on boundary.
        if not is_power2(self.p) and np.min(values[0]) <= 0:
            if self.p < 1:
                # Non-differentiable.
                return [None]
            else:
                # Round up to zero.
                values[0] = np.maximum(values[0], 0)

        grad_vals = float(self.p)*np.power(values[0], float(self.p)-1)
        return [power.elemwise_grad_to_diag(grad_vals, rows, cols)]
Example #2
0
    def _grad(self, values):
        """Gives the (sub/super)gradient of the atom w.r.t. each argument.

        Matrix expressions are vectorized, so the gradient is a matrix.

        Args:
            values: A list of numeric values for the arguments.

        Returns:
            A list of SciPy CSC sparse matrices or None.
        """
        rows = self.args[0].size[0] * self.args[0].size[1]
        cols = self.size[0] * self.size[1]
        if self.p == 0:
            # All zeros.
            return [sp.csc_matrix((rows, cols), dtype='float64')]
        # Outside domain or on boundary.
        if not is_power2(self.p) and np.min(values[0]) <= 0:
            if self.p < 1:
                # Non-differentiable.
                return [None]
            else:
                # Round up to zero.
                values[0] = np.maximum(values[0], 0)

        grad_vals = float(self.p) * np.power(values[0], float(self.p) - 1)
        return [power.elemwise_grad_to_diag(grad_vals, rows, cols)]
Example #3
0
 def _domain(self):
     """Returns constraints describing the domain of the node.
     """
     if (self.p < 1 and not self.p == 0) or \
        (self.p > 1 and not is_power2(self.p)):
         return [self.args[0] >= 0]
     else:
         return []
Example #4
0
 def _domain(self):
     """Returns constraints describing the domain of the node.
     """
     if (self.p < 1 and not self.p == 0) or \
        (self.p > 1 and not is_power2(self.p)):
         return [self.args[0] >= 0]
     else:
         return []
Example #5
0
 def is_decr(self, idx):
     """Is the composition non-increasing in argument idx?
     """
     if self.p <= 0:
         return True
     elif self.p > 1:
         if is_power2(self.p):
             return self.args[idx].is_negative()
         else:
             return False
     else:
         return False
Example #6
0
 def is_decr(self, idx):
     """Is the composition non-increasing in argument idx?
     """
     if self.p <= 0:
         return True
     elif self.p > 1:
         if is_power2(self.p):
             return self.args[idx].is_negative()
         else:
             return False
     else:
         return False
Example #7
0
 def numeric(self, values):
     # Throw error if negative and power doesn't handle that.
     if self.p < 0 and values[0].min() <= 0:
         raise ValueError(
             "power(x, %.1f) cannot be applied to negative or zero values."
             % float(self.p))
     elif not is_power2(self.p) and self.p != 0 and values[0].min() < 0:
         raise ValueError(
             "power(x, %.1f) cannot be applied to negative values." %
             float(self.p))
     else:
         return np.power(values[0], float(self.p))
Example #8
0
 def is_incr(self, idx):
     """Is the composition non-decreasing in argument idx?
     """
     if 0 <= self.p <= 1:
         return True
     elif self.p > 1:
         if is_power2(self.p):
             return self.args[idx].is_nonneg()
         else:
             return True
     else:
         return False
Example #9
0
 def monotonicity(self):
     if self.p == 0:
         return [u.monotonicity.INCREASING]
     if self.p == 1:
         return [u.monotonicity.INCREASING]
     if self.p < 0:
         return [u.monotonicity.DECREASING]
     if 0 < self.p < 1:
         return [u.monotonicity.INCREASING]
     if self.p > 1:
         if is_power2(self.p):
             return [u.monotonicity.SIGNED]
         else:
             return [u.monotonicity.INCREASING]
Example #10
0
 def monotonicity(self):
     if self.p == 0:
         return [u.monotonicity.INCREASING]
     if self.p == 1:
         return [u.monotonicity.INCREASING]
     if self.p < 0:
         return [u.monotonicity.DECREASING]
     if 0 < self.p < 1:
         return [u.monotonicity.INCREASING]
     if self.p > 1:
         if is_power2(self.p):
             return [u.monotonicity.SIGNED]
         else:
             return [u.monotonicity.INCREASING]
Example #11
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 []
Example #12
0
    def is_decr(self, idx) -> bool:
        """Is the composition non-increasing in argument idx?
        """
        if not _is_const(self.p):
            return self.p.is_nonpos() and self.args[idx].is_nonneg()

        p = self.p_rational
        if p <= 0:
            return True
        elif p > 1:
            if is_power2(p):
                return self.args[idx].is_nonpos()
            else:
                return False
        else:
            return False
Example #13
0
    def _grad(self, values):
        """Gives the (sub/super)gradient of the atom w.r.t. each argument.

        Matrix expressions are vectorized, so the gradient is a matrix.

        Args:
            values: A list of numeric values for the arguments.

        Returns:
            A list of SciPy CSC sparse matrices or None.
        """
        rows = self.args[0].size
        cols = self.size

        if self.p_rational is not None:
            p = self.p_rational
        elif self.p.value is not None:
            p = self.p.value
        else:
            raise ValueError("Cannot compute grad of parametrized power when "
                             "parameter value is unspecified.")

        if p == 0:
            # All zeros.
            return [sp.csc_matrix((rows, cols), dtype='float64')]
        # Outside domain or on boundary.
        if not is_power2(p) and np.min(values[0]) <= 0:
            if p < 1:
                # Non-differentiable.
                return [None]
            else:
                # Round up to zero.
                values[0] = np.maximum(values[0], 0)

        grad_vals = float(p) * np.power(values[0], float(p) - 1)
        return [power.elemwise_grad_to_diag(grad_vals, rows, cols)]