예제 #1
0
 def test_unconstrained_sage_2(self):
     # Background
     #
     #       This is Example 2 from a 2018 paper by Murray, Chandrasekaran, and Wierman
     #       (https://arxiv.org/pdf/1810.01614.pdf).
     #
     # Tests
     #
     #       (1) Check that primal / dual objective are -\infty for ell == 0.
     #
     #       (2) Check that primal / dual objectives are close to a reference value, for ell == 1.
     #
     #       (3) Recover a globally optimal solution at ell == 1.
     #
     alpha = np.array([[0, 0],
                       [1, 0],
                       [0, 1],
                       [1, 1],
                       [0.5, 1],
                       [1, 0.5]])
     c = np.array([0, 1, 1, 1.9, -2, -2])
     s = Signomial(alpha, c)
     expected = [-np.inf, -0.122211863]
     pd0, _ = primal_dual_vals(s, 0)
     assert pd0[0] == expected[0] and pd0[1] == expected[0]
     pd1, dual = primal_dual_vals(s, 1)
     assert abs(pd1[0] - expected[1]) < 1e-5 and abs(pd1[1] - expected[1]) < 1e-5
     solns = sig_solrec(dual)
     assert s(solns[0]) < 1e-6 + dual.value
예제 #2
0
 def test_conditional_constrained_sage_2(self):
     # Background
     #
     #       This is Problem 4 from a 2005 paper by Yanjun Wang and Zhian Liang.
     #       The optimal objective is between 11.95 and 11.96.
     #
     # Tests - (p, q, ell) = (0, 2, 0)
     #
     #       (1) Verify similar primal / dual objectives.
     #
     #       (2) Verify that primal objective is within 1 percent of a reference value.
     #
     #       (3) Recover a solution feasible within 1e-8, within 1 percent of optimality.
     #
     n = 2
     y = standard_sig_monomials(n)
     f = 3.7 * y[0] ** 0.85 + 1.985 * y[0] + 700.3 * y[1] ** -0.75
     gts = [1 - 0.7673 * y[1] ** 0.05 + 0.05 * y[0],
            5 - y[0],   y[0] - 0.1,
            450 - y[1], y[1] - 380]
     eqs = []
     X = infer_domain(f, gts, eqs)
     p, q, ell = 0, 2, 0
     vals, dual = constrained_primal_dual_vals(f, gts, eqs, p, q, ell, X, solver='MOSEK')
     assert abs(vals[0] - vals[1]) < 1e-1
     assert abs(vals[0] - 11.95) / vals[0] < 1e-2
     solns = sig_solrec(dual, ineq_tol=1e-8)
     assert (f(solns[0]) - dual.value) / dual.value < 1e-2
예제 #3
0
 def test_conditional_constrained_sage_1(self):
     # Background
     #
     #       This is Problem 1 from a 2014 paper by Xue-Ping Hou, Pei-Ping Shen, and Yong-Qiang Chen.
     #       It can also be found in * many * other papers.
     #       The optimal objective is 0.76508
     #
     # Tests - (p, q, ell) = (0, 1, 0).
     #
     #       (1) Check that primal and dual objectives are close.
     #
     #       (2) Check that primal objective is close to reference value.
     #
     #       (3) Verify that we can recover an optimal solution.
     #
     n = 4
     y = standard_sig_monomials(n)
     f = y[2] ** 0.8 * y[3] ** 1.2
     gts = [y[0] * y[3] ** -1 + y[1] ** -1 * y[3] ** -1 - 1,
            - y[0] ** -2 * y[2] ** -1 - y[1] * y[2] ** -1 + 1]
     gts = [-g for g in gts]
     gts += [1 - y[0], y[0] - 0.1,
             10 - y[1], y[1] - 5,
             15 - y[2], y[2] - 8,
             1 - y[3], y[3] - 0.01]
     eqs = []
     X = infer_domain(f, gts, eqs)
     p, q, ell = 0, 1, 0
     vals, dual = constrained_primal_dual_vals(f, gts, eqs, p, q, ell, X)
     assert abs(vals[0] - vals[1]) < 1e-5
     assert abs(vals[0] - 0.765082) < 1e-4
     solns = sig_solrec(dual, ineq_tol=0)
     assert f(solns[0]) < 1e-8 + dual.value
예제 #4
0
 def test_conditional_sage_1(self):
     # Background
     #
     #       This is Problem 1 from MCW2019. It appears in many papers on algorithms
     #       for signomial progamming. All constraints are convex.
     #
     # Tests
     #
     #       ell=0 and ell=3. Test for recovery of a feasible solution for
     #       ell=0, and test for recovery of an optimal solution for ell=3.
     #
     # Notes
     #
     #       ECOS can't solve the primal when ell > 0. Only try ell=3 if MOSEK is installed.
     #
     y = standard_sig_monomials(3)
     f = 0.5 * y[0] * y[1] ** -1 - y[0] - 5 * y[1] ** -1
     gts = [100 - y[1] * y[2] ** -1 - y[1] - 0.05 * y[0] * y[2],
            y[0] - 70, y[1] - 1, y[2] - 0.5,
            150 - y[0], 30 - y[1], 21 - y[2]]
     eqs = []
     X = infer_domain(f, gts, eqs)
     vals, prob = primal_dual_vals(f, 0, X)
     expect = -147.85712
     assert abs(vals[0] - expect) <= 1e-3
     assert abs(vals[1] - expect) <= 1e-3
     solutions = sig_solrec(prob)
     assert len(solutions) > 0
     if cl.Mosek.is_installed():
         vals, prob = primal_dual_vals(f, 3, X, solver='MOSEK')
         expect = -147.6666
         assert abs(vals[0] - expect) <= 1e-3
         assert abs(vals[1] - expect) <= 1e-3
         solutions = sig_solrec(prob)
         assert len(solutions) > 0
         x_star = solutions[0]
         gap = f(x_star) - prob.value
         assert abs(gap) <= 1e-3
     pass
예제 #5
0
 def test_constrained_sage_1a(self):
     # Tests - (p, q, ell) = (0, 1, 0)
     #
     #       (1) Verify that primal and dual objectives are close to a reference value.
     #
     #       (2) Recover a solution (feasible up to tol 1e-7) with at most 0.01 percent optimality gap
     #
     f, gs = TestSAGERelaxations._constrained_sage_1()
     expected = -0.6147
     actual, dual = constrained_primal_dual_vals(f, gs, [], p=0, q=1, ell=0, X=None)
     assert abs(actual[0] - expected) < 1e-4 and abs(actual[1] - expected) < 1e-4
     solns = sig_solrec(dual, ineq_tol=1e-7)
     assert (f(solns[0]) - dual.value) / abs(dual.value) < 1e-4
예제 #6
0
 def test_unconstrained_sage_1(self, presolve=False, compactdual=True, kernel_basis=False):
     # Background
     #
     #       This is Example 1 from a 2018 paper by Murray, Chandrasekaran, and Wierman
     #       (https://arxiv.org/pdf/1810.01614.pdf).
     #
     # Tests
     #
     #       (1) Check that primal / dual objectives are close to a reference values, for ell \in {0, 1}.
     #
     #       (2) Recover a globally optimal solution at ell == 1.
     #
     initial_presolve = sage_cones.SETTINGS['presolve_trivial_age_cones']
     initial_compactdual = sage_cones.SETTINGS['compact_dual']
     initial_kb = sage_cones.SETTINGS['kernel_basis']
     cl.presolve_trivial_age_cones(presolve)
     cl.compact_sage_duals(compactdual)
     cl.kernel_basis_age_witnesses(kernel_basis)
     alpha = np.array([[0, 0],
                       [1, 0],
                       [0, 1],
                       [1, 1],
                       [0.5, 0],
                       [0, 0.5]])
     c = np.array([0, 3, 2, 1, -4, -2])
     s = Signomial(alpha, c)
     expected = [-1.83333, -1.746505595]
     pd0, _ = primal_dual_vals(s, 0)
     self.assertAlmostEqual(pd0[0], expected[0], 4)
     self.assertAlmostEqual(pd0[1], expected[0], 4)
     pd1, dual = primal_dual_vals(s, 1)
     self.assertAlmostEqual(pd1[0], expected[1], 4)
     self.assertAlmostEqual(pd1[1], expected[1], 4)
     optsols = sig_solrec(dual)
     assert (s(optsols[0]) - dual.value) < 1e-6
     cl.presolve_trivial_age_cones(initial_presolve)
     cl.compact_sage_duals(initial_compactdual)
     cl.kernel_basis_age_witnesses(initial_kb)
예제 #7
0
 def test_conditional_constrained_sage_3(self):
     # Background
     #
     #       This is a modification of Problem 10 from the 1978 paper by M. Rijckaert and X. Martens.
     #       The bound constraints come from a different paper (but I dont recall where...).
     #       We also add an additional trivially-valid constraint (simply to strengthen the Lagrange dual).
     #       The optimal objective is reported in the literature as approximately -83.21.
     #
     # Tests - (p, q, ell) = (0, 1, 1)
     #
     #       (1) Verify similar primal / dual objectives.
     #
     #       (2) Recover a strictly feasible solution, within 0.7 % of optimality.
     #
     # Notes
     #
     #       With (p, q, ell) = (0, 0, 2) (not shown here), we get a SAGE bound of -83.253.
     #       If the (0,0,2) SAGE bound of -83.253 is to be believed, then the recovered solution
     #       actually has a relative optimality gap of only 0.003 percent.
     #
     n = 3
     x = standard_sig_monomials(n)
     f = 0.5 * x[0] * (x[1] ** -1) - x[0] - 5.0 * (x[1] ** -1)
     g = 1 - 0.01 * x[1] * (x[2] ** -1) - 0.01 * x[0] - 0.0005 * x[0] * x[2]
     g = 100.0 * g
     gts = [g, g * (x[1] ** -2),
            1e2 - x[0], 1e2 - x[1], 1e2 - x[2],
            x[0] - 1, x[1] - 1, x[2] - 1]
     eqs = []
     X = infer_domain(f, gts, eqs)
     p, q, ell = 0, 1, 1
     vals, dual = constrained_primal_dual_vals(f, gts, eqs, p, q, ell, X, solver='MOSEK')
     assert abs(vals[0] - vals[1]) < 1e-4
     assert abs(vals[0] - (-83.3235)) < 1e-4
     solns = sig_solrec(dual, ineq_tol=0)
     assert (f(solns[0]) - dual.value) / abs(dual.value) < 0.007
예제 #8
0
 def test_unconstrained_sage_4(self, presolve=False, compactdual=False, kernel_basis=False):
     # Background
     #
     #       This example was constructed soley as a test case for sageopt.
     #
     #       Minimize s(x) = exp(3*x) - 4*exp(2*x) + 7*exp(x) + exp(-x), over x \in R.
     #
     # Tests
     #
     #       (1) Check that primal / dual objectives are close to reference values, for ell \in {0, 1, 2}.
     #
     #       (2) Recover a globally optimal solution from the dual relaxation, when ell == 3.
     #
     # Notes
     #
     #       It may not be obvious, but the signomial "s" is actually convex!
     #
     initial_presolve = sage_cones.SETTINGS['presolve_trivial_age_cones']
     initial_compactdual = sage_cones.SETTINGS['compact_dual']
     initial_kb = sage_cones.SETTINGS['kernel_basis']
     cl.presolve_trivial_age_cones(presolve)
     cl.compact_sage_duals(compactdual)
     cl.kernel_basis_age_witnesses(kernel_basis)
     s = Signomial.from_dict({(3,): 1, (2,): -4, (1,): 7, (-1,): 1})
     expected = [3.464102, 4.60250026, 4.6217973]
     pds = [primal_dual_vals(s, ell) for ell in range(3)]
     for ell in range(3):
         assert abs(pds[ell][0][0] - expected[ell]) < 1e-5
         assert abs(pds[ell][0][1] - expected[ell]) < 1e-5
     dual = sig_relaxation(s, form='dual', ell=3)
     dual.solve(solver='ECOS', verbose=False)
     optsols = sig_solrec(dual)
     assert s(optsols[0]) < 1e-6 + dual.value
     cl.presolve_trivial_age_cones(initial_presolve)
     cl.compact_sage_duals(initial_compactdual)
     cl.kernel_basis_age_witnesses(initial_kb)