def test_conditional_sage_dual_1(self): n, m = 2, 6 x = Variable(shape=(n, ), name='x') cons = [1 >= vector2norm(x)] gts = [lambda z: 1 - np.linalg.norm(z, 2)] eqs = [] sigdom = SigDomain(n, coniclifts_cons=cons, gts=gts, eqs=eqs) np.random.seed(0) x0 = np.random.randn(n) x0 /= 2 * np.linalg.norm(x0) alpha = np.random.randn(m, n) c = np.array([1, 2, 3, 4, -0.5, -0.1]) v0 = np.exp(alpha @ x0) v = Variable(shape=(m, ), name='projected_v0') t = Variable(shape=(1, ), name='epigraph_var') sage_constraint = sage_cones.DualSageCone(v, alpha, name='test', X=sigdom, c=c) epi_constraint = vector2norm(v - v0) <= t constraints = [sage_constraint, epi_constraint] prob = Problem(CL_MIN, t, constraints) prob.solve(solver='ECOS') v0 = sage_constraint.violation(norm_ord=1, rough=False) assert v0 < 1e-6 v1 = sage_constraint.violation(norm_ord=np.inf, rough=True) assert v1 < 1e-6 val = prob.value assert val < 1e-7
def project(item, alpha): """ Calculates the shortest distance (the projection) of a vector to a cone parametrized by :math:'\\alpha' Parameters ---------- item - the point we are projecting alpha - the :math:'\\alpha' parameter for the Cone that we are projecting to Returns ------- The distance of the projection to the Cone """ from sageopt.coniclifts import MIN as CL_MIN item = Expression(item).ravel() w = Variable(shape=(item.size, )) t = Variable(shape=(1, )) cons = [vector2norm(item - w) <= t, PowCone(w, alpha)] prob = Problem(CL_MIN, t, cons) prob.solve(verbose=False) return prob.value
def test_vector2norm_2(self): x = Variable(shape=(3, ), name='x') y = Variable(shape=(1, ), name='y') nrm = vector2norm(x - np.array([0.1, 0.2, 0.3])) con = [nrm <= y] A_expect = np.array([ [0, 0, 0, 1, -1], # linear inequality constraint in terms of epigraph variable [0, 0, 0, 0, 1], # epigraph component in second order cone constraint [1, 0, 0, 0, 0], # start of main block in second order cone constraint [0, 1, 0, 0, 0], [0, 0, 1, 0, 0] ]) # end of main block in second order cone constraint b_expect = np.zeros(shape=(5, )) b_expect[0] = 0 b_expect[2] = -0.1 b_expect[3] = -0.2 b_expect[4] = -0.3 A, b, K, _, _, _ = compile_constrained_system(con) A = np.round(A.toarray(), decimals=1) assert np.all(A == A_expect) assert np.all(b == b_expect) assert K == [Cone('+', 1), Cone('S', 4)]
def test_ordinary_sage_dual_3(self): # provide a vector "c" in the dual SAGE cone constructor. # generate a point with zero distance from the dual SAGE cone n, m = 2, 6 np.random.seed(0) alpha = 10 * np.random.randn(m, n) x0 = np.random.randn(n) / 10 v0 = np.exp(alpha @ x0) dummy_vars = Variable(shape=(2, )).scalar_variables() c = np.array([1, 2, 3, 4, dummy_vars[0], dummy_vars[1]]) c = Expression(c) v = Variable(shape=(m, ), name='projected_v0') t = Variable(shape=(1, ), name='epigraph_var') sage_constraint = sage_cones.DualSageCone(v, alpha, X=None, name='test_con', c=c) epi_constraint = vector2norm(v - v0) <= t constraints = [sage_constraint, epi_constraint] prob = Problem(CL_MIN, t, constraints) prob.solve(solver='ECOS') viol = sage_constraint.violation(norm_ord=1, rough=False) assert viol < 1e-6 viol = sage_constraint.violation(norm_ord=np.inf, rough=True) assert viol < 1e-6 val = prob.value assert val < 1e-7
def test_separate_cone_constraints_2(self): num_vars = 5 x = Variable(shape=(num_vars, )) cons = [vector2norm(x) <= 1] prob = Problem(CL_MIN, Expression([0]), cons) A0, b0, K0 = prob.A, prob.b, prob.K assert A0.shape == (num_vars + 2, num_vars + 1) assert len(K0) == 2 assert K0[0].type == '+' and K0[0].len == 1 assert K0[1].type == 'S' and K0[1].len == num_vars + 1 A1, b1, K1, sepK1 = separate_cone_constraints(A0, b0, K0, dont_sep={'+'}) A1 = A1.toarray() assert A1.shape == (num_vars + 2, 2 * (num_vars + 1)) assert len(K1) == 2 assert K1[0].type == '+' and K1[0].len == 1 assert K1[1].type == '0' and K1[1].len == num_vars + 1 assert len(sepK1) == 1 assert sepK1[0].type == 'S' and sepK1[0].len == num_vars + 1 A0 = A0.toarray() temp = np.vstack( (np.zeros(shape=(1, num_vars + 1)), np.eye(num_vars + 1))) expect_A1 = np.hstack((A0, -temp)) assert np.allclose(expect_A1, A1)
def project(item, K): from sageopt.coniclifts import MIN as CL_MIN item = Expression(item).ravel() x = Variable(shape=(item.size, )) t = Variable(shape=(1, )) cons = [vector2norm(item - x) <= t, PrimalProductCone(x, K)] prob = Problem(CL_MIN, t, cons) prob.solve(verbose=False) return prob.value
def project(item, alpha, X): if np.all(item >= 0): return 0 c = Variable(shape=(item.size,)) t = Variable(shape=(1,)) cons = [ vector2norm(item - c) <= t, PrimalSageCone(c, alpha, X, 'temp_con') ] prob = Problem(CL_MIN, t, cons) prob.solve(verbose=False) return prob.value
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_ordinary_sage_dual_2(self): # generate a point with zero distance from the dual SAGE cone n, m = 2, 6 np.random.seed(0) alpha = 10 * np.random.randn(m, n) x0 = np.random.randn(n) / 10 v0 = np.exp(alpha @ x0) v = Variable(shape=(m, ), name='projected_v0') t = Variable(shape=(1, ), name='epigraph_var') sage_constraint = sage_cones.DualSageCone(v, alpha, X=None, name='test_con') epi_constraint = vector2norm(v - v0) <= t constraints = [sage_constraint, epi_constraint] prob = Problem(CL_MIN, t, constraints) prob.solve(solver='ECOS') viol = sage_constraint.violation(norm_ord=1, rough=False) assert viol < 1e-6 viol = sage_constraint.violation(norm_ord=np.inf, rough=True) assert viol < 1e-6 val = prob.value assert val < 1e-7
def test_ordinary_sage_dual_1(self): # generate a point which has positive distance from the dual SAGE cone n, m = 2, 6 np.random.seed(0) alpha = 10 * np.random.randn(m, n) v0 = 10 * np.abs(np.random.randn(m)) + 0.01 v0[0] = -v0[0] v = Variable(shape=(m, ), name='projected_v0') t = Variable(shape=(1, ), name='epigraph_var') sage_constraint = sage_cones.DualSageCone(v, alpha, X=None, name='test_con') epi_constraint = vector2norm(v - v0) <= t constraints = [sage_constraint, epi_constraint] prob = Problem(CL_MIN, t, constraints) prob.solve(solver='ECOS') viol = sage_constraint.violation(norm_ord=1, rough=False) assert viol < 1e-6 viol = sage_constraint.violation(norm_ord=np.inf, rough=True) assert viol < 1e-6 val = prob.value assert val + 1e-6 >= abs(v0[0])
def test_ordinary_sage_primal_2(self): n, m = 2, 6 np.random.seed(0) alpha = 1 * np.random.randn(m - 1, n) conv_comb = np.random.rand(m - 1) conv_comb /= np.sum(conv_comb) alpha_last = alpha.T @ conv_comb alpha = np.row_stack([alpha, alpha_last]) c0 = np.array([1, 2, 3, 4, -0.5, -0.1]) c = Variable(shape=(m, ), name='projected_c0') t = Variable(shape=(1, ), name='epigraph_var') sage_constraint = sage_cones.PrimalSageCone(c, alpha, X=None, name='test') epi_constraint = vector2norm(c - c0) <= t constraints = [sage_constraint, epi_constraint] prob = Problem(CL_MIN, t, constraints) prob.solve(solver='ECOS') # constraint violations v0 = sage_constraint.violation(norm_ord=1, rough=False) assert v0 < 1e-6 v1 = sage_constraint.violation(norm_ord=np.inf, rough=True) assert v1 < 1e-6 # certificates w4 = sage_constraint.age_witnesses[4].value c4 = sage_constraint.age_vectors[4].value drop4 = np.array([True, True, True, True, False, True]) level4 = np.sum(rel_entr(w4[drop4], np.exp(1) * c4[drop4])) - c4[4] assert level4 < 1e-6 w5 = sage_constraint.age_witnesses[5].value c5 = sage_constraint.age_vectors[5].value drop5 = np.array([True, True, True, True, True, False]) level5 = np.sum(rel_entr(w5[drop5], np.exp(1) * c5[drop5])) - c5[5] assert level5 < 1e-6