def set_affine_constraints(G, h, y, K_aff): constraints = [] i = 0 if K_aff[a2d.ZERO]: dim = K_aff[a2d.ZERO] constraints.append(G[i:i + dim, :] @ y == h[i:i + dim]) i += dim if K_aff[a2d.NONNEG]: dim = K_aff[a2d.NONNEG] constraints.append(G[i:i + dim, :] @ y <= h[i:i + dim]) i += dim for dim in K_aff[a2d.SOC]: expr = h[i:i + dim] - G[i:i + dim, :] @ y constraints.append(SOC(expr[0], expr[1:])) i += dim if K_aff[a2d.EXP]: dim = 3 * K_aff[a2d.EXP] expr = cp.reshape(h[i:i + dim] - G[i:i + dim, :] @ y, (dim // 3, 3), order='C') constraints.append(ExpCone(expr[:, 0], expr[:, 1], expr[:, 2])) i += dim if K_aff[a2d.POW3D]: alpha = np.array(K_aff[a2d.POW3D]) expr = cp.reshape(h[i:] - G[i:, :] @ y, (alpha.size, 3), order='C') constraints.append( PowCone3D(expr[:, 0], expr[:, 1], expr[:, 2], alpha)) return constraints
def graph_implementation(arg_objs, size, data=None): """Reduces the atom to an affine expression and list of constraints. Parameters ---------- arg_objs : list LinExpr for each argument. size : tuple The size of the resulting expression. data : Additional data required by the atom. Returns ------- tuple (LinOp for objective, list of constraints) """ x = arg_objs[0] y = arg_objs[1] t = lu.create_var((1, 1)) constraints = [ExpCone(t, x, y), lu.create_geq(y)] # 0 <= y # -t - x + y obj = lu.sub_expr(y, lu.sum_expr([x, t])) return (obj, constraints)
def kl_div_canon(expr, args): shape = expr.shape x = promote(args[0], shape) y = promote(args[1], shape) t = Variable(shape) constraints = [ExpCone(t, x, y)] obj = y - x - t return obj, constraints
def log_canon(expr, args): x = args[0] shape = expr.shape t = Variable(shape) ones = Constant(np.ones(shape)) # TODO(akshayka): ExpCone requires each of its inputs to be a Variable; # is this something that we want to change? constraints = [ExpCone(t, ones, x)] return t, constraints
def xexp_canon(expr, args): x = args[0] u = Variable(expr.shape, nonneg=True) t = Variable(expr.shape, nonneg=True) power_expr = power(x, 2) power_obj, constraints = power_canon(power_expr, power_expr.args) constraints += [ExpCone(u, x, t), u >= power_obj, x >= 0] return t, constraints
def entr_canon(expr, args): x = args[0] shape = expr.shape t = Variable(shape) # -x\log(x) >= t <=> x\exp(t/x) <= 1 # TODO(akshayka): ExpCone requires each of its inputs to be a Variable; # is this something that we want to change? ones = Constant(np.ones(shape)) constraints = [ExpCone(t, x, ones)] return t, constraints
def graph_implementation(self, arg_objs): rows, cols = self.size t = Variable(rows, cols) constraints = [] for i in xrange(rows): for j in xrange(cols): xi = arg_objs[0][i, j] x, y, z = Variable(), Variable(), Variable() constraints += [ ExpCone(x, y, z), x == t[i, j], y == xi, z == 1 ] return (t, constraints)
def suppfunc_canon(expr, args): y = args[0].flatten() # ^ That's the user-supplied argument to the support function. parent = expr._parent A, b, K_sels = parent.conic_repr_of_set() # ^ That defines the set "X" associated with this support function. eta = Variable(shape=(b.size, )) expr._eta = eta # ^ The main part of the duality trick for representing the epigraph # of this support function. n = A.shape[1] n0 = y.size if n > n0: # The description of the set "X" used in this support # function included n - n0 > 0 auxiliary variables. # We can pretend these variables were user-defined # by appending a suitable number of zeros to y. y_lift = hstack([y, np.zeros(shape=(n - n0, ))]) else: y_lift = y local_cons = [A.T @ eta + y_lift == 0] # now, the conic constraints on eta. # nonneg, exp, soc, psd nonnegsel = K_sels['nonneg'] if nonnegsel.size > 0: temp_expr = eta[nonnegsel] local_cons.append(temp_expr >= 0) socsels = K_sels['soc'] for socsel in socsels: tempsca = eta[socsel[0]] tempvec = eta[socsel[1:]] soccon = SOC(tempsca, tempvec) local_cons.append(soccon) psdsels = K_sels['psd'] for psdsel in psdsels: curmat = scs_psdvec_to_psdmat(eta, psdsel) local_cons.append(curmat >> 0) expsel = K_sels['exp'] if expsel.size > 0: matexpsel = np.reshape(expsel, (-1, 3)) curr_u = eta[matexpsel[:, 0]] curr_v = eta[matexpsel[:, 1]] curr_w = eta[matexpsel[:, 2]] # (curr_u, curr_v, curr_w) needs to belong to the dual # exponential cone, as used by the SCS solver. We map # this to a primal exponential cone as follows. ec = ExpCone(-curr_v, -curr_u, np.exp(1) * curr_w) local_cons.append(ec) epigraph = b @ eta return epigraph, local_cons
def simulate_chain(in_prob): # Get a ParamConeProg object reductions = [Dcp2Cone(), CvxAttr2Constr(), ConeMatrixStuffing()] chain = Chain(None, reductions) cone_prog, inv_prob2cone = chain.apply(in_prob) # Dualize the problem, reconstruct a high-level cvxpy problem for the dual. # Solve the problem, invert the dualize reduction. solver = ConicSolver() cone_prog = solver.format_constraints(cone_prog, exp_cone_order=[0, 1, 2]) data, inv_data = a2d.Dualize.apply(cone_prog) A, b, c, K_dir = data[s.A], data[s.B], data[s.C], data['K_dir'] y = cp.Variable(shape=(A.shape[1], )) constraints = [A @ y == b] i = K_dir[a2d.FREE] dual_prims = {a2d.FREE: y[:i], a2d.SOC: []} if K_dir[a2d.NONNEG]: dim = K_dir[a2d.NONNEG] dual_prims[a2d.NONNEG] = y[i:i + dim] constraints.append(y[i:i + dim] >= 0) i += dim for dim in K_dir[a2d.SOC]: dual_prims[a2d.SOC].append(y[i:i + dim]) constraints.append(SOC(y[i], y[i + 1:i + dim])) i += dim if K_dir[a2d.DUAL_EXP]: dual_prims[a2d.DUAL_EXP] = y[i:] y_de = cp.reshape(y[i:], ((y.size - i) // 3, 3), order='C') # fill rows first constraints.append( ExpCone(-y_de[:, 1], -y_de[:, 0], np.exp(1) * y_de[:, 2])) objective = cp.Maximize(c @ y) dual_prob = cp.Problem(objective, constraints) dual_prob.solve(solver='SCS', eps=1e-8) dual_prims[a2d.FREE] = dual_prims[a2d.FREE].value if K_dir[a2d.NONNEG]: dual_prims[a2d.NONNEG] = dual_prims[a2d.NONNEG].value dual_prims[a2d.SOC] = [expr.value for expr in dual_prims[a2d.SOC]] if K_dir[a2d.DUAL_EXP]: dual_prims[a2d.DUAL_EXP] = dual_prims[a2d.DUAL_EXP].value dual_duals = {s.EQ_DUAL: constraints[0].dual_value} dual_sol = cp.Solution(dual_prob.status, dual_prob.value, dual_prims, dual_duals, dict()) cone_sol = a2d.Dualize.invert(dual_sol, inv_data) # Pass the solution back up the solving chain. in_prob_sol = chain.invert(cone_sol, inv_prob2cone) in_prob.unpack(in_prob_sol)
def set_direct_constraints(y, K_dir): constraints = [] i = K_dir[a2d.FREE] if K_dir[a2d.NONNEG]: dim = K_dir[a2d.NONNEG] constraints.append(y[i:i + dim] >= 0) i += dim for dim in K_dir[a2d.SOC]: constraints.append(SOC(y[i], y[i + 1:i + dim])) i += dim if K_dir[a2d.EXP]: dim = y.size - i expr = cp.reshape(y[i:], (dim // 3, 3), order='C') constraints.append(ExpCone(expr[:, 0], expr[:, 1], expr[:, 2])) return constraints
def set_affine_constraints(G, h, y, K_aff): constraints = [] i = 0 if K_aff[a2d.ZERO]: dim = K_aff[a2d.ZERO] constraints.append(G[i:i + dim, :] @ y == h[i:i + dim]) i += dim if K_aff[a2d.NONNEG]: dim = K_aff[a2d.NONNEG] constraints.append(G[i:i + dim, :] @ y <= h[i:i + dim]) i += dim for dim in K_aff[a2d.SOC]: expr = h[i:i + dim] - G[i:i + dim, :] @ y constraints.append(SOC(expr[0], expr[1:])) i += dim if K_aff[a2d.EXP]: dim = G.shape[0] - i expr = cp.reshape(h[i:] - G[i:, :] @ y, (dim // 3, 3), order='C') constraints.append(ExpCone(expr[:, 0], expr[:, 1], expr[:, 2])) return constraints
def set_direct_constraints(y, K_dir): constraints = [] i = K_dir[a2d.FREE] if K_dir[a2d.NONNEG]: dim = K_dir[a2d.NONNEG] constraints.append(y[i:i + dim] >= 0) i += dim for dim in K_dir[a2d.SOC]: constraints.append(SOC(y[i], y[i + 1:i + dim])) i += dim if K_dir[a2d.EXP]: dim = 3 * K_dir[a2d.EXP] expr = cp.reshape(y[i:i + dim], (dim // 3, 3), order='C') constraints.append(ExpCone(expr[:, 0], expr[:, 1], expr[:, 2])) i += dim if K_dir[a2d.POW3D]: alpha = np.array(K_dir[a2d.POW3D]) expr = cp.reshape(y[i:], (alpha.size, 3), order='C') constraints.append( PowCone3D(expr[:, 0], expr[:, 1], expr[:, 2], alpha)) return constraints
def graph_implementation(arg_objs, size, data=None): """Reduces the atom to an affine expression and list of constraints. Parameters ---------- arg_objs : list LinExpr for each argument. size : tuple The size of the resulting expression. data : Additional data required by the atom. Returns ------- tuple (LinOp for objective, list of constraints) """ t = lu.create_var(size) x = arg_objs[0] ones = lu.create_const(np.mat(np.ones(size)), size) return (t, [ExpCone(x, ones, t)])
def exp_canon(expr, args): x = promote(args[0], expr.shape) t = Variable(expr.shape) ones = Constant(np.ones(expr.shape)) constraints = [ExpCone(x, ones, t)] return t, constraints