def test_paper_example_eye_minus_inv(self): X = cvxpy.Variable((2, 2), pos=True) obj = cvxpy.Minimize(cvxpy.trace(cvxpy.eye_minus_inv(X))) constr = [cvxpy.geo_mean(cvxpy.diag(X)) == 0.1, cvxpy.geo_mean(cvxpy.hstack([X[0, 1], X[1, 0]])) == 0.1] problem = cvxpy.Problem(obj, constr) problem.solve(gp=True, solver="ECOS") np.testing.assert_almost_equal(X.value, 0.1*np.ones((2, 2)), decimal=3) self.assertAlmostEqual(problem.value, 2.25)
def test_paper_example_eye_minus_inv(self): X = cvxpy.Variable((2, 2), pos=True) obj = cvxpy.Minimize(cvxpy.trace(cvxpy.eye_minus_inv(X))) constr = [cvxpy.geo_mean(cvxpy.diag(X)) == 0.1] problem = cvxpy.Problem(obj, constr) # smoke test. problem.solve(gp=True, solver="SCS")
def layout(self): constraints = [] for box in self.boxes: # Enforce that boxes lie in bounding box. constraints += [ box.bottom >= FloorPlan.MARGIN, box.top + FloorPlan.MARGIN <= self.height ] constraints += [ box.left >= FloorPlan.MARGIN, box.right + FloorPlan.MARGIN <= self.width ] # Enforce aspect ratios. constraints += [(1 / box.ASPECT_RATIO) * box.height <= box.width, box.width <= box.ASPECT_RATIO * box.height] # Enforce minimum area constraints += [ geo_mean(vstack([box.width, box.height])) >= math.sqrt( box.min_area) ] # Enforce the relative ordering of the boxes. for ordering in self.horizontal_orderings: constraints += self._order(ordering, True) for ordering in self.vertical_orderings: constraints += self._order(ordering, False) p = Problem(Minimize(2 * (self.height + self.width)), constraints) return p.solve()
def test_matrix_constraint(self) -> None: X = cp.Variable((2, 2), pos=True) a = cp.Parameter(pos=True, value=0.1) obj = cp.Minimize(cp.geo_mean(cp.vec(X))) constr = [cp.diag(X) == a, cp.hstack([X[0, 1], X[1, 0]]) == 2 * a] problem = cp.Problem(obj, constr) gradcheck(problem, gp=True) perturbcheck(problem, gp=True)
def test_geo_mean(self): """Test gradient for geo_mean """ expr = cp.geo_mean(self.x) self.x.value = [1, 2] self.assertItemsAlmostEqual(expr.grad[self.x].toarray(), [np.sqrt(2)/2, 1.0/2/np.sqrt(2)]) self.x.value = [0, 2] self.assertAlmostEqual(expr.grad[self.x], None) expr = cp.geo_mean(self.x, [1, 0]) self.x.value = [1, 2] self.assertItemsAlmostEqual(expr.grad[self.x].toarray(), [1, 0]) # No exception for single weight. self.x.value = [-1, 2] self.assertAlmostEqual(expr.grad[self.x], None)
def test_geo_mean(self): x = cvxpy.Variable(3, pos=True) p = [1, 2, 0.5] geo_mean = cvxpy.geo_mean(x, p) self.assertTrue(geo_mean.is_dgp()) self.assertTrue(geo_mean.is_log_log_affine()) self.assertTrue(geo_mean.is_log_log_convex()) self.assertTrue(geo_mean.is_log_log_concave())
def test_geo_mean(self) -> None: """Test domain for geo_mean """ dom = cp.geo_mean(self.x).domain prob = Problem(Minimize(sum(self.x)), dom) prob.solve(solver=cp.SCS, eps=1e-5) self.assertAlmostEqual(prob.value, 0) # No special case for only one weight. dom = cp.geo_mean(self.x, [0, 2]).domain dom.append(self.x >= -1) prob = Problem(Minimize(sum(self.x)), dom) prob.solve(solver=cp.SCS, eps=1e-5) self.assertItemsAlmostEqual(self.x.value, [-1, 0]) dom = cp.geo_mean(self.z, [0, 1, 1]).domain dom.append(self.z >= -1) prob = Problem(Minimize(sum(self.z)), dom) prob.solve(solver=cp.SCS, eps=1e-5) self.assertItemsAlmostEqual(self.z.value, [-1, 0, 0])
def test_geo_mean(self): x = cvxpy.Variable(3, pos=True) p = [1, 2, 0.5] geo_mean = cvxpy.geo_mean(x, p) dgp = cvxpy.Problem(cvxpy.Minimize(geo_mean), []) dgp2dcp = cvxpy.reductions.Dgp2Dcp(dgp) dcp = dgp2dcp.reduce() dcp.solve(SOLVER) self.assertEqual(dcp.value, -float("inf")) dgp.unpack(dgp2dcp.retrieve(dcp.solution)) self.assertEqual(dgp.value, 0.0) self.assertEqual(dgp.status, "unbounded") dgp._clear_solution() dgp.solve(SOLVER, gp=True) self.assertEqual(dgp.value, 0.0) self.assertEqual(dgp.status, "unbounded")
def test_geo_mean(self): atom = cp.geo_mean(self.x) self.assertEqual(atom.shape, tuple()) self.assertEqual(atom.curvature, s.CONCAVE) self.assertEqual(atom.sign, s.NONNEG) # Test copy with args=None copy = atom.copy() self.assertTrue(type(copy) is type(atom)) # A new object is constructed, so copy.args == atom.args but copy.args # is not atom.args. self.assertEqual(copy.args, atom.args) self.assertFalse(copy.args is atom.args) self.assertEqual(copy.get_data(), atom.get_data()) # Test copy with new args copy = atom.copy(args=[self.y]) self.assertTrue(type(copy) is type(atom)) self.assertTrue(copy.args[0] is self.y) self.assertEqual(copy.get_data(), atom.get_data())
def test_multi_step_dyad_completion(self) -> None: """ Consider four market equilibrium problems. The budgets "b" in these problems are chosen so that canonicalization of geo_mean(u, b) hits a recursive code-path in power_tools.dyad_completion(...). The reference solution is computed by taking the log of the geo_mean objective, which has the effect of making the problem ExpCone representable. """ if 'MOSEK' in cp.installed_solvers(): log_solve_args = {'solver': 'MOSEK'} else: log_solve_args = {'solver': 'ECOS'} n_buyer = 5 n_items = 7 np.random.seed(0) V = 0.5 * (1 + np.random.rand(n_buyer, n_items)) X = cp.Variable(shape=(n_buyer, n_items), nonneg=True) cons = [cp.sum(X, axis=0) <= 1] u = cp.sum(cp.multiply(V, X), axis=1) bs = np.array([[110, 14, 6, 77, 108], [15., 4., 8., 0., 9.], [14., 21., 217., 57., 6.], [3., 36., 77., 8., 8.]]) for i, b in enumerate(bs): log_objective = cp.Maximize(b @ cp.log(u)) log_prob = cp.Problem(log_objective, cons) log_prob.solve(**log_solve_args) expect_X = X.value geo_objective = cp.Maximize(cp.geo_mean(u, b)) geo_prob = cp.Problem(geo_objective, cons) geo_prob.solve() actual_X = X.value try: self.assertItemsAlmostEqual(actual_X, expect_X, places=3) except AssertionError as e: print(f'Failure at index {i} (when b={str(b)}).') log_prob.solve(**log_solve_args, verbose=True) print(X.value) geo_prob.solve(verbose=True) print(X.value) print('The valuation matrix was') print(V) raise e
def f_Gamma(c): # For fixed c solve the semidefinite program for Algorithm 4 # Variable Gamma_plus (for \Gamma_{i+1}) d_plus = variable(2*n, 1, name='d_plus') # Constraints constr = [] for j in range(2*n): ctt = less_equals(d_plus[j,0], 0) constr.append( less_equals(-d_plus[j,0], 0)) constr.append( less_equals( d_plus[j,0], d[j,0])) constr.append( less_equals( J[j,j]*d_plus[j,0] + sum([abs(J[i,j])*d_plus[i,0] for i in range(2*n)]) - abs(J[j,j])*d_plus[j,0], c* d_plus[j,0])) # Objective function obj = geo_mean(d_plus) # Find solution p = program(maximize(obj), constr) return d_plus.value
def test_3d_power_cone_approx(self): """ Use geo_mean((x,y), (alpha, 1-alpha)) >= |z| as a reformulation of PowCone3D(x, y, z, alpha). Check validity of the reformulation by solving orthogonal projection problems. """ if 'MOSEK' in cp.installed_solvers(): proj_solve_args = {'solver': 'MOSEK'} else: proj_solve_args = {'solver': 'SCS', 'eps': 1e-10} min_numerator = 2 denominator = 25 x = cp.Variable(3) np.random.seed(0) y = 10 * np.random.rand(3) # the third value doesn't matter for i, numerator in enumerate(range(min_numerator, denominator, 3)): alpha_float = numerator / denominator y[2] = (y[0]**alpha_float) * (y[1]**(1 - alpha_float)) + 0.05 objective = cp.Minimize(cp.norm(y - x, 2)) actual_constraints = [ cp.constraints.PowCone3D(x[0], x[1], x[2], [alpha_float]) ] actual_prob = cp.Problem(objective, actual_constraints) actual_prob.solve(**proj_solve_args) actual_x = x.value.copy() weights = np.array([alpha_float, 1 - alpha_float]) approx_constraints = [cp.geo_mean(x[:2], weights) >= cp.abs(x[2])] approx_prob = cp.Problem(objective, approx_constraints) approx_prob.solve() approx_x = x.value.copy() try: self.assertItemsAlmostEqual(actual_x, approx_x, places=4) except AssertionError as e: print(f'Failure at index {i} (when alpha={alpha_float}).') raise e
def h(): x = cp.Variable() y = cp.Variable() z = cp.Variable() obj = cp.Minimize(0) constraints = [ x + z <= 1 + cp.sqrt(x * y - z**2), x >= 0, y >= 0, ] problem = cp.Problem(obj, constraints) print(f"h before: {problem.is_dcp()}") t = cp.Variable() constraints = [ x + z - 1 <= t, cp.norm(cp.vstack([x, t])) <= cp.geo_mean(cp.vstack([x, y])), x >= 0, y >= 0, ] problem = cp.Problem(obj, constraints) print(f"h after: {problem.is_dcp()}") problem.solve()
import numpy as np import cvxpy as cp a = np.array([0.2, 0.02, 0.04, 0.1]) A = np.diag(a) b = np.array([0.5, 0.1, 0.0, 0.2]) b = np.asmatrix(b).T p = cp.Variable(4) obj = cp.Maximize(cp.geo_mean(p) - (0.5 * cp.quad_form(p, A) + b.T * p)) cons = [p > 0] prob = cp.Problem(obj, cons) prob.solve() p_opt = p.value print "Market clearing prices:" print p_opt print "Demand:" print 0.25 * pow(p_opt[1, 0] * p_opt[2, 0] * p_opt[3, 0], 0.25) * pow(p_opt[0, 0], -3.0/4.0) print 0.25 * pow(p_opt[0, 0] * p_opt[2, 0] * p_opt[3, 0], 0.25) * pow(p_opt[1, 0], -3.0/4.0) print 0.25 * pow(p_opt[1, 0] * p_opt[0, 0] * p_opt[3, 0], 0.25) * pow(p_opt[2, 0], -3.0/4.0) print 0.25 * pow(p_opt[1, 0] * p_opt[2, 0] * p_opt[0, 0], 0.25) * pow(p_opt[3, 0], -3.0/4.0) print "Supply:" print 0.2 * p_opt[0, 0] + 0.5 print 0.02 * p_opt[1, 0] + 0.1 print 0.04 * p_opt[2, 0] print 0.1 * p_opt[3, 0] + 0.2
import numpy as np import cvxpy as cp A_file = "~/development/cvxopt/hwk7/max_vol_box/A.csv" b_file = "~/development/cvxopt/hwk7/max_vol_box/b.csv" A = np.loadtxt(open(A_file, "rb"), delimiter=",") b = np.loadtxt(open(b_file, "rb"), delimiter=",") L = np.zeros_like(A) U = np.zeros_like(A) for i, j in it.product(range(A.shape[0]), range(A.shape[1])): L[i,j] = max(-A[i,j], 0) U[i,j] = max(A[i,j], 0) l = cp.Variable(A.shape[1], nonneg=True) u = cp.Variable(A.shape[1], nonneg=True) obj = cp.geo_mean(u - l) con = [L @ l + U @ u <= b] p = cp.Problem(cp.Maximize(obj), con) p.solve()
def area(self): return cvx.geo_mean(cvx.vstack([self.width, self.height]))
import numpy as np import cvxpy as cp from data.correlation_bounds_data import m, n, A, sigma np.set_printoptions(precision=4, suppress=True) Sigma = cp.Variable((n, n), PSD=True) constraints = [] for i in range(m): a = A[:,i] constraints.append(cp.quad_form(a, Sigma) == sigma[i] ** 2) rhos = [] for i in range(n): for j in range(i): denom = cp.geo_mean(cp.hstack([Sigma[i, i], Sigma[j, j]])) rho_ij = cp.quad_over_lin(Sigma[i, j], denom) rhos.append(rho_ij) rho_max = cp.max(cp.hstack(rhos)) obj = cp.Minimize(rho_max) problem = cp.Problem(obj, constraints) problem.solve() print(problem.status) print(Sigma.value) print(rho_max.value)
def mean_area(cls, w, h, area): return cvx.geo_mean(cvx.hstack([w, h])) >= np.sqrt(area)
(lambda x: x[2:0:-1], (2, ), [[3, 4, 5]], Constant([5, 4])), (lambda x: x[2::-1], (3, ), [[3, 4, 5]], Constant([5, 4, 3])), (lambda x: x[3:0:-1], (2, ), [[3, 4, 5]], Constant([5, 4])), (lambda x: x[3::-1], (3, ), [[3, 4, 5]], Constant([5, 4, 3])), ] atoms_maximize = [ (cp.entr, (2, 2), [[[1, math.e], [math.e**2, 1.0 / math.e]]], Constant([[0, -math.e], [-2 * math.e**2, 1.0 / math.e]])), (cp.log_det, tuple(), [[[20, 8, 5, 2], [8, 16, 2, 4], [5, 2, 5, 2], [2, 4, 2, 4]]], Constant([7.7424020218157814])), (cp.geo_mean, tuple(), [[4, 1]], Constant([2])), (cp.geo_mean, tuple(), [[0.01, 7]], Constant([0.2645751311064591])), (cp.geo_mean, tuple(), [[63, 7]], Constant([21])), (cp.geo_mean, tuple(), [[1, 10]], Constant([math.sqrt(10)])), (lambda x: cp.geo_mean(x, [1, 1]), tuple(), [[1, 10]], Constant([math.sqrt(10)])), (lambda x: cp.geo_mean(x, [.4, .8, 4.9]), tuple(), [[.5, 1.8, 17]], Constant([10.04921378316062])), (cp.harmonic_mean, tuple(), [[1, 2, 3]], Constant([1.6363636363636365])), (cp.harmonic_mean, tuple(), [[2.5, 2.5, 2.5, 2.5]], Constant([2.5])), (cp.harmonic_mean, tuple(), [[0, 1, 2]], Constant([0])), (lambda x: cp.diff(x, 0), (3, ), [[1, 2, 3]], Constant([1, 2, 3])), (cp.diff, (2, ), [[1, 2, 3]], Constant([1, 1])), (cp.diff, tuple(), [[1.1, 2.3]], Constant([1.2])), (lambda x: cp.diff(x, 2), tuple(), [[1, 2, 3]], Constant([0])), (cp.diff, (3, ), [[2.1, 1, 4.5, -.1]], Constant([-1.1, 3.5, -4.6])), (lambda x: cp.diff(x, 2), (2, ), [[2.1, 1, 4.5, -.1]], Constant([4.6, -8.1])), (lambda x: cp.diff(x, 1, axis=0), (1, 2), [np.array([[-5, -3], [2, 1]])], Constant([[7], [4]])),
import cvxpy as cp from scipy.stats import bernoulli from progressbar import progressbar # Retrieve data path = "../storage/max-volume-rectangle.csv" A = np.genfromtxt(path, skip_footer=1, delimiter=" ") b = np.genfromtxt(path, skip_header=len(A), delimiter=" ") # Problem definition n = A.shape[1] lower = cp.Variable(n) upper = cp.Variable(n) sides = upper - lower volume = cp.prod(sides) objective = cp.Maximize(cp.geo_mean(sides)) A_u = np.maximum(A, 0) A_l = np.maximum(-A, 0) constraints = [ sides >= 0, A_u @ upper - A_l @ lower <= b, ] problem = cp.Problem(objective, constraints) problem.solve() volume.value # constraints checker checks = 1000000 print(f"Starting {checks} random corner checks...") for _ in progressbar(range(checks)): mask = bernoulli.rvs(0.5, size=n)
import numpy as np import cvxpy as cp a = np.array([0.2, 0.02, 0.04, 0.1]) A = np.diag(a) b = np.array([0.5, 0.1, 0.0, 0.2]) b = np.asmatrix(b).T p = cp.Variable(4) obj = cp.Maximize(cp.geo_mean(p) - (0.5 * cp.quad_form(p, A) + b.T * p)) cons = [p > 0] prob = cp.Problem(obj, cons) prob.solve() p_opt = p.value print "Market clearing prices:" print p_opt print "Demand:" print 0.25 * pow(p_opt[1, 0] * p_opt[2, 0] * p_opt[3, 0], 0.25) * pow( p_opt[0, 0], -3.0 / 4.0) print 0.25 * pow(p_opt[0, 0] * p_opt[2, 0] * p_opt[3, 0], 0.25) * pow( p_opt[1, 0], -3.0 / 4.0) print 0.25 * pow(p_opt[1, 0] * p_opt[0, 0] * p_opt[3, 0], 0.25) * pow( p_opt[2, 0], -3.0 / 4.0) print 0.25 * pow(p_opt[1, 0] * p_opt[2, 0] * p_opt[0, 0], 0.25) * pow( p_opt[3, 0], -3.0 / 4.0) print "Supply:" print 0.2 * p_opt[0, 0] + 0.5 print 0.02 * p_opt[1, 0] + 0.1 print 0.04 * p_opt[2, 0]
] atoms_maximize = [ (cp.entr, (2, 2), [[[1, math.e], [math.e**2, 1.0 / math.e]]], Constant([[0, -math.e], [-2 * math.e**2, 1.0 / math.e]])), (cp.log_det, tuple(), [[[20, 8, 5, 2], [8, 16, 2, 4], [5, 2, 5, 2], [2, 4, 2, 4]]], Constant([7.7424020218157814])), (cp.geo_mean, tuple(), [[4, 1]], Constant([2])), (cp.geo_mean, tuple(), [[0.01, 7]], Constant([0.2645751311064591])), (cp.geo_mean, tuple(), [[63, 7]], Constant([21])), (cp.geo_mean, tuple(), [[1, 10]], Constant([math.sqrt(10)])), (lambda x: cp.geo_mean(x, [1, 1]), tuple(), [[1, 10]], Constant([math.sqrt(10)])), (lambda x: cp.geo_mean(x, [.4, .8, 4.9]), tuple(), [[.5, 1.8, 17]], Constant([10.04921378316062])), (cp.harmonic_mean, tuple(), [[1, 2, 3]], Constant([1.6363636363636365])), (cp.harmonic_mean, tuple(), [[2.5, 2.5, 2.5, 2.5]], Constant([2.5])), (cp.harmonic_mean, tuple(), [[1e-8, 1, 2]], Constant([0])), (lambda x: cp.diff(x, 0), (3,), [[1, 2, 3]], Constant([1, 2, 3])), (cp.diff, (2,), [[1, 2, 3]], Constant([1, 1])), (cp.diff, tuple(), [[1.1, 2.3]], Constant([1.2])), (lambda x: cp.diff(x, 2), tuple(), [[1, 2, 3]], Constant([0])), (cp.diff, (3,), [[2.1, 1, 4.5, -.1]], Constant([-1.1, 3.5, -4.6])), (lambda x: cp.diff(x, 2), (2,), [[2.1, 1, 4.5, -.1]], Constant([4.6, -8.1])), (lambda x: cp.diff(x, 1, axis=0), (1, 2), [np.array([[-5, -3], [2, 1]])], Constant([[7], [4]])), (lambda x: cp.diff(x, 1, axis=1), (2, 1), [np.array([[-5, -3], [2, 1]])],
def get_allocation(self, unflattened_throughputs, scale_factors, unflattened_priority_weights, cluster_spec, recurse_deeper=True): throughputs, index = super().flatten(unflattened_throughputs, cluster_spec) if throughputs is None: return None (m, n) = throughputs.shape (job_ids, worker_types) = index if recurse_deeper: all_throughputs_minus_job = [] for job_id in job_ids: unflattened_throughputs_minus_job = copy.copy( unflattened_throughputs) del unflattened_throughputs_minus_job[job_id] throughputs_minus_job = self.get_allocation( unflattened_throughputs_minus_job, scale_factors, unflattened_priority_weights, cluster_spec, recurse_deeper=False) all_throughputs_minus_job.append(throughputs_minus_job) # Row i of scale_factors_array is the scale_factor of job i # repeated len(worker_types) times. scale_factors_array = self.scale_factors_array(scale_factors, job_ids, m, n) priority_weights = np.array( [1. / unflattened_priority_weights[job_id] for job_id in job_ids]) proportional_throughputs = self._proportional_policy.get_throughputs( throughputs, index, cluster_spec) priority_weights = np.multiply( priority_weights.reshape((m, 1)), 1.0 / proportional_throughputs.reshape((m, 1))) x = cp.Variable(throughputs.shape) # Multiply throughputs by scale_factors to ensure that scale_factor # is taken into account while allocating times to different jobs. # A job run on 1 GPU should receive `scale_factor` more time than # a job run on `scale_factor` GPUs if throughputs are equal. objective = cp.Maximize( cp.geo_mean( cp.sum(cp.multiply( np.multiply(throughputs * priority_weights.reshape((m, 1)), scale_factors_array), x), axis=1))) # Make sure that the allocation can fit in the cluster. constraints = self.get_base_constraints(x, scale_factors_array) cvxprob = cp.Problem(objective, constraints) result = cvxprob.solve(solver=self._solver) if cvxprob.status != "optimal": print('WARNING: Allocation returned by policy not optimal!') throughputs = np.sum(np.multiply(throughputs, x.value), axis=1) throughputs_dict = { job_ids[i]: throughputs[i] for i in range(len(job_ids)) } if not recurse_deeper: return throughputs_dict discount_factors = np.zeros(len(job_ids)) for i, job_id in enumerate(job_ids): discount_factor = 1.0 for other_job_id in all_throughputs_minus_job[i]: discount_factor *= (throughputs_dict[other_job_id] / all_throughputs_minus_job[i][other_job_id]) discount_factors[i] = discount_factor discounted_allocation = np.multiply(x.value.T, discount_factors).T return super().unflatten(discounted_allocation.clip(min=0.0).clip(max=1.0), index), \ discount_factors