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 create_opt_vars(self, large_gamma=False, large_t=False): # init gamma from abs(N(0,1)) if large_gamma: gamma = cp.Variable((self.in_numel, self.in_numel), name='gamma') else: gamma = cp.Variable((self.in_numel,), name='gamma') self.constraints.append((gamma >= 0.)) s = cp.Variable(name='s') if large_t: lbda_n = sum(self.shapes[1:-1]) lbda_vec = cp.Variable((lbda_n,), name='lbda_vec') lbda_mat = cp.Variable((lbda_n, lbda_n), name='lbda_mat', symmetric=True) self.constraints.append((lbda_mat >= 0.)) lbda_mat_masked = cp.multiply((- np.ones((lbda_n, lbda_n)) + np.eye(lbda_n)), lbda_mat) lbda_mat_diag = cp.hstack([- cp.sum(lbda_mat_masked[i, i+1:]) for i in range(lbda_n)]) lbdas = cp.diag(lbda_vec) + lbda_mat_masked + cp.diag(lbda_mat_diag) else: lbdas = list() nus = list() etas = list() for i in range(1, len(self.shapes) - 1): if not large_t: now_lbda = cp.Variable((self.shapes[i],), name=f'lbda_{i}') now_nu = cp.Variable((self.shapes[i],), name=f'nu_{i}') now_eta = cp.Variable((self.shapes[i],), name=f'eta_{i}') if not large_t: self.constraints.append((now_lbda >= 0.)) self.constraints.append((now_nu >= 0.)) self.constraints.append((now_eta >= 0.)) if not large_t: lbdas.append(now_lbda) nus.append(now_nu) etas.append(now_eta) self.gamma = gamma self.lbdas = lbdas self.nus = nus self.etas = etas self.s = s
def solve_g_dual_cp(C, a, b, eta, tau): u = cp.Variable(shape=a.shape) v = cp.Variable(shape=b.shape) u_stack = cp.vstack([u.T for _ in range(nr)]) v_stack = cp.hstack([v for _ in range(nc)]) print(u_stack.shape, v_stack.shape) # obj = eta * cp.sum(cp.multiply(cp.exp(u + v.T) * cp.exp(v).T, 1 / cp.exp(C))) # obj = eta * cp.sum(cp.multiply(cp.exp(u_stack + v_stack), 1 / cp.exp(C))) obj = eta * cp.sum(cp.exp((u_stack + v_stack - C) / eta)) obj += tau * cp.sum(cp.multiply(cp.exp(-u / tau), a)) obj += tau * cp.sum(cp.multiply(cp.exp(-v / tau), b)) prob = cp.Problem(cp.Minimize(obj)) prob.solve() return prob.value, u.value, v.value
def _obtain_r_tilde(self, r_cs_param): ''' This function handles the smoothness and periodicity constraints when the data set is less than a year long. It operates by filling out the rest of the year with blank variables, which are subsequently dropped after the problem is solved. :param r_cs_param: the right matrix CVX variable :return: A cvx variable with second dimension at least 367 ''' if r_cs_param.shape[1] < 365 + 2: n_tilde = 365 + 2 - r_cs_param.shape[1] r_tilde = cvx.hstack( [r_cs_param, cvx.Variable(shape=(self._rank_k, n_tilde))]) else: r_tilde = r_cs_param return r_tilde
def solve(Q, C, D): q1 = cp.Variable(1) c = cp.Variable(T) q = cp.hstack([q1, cp.cumsum(c)[:-1]]) constraints = [ q <= Q, q >= 0, c <= C, c >= -D, q[-1] + c[-1] == q[0], u + c >= 0, ] obj = cp.Minimize(p @ (u + c)) problem = cp.Problem(obj, constraints) problem.solve() return q.value, c.value, problem.value
def sdp(D): lam = 1 n = D.shape[0] G = cp.Variable((n, n), symmetric=True) eta = cp.Variable((n, n)) constraints = [G >> 0] constraints += [eta[i, j] >= 0 for i in range(n) for j in range(n)] reg = lam * cp.norm(eta, p=1) Gii = cp.diag(G) hstacked = cp.hstack([cp.reshape(Gii, (n, 1)) for i in range(n)]) vstacked = cp.vstack([cp.reshape(Gii, (1, n)) for i in range(n)]) obj = reg + 0.5 * cp.sum((hstacked + vstacked - 2 * G + eta - D**2)**2) prob = cp.Problem(cp.Minimize(obj), constraints) prob.solve(verbose=False) U, S, V = np.linalg.svd(G.value) u, s = np.real(U), np.real(S) dim = 3 Xtag = np.dot(u, np.diag(np.sqrt(s)))[:,0:dim] return Xtag
def test_paper_example_logreg_is_dpp(self): N, n = 3, 2 beta = cp.Variable((n, 1)) b = cp.Variable((1, 1)) X = cp.Parameter((N, n)) Y = np.ones((N, 1)) lambd1 = cp.Parameter(nonneg=True) lambd2 = cp.Parameter(nonneg=True) log_likelihood = (1. / N) * cp.sum( cp.multiply(Y, X @ beta + b) - cp.log_sum_exp(cp.hstack([np.zeros((N, 1)), X @ beta + b]).T, axis=0, keepdims=True).T) regularization = -lambd1 * cp.norm(beta, 1) - lambd2 * cp.sum_squares(beta) problem = cp.Problem(cp.Maximize(log_likelihood + regularization)) self.assertTrue(log_likelihood.is_dpp()) self.assertTrue(problem.is_dcp()) self.assertTrue(problem.is_dpp())
def _optimize(self, A, disk, M): n = A.shape[0] print(n) constraints = [] X = cp.Variable(shape=(n, n), boolean=True) Y = cp.Variable(shape=(n, n), boolean=True) Z = cp.Variable(shape=n, boolean=True) W = cp.Variable(shape=(n, n), boolean=True) zero_v = np.zeros((n, 1)) one_v = np.ones((n, 1)) I = np.identity(n) Z_vec = cp.reshape(Z, (n, 1)) # W constraints Y_prev = cp.hstack([zero_v, Y[:, :n - 1]]) Y_prev_not = np.ones((n, n)) - Y_prev constraints.append(np.zeros((n, n)) <= Y + Y_prev_not - 2 * W) constraints.append(np.ones((n, n)) >= Y + Y_prev_not - 2 * W) # permutation constraints constraints.append(cp.sum(X, axis=1) == np.ones(n)) constraints.append(cp.sum(X, axis=0) == np.ones(n)) # cache limit constraints for i in range(n): constraints.append(cp.sum(Y[:, i]) <= M) # cache limit constraints.append(cp.sum(X[:, :(i + 1)], axis=1) >= Y[:, i]) # previous cache comparison constraints.append( W[:, i] <= X[:, i] + Z) # new cache elements must be less than disk + new elements constraints.append(W[:, i] >= X[:, i]) constraints.append(Y[:, i:i + 1] >= (A + I) @ X[:, i:i + 1]) # adjacency constraint constraints.append(cp.sum(Y[:, i] - Y_prev[:, i]) >= 0) # can only maintain or increase cache size obj = cp.Minimize(cp.sum(Z) + cp.sum(W) - cp.sum(X)) prob = cp.Problem(obj, constraints) prob.solve(solver=cp.GUROBI, verbose=True, Threads=state.NUM_THREADS) assert (prob.status in [cp.OPTIMAL, cp.OPTIMAL_INACCURATE]) return X.value, prob.value
def calc_Koopman(Yf, Yp, flag=1): solver_instance = cvxpy.CVXOPT #solver_instance = cvxpy.ECOS; if flag == 1: # moore penrose inverse, plain ol' least squares Koopman #Yp_inv = np.dot(np.transpose(Yp_final), np.linalg.inv( np.dot(Yp_final,np.transpose(Yp_final)) ) ); Yp_inv = np.linalg.pinv(Yp) K = np.dot(Yf, Yp_inv) if flag == 2: # cvx optimization approach - L2 + L1 lasso norm1_term = 0.0 all_col_handles = [None] * Yf.shape[0] for i in range(0, Yf.shape[0]): all_col_handles[i] = Variable(Yf.shape[0], 1) norm1_term = norm1_term + norm2(all_col_handles[i]) operator = all_col_handles[0] for i in range(1, Yf.shape[0]): operator = cvxpy.hstack(operator, all_col_handles[i]) print "[INFO]: CVXPY Koopman operator variable: " + repr(operator) print "[INFO]: Yf.shape in calc_Koopman: " + repr(Yf.shape) norm2_fit_term = norm2(norm2(Yf - operator * Yp, axis=0)) objective = Minimize(norm2_fit_term + norm1_term) constraints = [] prob = Problem(objective, constraints) result = prob.solve(verbose=True, solver=solver_instance) print "[INFO]: Finished executing cvx solver, printing CVXPY problem status" print(prob.status) K = operator.value if flag == 3: operator = Variable(Yf.shape[0], Yf.shape[0]) objective = Minimize(cvxpynorm(operator, 2)) constraints = [ cvxpynorm(Yf - operator * Yp, 'fro') / cvxpynorm(Yf, 'fro') < 0.01 ] prob = Problem(objective, constraints) result = prob.solve(verbose=True) #(solver=solver_instance); print(prob.status) K = operator.value return K
def test_problem_penalty(self): """ Compare cvxpy solutions to cvxopt ground truth """ from cvxpy import (matrix,variable,program,minimize, sum,abs,norm2,log,square,zeros,max, hstack,vstack) m, n = self.m, self.n A = matrix(self.A) b = matrix(self.b) # set tolerance to 5 significant digits tol_exp = 5 # l1 approximation x = variable(n) p = program(minimize(sum(abs(A*x + b)))) p.solve(True) np.testing.assert_array_almost_equal(x.value,self.x1,tol_exp) # l2 approximation x = variable(n) p = program(minimize(norm2(A*x + b))) p.solve(True) np.testing.assert_array_almost_equal(x.value,self.x2,tol_exp) # Deadzone approximation - implementation is currently ugly (need max along axis) x = variable(n) Axbm = abs(A*x+b)-0.5 Axbm_deadzone = vstack([max(hstack((Axbm[i,0],0.0))) for i in range(m)]) p = program(minimize(sum(Axbm_deadzone))) p.solve(True) obj_dz_cvxpy = np.sum(np.max([np.abs(A*x.value+b)-0.5,np.zeros((m,1))],axis=0)) np.testing.assert_array_almost_equal(obj_dz_cvxpy,self.obj_dz,tol_exp) # Log barrier x = variable(n) p = program(minimize(-sum(log(1.0-square(A*x + b))))) p.solve(True) np.testing.assert_array_almost_equal(x.value,self.cxlb,tol_exp)
def DR_W2_conditional_mean_variance_long_only_opt_cvx_kernel_new( X_mat, Y_mat, X0, reg_params, epsilon, rho_div_rho_min ): """ CVXPY solver kernel for conditional distributionally robust optimization problem: See problem formulation in DR_Conditional_EstimationW2.ipynb """ def compute_rho_min(X_mat, X0, epsilon): X_dist = np.linalg.norm(X_mat - X0, axis = 1) X_dist[np.isnan(X_dist)] = 1e8 X_cut = np.quantile(X_dist, q=epsilon, interpolation = 'higher') return X_dist[X_dist <= X_cut].mean() * epsilon rho = rho_div_rho_min * compute_rho_min(X_mat, X0, epsilon) X_dist = np.linalg.norm(X_mat - X0, axis = 1) X_dist[np.isnan(X_dist)] = 1e8 eta = reg_params epsilon_inv = 1/epsilon; N, sample_stock_num = Y_mat.shape m = cp.Variable(N, nonneg = True) beta = cp.Variable(sample_stock_num) alpha = cp.Variable(1) lambda1 = cp.Variable(1, nonneg = True) denom = cp.Variable(1, nonneg = True) lambda2 = cp.Variable(1) linear_expr = [email protected]*eta obj = lambda1*rho+lambda2*epsilon + cp.sum(cp.pos(epsilon_inv*m - 0.25*epsilon_inv*eta**2 - epsilon_inv*eta*alpha - lambda1*X_dist - lambda2))/N constraints = [m >= cp.hstack([cp.quad_over_lin(linear_expr[i], denom) for i in range(N)]), epsilon_inv*cp.quad_over_lin(beta, lambda1) + denom <= 1, beta >= 0, cp.sum(beta) == 1] prob = cp.Problem(cp.Minimize(obj), constraints) prob.solve() assert prob.status == 'optimal' return beta.value
def and_constraint(xs, y): """ y is true if all elements in xs is True xs: Variable(boolean=True) y : Variable(boolean=True) if dimenison of xs is 2 then: dimension 0 -> number of ands returns: list of Constraints """ N = len(xs) if isinstance(xs, list): xs = cvx.hstack(xs) C = [ 0 <= cvx.sum(xs) - N * y, N - 1 >= cvx.sum(xs) - N * y ] return C
def partB(): c0 = np.loadtxt("../Data/data/quiz4_class0.txt") c1 = np.loadtxt("../Data/data/quiz4_class1.txt") row0, col0 = c0.shape row1, col1 = c1.shape x = np.column_stack((np.vstack( (c0, c1)), np.ones(row0 + row1).reshape(-1, 1))) y = np.vstack((np.zeros(row0).reshape(-1, 1), np.ones(row1).reshape(-1, 1))) lambd = 0.01 theta = cvx.Variable((3, 1)) loss = -cvx.sum(cvx.multiply(y, x @ theta)) + cvx.sum( cvx.log_sum_exp(cvx.hstack([np.zeros((row1 + row0, 1)), x @ theta]), axis=1)) reg = cvx.sum_squares(theta) prob = cvx.Problem(cvx.Minimize(loss / (row1 + row0) + lambd * reg)) prob.solve() w = theta.value print(w) return w
def test_logistic_regression(self): np.random.seed(243) N, n = 10, 2 def sigmoid(z): return 1 / (1 + np.exp(-z)) X_np = np.random.randn(N, n) a_true = np.random.randn(n, 1) y_np = np.round(sigmoid(X_np @ a_true + np.random.randn(N, 1) * 0.5)) X_tf = tf.Variable(X_np) lam_tf = tf.Variable(1.0 * tf.ones(1)) a = cp.Variable((n, 1)) X = cp.Parameter((N, n)) lam = cp.Parameter(1, nonneg=True) y = y_np log_likelihood = cp.sum( cp.multiply(y, X @ a) - cp.log_sum_exp( cp.hstack([np.zeros((N, 1)), X @ a]).T, axis=0, keepdims=True).T) prob = cp.Problem( cp.Minimize(-log_likelihood + lam * cp.sum_squares(a))) fit_logreg = CvxpyLayer(prob, [X, lam], [a]) with tf.GradientTape(persistent=True) as tape: weights = fit_logreg(X_tf, lam_tf, solver_args={'eps': 1e-8})[0] summed = tf.math.reduce_sum(weights) grad_X_tf, grad_lam_tf = tape.gradient(summed, [X_tf, lam_tf]) def f_train(): prob.solve(solver=cp.SCS, eps=1e-8) return np.sum(a.value) numgrad_X_tf, numgrad_lam_tf = numerical_grad(f_train, [X, lam], [X_tf, lam_tf], delta=1e-6) np.testing.assert_allclose(grad_X_tf, numgrad_X_tf, atol=1e-2) np.testing.assert_allclose(grad_lam_tf, numgrad_lam_tf, atol=1e-2)
def min_R(self, calc_deg=True, max_deg=0., min_deg=-0.25): if self.R_cs.shape[1] < 365 + 2: n_tilde = 365 + 2 - self.R_cs.shape[1] R_tilde = cvx.hstack( [self.R_cs, cvx.Variable(shape=(self.k, n_tilde))]) else: R_tilde = self.R_cs W1 = np.diag(self.weights) f1 = cvx.sum( (0.5 * cvx.abs(self.D - self.L_cs.value * self.R_cs) + (self.tau - 0.5) * (self.D - self.L_cs.value * self.R_cs)) * W1) f2 = self.mu_R * cvx.norm( R_tilde[:, :-2] - 2 * R_tilde[:, 1:-1] + R_tilde[:, 2:], 'fro') constraints = [self.L_cs.value * self.R_cs >= 0, self.R_cs[0] >= 0] if self.D.shape[1] > 365: r = self.R_cs[0, :].T if calc_deg: constraints.extend([ cvx.multiply(1. / self.r0[:-365], r[365:] - r[:-365]) == self.beta, self.beta >= -.25 ]) if max_deg is not None: constraints.append(self.beta <= max_deg) if min_deg is not None: constraints.append(self.beta >= min_deg) else: constraints.append( cvx.multiply(1. / self.r0[:-365], r[365:] - r[:-365]) == 0) f3 = self.mu_R * cvx.norm(R_tilde[1:, :-365] - R_tilde[1:, 365:], 'fro') else: f3 = self.mu_R * cvx.norm(R_tilde[:, :-365] - R_tilde[:, 365:], 'fro') objective = cvx.Minimize(f1 + f2 + f3) problem = cvx.Problem(objective, constraints) problem.solve(solver='MOSEK') #problem.solve(solver=SOLVER_OBJ) if problem.status != 'optimal': raise ProblemStatusError('Minimize R status: ' + problem.status) self.r0 = self.R_cs.value[0, :]
def max_minimum_allocation_for_families(instance, families) -> AllocationToFamilies: """ Find the max-minimum (aka Egalitarian) allocation. :param agents: a matrix v in which each row represents an agent, each column represents an object, and v[i][j] is the value of agent i to object j. :param families: a list of lists. Each list represents a family and contains the indices of the agents in the family. :return allocation_matrix: a matrix alloc of a similar shape in which alloc[i][j] is the fraction allocated to agent i from object j. The allocation should maximize the leximin vector of utilities. >>> families = [ [0], [1] ] # two singleton families >>> max_minimum_allocation_for_families([ [3] , [5] ],families).round(3).matrix [[0.625] [0.375]] >>> max_minimum_allocation_for_families([ [4,2] , [1,4] ], families).round(3).matrix # two different items [[1. 0.] [0. 1.]] >>> alloc = max_minimum_allocation_for_families([ [3,3] , [1,1] ], families).round(3).matrix # two identical items >>> [sum(alloc[i]) for i in alloc.agents()] [0.5, 1.5] >>> v = [ [4,2] , [1,3] ] # two different items >>> a = max_minimum_allocation_for_families(v, families).round(3) >>> a Family #0 with members [0] gets { 80.0% of 0} with values [3.2]. Family #1 with members [1] gets { 20.0% of 0, 100.0% of 1} with values [3.2]. <BLANKLINE> >>> a.matrix [[0.8 0. ] [0.2 1. ]] >>> print(a.utility_profile()) [3.2 3.2] >>> families = [ [0, 1] ] # One couple >>> max_minimum_allocation_for_families([ [4,2] , [1,4] ], families).round(3).matrix [[1. 1.]] >>> families = [ [0, 1], [2, 3] ] # Two couples >>> a = max_minimum_allocation_for_families([ [4,2] , [1,4], [3,3], [5,5] ], families).round(3).matrix >>> a [[0.414 0.621] [0.586 0.379]] """ return max_welfare_allocation_for_families(instance, families, welfare_function=lambda utilities: cvxpy.min(cvxpy.hstack(utilities)), welfare_constraint_function=lambda utility: utility >= 0)
def partC(kernel): c0 = np.loadtxt("../Data/data/quiz4_class0.txt") c1 = np.loadtxt("../Data/data/quiz4_class1.txt") x = np.vstack((c0, c1)) row0, col0 = c0.shape row1, col1 = c1.shape y = np.vstack( (np.zeros(row0).reshape(-1, 1), np.ones(row1).reshape(-1, 1))).reshape(-1, 1) lambd = 0.01 alpha = cvx.Variable((row0 + row1, 1)) loss = -y.T @ kernel @ alpha + cvx.sum( cvx.log_sum_exp( cvx.hstack([np.zeros((row1 + row0, 1)), kernel @ alpha]), axis=1)) reg = cvx.quad_form(alpha, kernel) prob = cvx.Problem(cvx.Minimize(loss / (row1 + row0) + lambd * reg)) prob.solve() w = alpha.value print(w[:2]) return w
def test_max(self): x = cvxpy.Variable(pos=True) y = cvxpy.Variable(pos=True) prod1 = x * y**0.5 prod2 = 3.0 * x * y**0.5 obj = cvxpy.Minimize(cvxpy.max(cvxpy.hstack([prod1, prod2]))) constr = [x == 1.0, y == 4.0] dgp = cvxpy.Problem(obj, constr) dgp2dcp = cvxpy.reductions.Dgp2Dcp(dgp) dcp = dgp2dcp.reduce() dcp.solve(SOLVER) dgp.unpack(dgp2dcp.retrieve(dcp.solution)) self.assertAlmostEqual(dgp.value, 6.0) self.assertAlmostEqual(x.value, 1.0) self.assertAlmostEqual(y.value, 4.0) dgp._clear_solution() dgp.solve(SOLVER, gp=True) self.assertAlmostEqual(dgp.value, 6.0, places=4) self.assertAlmostEqual(x.value, 1.0)
def _direct_deconvolution(w, y, Nx, gamma_L2=0, gamma_L1=0): w = np.asarray(w) y = np.asarray(y) cplx = np.issubdtype(w.dtype, complex) or np.issubdtype(y.dtype, complex) if cplx: wr, wi = w.real, w.imag yr, yi = y.real, y.imag xr = cvx.Variable(Nx) xi = cvx.Variable(Nx) error = (cvx.sum_squares(cvx.conv(wr, xr) - cvx.conv(wi, xi) - yr) + cvx.sum_squares(cvx.conv(wi, xr) + cvx.conv(wr, xi) - yi)) u = cvx.norm(cvx.hstack(xr, xi), 2, axis=1) else: x = cvx.Variable(Nx) error = cvx.sum_squares(cvx.conv(w, x) - y) u = x cost = error if gamma_L1 != 0: gamma_L1 = cvx.Parameter(value=gamma_L1, sign="positive") cost = cost + gamma_L1 * cvx.norm(x, 1) if gamma_L2 != 0: gamma_L2 = cvx.Parameter(value=gamma_L2, sign="positive") cost = cost + gamma_L2 * cvx.sum_squares(x) objective = cvx.Minimize(cost) prob = cvx.Problem(objective) prob.solve() print("Problem Status: {0}".format(prob.status)) if cplx: result = np.array(xr.value).ravel() + 1j * np.array(xi.value).ravel() else: result = np.asarray(x.value).ravel() return result
def calc_Input_Koopman(Kol,Yf,Yp,Up,flag=1,lambda_val=0.0): solver_instance = cvxpy.SCS; Ki = None; if flag==1: # moore penrose inverse, plain ol' least squares input-Koopman #Yp_inv = np.dot(np.transpose(Yp_final), np.linalg.inv( np.dot(Yp_final,np.transpose(Yp_final)) ) ); Yfprime = Yf-np.dot(Kol,Yp) Up_inv = np.linalg.pinv(Up); Ki = np.dot(Yfprime,Up_inv); if flag ==2: # cvx optimization approach - L2 + L1 lasso norm1_term = 0.0; all_col_handles = [None]*Up.shape[0] for i in range(0,Up.shape[0]): #print(Yf.shape[0]) all_col_handles[i] = Variable(shape=(Yf.shape[0],1)) ;#Variable(shape=(Yf.shape[0],1) ); # if norm1_term < cvxpy.norm(all_col_handles[i],p=1): # norm1_term = cvxpy.norm(all_col_handles[i],p=1); #norm1_term = cvxpy.max(cvxpy.hstack( [norm1_term,cvxpy.norm(all_col_handles[i],p=1) ]) ); operator = cvxpy.hstack(all_col_handles); norm1_term =cvxpy.norm( operator,p=1); #operator = all_col_handles[0]; #for i in range(1,Yf.shape[0]): # operator = cvxpy.hstack([operator,all_col_handles[i]]); #operator. #print("[INFO]: CVXPY Koopman operator variable: " +repr(operator.shape)); #print(repr(operator)); #print("[INFO]: Yf.shape in calc_Koopman: " + repr(Yf.shape)); #print("[INFO]: Yp.shape in calc_Koopman: " + repr(Yp.shape)); Yfprime = Yf-np.dot(Kol,Yp) norm2_fit_term = cvxpy.norm(cvxpy.norm(Yfprime-operator*Up,p=2,axis=0),p=2); objective = Minimize(norm2_fit_term + lambda_val*norm1_term) constraints = []; prob = Problem(objective,constraints); result = prob.solve(verbose=True,solver=solver_instance,max_iters=np.int(1e7))#,reltol=1e-10,abstol=1e-10); print("[INFO]: Finished executing cvx solver, printing CVXPY problem status") print(prob.status); Ki = operator.value; return Ki;
def make_cvx_problem(): depth = cvx.Variable(len(juncdepth)) scale = cvx.Variable() objective = 0 constraints = [depth >= 1, scale >= 0] for iw, (iline, u) in T.items(): iu, iv = lines[iline] constraints.append( depth[iw] >= (1 - u) * depth[iu] + u * depth[iv]) for w, c in vp: w = invK @ w w /= LA.norm(w) for l in c: i, j = lines[l] uv = depth[i] * vertices[i] - depth[j] * vertices[j] objective += cvx.norm(cvx.hstack(cross(uv, w))) for i in range(len(juncdepth)): if juncdepth[i] is None or juncdepth[i] == 0: continue objective += lambda_ * cvx.square(depth[i] - scale * juncdepth[i]) problem = cvx.Problem(cvx.Minimize(objective), constraints) return problem, depth, scale
def cvx_kron(expr_1: Union[np.ndarray, Expression], expr_2: Union[np.ndarray, Expression]) -> Expression: """ Compute Kronecker product between CVXPY objects. By default, CVXPY does not support taking the Kronecker product when the argument on the left is equal to a CVXPY object and the object on the right is equal to a numpy object. At most one of :code:`expr_1` and :code:`b` may be CVXPY Variable objects. Kudos to Riley J. Murray for this function: https://github.com/cvxgrp/cvxpy/issues/457 :param expr_1: 2D numpy ndarray, or a CVXPY Variable with expr_1.ndim == 2 :param expr_2: 2D numpy ndarray, or a CVXPY Variable with expr_2.ndim == 2 """ expr = np.kron(expr_1, expr_2) num_rows = expr.shape[0] rows = [cvxpy.hstack(expr[i, :]) for i in range(num_rows)] full_expr = cvxpy.vstack(rows) return full_expr
def recover_coords_sdp(D): n = D.shape[0] G = cp.Variable((n, n), symmetric=True) eta = cp.Variable((n, n)) lam = 1 constraints = [G >> 0] constraints += [eta[i, j] >= 0 for i in range(n) for j in range(n)] reg = lam * cp.norm(eta, p=1) Gii = cp.diag(G) hstacked = cp.hstack([cp.reshape(Gii, (n, 1)) for i in range(n)]) vstacked = cp.vstack([cp.reshape(Gii, (1, n)) for i in range(n)]) obj = reg + 0.5 * cp.sum((hstacked + vstacked - 2 * G + eta - D**2)**2) #obj = 0.5 * cp.sum((hstacked + vstacked - 2 * G - D**2)) prob = cp.Problem(cp.Minimize(obj), constraints) prob.solve(verbose=True) #print("The optimal value is", prob.value) #print("A solution G is: {}".format(G.value)) u, s, v = np.linalg.svd(G.value) u, s = np.real(u), np.real(s) X = np.dot(u, np.diag(np.sqrt(s)))[:, :3] return X
def solve_problem(self, x_k, penalizer, p, delta, constraints=None, lower_limit=None, upper_limit=None): model_objective, actual_objective = self.get_model_objective(x_k, penalizer, p) if constraints is not None: if constraints.shape[1] == 2 * p.shape[0]: p1 = cvxpy.hstack([p, p]) else: p1 = p if lower_limit is not None and upper_limit is not None: constraints = [cvxpy.norm(p, self.trust_region_norm) <= delta, lower_limit <= cvxpy.matmul(constraints, p1), cvxpy.matmul(constraints, p1) <= upper_limit] elif lower_limit is None: constraints = [cvxpy.norm(p, self.trust_region_norm) <= delta, cvxpy.matmul(constraints, p1) >= upper_limit] elif upper_limit is None: constraints = [ cvxpy.norm(p, self.trust_region_norm) <= delta, lower_limit <= cvxpy.matmul(constraints, p1) ] else: constraints = [cvxpy.norm(p, self.trust_region_norm) <= delta] problem = cvxpy.Problem(cvxpy.Minimize(model_objective), constraints) # print problem.get_problem_data(self.solver)[0] if self.solver == "CVXOPT": start = time.time() result = problem.solve(solver=self.solver, warm_start=True, kktsolver=cvxpy.ROBUST_KKTSOLVER, verbose=False) end = time.time() else: # result = problem.solve(solver=self.solver, warm_start=True, verbose=False, max_iters=5000) start = time.time() result = problem.solve(solver=self.solver, warm_start=True, verbose=False, max_iters=100) # result = problem.solve(solver=self.solver, warm_start=True, verbose=False) end = time.time() self.solving_time += end - start return p.value, model_objective, actual_objective, problem.status, problem.value
def get_allocation_using_job_type_throughputs( self, unflattened_throughputs, job_id_to_job_type_key, scale_factors, unflattened_priority_weights, cluster_spec): job_ids = sorted(job_id_to_job_type_key.keys()) if len(job_ids) == 0: return None job_type_keys = sorted(unflattened_throughputs.keys()) worker_types = sorted(cluster_spec.keys()) num_workers = \ [cluster_spec[worker_type] for worker_type in worker_types] # Create a map from job type to list of job indexes. job_type_key_to_job_idx = {} for i, job_id in enumerate(job_ids): job_type_key = job_id_to_job_type_key[job_id] if job_type_key not in job_type_key_to_job_idx: job_type_key_to_job_idx[job_type_key] = [] job_type_key_to_job_idx[job_type_key].append(i) # Num jobs. n = len(job_ids) # Num job_types. a = len(unflattened_throughputs.keys()) # Num worker_types. m = len(worker_types) # Num varibles per job. num_vars_per_job = 1 + a # Set up scale factors. flattened_scale_factors = \ np.reshape([scale_factors[job_id] for job_id in job_ids], (n, 1)) scale_factors_array = np.tile(flattened_scale_factors, (1, num_vars_per_job * m)) # Set up flattened job type throughputs. flattened_throughputs = np.zeros(shape=(a, (1 + a) * m), dtype=np.float32) for i, job_type_key in enumerate(job_type_keys): for k, worker_type in enumerate(worker_types): for j, other_job_type_key in enumerate([None] + job_type_keys): if j > 0 and other_job_type_key[1] != job_type_key[1]: flattened_throughputs[i, k * (1 + a) + j] = 0.0 else: flattened_throughputs[i,k*(1+a)+j] = \ unflattened_throughputs[job_type_key][worker_type][other_job_type_key] # Set up masks to avoid double-counting allocation values when # computing constraint that the sum of allocation values of each # worker type must be <= the number of workers of that worker type. # TODO: Change this if we ever consider combinations larger than pairs. masks = np.full(shape=(n, num_vars_per_job), fill_value=0.5) masks[:, 0] = 1.0 # Allocation matrix. x = cp.Variable((n, num_vars_per_job * m)) constraints = [ # All allocation values must be >= 0. x >= 0, # The sum of allocation values for each job must be <= 1. cp.sum(x, axis=1) <= 1 ] # The sum of allocation values for each worker type must be <= # the number of workers of that type. per_worker_type_allocations = [] for i in range(m): relevant_vars = \ x[:,i*num_vars_per_job:(i+1)*num_vars_per_job] relevant_scale_factors = \ scale_factors_array[:,i*num_vars_per_job:(i+1)*num_vars_per_job] per_worker_type_allocations.append( cp.sum( cp.multiply(relevant_vars, cp.multiply(relevant_scale_factors, masks)))) constraints.append( cp.hstack(per_worker_type_allocations) <= num_workers) # Set the following constraints: # for all job type pairs a, b: # sum of allocation of all jobs of type a paired with type b == # sum of allocation of all jobs of type b paired with type a lhs = [] rhs = [] for i, job_type_key_0 in enumerate(job_type_keys): for j, job_type_key_1 in enumerate(job_type_keys): if j <= i: continue elif job_type_key_0[1] != job_type_key_1[1]: continue # Retrieve the list of jobs of each type. job_type_0_jobs = job_type_key_to_job_idx[job_type_key_0] job_type_1_jobs = job_type_key_to_job_idx[job_type_key_1] for k in range(m): job_type_0_mask = np.zeros(x.shape) job_type_1_mask = np.zeros(x.shape) # Allocation of job_type_0 jobs when paired with job_type_1 for job_idx in job_type_0_jobs: offset = k * num_vars_per_job + 1 + j job_type_0_mask[job_idx, offset] = 1 # Allocation of job_type_1 jobs when paired with job_type_0 for job_idx in job_type_1_jobs: offset = k * num_vars_per_job + 1 + i job_type_1_mask[job_idx, offset] = 1 lhs.append(cp.sum(x[job_type_0_mask == 1])) rhs.append(cp.sum(x[job_type_1_mask == 1])) assert (len(lhs) == len(rhs)) if len(lhs) > 0: constraints.append(cp.hstack(lhs) == cp.hstack(rhs)) # Add constraints to make all variables of the form i-A where job i # is of job type A equal. for i, job_type_key in enumerate(job_type_keys): for k in range(m): same_job_type_vars = [] job_type_jobs = job_type_key_to_job_idx[job_type_key] # Find all variables for job-job_type pairs where the job # types match. offset = k * num_vars_per_job + 1 + i for job_idx in job_type_jobs: same_job_type_vars.append(x[job_idx, offset]) # Constrain the variables to all be equal. c = cp.Variable() constraints.append(cp.hstack(same_job_type_vars) == c) throughputs_no_packed_jobs = np.zeros( (len(job_ids), len(worker_types))) for i, job_id in enumerate(job_ids): job_type_key = job_id_to_job_type_key[job_id] for j, worker_type in enumerate(worker_types): throughputs_no_packed_jobs[i, j] = \ unflattened_throughputs[job_type_key][worker_type][None] proportional_throughputs = self._proportional_policy.get_throughputs( throughputs_no_packed_jobs, (job_ids, worker_types), cluster_spec) # Allocation coefficients. all_coefficients = np.zeros((n, num_vars_per_job * m)) for i, job_id in enumerate(job_ids): job_type_key = job_id_to_job_type_key[job_id] job_type_idx = job_type_keys.index(job_type_key) if len(job_type_key_to_job_idx[job_type_key]) == 1: for k, worker_type in enumerate(worker_types): offset = k * num_vars_per_job + 1 + job_type_idx constraints.append(x[i, offset] == 0.0) proportional_throughput = proportional_throughputs[i] all_coefficients[i] = \ np.multiply(flattened_throughputs[job_type_idx], scale_factors_array[i]) /\ (unflattened_priority_weights[job_id] * proportional_throughput) objective = \ cp.Maximize(cp.min(cp.sum(cp.multiply(all_coefficients, x), axis=1))) cvxprob = cp.Problem(objective, constraints) result = cvxprob.solve(solver=self._solver) if cvxprob.status != "optimal": print('WARNING: Allocation returned by policy not optimal!') allocation = x.value.clip(min=0.0).clip(max=1.0) # Unflatten allocation. unflattened_allocation = {} for i, job_id in enumerate(job_ids): unflattened_allocation[job_id] = {} for j, worker_type in enumerate(worker_types): unflattened_allocation[job_id][worker_type] = {} for k, job_type_key in enumerate([None] + job_type_keys): unflattened_allocation[job_id][worker_type][job_type_key] = \ allocation[i, j * num_vars_per_job + k] return self.convert_job_type_allocation(unflattened_allocation, job_id_to_job_type_key)
def test_sum_largest(self): self.skipTest("Enable test once sum_largest is implemented.") x = cvxpy.Variable((4, ), pos=True) obj = cvxpy.Minimize(cvxpy.sum_largest(x, 3)) constr = [x[0] * x[1] * x[2] * x[3] >= 16] dgp = cvxpy.Problem(obj, constr) dgp2dcp = cvxpy.reductions.Dgp2Dcp(dgp) dcp = dgp2dcp.reduce() dcp.solve(SOLVER) dgp.unpack(dgp2dcp.retrieve(dcp.solution)) opt = 6.0 self.assertAlmostEqual(dgp.value, opt) self.assertAlmostEqual((x[0] * x[1] * x[2] * x[3]).value, 16, places=2) dgp._clear_solution() dgp.solve(SOLVER, gp=True) self.assertAlmostEqual(dgp.value, opt) self.assertAlmostEqual((x[0] * x[1] * x[2] * x[3]).value, 16, places=2) # An unbounded problem. x = cvxpy.Variable((4, ), pos=True) y = cvxpy.Variable(pos=True) obj = cvxpy.Minimize(cvxpy.sum_largest(x, 3) * y) constr = [x[0] * x[1] * x[2] * x[3] >= 16] dgp = cvxpy.Problem(obj, constr) dgp2dcp = cvxpy.reductions.Dgp2Dcp(dgp) dcp = dgp2dcp.reduce() opt = dcp.solve(SOLVER) self.assertEqual(dcp.value, -float("inf")) dgp.unpack(dgp2dcp.retrieve(dcp.solution)) self.assertAlmostEqual(dgp.value, 0.0) self.assertAlmostEqual(dgp.status, "unbounded") dgp._clear_solution() dgp.solve(SOLVER, gp=True) self.assertAlmostEqual(dgp.value, 0.0) self.assertAlmostEqual(dgp.status, "unbounded") # Another unbounded problem. x = cvxpy.Variable(2, pos=True) obj = cvxpy.Minimize(cvxpy.sum_largest(x, 1)) dgp = cvxpy.Problem(obj, []) dgp2dcp = cvxpy.reductions.Dgp2Dcp(dgp) dcp = dgp2dcp.reduce() opt = dcp.solve(SOLVER) self.assertEqual(dcp.value, -float("inf")) dgp.unpack(dgp2dcp.retrieve(dcp.solution)) self.assertAlmostEqual(dgp.value, 0.0) self.assertAlmostEqual(dgp.status, "unbounded") dgp._clear_solution() dgp.solve(SOLVER, gp=True) self.assertAlmostEqual(dgp.value, 0.0) self.assertAlmostEqual(dgp.status, "unbounded") # Composition with posynomials. x = cvxpy.Variable((4, ), pos=True) obj = cvxpy.Minimize( cvxpy.sum_largest( cvxpy.hstack([ 3 * x[0]**0.5 * x[1]**0.5, x[0] * x[1] + 0.5 * x[1] * x[3]**3, x[2] ]), 2)) constr = [x[0] * x[1] >= 16] dgp = cvxpy.Problem(obj, constr) dgp2dcp = cvxpy.reductions.Dgp2Dcp(dgp) dcp = dgp2dcp.reduce() dcp.solve(SOLVER) dgp.unpack(dgp2dcp.retrieve(dcp.solution)) # opt = 3 * sqrt(4) * sqrt(4) + (4 * 4 + 0.5 * 4 * epsilon) = 28 opt = 28.0 self.assertAlmostEqual(dgp.value, opt, places=2) self.assertAlmostEqual((x[0] * x[1]).value, 16.0, places=2) self.assertAlmostEqual(x[3].value, 0.0, places=2) dgp._clear_solution() dgp.solve(SOLVER, gp=True) self.assertAlmostEqual(dgp.value, opt, places=2) self.assertAlmostEqual((x[0] * x[1]).value, 16.0, places=2) self.assertAlmostEqual(x[3].value, 0.0, places=2)
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 solve_group_SDP( Sigma, groups=None, verbose=False, objective="abs", norm_type=2, num_iter=10, tol=1e-2, **kwargs, ): """ Solves the group SDP problem: extends the formulation from Barber and Candes 2015/ Candes et al 2018 (MX Knockoffs). Note this will be much faster with equal-sized groups and objective="abs." :param Sigma: true covariance (correlation) matrix, p by p numpy array. :param groups: numpy array of length p with integer values between 1 and m. :param verbose: if True, print progress of solver :param objective: How to optimize the S matrix for group knockoffs. (For ungrouped knockoffs, using the objective = 'abs' is strongly recommended.) There are several options: - 'abs': minimize sum(abs(Sigma - S)) between groups and the group knockoffs. - 'pnorm': minimize Lp-th matrix norm. Equivalent to abs when p = 1. - 'norm': minimize different type of matrix norm (see norm_type below). :param norm_type: Means different things depending on objective. - When objective == 'pnorm', i.e. objective is Lp-th matrix norm, which p to use. Can be any float >= 1. - When objective == 'norm', can be 'fro', 'nuc', np.inf, or 1 (i.e. which other norm to use). Defaults to 2. :param num_iter: We do a line search and scale S at the end to make absolutely sure there are no numerical errors. Defaults to 10. :param tol: Minimum eigenvalue of S must be greater than this. """ # By default we lower the convergence epsilon a bit for drastic speedup. if "eps" not in kwargs: kwargs["eps"] = 5e-3 # Default groups p = Sigma.shape[0] if groups is None: groups = np.arange(1, p + 1, 1) # Test corr matrix TestIfCorrMatrix(Sigma) # Check to make sure the objective is valid objective = str(objective).lower() if objective not in OBJECTIVE_OPTIONS: raise ValueError( f"Objective ({objective}) must be one of {OBJECTIVE_OPTIONS}") # Warn user if they're using a weird norm... if objective == "norm" and norm_type == 2: warnings.warn( "Using norm objective and norm_type = 2 can lead to strange behavior: consider using Frobenius norm" ) # Find minimum tolerance, possibly warn user if lower than they specified maxtol = np.linalg.eigh(Sigma)[0].min() / 1.1 if tol > maxtol and verbose: warnings.warn( f"Reducing SDP tol from {tol} to {maxtol}, otherwise SDP would be infeasible" ) tol = min(maxtol, tol) # Figure out sizes of groups m = groups.max() group_sizes = utilities.calc_group_sizes(groups) # Possibly solve non-grouped SDP if m == p: return solve_SDP( Sigma=Sigma, verbose=verbose, num_iter=num_iter, tol=tol, ) # Sort the covariance matrix according to the groups inds, inv_inds = utilities.permute_matrix_by_groups(groups) sortedSigma = Sigma[inds][:, inds] # Create blocks of semidefinite matrix S, # as well as the whole matrix S variables = [] constraints = [] S_rows = [] shift = 0 for j in range(m): # Create block variable gj = int(group_sizes[j]) Sj = cp.Variable((gj, gj), symmetric=True) constraints += [Sj >> 0] variables.append(Sj) # Create row of S if shift == 0 and shift + gj < p: rowj = cp.hstack([Sj, cp.Constant(np.zeros((gj, p - gj)))]) elif shift + gj < p: rowj = cp.hstack([ cp.Constant(np.zeros((gj, shift))), Sj, cp.Constant(np.zeros((gj, p - gj - shift))), ]) elif shift + gj == p and shift > 0: rowj = cp.hstack([cp.Constant(np.zeros((gj, shift))), Sj]) elif gj == p and shift == 0: rowj = cp.hstack([Sj]) else: raise ValueError( f"shift ({shift}) and gj ({gj}) add up to more than p ({p})") S_rows.append(rowj) # Incremenet shift shift += gj # Construct S and Grahm Matrix S = cp.vstack(S_rows) sortedSigma = cp.Constant(sortedSigma) constraints += [2 * sortedSigma - S >> 0] # Construct optimization objective if objective == "abs": objective = cp.Minimize(cp.sum(cp.abs(sortedSigma - S))) elif objective == "pnorm": objective = cp.Minimize(cp.pnorm(sortedSigma - S, norm_type)) elif objective == "norm": objective = cp.Minimize(cp.norm(sortedSigma - S, norm_type)) # Note we already checked objective is one of these values earlier # Construct, solve the problem. problem = cp.Problem(objective, constraints) problem.solve(verbose=verbose, **kwargs) if verbose: print("Finished solving SDP!") # Unsort and get numpy S = S.value if S is None: raise ValueError( "SDP formulation is infeasible. Try decreasing the tol parameter.") S = S[inv_inds][:, inv_inds] # Clip 0 and 1 values for i in range(p): S[i, i] = max(tol, min(1 - tol, S[i, i])) # Scale to make this PSD using binary search S, gamma = scale_until_PSD(Sigma, S, tol, num_iter) if verbose: mineig = np.linalg.eigh(2 * Sigma - S)[0].min() print( f"After SDP, mineig is {mineig} after {num_iter} line search iters. Gamma is {gamma}" ) # Return unsorted S value return S
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 link_tt_heuristic(link): ff = link.l / link.fd.v q_max = (link.l / link.fd.q_max) * link.v_dens rho_hat = link.fd.rho_max - link.v_dens cong = link.l / link.fd.w * (quad_over_lin(link.fd.rho_max ** .5, rho_hat) - 1) return cvx_max(hstack([ff, q_max, cong]))
def NPA1_constraint(self, proj=True): # Introduce the normalization factor renorm = lambda x, y: self.dimT**2 / (self.probQ1[x] * self.probQ2[y]) # The P matrix containing the information about the variables rho_variable is give by P = [] for a1, q1 in self.indices_A1Q1: P_row = [ renorm(q1, q2) * cp.trace(self.Phi_TTSS @ self.rho_TTSS(a1, q1, a2, q2)) for a2, q2 in self.indices_A2Q2 ] P.append(P_row) P = cp.bmat(P) # The Q matrix containing the information about the variables rho_variable and also some new variables Q = [] for a1, q1 in self.indices_A1Q1: Q_row = [] for a1p, q1p in self.indices_A1Q1: if q1 == q1p: if a1 == a1p: val = sum([ renorm(q1, q2) * cp.trace( self.Phi_TTSS @ self.rho_TTSS(a1, q1, a2, q2)) for a2, q2 in self.indices_A2Q2 ]) / self.dimQ2 else: if proj: val = cp.Constant( 0) # Assume projective measurements. else: val = cp.Variable() # Otherwise, just new variable else: val = cp.Variable() Q_row.append(val) Q.append(Q_row) Q = cp.bmat(Q) # The R matrix containing the information about the variables rho_variable and also some new variables R = [] for a2, q2 in self.indices_A2Q2: R_row = [] for a2p, q2p in self.indices_A2Q2: if q2 == q2p: if a2 == a2p: val = sum([ renorm(q1, q2) * cp.trace( self.Phi_TTSS @ self.rho_TTSS(a1, q1, a2, q2)) for a1, q1 in self.indices_A1Q1 ]) / self.dimQ1 else: if proj: val = cp.Constant( 0) # Assume projective measurements. else: val = cp.Variable() # Otherwise, just new variable else: val = cp.Variable() R_row.append(val) R.append(R_row) R = cp.bmat(R) # Constructing vector v of dimension dimA1*dimQ1+dimA2*dimQ2 v = [] for a1, q1 in self.indices_A1Q1: v.append( sum([ renorm(q1, q2) * cp.trace(self.Phi_TTSS @ self.rho_TTSS(a1, q1, a2, q2)) for a2, q2 in self.indices_A2Q2 ]) / self.dimQ2) for a2, q2 in self.indices_A2Q2: v.append( sum([ renorm(q1, q2) * cp.trace(self.Phi_TTSS @ self.rho_TTSS(a1, q1, a2, q2)) for a1, q1 in self.indices_A1Q1 ]) / self.dimQ1) v = cp.bmat([v]) w = cp.vstack([cp.Constant([[1]]), v.T]) # Builiding the matrix M that should be positive semi-definite (NPA constraint) M = cp.vstack([cp.hstack([Q, P]), cp.hstack([P.T, R])]) M = cp.vstack([v, M]) M = cp.hstack([w, M]) self.constraints.append(M >> 0) self.constraints.append(M - M.T == 0)
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 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 compute_decision_for_current_state(self, verbose=False): """ 1. Get the decision for the current state a. Get the SINDYc coefficients for the dynamics b. Do the computation 2. Use scipy.optimize to compute the best control action 3. Return the decision """ if verbose: print('Current state: {:s}'.format(np.array_str( self.current_state, precision=2))) # Compute the decision query_timer_start = time.time() # Compute the SINDYc coefficients for the dynamics coeff_state, coeff_input = self.compute_sindyc_coeff() # Compute the sublibrary for dynamics L_x = self.evaluate_sub_library_at_state(self.current_state) # One-step optimal control: Solve # minimize objective(delta_state, current_action) # subject to delta_state = Model(current_action) # lb <= u <= ub # for delta_state and current_action # # Here, the estimated next state is given by current_state + delta_state # under the influence of current_action current_action = cp.Variable((self.input_seq.shape[1],)) delta_state = cp.Variable((self.trajectory.shape[1],)) L_input = cp.hstack((current_action[input_indx] * L_x for input_indx in range(self.input_seq.shape[1]))) const = [current_action <= self.input_ub, current_action >= self.input_lb, delta_state == coeff_state.T@L_x + coeff_input.T@L_input] obj = self.cvxpy_objective(self.current_state, delta_state, current_action) prob = cp.Problem(cp.Minimize(obj), const) try: prob.solve(**self.cvxpy_args) except cp.SolverError: raise RuntimeError('CVXPY solver error') if prob.status in ['optimal', 'optimal_inaccurate']: current_decision = np.array([current_action.value]) else: raise RuntimeError('compute_decision_for_current_state failed' ' with CVXPY status: {:s}'.format(prob.status)) query_timer_end = time.time() query_time = query_timer_end - query_timer_start if verbose: # Update user print('Best action = {:s} | Estimated cost = {:1.4f} | Time = ' '{:1.4f} s '.format(np.array_str(current_decision, precision=2), prob.value, query_time)) # Get the next state self.current_state = self.one_step_dyn(self.current_state, current_decision) # Update the data matrices self.trajectory = np.vstack((self.trajectory, self.current_state)) self.input_seq = np.vstack((self.input_seq, current_decision)) self.cost_val_vec = np.hstack((self.cost_val_vec, prob.value)) # Return decision solution_dict = {'next_query': current_decision, 'lb_opt_val': prob.value, 'query_time': query_time} return solution_dict
def sys_norm_hinf_LMI(A, Bdisturbance, C, D = None): '''Compute a system's Hinfinity norm, using an LMI approach. Acl, Bdisturbance are system matrices, describing the systems dynamics: dx/dt = Acl*x + Bdisturbance*v where x is the system state and v is the disturbance. The system output is: z = C*x + D*v The matrix Acl must be Hurwitz for the Hinf norm to be finite. Parameters ---------- A : (n, n) Matrix Input Bdisturbance : (n, m) Matrix Input C : (q, n) Matrix Input D : (q,m) Matrix Input (optional) Returns ------- Jinf : Systems Hinf norm. See: Robust Controller Design By Convex Optimization, Alireza Karimi Laboratoire d'Automatique, EPFL ''' if not controlpy.analysis.is_hurwitz(A): return np.Inf n = A.shape[0] ndist = Bdisturbance.shape[1] nout = C.shape[0] X = cvxpy.Semidef(n) g = cvxpy.Variable() if D is None: D = np.matrix(np.zeros([nout, ndist])) r1 = cvxpy.hstack(cvxpy.hstack(A.T*X+X*A, X*Bdisturbance), C.T) r2 = cvxpy.hstack(cvxpy.hstack(Bdisturbance.T*X, -g*np.matrix(np.identity(ndist))), D.T) r3 = cvxpy.hstack(cvxpy.hstack(C, D), -g*np.matrix(np.identity(nout))) tmp = cvxpy.vstack(cvxpy.vstack(r1,r2),r3) constraints = [tmp == -cvxpy.Semidef(n + ndist + nout)] obj = cvxpy.Minimize(g) prob = cvxpy.Problem(obj, constraints) try: prob.solve()#solver='CVXOPT', kktsolver='robust') except cvxpy.error.SolverError: print('Solution not found!') return None if not prob.status == cvxpy.OPTIMAL: return None return g.value
np.random.seed(1) (m, n) = (70, 500) k = 10 z_true = np.zeros(n, dtype=complex) z_true[0:k] = np.random.randn(k) + 1j * np.random.randn(k) np.random.shuffle(z_true); z_true = np.asmatrix(z_true).T A = np.random.randn(m, n) + 1j * np.random.randn(m, n) A = np.asmatrix(A) b = A*z_true; b = np.asmatrix(b) zr = cvx.Variable(n) zi = cvx.Variable(n) t = cvx.Variable(m) obj = cvx.Minimize(cvx.sum_entries(t)) #AA = cvx.norm2(cvx.hstack(cvx.vstack(A.real,A.imag),cvx.vstack(-A.imag,A.real))) z = cvx.vstack(zr,zi) constraints = [ cvx.norm2(cvx.hstack(cvx.vstack(A[i,:].real,A[i,:].imag), cvx.vstack(-A[i,:].imag,A[i,:].real))*z -cvx.vstack(b[i].real,b[i].imag)) <= t[i] for i in range(m)] ''' constraints = [ cvx.norm2(cvx.hstack(cvx.vstack(A.real,A.imag),cvx.vstack(-A.imag,A.real))*z - cvx.vstack(b.real,b.imag)) <= t] ''' prob = cvx.Problem(obj, constraints) sol = prob.solve(solver=cvx.ECOS) print 'status: {}'.format(prob.status) print 'norm z: {}'.format(cvx.norm2(z).value) print 'norm z_true: {}'.format((cvx.norm2(z_true.real)+cvx.norm2(z_true.imag)).value) for i in range(n): print '{} + {}j' .format(zr[i].value,zi[i].value)
""" @author: cyrusl EE 364A Convex Optimization Homework 5 A5.2 Minimax rational fit Due 7/25/2014 """ import numpy as np import cvxpy as cvx import matplotlib.pyplot as plt k = 201 t = np.asmatrix(np.linspace(-3,3,k)).T y = np.exp(t) one = np.asmatrix(np.ones((k,1))) Tpow = cvx.hstack(one, t, cvx.square(t)) u = np.exp(3) l = 0 tol = 1e-3 while u-l >= tol: mid = (l+u)/2 a = cvx.Variable(3) b = cvx.Variable(2) obj = cvx.Minimize(0) constraints = [cvx.abs(Tpow*a - cvx.mul_elemwise(y, Tpow*cvx.vstack(1, b))) <= mid * Tpow*cvx.vstack(1, b)] prob = cvx.Problem(obj, constraints) sol = prob.solve(solver=cvx.CVXOPT) if prob.status == cvx.OPTIMAL: print('gamma = {}', format(mid)) u = mid a_opt = a