def get_constr_error(constr): if isinstance(constr, cp.constraints.Equality): error = cp.abs(constr.args[0] - constr.args[1]) elif isinstance(constr, cp.constraints.Inequality): error = cp.pos(constr.args[0] - constr.args[1]) elif isinstance(constr, cp.constraints.PSD): mat = constr.args[0] - constr.args[1] error = cp.neg(cp.lambda_min(mat + mat.T) / 2) return cp.sum(error)
def get_constr_error(constr): if isinstance(constr, cvx.constraints.EqConstraint): error = cvx.abs(constr.args[0] - constr.args[1]) elif isinstance(constr, cvx.constraints.LeqConstraint): error = cvx.pos(constr.args[0] - constr.args[1]) elif isinstance(constr, cvx.constraints.PSDConstraint): mat = constr.args[0] - constr.args[1] error = cvx.neg(cvx.lambda_min(mat + mat.T)/2) return cvx.sum_entries(error)
def gen_data_ndim(nb_datapoints, dim, savefile, rand_seed=7): """Sampling according to Table 1 in manuscript: - uniform point positioning (x) in [0,1] for each dimension - uniform eigenvalues in [-1,1] - ortho-normal basis/matrix (eigvecs) of eigenvectors :param nb_datapoints: how many data points to sample :param dim: dimensionality of SDP sub-problem to sample :param savefile: file to save sampled data in :param rand_seed: random seed, pre-set to 7 :return: None """ np.random.seed(rand_seed) X = cvx.Variable(dim, dim) data_points = [] t_init = timer() t0 = timer() for data_pt_nb in range(1, nb_datapoints + 1): # ortho-normal basis/matrix (eigvecs) of eigenvectors eigvecs = ortho_group.rvs(dim) # uniform eigenvalues in [-1,1] eigvals = np.random.uniform(-1, 1, dim).tolist() # construct sampled Q from eigen-decomposition Q = np.matmul(np.matmul(eigvecs, np.diag(eigvals)), np.transpose(eigvecs)) # uniform point positioning (x) in [0,1] for each dimension x = np.random.uniform(0, 1, dim).tolist() # construct cvx SDP sub-problem obj_sdp = cvx.Minimize(cvx.sum_entries(cvx.mul_elemwise(Q, X))) constraints = [ cvx.lambda_min( cvx.hstack(cvx.vstack(1, np.array(x)), cvx.vstack(cvx.vec(x).T, X))) >= 0, *[X[ids, ids] <= x[ids] for ids in range(0, dim)] ] prob = cvx.Problem(obj_sdp, constraints) # solve it using Mosek SDP solver prob.solve(verbose=False, solver=cvx.MOSEK) # store upper triangular matrix in array (row major) since it is symmetric Q = np.triu(Q, 1) + np.triu(Q, 0) # save eigendecomposition, point positioning, matrix Q and solution of SDP sub-problem data_points.append([ *eigvecs.T.flatten(), *eigvals, *x, *list(Q[np.triu_indices(dim)]), obj_sdp.value ]) # save to file and empty data_points buffer every 1000 entries if not data_pt_nb % 1000: t1 = timer() with open(savefile, "a") as f: for line in data_points: f.write(",".join(str(x) for x in line) + "\n") data_points = [] print( str(data_pt_nb) + " " + str(dim) + "D points, time = " + str(t1 - t0) + "s" + ", total = " + str(t1 - t_init) + "s") t0 = t1
def e_optimal(A, N): # Initializing Variables, Objective, and Constraints W = cp.Variable(N) obj = cp.Maximize(cp.lambda_min(cp.sum([W[i] * A[i] for i in range(N)]))) const = [0 <= W, cp.sum(W) == 1] # Creating Problem & Solving prob = cp.Problem(obj, const) prob.solve() return prob
def smallestCircumScribedEllip(ptS, P=None, obj=None, maxChange=[None, None], Pold=None, **kwargs): #ptS holds the points columnwise #mindCondition < lambda_max/lambda_min opts = {'minCondition': 1.e3} opts.update(kwargs) Pold = (Pold.T + Pold) / 2. dim = ptS.shape[0] if P is None: P = cvxpy.Semidef(dim, "P") cstr = [cvxpy.quad_form(aPt, P) <= 1. for aPt in ptS.T] eigMax = np.max(np.linalg.eigh(Pold)[0]) #restrict changement zeta = cvxpy.Variable(1) if not (Pold is None) and not (maxChange[0] is None): cstr.append(eigMax * maxChange[0] * np.identity(dim) < P - zeta * Pold) if not (Pold is None) and not (maxChange[1] is None): cstr.append(P - zeta * Pold < eigMax * maxChange[1] * np.identity(dim)) if not (opts['minCondition'] is None): cstr.append( cvxpy.lambda_max(P) < opts['minCondition'] * cvxpy.lambda_min(P)) if obj is None: obj = cvxpy.Maximize(cvxpy.log_det(P)) prob = cvxpy.Problem(obj, cstr) #prob.solve(); prob.solve(solver='CVXOPT', verbose=False, kktsolver=cvxpy.ROBUST_KKTSOLVER) assert prob.status == 'optimal', "Failed to solve circumscribed ellip prob" Pval = np.array(P.value) return Pval
# Z = cvx.Variable(3,3) # objective = cvx.Minimize( sum(cvx.square(P - Z)) ) # constr = [cvx.constraints.semi_definite.SDP(P)] # prob = cvx.Problem(objective, constr) # prob.solve() import cvxpy as cp import numpy as np import cvxopt # create data P P = cp.Parameter(3,3) Z = cp.semidefinite(3) objective = cp.Minimize( cp.lambda_max(P) - cp.lambda_min(P - Z) ) prob = cp.Problem(objective, [Z >= 0]) P.value = cvxopt.matrix(np.matrix('4 1 3; 1 3.5 0.8; 3 0.8 1')) prob.solve() print "optimal value =", prob.value # [ 4, 1+2*j, 3-j ; ... # 1-2*j, 3.5, 0.8+2.3*j ; ... # 3+j, 0.8-2.3*j, 4 ]; # # % Construct and solve the model # n = size( P, 1 ); # cvx_begin sdp # variable Z(n,n) hermitian toeplitz # dual variable Q
minimize || Z - P ||_F subject to Z >= 0 Adapted from an example provided in the SeDuMi documentation and CVX examples. Unlike those examples, the data is real (not complex) and the result is only required to be PSD (instead of also Toeplitz) """ import cvxpy as cp import numpy as np import cvxopt # create data P P = cp.Parameter(3,3) Z = cp.SDPVar(3,3) objective = cp.Minimize( cp.lambda_max(P) - cp.lambda_min(P - Z) ) prob = cp.Problem(objective) P.value = cvxopt.matrix(np.matrix('4 1 3; 1 3.5 0.8; 3 0.8 1')) prob.solve() # [ 4, 1+2*j, 3-j ; ... # 1-2*j, 3.5, 0.8+2.3*j ; ... # 3+j, 0.8-2.3*j, 4 ]; # # % Construct and solve the model # n = size( P, 1 ); # cvx_begin sdp # variable Z(n,n) hermitian toeplitz # dual variable Q # minimize( norm( Z - P, 'fro' ) )
def main(args): system = System(args) control = Cmrac(system) x = system.reset() control.reset() data = Data() for i in range(args.ts.size): t = args.ts[i] u = control.get_inputs(t, x) # step next_x = system.step(t, x, u) # controller update current_data = control.update(t, x) data.append('time', t) data.append('state', x) data.append('input', u) [data.append(*item) for item in current_data.items()] x = next_x data.system = system data.control = control # Plot # plot_basis(data) # # SDP # N = cvx.Parameter(nonneg=True) # mineig = [] # for n in range(10, 21): # N.value = n # a = cvx.Variable(N.value, nonneg=True) # s = cvx.Variable(1, nonneg=True) # constr = [sum(a) == 5] # basis = np.array([system.unc.basis(state).tolist() # for state in data.state]) # expr = 0 # for ai, phi in zip(a, basis[:N.value]): # expr += phi[:, np.newaxis] * phi * ai # constr += [expr - s * np.eye(5) >> 0] # obj = cvx.Maximize(s) # prob = cvx.Problem(obj, constr) # prob.solve(solver=cvx.CVXOPT, verbose=True) # mineig.append(s.value) # SDP N = cvx.Parameter(nonneg=True) mineig = [] for n in range(10, 22): N.value = n a = cvx.Variable(N.value, nonneg=True) # s = cvx.Variable(1, nonneg=True) constr = [sum(a) == 5] basis = np.array( [system.unc.basis(state).tolist() for state in data.state]) expr = 0 for ai, phi in zip(a, basis[:N.value]): expr += phi[:, np.newaxis] * phi * ai # constr += [expr - s * np.eye(5) >> 0] obj = cvx.Maximize(cvx.lambda_min(expr)) prob = cvx.Problem(obj, constr) result = prob.solve(solver=cvx.CVXOPT, verbose=True) mineig.append(result) plt.figure() plt.plot(mineig) plt.show() return data
def solve_original_sdp(adj, qs): """ Original gain design formulation. Solved as SDP with CVXPY. See K. Fathian et al., "Robust 3D Distributed Formation Control with Collision Avoidance and Application to Multirotor Aerial Vehicles," ICRA'18 Parameters ---------- adj: nxn numpy array adjacency matrix encoding the sensing topology of swarm qs: nx3 numpy array desired positions (in R^3) of all the agents w.r.t the current agent's coordinate frame. Returns ------- A: 3nx3n numpy array symmetric nsd matrix with the last 5 or 6 (based on nullity) eigenvalues constrained to be zero. This gain matrix contains subblocks for each agent. """ n = np.shape(adj)[0] # Number of agents oneX = np.kron(np.ones(n), [1, 0, 0]) oneY = np.kron(np.ones(n), [0, 1, 0]) oneZ = np.kron(np.ones(n), [0, 0, 1]) # 90 deg rotation about z R = np.array([[0, -1, 0], [+1, 0, 0], [0, 0, +1]], dtype=np.float32) # Rotate 90 degrees about z-axis qsBar = np.zeros_like(qs) for i, vec in enumerate(qs): qsBar[i] = np.matmul(R, vec.T) # Project onto x-y plane qsp = np.copy(qs) qsp[:, 2] = 0 # formations that have the same z coordinate are "flat", which causes # a rank deficiency in N. We use 'nullity' to choose the appropriate # number of linearly independent columns of U (from svd of N). flat = (np.std(qs[:, 2]) <= 1e-2) nullity = 5 if flat else 6 # Kernel space N = np.vstack( (qs.flatten(), qsBar.flatten(), qsp.flatten(), oneX, oneY, oneZ)).T # Get orthogonal complement of kernel of A U, diag, Vh = np.linalg.svd(N) Q = U[:, nullity:3 * n] # Subspace constraints for given sensing topology S = 1 - np.kron(adj + np.eye(n), np.ones((3, 3))) # Solve via CVX A = cp.Variable((3 * n, 3 * n), symmetric=True) obj = cp.Maximize(cp.lambda_min(cp.matmul(Q.T, cp.matmul(A, Q)))) constraints = [ cp.matmul(A, N) == 0, # Kernel of A cp.multiply(A, S) == 0, # For agents that are not neighbors cp.norm(A) <= 10 ] for i in range(n): for j in range(n): if adj[i, j]: # If agents are neighbors constraints.append(A[3 * i, 3 * j] == A[3 * i + 1, 3 * j + 1]) constraints.append(A[3 * i, 3 * j + 1] == -A[3 * i + 1, 3 * j]) constraints.append(A[3 * i:3 * i + 2, 3 * j + 2] == 0) constraints.append(A[3 * i + 2, 3 * j:3 * j + 2] == 0) prob = cp.Problem(obj, constraints) prob.solve(eps=1e-6) if prob.status not in ["infeasible", "unbounded"]: Ar = -np.copy(A.value) # Make matrix negative semi-definite Ar /= np.max(np.abs(Ar)) # Scale matrix # Since we aren't very confident in our solver right now # (cvxpy seems to be choosing SCS to solve the SDP), # we will manually enforce symmetry of the gain matrix. Ar = 0.5 * (np.array(Ar) + np.array(Ar).T) else: Ar = None return Ar
def __sel_eigcut_by_ordering_on_measure(self, strat, vars_values, cut_round, sel_size=0): """Apply selection strategy to rank sub-problems (feasibility/ optimality/ combined/ exact/ random/ figure 8) """ nb_lifted, agg_list, Q, get_eigendecomp = self._nb_lifted, self._agg_list, self._Q, self._get_eigendecomp X_vals, x_vals = list(vars_values[0:nb_lifted]), list(vars_values[nb_lifted:]) rank_list = [0] * len(agg_list) feas_sel, opt_sel, exact_sel, comb_sel, rand_sel, figure_8 = \ (strat == 1), (strat == 2), (strat == 3), (strat == 4), (strat == 5), (strat == -1) # If optimality selection involved if opt_sel or comb_sel or exact_sel: nns = self._nns for agg_idx, (set_inds, Xarr_inds, Q_slice, max_elem) in enumerate(agg_list): dim_act = len(set_inds) curr_pt = itemgetter(*set_inds)(x_vals) X_slice = itemgetter(*Xarr_inds)(X_vals) obj_improve = - sum(map(mul, Q_slice, X_slice)) * max_elem # Optimality selection via neural networks (alone or combined with feasibility) if opt_sel or comb_sel: # Estimate objective improvement using neural network (after casting input to right ctype) obj_improve += nns[dim_act - 2][0](nns[dim_act - 2][1](*curr_pt, *Q_slice)) * max_elem # Combining opt + feas selection if comb_sel: # Check smallest eigenvalue for valid cuts eigval = get_eigendecomp(dim_act, curr_pt, X_slice, False)[0] if obj_improve > CutSolver._THRES_MIN_OPT: # strong cut if eigval < CutSolver._THRES_NEG_EIGVAL: # valid strong cut obj_improve += CutSolver._BIG_M else: # invalid cut obj_improve -= CutSolver._BIG_M else: # not strong but potentially valid cut obj_improve = -eigval # Optimality selection via exact SDP solution elif exact_sel: X_sdp = cvx.Variable(dim_act, dim_act) constr_sdp = [X_sdp[ids, ids] <= curr_pt[ids] for ids in range(dim_act)] + \ [cvx.lambda_min(cvx.hstack(cvx.vstack(1, np.array(curr_pt)), cvx.vstack(cvx.vec(np.array(curr_pt)).T, X_sdp))) >= 0] obj_sdp_coeffs = Q[np.array(set_inds), np.array([[Ind] for Ind in set_inds])] obj_sdp = cvx.Minimize(cvx.sum_entries(cvx.mul_elemwise(obj_sdp_coeffs, X_sdp))) prob = cvx.Problem(obj_sdp, constr_sdp) prob.solve(verbose=False, solver=cvx.MOSEK) if prob.status == 'optimal': obj_improve += obj_sdp.value else: print('Mosek error when solving a sub-problem!') obj_improve = - CutSolver._BIG_M rank_list[agg_idx] = (agg_idx, obj_improve, curr_pt, X_slice, Xarr_inds, Q_slice) # Order by expected objective improvement rank_list.sort(key=lambda tup: tup[1], reverse=True) # Random selection elif rand_sel: # random ordering shuffle with seed np.random.shuffle(agg_list) rank_list = agg_list # Feasibility (-only) selection elif feas_sel: rank_list = [] # Rank by eigenvalues (when negative) for agg_idx, (set_inds, Xarr_inds, _, _) in enumerate(agg_list): dim_act = len(set_inds) curr_pt = itemgetter(*set_inds)(x_vals) X_slice = itemgetter(*Xarr_inds)(X_vals) eigvals, evecs = get_eigendecomp(dim_act, curr_pt, X_slice, True) if eigvals[0] < CutSolver._THRES_NEG_EIGVAL: rank_list.append((-eigvals[0], evecs.T[0], set_inds, Xarr_inds, dim_act,agg_idx)) rank_list.sort(key=lambda tup: tup[0], reverse=True) #################### # Special separate case for Figure 8 # Comparison of exact vs estimated (neural net) measures for optimality cut selection #################### elif figure_8: exact_list, this_round_cuts, nb_cuts_sel_by_both = [], [], 0 nns = self._nns for agg_idx, (set_inds, Xarr_inds, Q_slice, max_elem) in enumerate(agg_list): dim_act = len(set_inds) curr_pt = itemgetter(*set_inds)(x_vals) X_slice = itemgetter(*Xarr_inds)(X_vals) curr_obj = sum(map(mul, Q_slice, X_slice)) * max_elem # optimality selection via estimated (neural network) ordering obj_improve = nns[dim_act - 2][0](nns[dim_act - 2][1](*(curr_pt + Q_slice))) * max_elem - curr_obj rank_list[agg_idx] = (agg_idx, obj_improve, curr_pt, X_slice, Xarr_inds, Q_slice) # optimality based exact ordering (for comparison) X_sdp = cvx.Variable(dim_act, dim_act) constr_sdp = [X_sdp[ids, ids] <= curr_pt[ids] for ids in range(dim_act)] + \ [cvx.lambda_min(cvx.hstack(cvx.vstack(1, np.array(curr_pt)), cvx.vstack(cvx.vec(np.array(curr_pt)).T, X_sdp))) >= 0] obj_sdp_coeffs = Q[np.array(set_inds), np.array([[Ind] for Ind in set_inds])] obj_sdp = cvx.Minimize(cvx.sum_entries(cvx.mul_elemwise(obj_sdp_coeffs, X_sdp))) prob = cvx.Problem(obj_sdp, constr_sdp) prob.solve(verbose=False, solver=cvx.MOSEK) if prob.status == 'optimal': obj_improve_exact = obj_sdp.value - curr_obj else: print('Mosek error when solving a sub-problem!') obj_improve_exact = - CutSolver._BIG_M exact_list.append((agg_idx, obj_improve_exact)) # Sort by estimated optimality measure rank_list.sort(key=lambda tup: tup[1], reverse=True) # Sort by exact optimality measure exact_list.sort(key=lambda tup: tup[1], reverse=True) for estim_idx, cut in enumerate(rank_list): cut_idx = cut[0] exact_idx = [elem[0] for elem in exact_list].index(cut_idx) sel_by_estim = 1 if estim_idx < sel_size else 0 # if cut is selected by estimated measure sel_by_exact = 1 if exact_idx < sel_size else 0 # if cut is selected by exact measure this_round_cuts.append([cut_round, cut_idx, sel_by_estim, sel_by_exact, cut[1], exact_list[exact_idx][1]]) if sel_by_estim and sel_by_exact: nb_cuts_sel_by_both += 1 return rank_list, nb_cuts_sel_by_both / sel_size, this_round_cuts return rank_list
def gen_sdp_surface_2d(Q, iters, pt_tan, savefile): """Generate the semidefinite surface/underestimator for semidefinite 2D sub-problems with given Q on a mesh with distance between points 1/(iters-1) and finds hyoperplane tangent to the SDP surface at tangent point pt_tan """ dim = 2 # 2x2 variable X holding the relaxed bilinear/quadratic terms. X = cvx.Variable(2, 2) x = cvx.Variable(2) # Create objective obj_expr = 0 for i in range(dim): for j in range(dim): obj_expr += Q[i, j] * X[i, j] obj = cvx.Minimize(obj_expr) # deviation from point pt_tan dev = 0.01 # Create 3 additional points around pt_tan to determine a hyperplane tangent to # the SDP surface at approximately pt_tan pts = [ pt_tan, [pt_tan[0] - dev, pt_tan[1] - dev], [pt_tan[0] - dev, pt_tan[1] + dev], [pt_tan[0] + math.sqrt(2 * pow(dev, 2)), pt_tan[1]] ] res_points = [] # Calculate for point of SDP surface for pt_tan and the 3 points around it determining hyperplane for i in range(0, dim + 2): pt = np.array(pts[i]) constraints = [ cvx.lambda_min( cvx.bmat([[1, *pt], [pt[0], X[0, :]], [pt[1], X[1, :]]])) >= 0, X[0, 0] <= pt[0], X[1, 1] <= pts[i][1] ] prob = cvx.Problem(obj, constraints) prob.solve(verbose=False, solver=cvx.MOSEK) res_points.append([*pts[i], obj_expr.value]) # Hyperplane equation calculations vectors = [[1, *([0] * dim)]] for i in range(2, dim + 2): vectors.append( [x - y for x, y in zip(res_points[i], res_points[i - 1])]) hp_sols = np.linalg.solve(np.array(vectors), vectors[0]) coeffs = [*np.ndarray.tolist(hp_sols), -np.dot(hp_sols, res_points[1])] # Separating the hyperplane obj_hp = obj_expr - (coeffs[0] * x[0] + coeffs[1] * x[1] + coeffs[dim + 1]) / (-coeffs[dim]) obj_sdp_hp = cvx.Minimize(obj_hp) constraints_hp = [ cvx.lambda_min(cvx.hstack(cvx.vstack(1, x), cvx.vstack(x.T, X))) >= 0, *[X[ids, ids] <= x[ids] for ids in range(0, dim)], x[0] >= 0, x[1] >= 0, x[0] <= 1, x[1] <= 1 ] prob = cvx.Problem(obj_sdp_hp, constraints_hp) prob.solve(verbose=False, solver=cvx.MOSEK) # Constant coordinate minus distance to hyperplane (bring out hyperplane till tangent) coeffs[dim + 1] += obj_hp.value * (-coeffs[dim]) # Determine points on SDP surface and on hyperplane tangent to it at pt_tan # on a mesh grid, with spaces in between them of 1/(iters-1) data_points = [] for i in range(1, iters + 1): for j in range(1, iters + 1): pt = [(i - 1) / float(iters - 1), (j - 1) / float(iters - 1)] obj_value = 0 for r in range(0, dim): for c in range(0, dim): obj_value += Q[r, c] * pt[r] * pt[c] # Mosek fails due to numerical error at pt=[0,0], but solution is obviously 0 if i == 1 and j == 1: hp_value = (np.dot(coeffs[0:dim], pt[0:dim]) + coeffs[dim + 1]) / (-coeffs[dim]) data_points.append([pt[0], pt[1], obj_value, hp_value, 0]) continue constraints = [ cvx.lambda_min( cvx.bmat([[1, *pt], [pt[0], X[0, :]], [pt[1], X[1, :]]])) >= 0, X[0, 0] <= pt[0], X[1, 1] <= pt[1] ] prob = cvx.Problem(obj, constraints) prob.solve(verbose=False, solver=cvx.MOSEK) # hyperplane value at pt hp_value = (np.dot(coeffs[0:dim], pt[0:dim]) + coeffs[dim + 1]) / (-coeffs[dim]) data_points.append( [pt[0], pt[1], obj_value, hp_value, obj_expr.value]) # save all data point in .csv file with open(savefile, "w") as f: for line in data_points: f.write(",".join(str(x) for x in line) + "\n")
def solve_random_inst_3d(nb_vars, nb_instances, savefile): """Calculates percent gap between M and S+M closed by M+S_3 for randomly generated (dense BoxQP) instances :param nb_vars: size of instances (number of unlifted variables x) :param nb_instances: number of problem instances to sample :param savefile: file to save results :return: None """ # variables for problems of dimension nb_vars X = cvx.Variable(nb_vars, nb_vars) x = cvx.Variable(nb_vars) # (M) McCormick constraints constraints_rlt = [] for i in range(nb_vars): constraints_rlt.extend([ X[i, i] <= x[i], X[i, i] >= 0, X[i, i] >= 2 * x[i] - 1, x[i] <= 1 ]) for j in range(i + 1, nb_vars): constraints_rlt.extend([ X[i, j] >= 0, X[i, j] >= x[i] + x[j] - 1, X[i, j] <= x[i], X[i, j] <= x[j], X[i, j] == X[j, i] ]) # (M+S) McCormick + full SDP constraint constraints_sdp = deepcopy(constraints_rlt) constraints_sdp.append( cvx.lambda_min(cvx.hstack(cvx.vstack(1, x), cvx.vstack(x.T, X))) >= 0) # (M+S_3) McCormick + 3D SDP constraints constraints_3d = deepcopy(constraints_rlt) for i in range(nb_vars): for j in range(i + 1, nb_vars): for k in range(j + 1, nb_vars): set_inds = [i, j, k] constraints_3d += \ [cvx.lambda_min(cvx.hstack( cvx.vstack(1, x[i], x[j], x[k]), cvx.vstack(cvx.hstack(x[i], x[j], x[k]), X[np.array(set_inds), np.array([[Ind] for Ind in set_inds])]))) >= 0] # generate random Q and therefore objectives for nb_instances problem instances and solve them for sample_nb in range(nb_instances): # generate random Q according to Table 1 in manuscript eigvecs = ortho_group.rvs(nb_vars) eigvals = np.random.uniform(-1, 1, nb_vars).tolist() Q = np.matmul(np.matmul(eigvecs, np.diag(eigvals)), np.transpose(eigvecs)) # Create objective obj_expr = 0 for i in range(0, nb_vars): for j in range(0, nb_vars): obj_expr += Q[i, j] * X[i, j] obj = cvx.Minimize(obj_expr) solution = [] for constraints in [constraints_sdp, constraints_3d, constraints_rlt]: prob = cvx.Problem(obj, constraints) prob.solve(verbose=False, solver=cvx.MOSEK) solution.append(obj.value) # Calculate the percent gap between M+S and M closed by M+S_3 if solution[0] - solution[2] <= 10e-5: percent_gap = 1 # if there is no gap, the percent closed is 1 else: percent_gap = (solution[1] - solution[2]) / (solution[0] - solution[2]) solution.append(min(1, percent_gap)) print("nb_vars=" + str(nb_vars) + ", sample_nb=" + str(sample_nb) + ", percent=" + str(solution[-1])) with open(savefile, "a") as f: f.write((str(nb_vars) + "," + str(sample_nb) + ",") + ",".join(str(x) for x in solution) + "\n")
n = 20 N = 1000 C = np.random.random_sample((n, n)) C = - C.dot(C.T) + 1000 * np.eye(n) # print(np.linalg.eigvals(C)) import cvxpy as cp mX = cp.Symmetric(n, n) constraints = [cp.lambda_min(mX) >= 0, cp.diag(mX) == 1] obj = cp.Maximize(cp.trace(C * mX)) maxcut = cp.Problem(obj, constraints).solve() print(maxcut) # print(mX.value) data = np.zeros(N) for i in range(N): X = np.matrix(np.random.randint(0, 2, n) * 2 - 1).T data[i] = X.T.dot(C).dot(X)[0][0] fig = plt.figure(figsize=[10, 5]) plt.plot(data, 'bo', markersize=1) plt.plot([maxcut], 'ro') plt.plot([maxcut for i in range(N)], 'ro', markersize=0.2) plt.show()