Exemplo n.º 1
0
def test_constant_atoms(atom_info, objective_type) -> None:

    atom, size, args, obj_val = atom_info

    for indexer in get_indices(size):
        for solver in SOLVERS_TO_TRY:
            # Atoms with Constant arguments.
            prob_val = obj_val[indexer].value
            const_args = [Constant(arg) for arg in args]
            problem = Problem(objective_type(atom(*const_args)[indexer]))
            run_atom(atom, problem, prob_val, solver)

            # Atoms with Variable arguments.
            variables = []
            constraints = []
            for idx, expr in enumerate(args):
                variables.append(Variable(intf.shape(expr)))
                constraints.append(variables[-1] == expr)
            objective = objective_type(atom(*variables)[indexer])
            new_obj_val = prob_val
            if objective_type == cp.Maximize:
                objective = -objective
                new_obj_val = -new_obj_val
            problem = Problem(objective, constraints)
            run_atom(atom, problem, new_obj_val, solver)

            # Atoms with Parameter arguments.
            parameters = []
            for expr in args:
                parameters.append(Parameter(intf.shape(expr)))
                parameters[-1].value = intf.DEFAULT_INTF.const_to_matrix(expr)
            objective = objective_type(atom(*parameters)[indexer])
            run_atom(atom, Problem(objective), prob_val, solver)
Exemplo n.º 2
0
    def _validate_value(self, val):
        """Check that the value satisfies the leaf's symbolic attributes.

        Parameters
        ----------
        val : numeric type
            The value assigned.

        Returns
        -------
        numeric type
            The value converted to the proper matrix type.
        """
        if val is not None:
            # Convert val to ndarray or sparse matrix.
            val = intf.convert(val)
            if intf.shape(val) != self.shape:
                raise ValueError(
                    "Invalid dimensions %s for %s value." %
                    (intf.shape(val), self.__class__.__name__)
                )
            projection = self.project(val)
            # ^ might be a numpy array, or sparse scipy matrix.
            delta = np.abs(val - projection)
            # ^ might be a numpy array, scipy matrix, or sparse scipy matrix.
            if intf.is_sparse(delta):  # is a scipy sparse matrix
                is_close_enough = np.allclose(delta.data, 0)
                # ^ only check for near-equality on nonzero values.
            else:
                delta = np.array(delta)  # make sure we have a numpy array.
                is_close_enough = np.allclose(delta, 0, atol=1e-8)
            if not is_close_enough:
                if self.attributes['nonneg']:
                    attr_str = 'nonnegative'
                elif self.attributes['nonpos']:
                    attr_str = 'nonpositive'
                elif self.attributes['diag']:
                    attr_str = 'diagonal'
                elif self.attributes['PSD']:
                    attr_str = 'positive semidefinite'
                elif self.attributes['NSD']:
                    attr_str = 'negative semidefinite'
                elif self.attributes['imag']:
                    attr_str = 'imaginary'
                else:
                    attr_str = ([k for (k, v) in self.attributes.items() if v] + ['real'])[0]
                raise ValueError(
                    "%s value must be %s." % (self.__class__.__name__, attr_str)
                )
        return val
Exemplo n.º 3
0
    def test_numpy_scalars(self) -> None:
        n = 6
        eps = 1e-6
        np.random.seed(10)
        P0 = np.random.randn(n, n)
        eye = np.eye(n)
        P0 = P0.T.dot(P0) + eps * eye

        print(P0)

        P1 = np.random.randn(n, n)
        P1 = P1.T.dot(P1)
        P2 = np.random.randn(n, n)
        P2 = P2.T.dot(P2)
        P3 = np.random.randn(n, n)
        P3 = P3.T.dot(P3)

        q0 = np.random.randn(n, 1)
        q1 = np.random.randn(n, 1)
        q2 = np.random.randn(n, 1)
        q3 = np.random.randn(n, 1)

        r0 = np.random.randn(1, 1)
        r1 = np.random.randn(1, 1)
        r2 = np.random.randn(1, 1)
        r3 = np.random.randn(1, 1)

        slack = cvx.Variable()
        # Form the problem
        x = cvx.Variable(n)
        objective = cvx.Minimize(0.5 * cvx.quad_form(x, P0) + q0.T @ x + r0 +
                                 slack)
        constraints = [
            0.5 * cvx.quad_form(x, P1) + q1.T @ x + r1 <= slack,
            0.5 * cvx.quad_form(x, P2) + q2.T @ x + r2 <= slack,
            0.5 * cvx.quad_form(x, P3) + q3.T @ x + r3 <= slack,
        ]

        # We now find the primal result and compare it to the dual result
        # to check if strong duality holds i.e. the duality gap is effectively zero
        p = cvx.Problem(objective, constraints)
        p.solve(solver=cvx.SCS)

        # Note that since our data is random,
        # we may need to run this program multiple times to get a feasible primal
        # When feasible, we can print out the following values
        print(x.value)  # solution
        lam1 = constraints[0].dual_value
        lam2 = constraints[1].dual_value
        lam3 = constraints[2].dual_value
        print(type(lam1))

        P_lam = P0 + lam1 * P1 + lam2 * P2 + lam3 * P3
        q_lam = q0 + lam1 * q1 + lam2 * q2 + lam3 * q3
        r_lam = r0 + lam1 * r1 + lam2 * r2 + lam3 * r3
        dual_result = -0.5 * q_lam.T.dot(P_lam).dot(q_lam) + r_lam
        print(dual_result.shape)
        self.assertEqual(intf.shape(dual_result), (1, 1))
Exemplo n.º 4
0
 def __init__(self, value):
     # Keep sparse matrices sparse.
     if intf.is_sparse(value):
         self._value = intf.DEFAULT_SPARSE_INTF.const_to_matrix(
             value, convert_scalars=True)
         self._sparse = True
     else:
         self._value = intf.DEFAULT_INTF.const_to_matrix(value)
         self._sparse = False
     self._imag = None
     self._nonneg = self._nonpos = None
     self._symm = None
     self._herm = None
     self._eigvals = None
     super(Constant, self).__init__(intf.shape(self.value))
Exemplo n.º 5
0
 def __init__(self, value) -> None:
     # Keep sparse matrices sparse.
     if intf.is_sparse(value):
         self._value = intf.DEFAULT_SPARSE_INTF.const_to_matrix(
             value, convert_scalars=True)
         self._sparse = True
     else:
         self._value = intf.DEFAULT_INTF.const_to_matrix(value)
         self._sparse = False
     self._imag: Optional[bool] = None
     self._nonneg: Optional[bool] = None
     self._nonpos: Optional[bool] = None
     self._symm: Optional[bool] = None
     self._herm: Optional[bool] = None
     self._top_eig: Optional[float] = None
     self._bottom_eig: Optional[float] = None
     self._cached_is_pos = None
     super(Constant, self).__init__(intf.shape(self.value))
Exemplo n.º 6
0
    def _validate_value(self, val):
        """Check that the value satisfies the leaf's symbolic attributes.

        Parameters
        ----------
        val : numeric type
            The value assigned.

        Returns
        -------
        numeric type
            The value converted to the proper matrix type.
        """
        if val is not None:
            # Convert val to ndarray or sparse matrix.
            val = intf.convert(val)
            if intf.shape(val) != self.shape:
                raise ValueError("Invalid dimensions %s for %s value." %
                                 (intf.shape(val), self.__class__.__name__))
            projection = self.project(val)
            # ^ might be a numpy array, or sparse scipy matrix.
            delta = np.abs(val - projection)
            # ^ might be a numpy array, scipy matrix, or sparse scipy matrix.
            if intf.is_sparse(delta):
                # ^ based on current implementation of project(...),
                #   is is not possible for this Leaf to be PSD/NSD *and*
                #   a sparse matrix.
                close_enough = np.allclose(delta.data,
                                           0,
                                           atol=SPARSE_PROJECTION_TOL)
                # ^ only check for near-equality on nonzero values.
            else:
                # the data could be a scipy matrix, or a numpy array.
                # First we convert to a numpy array.
                delta = np.array(delta)
                # Now that we have the residual, we need to measure it
                # in some canonical way.
                if self.attributes['PSD'] or self.attributes['NSD']:
                    # For PSD/NSD Leafs, we use the largest-singular-value norm.
                    close_enough = LA.norm(delta,
                                           ord=2) <= PSD_NSD_PROJECTION_TOL
                else:
                    # For all other Leafs we use the infinity norm on
                    # the vectorized Leaf.
                    close_enough = np.allclose(delta,
                                               0,
                                               atol=GENERAL_PROJECTION_TOL)
            if not close_enough:
                if self.attributes['nonneg']:
                    attr_str = 'nonnegative'
                elif self.attributes['pos']:
                    attr_str = 'positive'
                elif self.attributes['nonpos']:
                    attr_str = 'nonpositive'
                elif self.attributes['neg']:
                    attr_str = 'negative'
                elif self.attributes['diag']:
                    attr_str = 'diagonal'
                elif self.attributes['PSD']:
                    attr_str = 'positive semidefinite'
                elif self.attributes['NSD']:
                    attr_str = 'negative semidefinite'
                elif self.attributes['imag']:
                    attr_str = 'imaginary'
                else:
                    attr_str = ([k
                                 for (k, v) in self.attributes.items() if v] +
                                ['real'])[0]
                raise ValueError("%s value must be %s." %
                                 (self.__class__.__name__, attr_str))
        return val
Exemplo n.º 7
0
 def validate_matrix(self, matrix):
     if self.size != intf.shape(matrix):
         raise Exception(("The argument's dimensions must match "
                          "the variable's dimensions."))