def test_round_attr(self): """Test rounding for attributes. """ # Nonpos v = Variable(1, nonpos=True) self.assertAlmostEqual(v.project(1), 0) v = Variable(2, nonpos=True) self.assertItemsAlmostEqual(v.project(np.array([1, -1])), [0, -1]) # Nonneg v = Variable(1, nonneg=True) self.assertAlmostEqual(v.project(-1), 0) v = Variable(2, nonneg=True) self.assertItemsAlmostEqual(v.project(np.array([1, -1])), [1, 0]) # Boolean v = Variable((2, 2), boolean=True) self.assertItemsAlmostEqual(v.project(np.array([[1, -1], [1, 0]]).T), [1, 0, 1, 0]) # Integer v = Variable((2, 2), integer=True) self.assertItemsAlmostEqual(v.project(np.array([[1, -1.6], [1, 0]]).T), [1, -2, 1, 0]) # Symmetric v = Variable((2, 2), symmetric=True) self.assertItemsAlmostEqual(v.project(np.array([[1, -1], [1, 0]])), [1, 0, 0, 0]) # PSD v = Variable((2, 2), PSD=True) self.assertItemsAlmostEqual(v.project(np.array([[1, -1], [1, -1]])), [1, 0, 0, 0]) # NSD v = Variable((2, 2), NSD=True) self.assertItemsAlmostEqual(v.project(np.array([[1, -1], [1, -1]])), [0, 0, 0, -1]) # diag v = Variable((2, 2), diag=True) self.assertItemsAlmostEqual( v.project(np.array([[1, -1], [1, 0]])).todense(), [1, 0, 0, 0]) # Hermitian v = Variable((2, 2), hermitian=True) self.assertItemsAlmostEqual(v.project(np.array([[1, -1j], [1, 0]])), [1, 0.5 + 0.5j, 0.5 - 0.5j, 0]) A = Constant(np.array([[1.0]])) self.assertEqual(A.is_psd(), True) self.assertEqual(A.is_nsd(), False) A = Constant(np.array([[-1.0]])) self.assertEqual(A.is_psd(), False) self.assertEqual(A.is_nsd(), True) A = Constant(np.array([[0.0]])) self.assertEqual(A.is_psd(), True) self.assertEqual(A.is_nsd(), True)
def test_constant_psd_nsd(self): n = 5 np.random.randn(0) U = np.random.randn(n, n) U = U @ U.T (evals, U) = np.linalg.eigh(U) # U is now an orthogonal matrix # Try four indefinite matrices with different eigenvalue # spread around the origin. v1 = np.array([3, 2, 1, 1e-8, -1]) P = Constant(U @ np.diag(v1) @ U.T) self.assertFalse(P.is_psd()) self.assertFalse(P.is_nsd()) v2 = np.array([3, 2, 2, 1e-6, -1]) P = Constant(U @ np.diag(v2) @ U.T) self.assertFalse(P.is_psd()) self.assertFalse(P.is_nsd()) v3 = np.array([3, 2, 2, 1e-4, -1e-6]) P = Constant(U @ np.diag(v3) @ U.T) self.assertFalse(P.is_psd()) self.assertFalse(P.is_nsd()) v4 = np.array([-1, 3, 0, 0, 0]) P = Constant(U @ np.diag(v4) @ U.T) self.assertFalse(P.is_psd()) self.assertFalse(P.is_nsd()) # Try a test case given in GitHub issue 1451. # (Should be equivalent to v4 above). P = Constant(np.array([[1, 2], [2, 1]])) x = Variable(shape=(2, )) expr = cp.quad_form(x, P) self.assertFalse(expr.is_dcp()) self.assertFalse((-expr).is_dcp()) self.assertFalse(gershgorin_psd_check(P.value, tol=0.99)) # Useful Gershgorin disc check P = Constant(np.array([[2, 1], [1, 2]])) self.assertTrue(gershgorin_psd_check(P.value, tol=0.0)) # Verify good behavior for large eigenvalues P = Constant(np.diag(9 * [1e-4] + [-1e4])) self.assertFalse(P.is_psd()) self.assertFalse(P.is_nsd()) # Check a case when the matrix is in fact PSD. P = Constant(np.ones(shape=(5, 5))) self.assertTrue(P.is_psd()) self.assertFalse(P.is_nsd()) # Check with sparse inputs P = Constant(sp.eye(10)) self.assertTrue(gershgorin_psd_check(P.value, s.EIGVAL_TOL)) self.assertTrue(P.is_psd()) self.assertTrue((-P).is_nsd()) Q = -s.EIGVAL_TOL / 2 * P self.assertTrue(gershgorin_psd_check(Q.value, s.EIGVAL_TOL)) Q = -1.1 * s.EIGVAL_TOL * P self.assertFalse(gershgorin_psd_check(Q.value, s.EIGVAL_TOL)) self.assertFalse(Q.is_psd())