def synth_h2_state_feedback_LMI(A, Binput, Bdist, C1, D12): #Dullerud p 217 (?) n = A.shape[0] #num states m = Binput.shape[1] #num control inputs q = C1.shape[0] #num outputs to "be kept small" X = cvxpy.Variable(n,n) Y = cvxpy.Variable(m,n) Z = cvxpy.Variable(q,q) tmp1 = cvxpy.hstack(X, (C1*X+D12*Y).T) tmp2 = cvxpy.hstack((C1*X+D12*Y), Z) tmp = cvxpy.vstack(tmp1, tmp2) constraints = [A*X + Binput*Y + X*A.T + Y.T*Binput.T + Bdist*Bdist.T == -cvxpy.Semidef(n), tmp == cvxpy.Semidef(n+q), ] obj = cvxpy.Minimize(cvxpy.trace(Z)) prob = cvxpy.Problem(obj, constraints) prob.solve(solver='CVXOPT', kktsolver='robust') K = -Y.value*np.linalg.inv(X.value) return K
def sys_norm_h2_LMI(Acl, Bdisturbance, C): #doesn't work very well, if problem poorly scaled Riccati works better. #Dullerud p 210 n = Acl.shape[0] X = cvxpy.Semidef(n) Y = cvxpy.Semidef(n) constraints = [ Acl*X + X*Acl.T + Bdisturbance*Bdisturbance.T == -Y, ] obj = cvxpy.Minimize(cvxpy.trace(Y)) prob = cvxpy.Problem(obj, constraints) prob.solve() eps = 1e-16 if np.max(np.linalg.eigvals((-Acl*X - X*Acl.T - Bdisturbance*Bdisturbance.T).value)) > -eps: print('Acl*X + X*Acl.T +Bdisturbance*Bdisturbance.T is not neg def.') return np.Inf if np.min(np.linalg.eigvals(X.value)) < eps: print('X is not pos def.') return np.Inf return np.sqrt(np.trace(C*X.value*C.T))
def solve_sdp(G): """ Solves the SDP problem: maximize 1' * s subject to 0 <= s <= 1 [G, G - diag(s); G - diag(s), G] >= 0 """ G = np.asarray(G) assert G.ndim == 2 and G.shape[0] == G.shape[1] p = G.shape[0] # Define the problem. s = cvx.Variable(p) objective = cvx.Maximize(cvx.sum_entries(s)) constraints = [ 0 <= s, s <= 1, 2 * G - cvx.diag(s) == cvx.Semidef(p), ] prob = cvx.Problem(objective, constraints) # Solve the problem. prob.solve() assert prob.status == cvx.OPTIMAL # Return as array, not as matrix. return np.asarray(s.value).flatten()
def solve_spectral(prob, *args, **kwargs): """Solve the spectral relaxation with lambda = 1. """ # TODO: do this efficiently without SDP lifting # lifted variables and semidefinite constraint X = cvx.Semidef(prob.n + 1) W = prob.f0.homogeneous_form() rel_obj = cvx.Minimize(cvx.sum_entries(cvx.mul_elemwise(W, X))) W1 = sum([f.homogeneous_form() for f in prob.fs if f.relop == '<=']) W2 = sum([f.homogeneous_form() for f in prob.fs if f.relop == '==']) rel_prob = cvx.Problem( rel_obj, [ cvx.sum_entries(cvx.mul_elemwise(W1, X)) <= 0, cvx.sum_entries(cvx.mul_elemwise(W2, X)) == 0, X[-1, -1] == 1 ] ) rel_prob.solve(*args, **kwargs) if rel_prob.status not in [cvx.OPTIMAL, cvx.OPTIMAL_INACCURATE]: raise Exception("Relaxation problem status: %s" % rel_prob.status) (w, v) = LA.eig(X.value) return np.sqrt(np.max(w))*np.asarray(v[:-1, np.argmax(w)]).flatten(), rel_prob.value
def solve_sdr(prob, *args, **kwargs): """Solve the SDP relaxation. """ # lifted variables and semidefinite constraint X = cvx.Semidef(prob.n + 1) W = prob.f0.homogeneous_form() rel_obj = cvx.Minimize(cvx.sum_entries(cvx.mul_elemwise(W, X))) rel_constr = [X[-1, -1] == 1] for f in prob.fs: W = f.homogeneous_form() lhs = cvx.sum_entries(cvx.mul_elemwise(W, X)) if f.relop == '==': rel_constr.append(lhs == 0) else: rel_constr.append(lhs <= 0) rel_prob = cvx.Problem(rel_obj, rel_constr) rel_prob.solve(*args, **kwargs) if rel_prob.status not in [cvx.OPTIMAL, cvx.OPTIMAL_INACCURATE]: raise Exception("Relaxation problem status: %s" % rel_prob.status) return X.value, rel_prob.value
def sdp_partition(graph, constraints, k): if k != 2: raise Exception('SDP only applicable for 2 partitions') adjmat = nx.to_numpy_matrix(graph, weight='weight') n = nx.number_of_nodes(graph) Y = cvx.Semidef(n) obj = cvx.Maximize( cvx.sum_entries(cvx.mul_elemwise(np.tril(adjmat), (1 - Y)))) consts = [Y == Y.T] for i in range(n): consts.append(Y[i, i] == 1) for c1 in constraints.keys(): for c2 in constraints.keys(): if constraints[c1] != constraints[c2]: consts.append(Y[c1, c2] <= math.cos(2 * math.pi / k)) else: consts.append(Y[c1, c2] == 1) prob = cvx.Problem(obj, consts) prob.solve(solver='SCS') vecs = Y.value random_cut = sample_spherical(1, ndim=n) partition = {} signs = [] for i in range(n): signs.append(np.sign(np.dot(vecs[i, :], random_cut))) for con in constraints: for i in range(n): if signs[con] == signs[i]: partition[i] = constraints[con] return partition
def test_synthesis(A, B): sf = 10.0 # Problem data. N_u = B.shape[1] N_x = A.shape[0] Cv = np.eye(N_u) Avbar = cvxpy.Variable(rows=N_u, cols=N_u) Bvbar = cvxpy.Variable(rows=N_u, cols=N_x) P1 = cvxpy.Semidef(A.shape[0]) #,cols=A.shape[0]); # P2 = cvxpy.Semidef(N_u) #,cols=N_u); Zeros = cvxpy.Variable(rows=N_x + N_u + N_x + N_u, cols=N_x + N_u + N_x + N_u) # Construct the problem. objective = cvxpy.Minimize(cvxpy.norm1(Avbar) + cvxpy.norm1(Bvbar)) #+cvxpy.norm2(Bv)) #PMatrix = cvxpy.vstack([cvxpy.hstack([P1,np.zeros(N_x,N_u)]), cvxpy.hstack([np.zeros(( N_u,N_x )),P2]) ]); #QMatrix = cvxpy.vstack([cvxpy.hstack([A,np.matmul(B,Cv)]), cvxpy.hstack([Bv,Av]) ]); #SystemMatrix = cvxpy.vstack([cvxpy.hstack([PMatrix,QMatrix]),cvxpy.hstack([QMatrix,PMatrix])]) SystemMatrix1 = cvxpy.hstack([P1, np.zeros((N_x, N_u)), A.T * P1, Bvbar.T]) SystemMatrix2 = cvxpy.hstack( [np.zeros((N_u, N_x)), P2, np.matmul(Cv.T, B.T) * P1, Avbar]) SystemMatrix3 = cvxpy.hstack( [P1 * A, P1 * np.matmul(B, Cv), P1, np.zeros((N_x, N_u))]) SystemMatrix4 = cvxpy.hstack([Bvbar, Avbar, np.zeros((N_u, N_x)), P2]) SystemMatrix = cvxpy.vstack( [SystemMatrix1, SystemMatrix2, SystemMatrix3, SystemMatrix4]) constraints = [Zeros == 1e-10, Zeros << SystemMatrix, 0 < P1, 0 < P2] prob = cvxpy.Problem(objective, constraints) # The optimal objective is returned by prob.solve(). result = prob.solve(verbose=True, solver='SCS') return result, Avbar.value, Bvbar.value, Cv, P1.value, P2.value, SystemMatrix.value
def learn_with_similarity_label(self, data, label, mode, lam): """ Implement the metric learning algorithm in "Distance metric learning, with application to clustering with side-information" by Eric P. Xing, et al. The alg learns distance metrics from similarity labels of data pairs """ n_feature = data[0][0].shape[0] index_s = [i for i, x in enumerate(label) if x == 1] index_ns = [i for i, x in enumerate(label) if x == 0] X_s = [list(data[i][0] - data[i][1]) for i in index_s] X_ns = [list(data[i][0] - data[i][1]) for i in index_ns] # mode tells if the learned Mahalanobis distance metrics are specified by a diagonal matrix or a # fully-parametrized matrix if mode == "diag": x = cvx.Variable(rows=n_feature, cols=1) obj = 0 for i in range(len(X_s)): obj = obj + cvx.sum_entries(mul_elemwise(np.square(X_s[i]), x)) obj_neg = 0 for i in range(len(X_ns)): obj_neg = obj_neg + sqrt( cvx.sum_entries(cvx.mul_elemwise(np.square(X_ns[i]), x))) obj = obj - cvx.log(obj_neg) obj = obj + lam * norm(x, 1) constraints = [x >= 0] obj_cvx = cvx.Minimize(obj) prob = cvx.Problem(obj_cvx, constraints) prob.solve(solver=SCS) x_mat = np.diag(x.value.transpose().tolist()[0]) if prob.status == 'optimal' or prob.status == 'optimal_inaccurate': return prob.status, prob.value, x_mat else: return prob.status, np.nan, np.nan if mode == "full": lam = 1 A = cvx.Semidef(n_feature) obj = 0 for i in range(len(X_s)): obj = obj + cvx.quad_form(X_s[i], A) obj += lam * norm(A, 1) const = 0 for i in range(len(X_ns)): const = const + cvx.sqrt(cvx.quad_form(X_ns[i], A)) constraints = [const >= 1] obj_cvx = cvx.Minimize(obj) prob = cvx.Problem(obj_cvx, constraints) prob.solve(solver=MOSEK) if prob.status == 'optimal' or prob.status == 'optimal_inaccurate': return prob.status, prob.value, A.value else: return prob.status, np.nan, np.nan
def dilat_lvggm_ccg_cvx_sub(S, alpha, beta, covariance_h, precision_h, max_iter_in=1000, threshold_in=1e-3, verbose=False): ''' A cvx implementation of the Decayed-influence Latent variable Gaussian Graphial Model The subproblem in Convex-Concave Procedure min_{R} -log det(R) + trace(R*S_t) + alpha*||[1,0]*R*[1;0]||_1 + gamma*||[0, Theta]*R*[1;0]||_{1,2} s.t. [0,1]*R*[0;1] = Theta^{-1} R >= 0 S_t = [Cov(X), -Cov*B*Theta; -Theta*B'*Cov, beta I] ''' if np.linalg.norm(S-S.T) > 1e-3: raise ValueError("Covariance matrix should be symmetric.") n = S.shape[0] #n1 = covariance.shape[0] n2 = covariance_h.shape[0] n1 = n - n2 #if n != (n1+n2): if n1 < 0: raise ValueError("dimension mismatch n=%d, n1=%d, n2=%d" % (n,n1,n2)) mask = np.zeros((n,n)) mask[np.ix_(np.arange(n1), np.arange(n1))] J1 = np.zeros((n, n1)) J1[np.arange(n1),:] = np.eye(n1) J2 = np.zeros((n, n2)) J2[np.arange(n1,n), :] = np.eye(n2) Q = np.zeros((n,n2)) Q[np.arange(n1,n),:] = precision_h #Q = np.zeros((n, n1)) #Q[np.arange(n1),:] = -covariance J1 = np.asmatrix(J1) J2 = np.asmatrix(J2) Q = np.asmatrix(Q) S - np.asmatrix(S) R = cvx.Semidef(n) # define the SDP problem objective = cvx.Minimize(-cvx.log_det(R) + cvx.trace(S*R) + alpha*(cvx.norm((J1.T*R*J1), 1) + beta*cvx.mixed_norm((J1.T*R*Q).T, 2, 1) ))#beta*cvx.norm( (J1.T*R*Q), 1)) ) constraints = [J2.T*R*J2 == covariance_h] # solve the problem problem = cvx.Problem(objective, constraints) problem.solve(verbose = verbose) return np.asarray(R.value)
def _semidef_complex_as_real(dim): """Returns a cvxpy Semidefinite matrix and constraints for representing a complex hermitian non-neg. matrix represented as Z = X + iY <==> Z' = [X -Y; Y X] (*) :param dim: Dimension of the complex matrix :returns: cvxpy.Semidef(2 * dim), List of constaints ensuring the structure in (*) """ z = cvx.Semidef(2 * dim) return z, [z[:dim, :dim] == z[dim:, dim:], z[:dim, dim:] == -z[dim:, :dim]]
def sdp_mosek(omega, fmin): k_ = omega.shape[0] Y = [] C = [] C.append(np.zeros((k_, k_))) C[0][-1, -1] = 0 Y.append(cvx.Semidef(k_)) cost_sum = Y[0] * C[0] for i in range(1, k_): Y.append(cvx.Semidef(k_)) C.append(np.zeros((k_, k_))) C[i][-1, i - 1] = 1 / 2 C[i][i - 1, -1] = 1 / 2 C[i][-1, -1] = -fmin cost_sum += Y[i] * C[i] constraints = [sum(Y) == omega] objective = cvx.Minimize(cvx.trace(cost_sum)) prob = cvx.Problem(objective, constraints) opt_val = prob.solve(solver=cvx.MOSEK, verbose=0) # Assert a valid solution is returned assert (isinstance(opt_val, np.ndarray) or isinstance(opt_val, float))\ and np.isfinite(opt_val) M = -constraints[0].dual_value M = np.asarray((M + M.T) / 2) # From matrix to array Y_return = [] for y in Y: Y_return.append(np.asarray(y.value)) return opt_val, M, Y_return, C
def setUpClass(cls): cls.X = cvxpy.Semidef(3) cls.constraints = [] for i in range(3): cls.constraints += [cls.X[i, i] == 1] cls.constraints += [ cls.X[0, 1] >= -0.2, cls.X[0, 1] <= -0.1, cls.X[1, 2] >= 0.4, cls.X[1, 2] <= 0.5 ] cls.temp_folder = os.path.abspath("./temp") if not os.path.exists(cls.temp_folder): os.makedirs(cls.temp_folder)
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
def sdp_km(D, n_clusters): ones = np.ones((D.shape[0], 1)) Z = cp.Semidef(D.shape[0]) objective = cp.Maximize(cp.trace(D * Z)) constraints = [Z >= 0, Z * ones == ones, cp.trace(Z) == n_clusters] prob = cp.Problem(objective, constraints) prob.solve(solver=cp.SCS, verbose=False) Q = np.asarray(Z.value) rs = Q.sum(axis=1) print('Q', Q.min(), Q.max(), '|', rs.min(), rs.max(), '|', np.trace(Q), np.trace(D.dot(Q))) print('Final objective', np.trace(D.dot(Q))) return Q
def _solve_soft_bias_correction_cvxpy(UE, EUT, I, N, B, tuning): X = cvx.Semidef(N.shape[0], name='T') objective = (cvx.Minimize( cvx.sum_squares(EUT * (X - I) * UE) + cvx.quad_over_lin(N.T * X * B.T, tuning))) constraints = [X >> 0] prob = cvx.Problem(objective, constraints) print("Large constants:") for c in prob.constants(): try: print("\tConstant of size:", c.value.shape, type(c.value)) except AttributeError: pass prob.solve(solver=cvx.SCS, verbose=True, gpu=True) return X.value, prob.value
def getLargestInnerEllip(pt, maxChange=[None, None], Pold=None, optsIn={}): #Opts opts = {'conv': 1e-2} opts.update(optsIn) #There are faster ways to do this, but this is very convenient dim, Npt = pt.shape if Pold is None: Pval = np.identity(dim) else: Pval = Pold oldDet = 2 * det(Pval) #To avoid constant recreation of vars P = cvxpy.Semidef(pt.shape[0], "P") obj = cvxpy.Maximize(cvxpy.log_det(P)) while ((np.abs(oldDet - det(Pval)) / oldDet) > opts['conv']): oldDet = det(Pval) CpreTrans = chol(Pval).T CpreTransI = inv(CpreTrans) ptPre = ndot(CpreTrans, pt) normPtsq = colWiseSquaredNorm(ptPre) ptI = np.divide(ptPre, np.tile(normPtsq, (dim, 1))) #Adapt old PoldInvA = inv(ndot(CpreTransI.T, Pold, CpreTransI)) ptInM = np.max(colWiseSquaredKerNorm(PoldInvA, ptI)) PoldInvA = PoldInvA / ptInM #Solve PpreInv = smallestCircumScribedEllip(ptI, P=P, obj=obj, maxChange=maxChange, Pold=PoldInvA) Ppre = inv(PpreInv) Pval = ndot(CpreTrans.T, Ppre, CpreTrans) thisAlpha = ((det(Pval))**(1. / float(dim))) thisP = Pval / thisAlpha return [thisP, thisAlpha]
def pick_bundle(A, tau, dim): # varaible t = cvx.Variable() lamda = cvx.Variable() #constraint_matrix = cvx.Variable(dim + 1, dim + 1) constraint_matrix = cvx.Semidef(dim+1) I = np.eye(dim) # objective obj = cvx.Maximize(-t-lamda) # constraints constraints = [] for i in range(dim): for j in range(dim): constraints += [ constraint_matrix[i,j] == A[i,j] + lamda * I[i,j] ] for i in range(dim): constraints += [ constraint_matrix[i,dim] == 0] for j in range(dim): constraints += [ constraint_matrix[dim,j] == 0] constraints += [constraint_matrix[dim,dim] == t] # solve prob = cvx.Problem(obj, constraints) prob.solve() #print prob.status #print constraint_matrix #print "t = ", t.value #print "lambda = ", lamda.value if (prob.status == 'optimal'): print prob.value #print "length = ", len(constraints) #print "dual = ", constraints[len(constraints)-1].dual_value print "lambda = ", lamda.value # print "smallest eigen vector = " #A_prime = A+lamda.value*np.eye(dim) A_prime = A-prob.value print A_prime
def sos_to_sdp_min(syms, poly, z): deg = len(z) Q = cvx.Semidef(deg) q = cvx.vec(Q) gamma = cvx.Variable() A, b = construct_constraints_min(syms, poly, z) const_val = np.asscalar(b[-1]) - gamma A = A[:-1] b = b[:-1] constraints = [A * q == b, q[0] == const_val] obj = cvx.Maximize(gamma) prob = cvx.Problem(obj, constraints) opt_val = prob.solve(solver=cvx.SCS) Q = np.matrix(Q.value) return (prob.status, opt_val, Q)
def MVU(Y, Omega, p): """This is an implementation of Maximum Variance Unfolding using CVXPY; Args: Y - A m by n matrix of n data points in m dimensional space. Omega - A 0-1 matrix that encodes the distances to obsere. 1 for a distance to enforce and 0 for a free distance p - The dimension of the low dimensional space. Returns: XHat - .A p by n matrix of n data points in p dimensional space. """ assert isinstance(Y, np.matrix), 'Y must be a matrix' n = Y.shape[1] assert Omega.shape[0] == Omega.shape[0] == n, 'Omega wrong size' Sy = Y.T * Y K = cvxpy.Semidef(n) # We want to maximize the trace(K), and that is the same thing as # minimizing -trace(K). Note, trace(K) is affine, so both trace(K) # and -trace(K) are convex. objective = cvxpy.Minimize(-cvxpy.trace(K)) constraints = [] # constraints.append(cvxpy.sum_entries(K) == 0) for i in range(n): for j in range(n): if Omega[i, j] == 1: constraints.append(K[i, j] == Sy[i, j]) prob = cvxpy.Problem(objective, constraints) result = prob.solve(solver='SCS', eps=1e-6) U, E, UT = np.linalg.svd(np.matrix(K.value)) return np.diag(np.sqrt(E[:p])) * UT[:p, :]
def sdp_relaxation(Y, z, printing=False): """ SDP solver of the observation Y and ground truth z. """ if printing: print('Solving sdp relaxation problem...') n, _ = Y.shape X = cvx.Semidef(n) A = X * Y objective = cvx.Maximize(cvx.trace(A)) constraints = [cvx.diag(X) == 1] problem = cvx.Problem(objective, constraints) problem.solve() if printing: print('Status: ' + problem.status) print('Optimal value: \n', problem.value) print('Verifying optimality (dual value): \n', np.sum(constraints[0].dual_value)) print('Optimal X: \n', X.value) print('Optimal dual D (only diagonal entries): \n', constraints[0].dual_value) return problem.value, X, constraints[0].dual_value
def sdp_prob(): # {LP, SDP, SOCP} x = cp.Semidef(2) return cp.Problem(cp.Minimize(cp.norm(3 * x, 'fro')))
def ntf_fir_from_digested(order, osrs, H_inf, f0s, zf, **opts): """ Synthesize FIR NTF with minmax approach from predigested specification Version for the cvxpy_tinoco modeler. """ verbose = opts['show_progress'] if opts['cvxpy_opts']['solver'] == 'cvxopt': opts['cvxpy_opts']['solver'] = cvxpy.CVXOPT elif opts['cvxpy_opts']['solver'] == 'scs': opts['cvxpy_opts']['solver'] = cvxpy.SCS # State space representation of NTF A = np.matrix(np.eye(order, order, 1)) B = np.matrix(np.vstack((np.zeros((order-1, 1)), 1.))) # C contains the NTF coefficients D = np.matrix(1) # Set up the problem bands = len(f0s) c = cvxpy.Variable(1, order) F = [] gg = cvxpy.Variable(bands, 1) for idx in range(bands): f0 = f0s[idx] osr = osrs[idx] omega0 = 2*f0*np.pi Omega = 1./osr*np.pi P = cvxpy.Symmetric(order) Q = cvxpy.Semidef(order) if f0 == 0: # Lowpass modulator M1 = A.T*P*A+Q*A+A.T*Q-P-2*Q*np.cos(Omega) M2 = A.T*P*B + Q*B M3 = B.T*P*B - gg[idx, 0] M = cvxpy.bmat([[M1, M2, c.T], [M2.T, M3, D], [c, D, -1]]) F += [M << 0] if zf: # Force a zero at DC F += [cvxpy.sum_entries(c) == -1] else: # Bandpass modulator M1r = (A.T*P*A + Q*A*np.cos(omega0) + A.T*Q*np.cos(omega0) - P - 2*Q*np.cos(Omega)) M2r = A.T*P*B + Q*B*np.cos(omega0) M3r = B.T*P*B - gg[idx, 0] M1i = A.T*Q*np.sin(omega0) - Q*A*np.sin(omega0) M21i = -Q*B*np.sin(omega0) M22i = B.T*Q*np.sin(omega0) Mr = cvxpy.bmat([[M1r, M2r, c.T], [M2r.T, M3r, D], [c, D, -1]]) Mi = cvxpy.bmat([[M1i, M21i, np.zeros((order, 1))], [M22i, 0, 0], [np.zeros((1, order)), 0, 0]]) M = cvxpy.bmat([[Mr, Mi], [-Mi, Mr]]) F += [M << 0] if zf: # Force a zero at z=np.exp(1j*omega0) nn = np.arange(order).reshape((order, 1)) vr = np.matrix(np.cos(omega0*nn)) vi = np.matrix(np.sin(omega0*nn)) vn = np.matrix( [-np.cos(omega0*order), -np.sin(omega0*order)]) F += [c*cvxpy.hstack(vr, vi) == vn] if H_inf < np.inf: # Enforce the Lee constraint R = cvxpy.Semidef(order) MM = cvxpy.bmat([[A.T*R*A-R, A.T*R*B, c.T], [B.T*R*A, -H_inf**2+B.T*R*B, D], [c, D, -1]]) F += [MM << 0] target = cvxpy.Minimize(cvxpy.max_entries(gg)) p = cvxpy.Problem(target, F) p.solve(verbose=verbose, **opts['cvxpy_opts']) return np.hstack((1, np.asarray(c.value)[0, ::-1]))
def sls_common_lyapunov(A, B, Q, R, eps_A, eps_B, tau, logger=None): """ Solves the common Lyapunov relaxation to the robust synthesis problem. Taken from lstd-lqr/blob/master/code/policy_iteration.ipynb learning-lqr/experiments/matlab/sls_synth_yalmip/common_lyap_synth_var2_alpha.m """ if logger is None: logger = logging.getLogger(__name__) d, p = B.shape X = cvx.Symmetric(d) # inverse Lyapunov function Z = cvx.Variable(p, d) # -K*X W_11 = cvx.Symmetric(d) W_12 = cvx.Variable(d, p) W_22 = cvx.Symmetric(p) alph = cvx.Variable() # scalar for tuning the H_inf constraint constraints = [] # H2 cost: trace(W)=H2 cost mat1 = cvx.bmat([[X, X, Z.T], [X, W_11, W_12], [Z, W_12.T, W_22]]) constraints.append(mat1 == cvx.Semidef(2 * d + p)) # H_infinity constraint mat2 = cvx.bmat( [[X - np.eye(d), (A * X + B * Z), np.zeros((d, d)), np.zeros((d, p))], [(X * A.T + Z.T * B.T), X, eps_A * X, eps_B * Z.T], [ np.zeros((d, d)), eps_A * X, alph * (tau**2) * np.eye(d), np.zeros((d, p)) ], [ np.zeros((p, d)), eps_B * Z, np.zeros((p, d)), (1 - alph) * (tau**2) * np.eye(p) ]]) constraints.append(mat2 == cvx.Semidef(3 * d + p)) # constrain alpha to be in [0,1]: constraints.append(alph >= 0) constraints.append(alph <= 1) # Solve! objective = cvx.Minimize(cvx.trace(Q * W_11) + cvx.trace(R * W_22)) prob = cvx.Problem(objective, constraints) try: obj = prob.solve(solver=cvx.MOSEK) except cvx.SolverError: logger.warn("SolverError encountered") return (False, None, None, None) if prob.status == cvx.OPTIMAL: logging.debug("common_lyapunov: found optimal solution") X_value = np.array(X.value) P_value = scipy.linalg.solve(X_value, np.eye(d), sym_pos=True) # NOTE: the K returned here is meant to be used # as A + BK **NOT** A - BK K_value = np.array(Z.value).dot(P_value) return (True, obj, P_value, K_value) else: logging.debug("common_lyapunov: could not solve (status={})".format( prob.status)) return (False, None, None, None)
# compute log loss loss = 0. for q in S: i, j, k = q # should this be Mt^T * K?? Mt = (2. * np.outer(X[i], X[j]) - 2. * np.outer(X[i], X[k]) - np.outer(X[j], X[j]) + np.outer(X[k], X[k])) score = cvx.trace(Mt.T * K) loss = loss + cvx.logistic(-score) # regularize with the 1,2 norm loss = loss / len(S) + lam * cvx.mixed_norm(K, 2, 1) return loss # create L1 problem K = cvx.Semidef(p) objectiveL1 = cvx.Minimize(costL1(K, X, S, lam1)) probL1 = cvx.Problem(objectiveL1) # solve the L1 problemLasso method: print("Beginning test with L_1") ts = time() probL1.solve(verbose=True) tot_time = time() - ts Khat_L1 = np.array(K.value) emp_loss, log_loss = lossK(Khat_L1, X, S) print("L_1 regularization: Time=%f, emp_loss=%f, log_loss=%f" % (tot_time, emp_loss, log_loss)) # create L_{1,2} problem K = cvx.Semidef(p)
def calculateEmbeddingMatrix( D, verbose=False, target_dist=1.1, jlt_tries=30 ): assert isMetricSpaceMatrix(D) n = D.shape[0] if int(cvx.__version__.split(".")[0]) == 0: Q = cvx.Semidef(n) d = cvx.NonNegative() else: Q = cvx.Variable(shape=(n, n), PSD=True) d = cvx.Variable(shape=(1, 1), nonneg=True) # print(D) # c = matrix(([1]*n)) log.debug("Generating constraints for embedding:") log.debug(f"Distance matrix: {D}") constraints = [] for i in range(n): for j in range(i, n): constraints += [D[i, j] ** 2 <= Q[i, i] + Q[j, j] - 2 * Q[i, j]] constraints += [ Q[i, i] + Q[j, j] - 2 * Q[i, j] <= d * D[i, j] ** 2 ] log.debug( f"adding constraint: {D[i,j]}**2 <= Q{[i,i]} + Q{[j,j]} - 2*Q{[i,j]}" ) log.debug( f"adding constraint: Q{[i,i]} + Q{[j,j]} - 2*Q{[i,j]} <= d * {D[i,j]}**2 " ) obj = cvx.Minimize(d) prob = cvx.Problem(obj, constraints) solvers = cvx.installed_solvers() if "MOSEK" in solvers: log.info("Solving problem with MOSEK solver") prob.solve(solver=cvx.MOSEK, verbose=verbose) elif "CVXOPT" in solvers: prob.solve( solver=cvx.CVXOPT, kktsolver=cvx.ROBUST_KKTSOLVER, verbose=verbose, ) log.info("Solving problem with CVXOPT solver") else: prob.solve(verbose=verbose) log.warning( "CVXOPT not installed. Solving problem with default solver." ) if prob.status != cvx.OPTIMAL: log.warning( "embedding optimization status non-optimal: " + str(prob.status) ) return None, None # print(Q.value) # print(np.linalg.eigvals(np.matrix(Q.value))) # print(np.linalg.eigh(np.matrix(Q.value))) # print(type(np.matrix(Q.value))) # print(np.matrix(Q.value)) try: L = np.linalg.cholesky(np.array(Q.value)) except np.linalg.LinAlgError: eigenvals, eigenvecs = np.linalg.eigh(np.array(Q.value)) min_eigenv = min(eigenvals) if min_eigenv < 0: log.warning( "Warning, matrix not positive semidefinite." + "Trying to correct for numerical errors with minimal eigenvalue: " + str(min_eigenv) + " (max. eigenvalue:" + str(max(eigenvals)) + ")." ) Q_new_t = ( np.transpose(eigenvecs) @ np.array(Q.value) @ eigenvecs ) # print(eigenvals) # print(Q_new_t) # should be = diagonal(eigenvalues) # print(np.transpose(eigenvecs) * eigenvecs) # should be = Identity matrix Q_new_t += np.diag([-min_eigenv] * len(eigenvals)) Q_new = eigenvecs @ Q_new_t @ np.transpose(eigenvecs) L = np.linalg.cholesky(Q_new) log.debug(f"Shape of lower-triangular matrix L: {L.shape}") lowerdim, d = jlt_search(D, L, target_dist, num_tries=jlt_tries) # print(lowerdim) # return L,d.value return lowerdim, d
def forward_single_d_cvx_Filter(Q, q, G, h, A, b, d, epsilon, xi, delta, T, p=None, sol_opt=cp.CVXOPT, verbose=False): """ This function processes the SDP :param Q: :param q: :param G: :param h: :param A: :param b: :param xi: :param d: :param epsilon: :param delta: :param T: :param p: :param sol_opt: :param verbose: :return: """ nz, neq, nineq = q.shape[0], A.shape[0] if A is not None else 0, G.shape[0] if p.shape == (T,): p = np.expand_dims(p, 1) # convert the price into a column vector if d.shape == (T,): d = np.expand_dims(d, 1) if verbose: print("\n inside the cvx np filter :", T, nz ) print([part.shape for part in [Q, q, G, h, A, b]]) x_ = cp.Variable(nz) GAMMA = cp.Semidef(T) # assert T == nz / 3 # print("x size {}, num of ineq {}".format(x_.size, nineq)) term1 = GAMMA * epsilon + d obj = cp.Minimize(0.5 * cp.quad_form(x_, Q) + q.T * x_ + p.T * cp.pos(term1) + cp.pos(cp.norm(GAMMA, "nuc") - xi ) ) eqCon = A * x_ == b if neq > 0 else None soc_ineqCon = [cp.norm(GAMMA[:, i], 2) <= (d[i, 0] / abs(ut.function_normal_cdf_inv(delta))) for i in range(T)] # ut.function_normal_cdf_inv(delta) # eqCon_sdp = None # convert the SDP constraint in the objective, # eqCon_sdp = cp.norm(GAMMA, "nuc") == xi if nineq > 0: slacks = cp.Variable(nineq) # define slack variables ineqCon = G * x_ + slacks == h slacksCon = slacks >= 0 else: ineqCon = slacks = slacksCon = None cons_collected = [eqCon, ineqCon] + soc_ineqCon + [slacksCon] cons = [constraint for constraint in cons_collected if constraint is not None] prob = cp.Problem(obj, cons) # ------------------------------ # calculate time # ------------------------------ # start = time.perf_counter() if sol_opt == cp.MOSEK: # mosek params: https://docs.mosek.com/9.0/javafusion/parameters.html mosek_param_setting = {"MSK_DPAR_BASIS_TOL_X": 1e-4, "MSK_DPAR_BASIS_TOL_S": 1e-5, "MSK_DPAR_INTPNT_CO_TOL_DFEAS": 1e-5, "MSK_DPAR_INTPNT_CO_TOL_MU_RED": 1e-5, "MSK_DPAR_INTPNT_TOL_INFEAS": 1e-5, "MSK_DPAR_INTPNT_CO_TOL_PFEAS": 1e-5, "MSK_DPAR_INTPNT_CO_TOL_REL_GAP": 1e-5} # The first 5 items might be not important, we discovered that # most relavent metrics is 'MSK_DPAR_INTPNT_CO_TOL_PFEAS' and 'MSK_DPAR_INTPNT_CO_TOL_REL_GAP' prob.solve(solver=sol_opt, verbose=verbose, mosek_params=mosek_param_setting) # solver=cp.SCS, max_iters=5000, verbose=False) else: prob.solve(solver=sol_opt, verbose=verbose) # e.g. prob.solve(solver=cp.SCS, max_iters=10000, verbose=True) assert ('optimal' in prob.status) # end = time.perf_counter() # print("[CVX - %s] Compute solution : %.4f s." % (sol_opt, end - start)) xhat = np.array(x_.value).ravel() GAMMA_hat = np.array(GAMMA.value) lam = np.array(eqCon.dual_value).ravel() if eqCon is not None else None # lam_socp = np.array(soc_ineqCon.dual_value).ravel() if soc_ineqCon is not None else None if ineqCon is not None: mu = np.array(ineqCon.dual_value).ravel() slacks = np.array(slacks.value).ravel() else: mu = slacks = None # return prob.value, xhat, GAMMA_hat, lam, lam_socp, mu, slacks return prob.value, xhat, GAMMA_hat, lam, mu, slacks
def N4SID(u, y, NumRows, NumCols, NSig, require_stable=False): """ A,B,C,D,Cov,Sigma = N4SID(u,y,NumRows,NumCols,n,require_stable=False) Let NumVals be the number of input and output values available In this case: u - NumInputs x NumVals array of inputs y - NumOutputs x NumVals array of outputs NumRows - Number of block rows in the past and future block Hankel matrices NumCols - Number of columns in the past and future block Hankel matrices n - desired state dimension. For the algorithm to work, you must have: NumVals >= 2*NumRows + NumCols - 1 Returns A,B,C,D - the state space realization from inputs to outputs Cov - the joint covariance of the process and measurement noise Sigma - the singular values of the oblique projection of row space of future outputs along row space of future inputs on the row space of past inputs and outputs. Examining Sigma can be used to determine the required state dimension require_stable - An optional boolean parameter. Default is False If False, the standard N4SID algorithm is used If True, the state matrix, A, will have spectral radius < 1. In order to run with require_stable=True, cvxpy must be installed. """ NumInputs = u.shape[0] NumOutputs = y.shape[0] NumDict = { 'Inputs': NumInputs, 'Outputs': NumOutputs, 'Dimension': NSig, 'Rows': NumRows, 'Columns': NumCols } GammaDict, S = preProcess(u, y, NumDict) GamData = GammaDict['Data'] GamYData = GammaDict['DataY'] if not require_stable: K = la.lstsq(GamData.T, GamYData.T)[0].T else: Kvar = cvx.Variable(NSig + NumOutputs, NSig + NumInputs * NumRows) Avar = Kvar[:NSig, :NSig] Pvar = cvx.Semidef(NSig) LyapCheck = cvx.vstack(cvx.hstack(Pvar, Avar), cvx.hstack(Avar.T, np.eye(NSig))) Constraints = [LyapCheck >> 0, Pvar << np.eye(NSig)] diffVar = GamYData - Kvar * GamData objFun = cvx.norm(diffVar, 'fro') Objective = cvx.Minimize(objFun) Prob = cvx.Problem(Objective, Constraints) result = Prob.solve() K = Kvar.value AID, BID, CID, DID, CovID = postProcess(K, GammaDict, NumDict) return AID, BID, CID, DID, CovID, S
def latent_variable_gmm_cvx(X_o, alpha=1, lambda_s=1, S_init=None, verbose=False): ''' A cvx implementation of the Latent Variable Gaussian Graphical Model see review of "Venkat Chandrasekaran, Pablo A Parrilo, and Alan S Willsky. Latent variable graphical model selection via convex optimization. The Annals of Statistics, 40(4):1935–1967, 2012." min_{S, L} -log det (S-L) + trace(emp_Cov*(S-L)) + alpha*lambda_s*\|S\|_{1} + alpha*\|L\|_{*} s.t. S-L \succeq 0 L \succeq 0 return S, L ''' n, m = X_o.shape emp_cov = np.cov(X_o) if alpha == 0: if return_costs: precision = np.linalg.pinv(emp_cov) cost = -2. * log_likelihood(emp_cov, precision) cost += n_features * np.log(2 * np.pi) d_gap = np.sum(emp_cov * precision) - n return emp_cov, precision, (cost, d_gap) else: return emp_cov, np.linalg.pinv(emp_cov) costs = list() if S_init is None: covariance_o = emp_cov.copy() else: covariance_o = S_init.copy() # As a trivial regularization (Tikhonov like), we scale down the # off-diagonal coefficients of our starting point: This is needed, as # in the cross-validation the cov_init can easily be # ill-conditioned, and the CV loop blows. Beside, this takes # conservative stand-point on the initial conditions, and it tends to # make the convergence go faster. covariance_o *= 0.95 diagonal_o = emp_cov.flat[::n + 1] covariance_o.flat[::n + 1] = diagonal_o # define the low-rank term L and sparse term S L = cvx.Semidef(n) S = cvx.Symmetric(n) # define the SDP problem objective = cvx.Minimize(-cvx.log_det(S - L) + cvx.trace(covariance_o * (S - L)) + alpha * lambda_s * cvx.norm(S, 1) + alpha * cvx.norm(L, "nuc")) constraints = [S - L >> 0] # solve the problem problem = cvx.Problem(objective, constraints) problem.solve(verbose=verbose) return (S.value, L.value)
# Set the values of the relevant matrices in the LMI A_hat.value = np.array([[1, alpha.value - 1], [0, 0]]) B_hat.value = np.array([[alpha.value, -1], [0, -1]]) C1_hat.value = np.array([[-1, -1], [0, 0]]) C2_hat.value = np.array([[1, alpha.value - 1], [0, 0]]) D1_hat.value = np.array([[-1, 0], [1, 0]]) D2_hat.value = np.array([[alpha.value, -1], [0, 1]]) M1.value = np.array([[ -2 * rho0.value**-2, 1.0 / rho0.value * (kappa.value**-0.5 + kappa.value**0.5) ], [1. / rho0.value * (kappa.value**-0.5 + kappa.value**0.5), -2]]) M2.value = np.array([[0, 1], [1, 0]]) zeros.value = np.zeros((2, 2)) # Variables P = cvx.Semidef(2) lam1 = cvx.Variable() lam2 = cvx.Variable() # Create the (constant) objective function obj = cvx.Minimize(c) # Create the matrices for the LMI mat1 = cvx.bmat([[A_hat.T * P * A_hat - tau**2 * P, A_hat.T * P * B_hat], [B_hat.T * P * A_hat, B_hat.T * P * B_hat]]) mat2 = cvx.bmat([[C1_hat, D1_hat], [C2_hat, D2_hat]]) mat3 = cvx.bmat([[lam1 * M1, zeros], [zeros, lam2 * M2]]) # Create the constraints: LMI, lambda1 and lambda 2 non-negative, P positive definite constraints = [mat1 + mat2 * mat3 * mat2 << 0, lam1 >= 0, lam2 >= 0, P >> 1e-9]
# print('\ntime elapsed=', time.time()-tt) # exec(open('file.py').read()) # newArray = np.array([[0,1,2], [3,4,5], [6,7,8]]) # sliceArray = PTl[np.asmatrix([1,3,5]).T, [1,3,5]] # pl.figure(figsize=(6, 6)) # fig = pl.figure() # ax = fig.gca(projection='3d') # ax.plot(xs=p.value[0,:].A1,ys=p.value[1,:].A1,zs=p.value[2,:].A1) # legend(loc='upper center', bbox_to_anchor=(0.5, 1.05), prop={'size': 18}) # print(dir(ct)) # raise Exception('exit') # print(cv.installed_solvers()) import quad_metric_data as ct P = cv.Semidef(ct.n) # cv.Variable(ct.n, ct.n) # slower def OBJ(X, Y, n_, N, d_, P): U = cv.Parameter(n_, N) # *X.shape UUT = cv.Parameter(n_, n_) dd = cv.Parameter(N, sign="positive") # THIS AFFECTS CONVEXITY!!!!!! # DIDN'T KNOW UNTIL ACCIDENTALLY MADE dd A PARAMETER U.value = X - Y UUT.value = np.dot(X - Y, (X - Y).T) dd.value = d_ term1 = sum(d_**2) # term2 = sum([dd[i]*cv.sqrt(cv.quad_form(U[:, i], P)) for i in range(N)])