def test_linear_equality_1(self): n, m = 3, 2 np.random.seed(0) x0 = np.random.randn(n, ).round(decimals=5) A = np.random.randn(m, n).round(decimals=5) b0 = A @ x0 x = Variable(shape=(n, ), name='x') constraint = A @ x == b0 # Test basic constraint attributes assert constraint.epigraph_checked # equality constraints are automatically checked. my_vars = constraint.variables() assert len(my_vars) == 1 and my_vars[0].name == x.name # Test ability to correctly compute violations x.value = x0 viol = constraint.violation() assert viol < 1e-15 viol = constraint.violation(norm_ord=1) assert viol < 1e-15 x.value = np.zeros(n, ) viol = constraint.violation() assert abs(viol - np.linalg.norm(b0, ord=2)) < 1e-15 viol = constraint.violation(norm_ord=np.inf) assert abs(viol - np.linalg.norm(b0, ord=np.inf)) < 1e-15
def test_block(self): A = np.eye(2) * 2 A_cl = Variable(shape=A.shape) A_cl.value = A B = np.eye(3) * 3 expected = np.block([[A, np.zeros((2, 3))], [np.ones((3, 2)), B]]) actual = aff.block([[A_cl, np.zeros((2, 3))], [np.ones((3, 2)), B]]) assert np.allclose(expected, actual.value) A_cl.value = 1 + A # or 2*A, or really anything different from A itself. assert not np.allclose(expected, actual.value)
def test_array_split(self): x = np.arange(8.0) x_cl = Variable(shape=x.shape) x_cl.value = x expected = np.array_split(x, 3) actual = aff.array_split(x_cl, 3) assert np.all( [np.allclose(expected[i], actual[i].value) for i in range(3)]) x_cl.value = 1 + x assert not np.all( [np.allclose(expected[i], actual[i].value) for i in range(3)])
def test_dsplit(self): x = np.arange(16.0).reshape(2, 2, 4) x_cl = Variable(shape=x.shape) x_cl.value = x expected = np.dsplit(x, 2) actual = aff.dsplit(x_cl, 2) assert np.all( [np.allclose(expected[i], actual[i].value) for i in range(2)]) x_cl.value = 1 + x assert not np.all( [np.allclose(expected[i], actual[i].value) for i in range(2)])
def test_column_stack(self): a = np.array((1, 2, 3)) b = np.array((2, 3, 4)) a_cl = Variable(shape=a.shape) a_cl.value = a b_cl = Variable(shape=b.shape) b_cl.value = b expected = np.column_stack((a, b)) actual = aff.column_stack((a_cl, b_cl)) assert np.allclose(expected, actual.value) a_cl.value = 1 + a assert not np.allclose(expected, actual.value)
def test_diagflat(self): x = np.array([[1, 2], [3, 4]]) x_cl = Variable(shape=x.shape) x_cl.value = x expected = np.diagflat(x) actual = aff.diagflat(x_cl) assert np.allclose(expected, actual.value)
def test_pos_1(self): x = Variable(shape=(3, ), name='x') con = [cl_pos(affine.sum(x) - 7) <= 5] A_expect = np.array([[0, 0, 0, -1], [0, 0, 0, 1], [-1, -1, -1, 1]]) A, b, K, _1, _2, _3 = compile_constrained_system(con) A = np.round(A.toarray(), decimals=1) assert np.all(A == A_expect) assert np.all(b == np.array([5, 0, 7])) assert K == [Cone('+', 1), Cone('+', 2)] # value propagation x.value = np.array([4, 4, 4]) viol = con[0].violation() assert viol == 0 x.value = np.array([4.2, 3.9, 4.0]) viol = con[0].violation() assert abs(viol - 0.1) < 1e-7
def test_concatenate(self): a = np.array([[1, 2], [3, 4]]) a_cl = Variable(shape=a.shape) a_cl.value = a b = np.array([[5, 6]]) b_cl = Variable(shape=b.shape) b_cl.value = b expected = np.concatenate((a, b)) actual = aff.concatenate((a_cl, b_cl)) assert np.allclose(expected, actual.value) expected1 = np.concatenate((b, a)) actual1 = aff.concatenate((b_cl, a_cl)) assert np.allclose(expected1, actual1.value) a_cl.value = 1 + a assert not np.allclose(expected, actual.value) assert not np.allclose(expected1, actual1.value)
def test_triu(self): A = np.random.randn(5, 5).round(decimals=3) A_cl = Variable(shape=A.shape) A_cl.value = A temp = aff.triu(A) expr0 = aff.sum(temp) expr1 = aff.sum(np.triu(A_cl)) assert Expression.are_equivalent(expr0, expr1.value)
def test_tile(self): x = np.array([0, 1, 2]) x_cl = Variable(shape=x.shape) x_cl.value = x A = aff.tile(x_cl, 2) assert np.allclose(np.tile(x, 2), A.value) expr0 = aff.sum(A) expr1 = aff.sum(x) * 2 assert Expression.are_equivalent(expr0.value, expr1)
def test_abs_1(self): x = Variable(shape=(2, ), name='x') one_norm = affine.sum(cl_abs(x)) con = [one_norm <= 5] A_expect = np.array([[0, 0, -1, -1], [1, 0, 1, 0], [-1, 0, 1, 0], [0, 1, 0, 1], [0, -1, 0, 1]]) A, b, K, _1, _2, _3 = compile_constrained_system(con) A = np.round(A.toarray(), decimals=1) assert np.all(A == A_expect) assert np.all(b == np.array([5, 0, 0, 0, 0])) assert K == [Cone('+', 1), Cone('+', 2), Cone('+', 2)] # value propagation x.value = np.array([1, -2]) viol = con[0].violation() assert viol == 0 x.value = np.array([-3, 3]) viol = con[0].violation() assert viol == 1
def test_kron(self): I = np.eye(2) X = Variable(shape=(2, 2)) expr0 = aff.kron(I, X) expr1 = aff.kron(X, I) X0 = np.random.randn(2, 2).round(decimals=3) X.value = X0 assert np.allclose(expr0.value, np.kron(I, X0)) assert np.allclose(expr1.value, np.kron(X0, I))
def test_stack(self): array = np.random.randn(3, 4) arrays = [array for _ in range(10)] a_cl = Variable(shape=array.shape) a_cl.value = array arrays_cl = [a_cl for _ in range(10)] expected = np.stack(arrays, axis=0) actual = aff.stack(arrays_cl, axis=0) assert np.allclose(expected, actual.value) assert Expression.are_equivalent(expected.shape, actual.shape) expected1 = np.stack(arrays, axis=1) actual1 = aff.stack(arrays_cl, axis=1) assert np.allclose(expected1, actual1.value) assert Expression.are_equivalent(expected.shape, actual.shape) a_cl.value = 1 + array assert not np.allclose(expected, actual.value) assert not np.allclose(expected1, actual1.value)
def test_ordinary_sage_primal_1(self): n, m = 2, 5 np.random.seed(0) alpha = np.random.randn(m, n) c = Variable(shape=(m, ), name='test_c') constraint = sage_cones.PrimalSageCone(c, alpha, X=None, name='test') c0 = np.ones(shape=(m, )) c.value = c0 viol_default = constraint.violation() assert viol_default == 0
def test_power_cone(self): n = 4 rng = np.random.default_rng(12345) # Create w and z in one array, where the last one will be z wz = Variable(shape=(n + 1, ), name='wz') # Make the last element negative to indicate that that element is z in the wz variable lamb = rng.random((n, )) # Check if wrong sizes that error is raised self.assertRaises(ValueError, PowCone, wz, lamb) # Check if no negative number lamb, error is raised lamb = rng.random((n + 1, )) self.assertRaises(ValueError, PowCone, wz, lamb) # Check if not sum to 0, error is raised lamb[-1] = -5 * np.sum(lamb[:-1]) self.assertRaises(ValueError, PowCone, wz, lamb) # Check if violation is correct for a point exactly on the power cone defined lamb = np.ones((n + 1, )) lamb[-1] = -1 * np.sum(lamb[:-1]) wz.value = np.array([1, 1, 1, 1, 1]) pow_cone_constraint = PowCone(wz, lamb) v1 = pow_cone_constraint.violation(rough=True) assert v1 < 1e-15 # Check if violation is correct for point inside of power cone wz.value = np.array([2, 1, 1, 1, 1]) pow_cone_constraint = PowCone(wz, lamb) v1 = pow_cone_constraint.violation(rough=True) assert np.allclose(v1, 0) # Check if violation is correct for point inside of power cone wz.value = np.array([1, 1, 1, 1, 2]) pow_cone_constraint = PowCone(wz, lamb) v1 = pow_cone_constraint.violation(rough=True) assert np.allclose(v1, 1)
def test_repeat(self): x = np.array([3]) x_cl = Variable(shape=x.shape) x_cl.value = x A = aff.repeat(x_cl, 4) assert np.allclose(np.repeat(x, 4), A.value) expr0 = aff.sum(A.value) expr1 = aff.sum(x_cl) * 4 assert Expression.are_equivalent(expr0, expr1.value) # x_cl.value = x + 1 # assert not np.allclose(np.repeat(x, 4), A) x1 = np.array([[1, 2], [3, 4]]) x1_cl = Variable(shape=x1.shape) x1_cl.value = x1 A1 = aff.repeat(x1_cl, 2) assert np.allclose(np.repeat(x1, 2), A1.value) expr2 = aff.sum(A1.value) expr3 = aff.sum(x1_cl) * 2 assert Expression.are_equivalent(expr2, expr3.value)
def test_relent_1(self): # compilation and evaluation x = Variable(shape=(2, ), name='x') y = Variable(shape=(2, ), name='y') re = relent(2 * x, np.exp(1) * y) con = [re <= 10, 3 <= x, x <= 5] # compilation A, b, K, _, _, _ = compile_constrained_system(con) A_expect = np.array([ [0., 0., 0., 0., -1., -1.], # linear inequality on epigraph for relent constr [1., 0., 0., 0., 0., 0.], # bound constraints on x [0., 1., 0., 0., 0., 0.], # [-1., 0., 0., 0., 0., 0.], # more bound constraints on x [0., -1., 0., 0., 0., 0.], # [0., 0., 0., 0., -1., 0.], # first exponential cone [0., 0., 2.72, 0., 0., 0.], # [2., 0., 0., 0., 0., 0.], # [0., 0., 0., 0., 0., -1.], # second exponential cone [0., 0., 0., 2.72, 0., 0.], # [0., 2., 0., 0., 0., 0.] ]) # A = np.round(A.toarray(), decimals=2) assert np.all(A == A_expect) assert np.all( b == np.array([10., -3., -3., 5., 5., 0., 0., 0., 0., 0., 0.])) assert K == [ Cone('+', 1), Cone('+', 2), Cone('+', 2), Cone('e', 3), Cone('e', 3) ] # value propagation x0 = np.array([1, 2]) x.value = x0 y0 = np.array([3, 4]) y.value = y0 actual = re.value expect = np.sum(rel_entr(2 * x0, np.exp(1) * y0)) assert abs(actual - expect) < 1e-7
def test_dot(self): x = Variable(shape=(4, )) a = np.array([1, 2, 3, 4]) expr0 = aff.dot(x, a) expr1 = aff.dot(a, x) x0 = np.random.rand(4).round(decimals=4) expect = np.dot(a, x0) x.value = x0 actual0 = expr0.value actual1 = expr1.value assert actual0 == expect assert actual1 == expect assert Expression.are_equivalent(expr0, expr1)
def test_outer(self): x = Variable(shape=(3, )) x0 = np.random.randn(3).round(decimals=3) x.value = x0 a = np.array([1, 2, 3, 4]) expr0 = aff.outer(a, x) assert np.allclose(expr0.value, np.outer(a, x0)) expr1 = aff.outer(x, a) assert np.allclose(expr1.value, np.outer(x0, a)) b = np.array([9, 8]) expr2 = aff.outer(b, x) assert np.allclose(expr2.value, np.outer(b, x0)) expr3 = aff.outer(x, b) assert np.allclose(expr3.value, np.outer(x0, b))
def test_linear_inequality_1(self): n, m = 2, 4 A = np.ones(shape=(m, n)) x = Variable(shape=(n, ), name='x') constraint = A @ x >= 0 # Test basic constraint attributes assert not constraint.epigraph_checked my_vars = constraint.variables() assert len(my_vars) == 1 and my_vars[0].name == x.name # Test ability to correctly compute violations x0 = np.ones(shape=(n, )) x.value = x0 viol = constraint.violation() assert viol == 0 x0 = np.zeros(shape=(n, )) x0[0] = -1 x.value = x0 viol_one_norm = constraint.violation(norm_ord=1) assert abs(viol_one_norm - 4) < 1e-15 viol_inf_norm = constraint.violation(norm_ord=np.inf) assert abs(viol_inf_norm - 1) < 1e-15
def test_inner(self): # test with scalar inputs x = Variable() a = 2.0 expr0 = aff.inner(a, x) expr1 = aff.inner(x, a) assert Expression.are_equivalent(expr0, expr1) # test with multidimensional arrays a = np.arange(24).reshape((2, 3, 4)) x = Variable(shape=(4, )) x.value = np.arange(4) expr = aff.inner(a, x) expect = np.inner(a, np.arange(4)) actual = expr.value assert np.allclose(expect, actual)
def test_multi_dot(self): A = np.random.rand(5, 3).round(decimals=3) X = Variable(shape=(3, 3), var_properties=['symmetric']) X0 = np.random.rand(3, 3).round(decimals=3) X0 += X0.T X.value = X0 B = np.random.rand(3, 3).round(decimals=3) C = np.random.rand(3, 7).round(decimals=3) chain1 = [A, X, B, C] expr1 = aff.multi_dot(chain1) expect1 = np.linalg.multi_dot([A, X0, B, C]) actual1 = expr1.value assert np.allclose(expect1, actual1) chain2 = [A, B, X, C] expr2 = aff.multi_dot(chain2) expect2 = np.linalg.multi_dot([A, B, X0, C]) actual2 = expr2.value assert np.allclose(expect2, actual2)
def test_vector2norm_1(self): x = Variable(shape=(3, ), name='x') nrm = vector2norm(x) con = [nrm <= 1] A_expect = np.array([ [0, 0, 0, -1], # linear inequality constraint in terms of epigraph variable [0, 0, 0, 1], # epigraph component in second order cone constraint [1, 0, 0, 0], # start of main block in second order cone constraint [0, 1, 0, 0], [0, 0, 1, 0] ]) # end of main block in second order cone constraint A, b, K, _1, _2, _3 = compile_constrained_system(con) A = np.round(A.toarray(), decimals=1) assert np.all(A == A_expect) assert np.all(b == np.array([1, 0, 0, 0, 0])) assert K == [Cone('+', 1), Cone('S', 4)] # value propagation x.value = np.zeros(3) viol = con[0].violation() assert viol == 0
def test_dstack(self): a = np.array((1, 2, 3)) b = np.array((2, 3, 4)) a_cl = Variable(shape=a.shape) a_cl.value = a b_cl = Variable(shape=b.shape) b_cl.value = b expected = np.dstack((a, b)) actual = aff.dstack((a_cl, b_cl)) assert np.allclose(expected, actual.value) c = np.array([[1], [2], [3]]) d = np.array([[2], [3], [4]]) expected1 = np.dstack((c, d)) c_cl = Variable(shape=c.shape) c_cl.value = c d_cl = Variable(shape=d.shape) d_cl.value = d actual1 = aff.dstack((c_cl, d_cl)) assert np.allclose(expected1, actual1.value) a_cl.value = 1 + a assert not np.allclose(expected, actual.value) c_cl.value = 1 + c assert not np.allclose(expected1, actual1.value)