def ntf_fir_from_digested(Qs, A, C, H_inf, **opts): """ Synthesize FIR NTF from predigested specification Version for the cvxpy 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 order = np.size(Qs, 0)-1 br = cvxpy.Variable(order, 1, name='br') b = cvxpy.vstack(1, br) X = cvxpy.Symmetric(order, name='X') target = cvxpy.Minimize(cvxpy.norm2(Qs*b)) B = np.vstack((np.zeros((order-1, 1)), 1.)) C = C+br[::-1].T D = np.matrix(1.) M1 = A.T*X M2 = M1*B M = cvxpy.bmat([[M1*A-X, M2, C.T], [M2.T, B.T*X*B-H_inf**2, D], [C, D, np.matrix(-1.)]]) constraints = [M << 0, X >> 0] p = cvxpy.Problem(target, constraints) p.solve(verbose=verbose, **opts['cvxpy_opts']) return np.hstack((1, np.asarray(br.value.T)[0]))
def relax(self): """Relaxation [I X; X^T I] is PSD. """ rows, cols = self.size constr = super(Orthog, self).relax() mat = cvx.bmat([[np.eye(rows), self], [X.T, np.eye(cols)]]) return constr + [mat >> 0]
def pos_noherm(*Xs): constraints =[ cvxpy.bmat([ [X.re, -X.im], [X.im, X.re] ]) >> 0 for X in Xs ] return constraints
def dnorm_problem(dim): # Start assembling constraints and variables. constraints = [] # Make a complex variable for X. X = complex_var(dim ** 2, dim ** 2, "X") # Make complex variables for rho0 and rho1. rho0 = complex_var(dim, dim, "rho0") rho1 = complex_var(dim, dim, "rho1") constraints += dens(rho0, rho1) # Finally, add the tricky positive semidefinite constraint. # Since we're using column-stacking, but Watrous used row-stacking, # we need to swap the order in Rho0 and Rho1. This is not straightforward, # as CVXPY requires that the constant be the first argument. To solve this, # We conjugate by SWAP. W = qudit_swap(dim).data.todense() W = Complex(re=W.real, im=W.imag) Rho0 = conj(W, kron(np.eye(dim), rho0)) Rho1 = conj(W, kron(np.eye(dim), rho1)) Y = cvxpy.bmat([ [Rho0.re, X.re, -Rho0.im, -X.im], [X.re.T, Rho1.re, X.im.T, -Rho1.im], [Rho0.im, X.im, Rho0.re, X.re], [-X.im.T, Rho1.im, X.re.T, Rho1.re], ]) constraints += [Y >> 0] logger.debug("Using {} constraints.".format(len(constraints))) Jr = cvxpy.Parameter(dim ** 2, dim ** 2) Ji = cvxpy.Parameter(dim ** 2, dim ** 2) # The objective, however, depends on J. objective = cvxpy.Maximize(cvxpy.trace( Jr.T * X.re + Ji.T * X.im )) problem = cvxpy.Problem(objective, constraints) return problem, Jr, Ji, X, rho0, rho1
Iij = Iij / 1000 # Scale intensities to kind of match distances c = cvx.Variable((dim, 3)) constr = [] inv_distances = [[0 for i in range(dim)] for j in range(dim)] # for i in range(dim): # for j in range(i, dim): # constr.append(c[i, j] >= Rij[i, j]) # This needs to be a sphere packing problem for i in range(dim - 1): for j in range(i + 1, dim): distance = cvx.norm(cvx.vec(c[i, :] - c[j, :]), 2) inv_distances[i][j] = cvx.inv_pos(distance) constr.append(distance >= Rij[i, j]) prob = cvx.Problem( cvx.Maximize(cvx.norm(cvx.multiply(Iij, cvx.bmat(inv_distances)), 1)), constr) #prob = cvx.Problem(cvx.Minimize(cvx.max(cvx.max(cvx.abs(cvx.multiply(cvx.inv_pos(cvx.multiply(1./Iij.flatten(), c)), 1/100))))), constr) prob.solve(method="dccp", solver=cvx.MOSEK, verbose=True) rij_opt = np.reshape(c.value, (dim, dim)) r = rij[0, 1] / rij_opt[0, 1] for i, j in product(range(dim), range(dim)): if i >= j: continue print("d[%d,%d]: %1.2f(true) %1.2f(sol.)" % (i, j, rij[i, j], rij_opt[i, j] * r)) df['opt. distance'] = df.index.size * [0] for i1 in range(dim): for i2 in range(dim):
def main(ii): LMI = [] for epsilon in epsilon_vals: for kappa in kappa_vals: P_0 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) P_1 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) P_2 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) P_3 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) P_4 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) Q_0 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) Q_1 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) Q_2 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) Q_3 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) Q_4 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) S_0 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) S_1 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) S_2 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) S_3 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) S_4 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) R = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega), PSD=True) S1 = cp.Variable((2 * n_p + n_omega, 2 * n_p + n_omega)) gamma_sq = cp.Variable(nonneg=True) beta = cp.Variable(nonneg=True) X_0 = cp.Variable((n_p, n_p)) X_1 = cp.Variable((n_p, n_p)) X_2 = cp.Variable((n_p, n_p)) X_3 = cp.Variable((n_p, n_p)) X_4 = cp.Variable((n_p, n_p)) Y_0 = cp.Variable((n_p, n_p)) Y_1 = cp.Variable((n_p, n_p)) Y_2 = cp.Variable((n_p, n_p)) Y_3 = cp.Variable((n_p, n_p)) Y_4 = cp.Variable((n_p, n_p)) Z_0 = cp.Variable((n_omega, n_omega)) Z_1 = cp.Variable((n_omega, n_omega)) Z_2 = cp.Variable((n_omega, n_omega)) Z_3 = cp.Variable((n_omega, n_omega)) Z_4 = cp.Variable((n_omega, n_omega)) A_K_tilde_0 = cp.Variable((n_p, n_p)) A_K_tilde_1 = cp.Variable((n_p, n_p)) A_K_tilde_2 = cp.Variable((n_p, n_p)) A_K_tilde_3 = cp.Variable((n_p, n_p)) A_K_tilde_4 = cp.Variable((n_p, n_p)) B_K_tilde_0 = cp.Variable((n_p, n_y)) B_K_tilde_1 = cp.Variable((n_p, n_y)) B_K_tilde_2 = cp.Variable((n_p, n_y)) B_K_tilde_3 = cp.Variable((n_p, n_y)) B_K_tilde_4 = cp.Variable((n_p, n_y)) L_K_tilde_0 = cp.Variable((n_omega, n_p)) L_K_tilde_1 = cp.Variable((n_omega, n_p)) L_K_tilde_2 = cp.Variable((n_omega, n_p)) L_K_tilde_3 = cp.Variable((n_omega, n_p)) L_K_tilde_4 = cp.Variable((n_omega, n_p)) L_d_tilde_0 = cp.Variable((n_omega, n_y)) L_d_tilde_1 = cp.Variable((n_omega, n_y)) L_d_tilde_2 = cp.Variable((n_omega, n_y)) L_d_tilde_3 = cp.Variable((n_omega, n_y)) L_d_tilde_4 = cp.Variable((n_omega, n_y)) L_y_tilde_0 = cp.Variable((n_omega, n_y)) L_y_tilde_1 = cp.Variable((n_omega, n_y)) L_y_tilde_2 = cp.Variable((n_omega, n_y)) L_y_tilde_3 = cp.Variable((n_omega, n_y)) L_y_tilde_4 = cp.Variable((n_omega, n_y)) C_theta_tilde_theta_0 = cp.Variable((n_u, n_p)) C_theta_tilde_theta_1 = cp.Variable((n_u, n_p)) C_theta_tilde_theta_2 = cp.Variable((n_u, n_p)) C_theta_tilde_theta_3 = cp.Variable((n_u, n_p)) C_theta_tilde_theta_4 = cp.Variable((n_u, n_p)) C_theta_tilde_theta_5 = cp.Variable((n_u, n_p)) C_theta_tilde_theta_6 = cp.Variable((n_u, n_p)) A_theta_tilde_theta_0 = cp.Variable((n_p, n_p)) A_theta_tilde_theta_1 = cp.Variable((n_p, n_p)) A_theta_tilde_theta_2 = cp.Variable((n_p, n_p)) A_theta_tilde_theta_3 = cp.Variable((n_p, n_p)) A_theta_tilde_theta_4 = cp.Variable((n_p, n_p)) A_theta_tilde_theta_5 = cp.Variable((n_p, n_p)) A_theta_tilde_theta_6 = cp.Variable((n_p, n_p)) B_theta_tilde_theta_0 = cp.Variable((n_p, n_y)) B_theta_tilde_theta_1 = cp.Variable((n_p, n_y)) B_theta_tilde_theta_2 = cp.Variable((n_p, n_y)) B_theta_tilde_theta_3 = cp.Variable((n_p, n_y)) B_theta_tilde_theta_4 = cp.Variable((n_p, n_y)) B_theta_tilde_theta_5 = cp.Variable((n_p, n_y)) B_theta_tilde_theta_6 = cp.Variable((n_p, n_y)) D_K_theta_0 = cp.Variable((n_u, n_y)) D_K_theta_1 = cp.Variable((n_u, n_y)) D_K_theta_2 = cp.Variable((n_u, n_y)) D_K_theta_3 = cp.Variable((n_u, n_y)) D_K_theta_4 = cp.Variable((n_u, n_y)) D_K_theta_5 = cp.Variable((n_u, n_y)) D_K_theta_6 = cp.Variable((n_u, n_y)) L_K_theta_tilde_theta_0 = cp.Variable((n_omega, n_p)) L_K_theta_tilde_theta_1 = cp.Variable((n_omega, n_p)) L_K_theta_tilde_theta_2 = cp.Variable((n_omega, n_p)) L_K_theta_tilde_theta_3 = cp.Variable((n_omega, n_p)) L_K_theta_tilde_theta_4 = cp.Variable((n_omega, n_p)) L_K_theta_tilde_theta_5 = cp.Variable((n_omega, n_p)) L_K_theta_tilde_theta_6 = cp.Variable((n_omega, n_p)) L_y_theta_tilde_theta_0 = cp.Variable((n_omega, n_y)) L_y_theta_tilde_theta_1 = cp.Variable((n_omega, n_y)) L_y_theta_tilde_theta_2 = cp.Variable((n_omega, n_y)) L_y_theta_tilde_theta_3 = cp.Variable((n_omega, n_y)) L_y_theta_tilde_theta_4 = cp.Variable((n_omega, n_y)) L_y_theta_tilde_theta_5 = cp.Variable((n_omega, n_y)) L_y_theta_tilde_theta_6 = cp.Variable((n_omega, n_y)) E_K_tilde_theta_0 = cp.Variable((n_p, n_u)) E_K_tilde_theta_1 = cp.Variable((n_p, n_u)) E_K_tilde_theta_2 = cp.Variable((n_p, n_u)) E_K_tilde_theta_3 = cp.Variable((n_p, n_u)) E_K_tilde_theta_4 = cp.Variable((n_p, n_u)) E_K_tilde_theta_5 = cp.Variable((n_p, n_u)) E_K_tilde_theta_6 = cp.Variable((n_p, n_u)) F_K_tilde_theta_0 = cp.Variable((n_omega, n_u)) F_K_tilde_theta_1 = cp.Variable((n_omega, n_u)) F_K_tilde_theta_2 = cp.Variable((n_omega, n_u)) F_K_tilde_theta_3 = cp.Variable((n_omega, n_u)) F_K_tilde_theta_4 = cp.Variable((n_omega, n_u)) F_K_tilde_theta_5 = cp.Variable((n_omega, n_u)) F_K_tilde_theta_6 = cp.Variable((n_omega, n_u)) T_bar_theta_0 = cp.Variable((n_u, n_u), diag=True) T_bar_theta_1 = cp.Variable((n_u, n_u), diag=True) T_bar_theta_2 = cp.Variable((n_u, n_u), diag=True) T_bar_theta_3 = cp.Variable((n_u, n_u), diag=True) T_bar_theta_4 = cp.Variable((n_u, n_u), diag=True) T_bar_theta_5 = cp.Variable((n_u, n_u), diag=True) T_bar_theta_6 = cp.Variable((n_u, n_u), diag=True) G_hat_theta_0 = cp.Variable((n_u, 2 * n_p + n_omega)) G_hat_theta_1 = cp.Variable((n_u, 2 * n_p + n_omega)) G_hat_theta_2 = cp.Variable((n_u, 2 * n_p + n_omega)) G_hat_theta_3 = cp.Variable((n_u, 2 * n_p + n_omega)) G_hat_theta_4 = cp.Variable((n_u, 2 * n_p + n_omega)) G_hat_theta_5 = cp.Variable((n_u, 2 * n_p + n_omega)) G_hat_theta_6 = cp.Variable((n_u, 2 * n_p + n_omega)) G_1_hat_theta_0 = cp.Variable((n_u, 2 * n_p + n_omega)) G_1_hat_theta_1 = cp.Variable((n_u, 2 * n_p + n_omega)) G_1_hat_theta_2 = cp.Variable((n_u, 2 * n_p + n_omega)) G_1_hat_theta_3 = cp.Variable((n_u, 2 * n_p + n_omega)) G_1_hat_theta_4 = cp.Variable((n_u, 2 * n_p + n_omega)) G_1_hat_theta_5 = cp.Variable((n_u, 2 * n_p + n_omega)) G_1_hat_theta_6 = cp.Variable((n_u, 2 * n_p + n_omega)) LMI += [cp.bmat([[R, S1], [S1.T, R]]) >> 0] LMI += [(delta - beta) >= 0] for rho_1 in rho_1_vals: for rho_2 in rho_2_vals: A_p, B_p, D_p, C_y, C_z, D_zu, D_zd = Sys_Dyn( rho_1, rho_2, delta_1, W_e, W_u) X = Mat_No_Delay(rho_1, rho_2, X_0, X_1, X_2, X_3, X_4) Y = Mat_No_Delay(rho_1, rho_2, Y_0, Y_1, Y_2, Y_3, Y_4) Z = Mat_No_Delay(rho_1, rho_2, Z_0, Z_1, Z_2, Z_3, Z_4) L_d_tilde = Mat_No_Delay(rho_1, rho_2, L_d_tilde_0, L_d_tilde_1, L_d_tilde_2, L_d_tilde_3, L_d_tilde_4) A_K_tilde = Mat_No_Delay(rho_1, rho_2, A_K_tilde_0, A_K_tilde_1, A_K_tilde_2, A_K_tilde_3, A_K_tilde_4) B_K_tilde = Mat_No_Delay(rho_1, rho_2, B_K_tilde_0, B_K_tilde_1, B_K_tilde_2, B_K_tilde_3, B_K_tilde_4) L_K_tilde = Mat_No_Delay(rho_1, rho_2, L_K_tilde_0, L_K_tilde_1, L_K_tilde_2, L_K_tilde_3, L_K_tilde_4) L_y_tilde = Mat_No_Delay(rho_1, rho_2, L_y_tilde_0, L_y_tilde_1, L_y_tilde_2, L_y_tilde_3, L_y_tilde_4) P_bar = Mat_No_Delay(rho_1, rho_2, P_0, P_1, P_2, P_3, P_4) Q_bar = Mat_No_Delay(rho_1, rho_2, Q_0, Q_1, Q_2, Q_3, Q_4) S_bar = Mat_No_Delay(rho_1, rho_2, S_0, S_1, S_2, S_3, S_4) B_w_hat = cp.bmat([[D_p, (B_p * J)], [(X @ D_p), ((X @ B_p) * J)], [(L_d_tilde @ C_y @ D_p), (Z @ H) + ((L_d_tilde @ C_y @ B_p) * J) ]]) C_hat = cp.bmat([[(C_z @ Y), C_z, (D_zu @ V)], [ np.zeros((C_ew.shape[0], n_p)), np.zeros((C_ew.shape[0], n_p)), C_ew ]]) D_psi = np.block([[-D_zu], [np.zeros((C_ew.shape[0], n_u))]]) D_w = np.block([[D_zd, np.dot(D_zu, J)], [ np.zeros((C_ew.shape[0], n_d)), np.zeros((C_ew.shape[0], n_nu)) ]]) E_hat = cp.bmat( [[E, np.zeros((n_p, n_p)), np.zeros((n_p, n_p))], [(X @ E), np.zeros((n_p, n_p)), np.zeros((n_p, n_p))], [(L_d_tilde @ C_y @ E), np.zeros((n_omega, n_p)), np.zeros((n_omega, n_p))]]) for rho_1_d in rho_1_vals: for rho_2_d in rho_2_vals: L_K_theta_tilde_theta = Mat_Delay( rho_1, rho_1_d, rho_2, rho_2_d, L_K_theta_tilde_theta_0, L_K_theta_tilde_theta_1, L_K_theta_tilde_theta_2, L_K_theta_tilde_theta_3, L_K_theta_tilde_theta_4, L_K_theta_tilde_theta_5, L_K_theta_tilde_theta_6) A_theta_tilde_theta = Mat_Delay( rho_1, rho_1_d, rho_2, rho_2_d, A_theta_tilde_theta_0, A_theta_tilde_theta_1, A_theta_tilde_theta_2, A_theta_tilde_theta_3, A_theta_tilde_theta_4, A_theta_tilde_theta_5, A_theta_tilde_theta_6) B_theta_tilde_theta = Mat_Delay( rho_1, rho_1_d, rho_2, rho_2_d, B_theta_tilde_theta_0, B_theta_tilde_theta_1, B_theta_tilde_theta_2, B_theta_tilde_theta_3, B_theta_tilde_theta_4, B_theta_tilde_theta_5, B_theta_tilde_theta_6) C_theta_tilde_theta = Mat_Delay( rho_1, rho_1_d, rho_2, rho_2_d, C_theta_tilde_theta_0, C_theta_tilde_theta_1, C_theta_tilde_theta_2, C_theta_tilde_theta_3, C_theta_tilde_theta_4, C_theta_tilde_theta_5, C_theta_tilde_theta_6) T_bar_theta = Mat_Delay( rho_1, rho_1_d, rho_2, rho_2_d, T_bar_theta_0, T_bar_theta_1, T_bar_theta_2, T_bar_theta_3, T_bar_theta_4, T_bar_theta_5, T_bar_theta_6) E_K_tilde_theta = Mat_Delay( rho_1, rho_1_d, rho_2, rho_2_d, E_K_tilde_theta_0, E_K_tilde_theta_1, E_K_tilde_theta_2, E_K_tilde_theta_3, E_K_tilde_theta_4, E_K_tilde_theta_5, E_K_tilde_theta_6) F_K_tilde_theta = Mat_Delay( rho_1, rho_1_d, rho_2, rho_2_d, F_K_tilde_theta_0, F_K_tilde_theta_1, F_K_tilde_theta_2, F_K_tilde_theta_3, F_K_tilde_theta_4, F_K_tilde_theta_5, F_K_tilde_theta_6) G_hat_theta = Mat_Delay( rho_1, rho_1_d, rho_2, rho_2_d, G_hat_theta_0, G_hat_theta_1, G_hat_theta_2, G_hat_theta_3, G_hat_theta_4, G_hat_theta_5, G_hat_theta_6) G_1_hat_theta = Mat_Delay( rho_1, rho_1_d, rho_2, rho_2_d, G_1_hat_theta_0, G_1_hat_theta_1, G_1_hat_theta_2, G_1_hat_theta_3, G_1_hat_theta_4, G_1_hat_theta_5, G_1_hat_theta_6) D_K_theta = Mat_Delay(rho_1, rho_1_d, rho_2, rho_2_d, D_K_theta_0, D_K_theta_1, D_K_theta_2, D_K_theta_3, D_K_theta_4, D_K_theta_5, D_K_theta_6) L_y_theta_tilde_theta = Mat_Delay( rho_1, rho_1_d, rho_2, rho_2_d, L_y_theta_tilde_theta_0, L_y_theta_tilde_theta_1, L_y_theta_tilde_theta_2, L_y_theta_tilde_theta_3, L_y_theta_tilde_theta_4, L_y_theta_tilde_theta_5, L_y_theta_tilde_theta_6) Q_bar_delayed = Mat_No_Delay( rho_1_d, rho_2_d, Q_0, Q_1, Q_2, Q_3, Q_4) P_bar_delayed = Mat_No_Delay( rho_1_d, rho_2_d, P_0, P_1, P_2, P_3, P_4) S_h = Mat_No_Delay(rho_1_d, rho_2_d, S_0, S_1, S_2, S_3, S_4) A_d_hat = cp.bmat( [[(B_p @ C_theta_tilde_theta), (B_p @ D_K_theta @ C_y), np.zeros((n_p, n_omega))], [ A_theta_tilde_theta, (B_theta_tilde_theta @ C_y), np.zeros((n_p, n_omega)) ], [ L_K_theta_tilde_theta, (L_y_theta_tilde_theta @ C_y), np.zeros((n_omega, n_omega)) ]]) K_bb_theta = cp.bmat([[ C_theta_tilde_theta, (D_K_theta @ C_y), np.zeros((n_u, n_omega)) ]]) B_psi_hat_theta = cp.bmat([[(-B_p @ T_bar_theta)], [E_K_tilde_theta], [F_K_tilde_theta]]) C_d_hat = cp.bmat([[(D_zu @ C_theta_tilde_theta), (D_zu @ D_K_theta @ C_y), np.zeros((n_z, n_omega))], [ np.zeros( (C_ew.shape[0], n_p)), np.zeros( (C_ew.shape[0], n_p)), np.zeros((C_ew.shape[0], n_omega)) ]]) L_13 = R - S1 + A_d_hat L_14 = S1 L_15 = B_psi_hat_theta + (G_hat_theta.T) - ( K_bb_theta.T) + 2 * (V_bar.T) L_16 = B_w_hat L_17 = C_hat.T L_18 = E_hat L_19 = epsilon * cp.bmat([[(G_A @ Y), G_A, (G_B @ V)], [ np.zeros((n_p, n_p)), np.zeros((n_p, n_p)), np.zeros( (n_p, n_omega)) ], [ np.zeros((n_p, n_p)), np.zeros((n_p, n_p)), np.zeros( (n_p, n_omega)) ]]).T L_22 = -2 * kappa * cp.bmat( [[Y, np.eye(n_p), np.zeros((n_p, n_omega))], [np.eye(n_p), X, np.zeros((n_p, n_omega))], [ np.zeros((n_omega, n_p)), np.zeros((n_omega, n_p)), Z ]]) + (theta_max**2) * R L_23 = kappa * A_d_hat L_24 = np.zeros( (2 * n_p + n_omega, 2 * n_p + n_omega)) L_25 = kappa * B_psi_hat_theta L_26 = kappa * B_w_hat L_27 = np.zeros( (2 * n_p + n_omega, (C_hat.T).shape[1])) L_28 = kappa * E_hat L_29 = np.zeros((2 * n_p + n_omega, 3 * n_p)) L_34 = R - S1.T L_35 = G_1_hat_theta.T + K_bb_theta.T L_36 = np.zeros( (2 * n_p + n_omega, B_w_hat.shape[1])) L_37 = C_d_hat.T L_38 = np.zeros((2 * n_p + n_omega, 3 * n_p)) L_39 = epsilon * (cp.bmat( [[(G_B @ C_theta_tilde_theta), (G_B @ D_K_theta @ C_y), np.zeros((n_p, n_omega))], [ np.zeros((n_p, n_p)), np.zeros((n_p, n_p)), np.zeros((n_p, n_omega)) ], [ np.zeros((n_p, n_p)), np.zeros((n_p, n_p)), np.zeros((n_p, n_omega)) ]])).T L_44 = -S_h - R L_45 = np.zeros( (2 * n_p + n_omega, T_bar_theta.shape[1])) L_46 = np.zeros( (2 * n_p + n_omega, B_w_hat.shape[1])) L_47 = np.zeros( (2 * n_p + n_omega, (C_hat.T).shape[1])) L_48 = np.zeros((2 * n_p + n_omega, 3 * n_p)) L_49 = np.zeros((2 * n_p + n_omega, 3 * n_p)) L_55 = -4 * T_bar_theta L_56 = 2 * J_bar L_57 = T_bar_theta * (D_psi.T) L_58 = np.zeros((T_bar_theta.shape[0], 3 * n_p)) L_59 = epsilon * (T_bar_theta @ (np.block( [[-G_B], [np.zeros( (n_p, n_u))], [np.zeros((n_p, n_u))]])).T) L_66 = -np.eye(B_w_hat.shape[1]) L_67 = D_w.T L_68 = np.zeros(((D_w.T).shape[0], 3 * n_p)) L_69 = epsilon * ((np.block( [[G_D, np.dot(G_B, J)], [np.zeros((n_p, n_d)), np.zeros((n_p, n_nu))], [np.zeros((n_p, n_d)), np.zeros((n_p, n_nu))]])).T) L_77 = -gamma_sq * np.eye((D_w.T).shape[1]) L_78 = np.zeros(((D_w.T).shape[1], 3 * n_p)) L_79 = np.zeros(((D_w.T).shape[1], 3 * n_p)) L_88 = -epsilon * np.eye(3 * n_p) L_89 = np.zeros((3 * n_p, 3 * n_p)) L_99 = -epsilon * np.eye(3 * n_p) for v_1 in v_1_val: for v_2 in v_2_val: P_dot = v_1 * (P_1 + rho_1 * P_2) + v_2 * ( P_3 + rho_2 * P_4) L_d_tilde_dot = v_1 * (L_d_tilde_1 + rho_1 * L_d_tilde_2) + \ v_2 * (L_d_tilde_3 + rho_2 * L_d_tilde_4) A_hat = cp.bmat([ [A_p @ Y, A_p, B_p @ V], [ A_K_tilde, (X @ A_p + B_K_tilde @ C_y), X @ B_p @ V ], [ L_K_tilde, (L_d_tilde @ C_y @ A_p) + (L_d_tilde_dot - L_y_tilde) @ C_y, (Z @ W + L_d_tilde @ C_y @ B_p @ V) ] ]) L_11 = A_hat + A_hat.T + Q_bar + S_bar + P_dot - R L_12 = P_bar - (cp.bmat( [[ Y, np.eye(n_p), np.zeros((n_p, n_omega)) ], [ np.eye(n_p), X, np.zeros((n_p, n_omega)) ], [ np.zeros((n_omega, n_p)), np.zeros((n_omega, n_p)), Z ]])) + kappa * (A_hat.T) for v_3 in v_3_val: L_33 = -2 * R + S1 + S1.T - ( 1 - v_3 * theta_prime) * Q_bar_delayed L = cp.bmat([ [ L_11, L_12, L_13, L_14, L_15, L_16, L_17, L_18, L_19 ], [ L_12.T, L_22, L_23, L_24, L_25, L_26, L_27, L_28, L_29 ], [ L_13.T, L_23.T, L_33, L_34, L_35, L_36, L_37, L_38, L_39 ], [ L_14.T, L_24.T, L_34.T, L_44, L_45, L_46, L_47, L_48, L_49 ], [ L_15.T, L_25.T, L_35.T, L_45.T, L_55, L_56, L_57, L_58, L_59 ], [ L_16.T, L_26.T, L_36.T, L_46.T, L_56.T, L_66, L_67, L_68, L_69 ], [ L_17.T, L_27.T, L_37.T, L_47.T, L_57.T, L_67.T, L_77, L_78, L_79 ], [ L_18.T, L_28.T, L_38.T, L_48.T, L_58.T, L_68.T, L_78.T, L_88, L_89 ], [ L_19.T, L_29.T, L_39.T, L_49.T, L_59.T, L_69.T, L_79.T, L_89.T, L_99 ] ]) LMI += [L << 0] ii += 1 for counter in (range(1, n_u + 1)): LMI_sat_d = cp.bmat([ [ beta * np.eye(n_u), K_bb_theta[:counter, :] - G_1_hat_theta[:counter, :] ], [(K_bb_theta[:counter, :] - G_1_hat_theta[:counter, :]).T, (u_bar[counter - 1]**2) * P_bar_delayed] ]) LMI += [LMI_sat_d >> 0] LMI_sat = cp.bmat( [[ beta * np.eye(n_u), K_bb_theta[:counter, :] - G_hat_theta[:counter, :] ], [(K_bb_theta[:counter, :] - G_hat_theta[:counter, :]).T, (u_bar[counter - 1]**2) * P_bar]]) LMI += [LMI_sat >> 0] LMI += [Q_bar == Q_bar.T] LMI += [Q_bar >> 0] LMI += [S_bar == S_bar.T] LMI += [S_bar >> 0] LMI += [P_bar == P_bar.T] LMI += [P_bar_delayed == P_bar_delayed.T] prob = cp.Problem(cp.Minimize(gamma_sq), LMI) print(ii) print(cp.installed_solvers()) prob.solve(solver=cp.SCS, verbose=True, max_iters=5000, eps=1e-1) # # prob.solve(solver=cp.MOSEK, verbose=True, mosek_params={mosek.dparam.intpnt_co_tol_pfeas: 1.0e-1, # mosek.iparam.intpnt_solve_form: mosek.solveform.primal}) print("optimal value with:", prob.value) print("status:", prob.status) print("gamma=", np.sqrt(gamma_sq.value))
def diamonddist(A, B, mxBasis='gm', dimOrStateSpaceDims=None): """ Returns the approximate diamond norm describing the difference between gate matrices A and B given by : D = ||A - B ||_diamond = sup_rho || AxI(rho) - BxI(rho) ||_1 Parameters ---------- A, B : numpy array The *gate* matrices to use when computing the diamond norm. mxBasis : {"std","gm","pp","qt"}, optional the basis of the gate matrices A and B : standard (matrix units), Gell-Mann, Pauli-product, or Qutrit respectively. dimOrStateSpaceDims : int or list of ints, optional Structure of the density-matrix space, which further specifies the basis of gateMx (see BasisTools). Returns ------- float Diamond norm """ #currently cvxpy is only needed for this function, so don't import until here import cvxpy as _cvxpy # This SDP implementation is a modified version of Kevin's code #Compute the diamond norm #Uses the primal SDP from arXiv:1207.5726v2, Sec 3.2 #Maximize 1/2 ( < J(phi), X > + < J(phi).dag, X.dag > ) #Subject to [[ I otimes rho0, X], # [X.dag, I otimes rho1]] >> 0 # rho0, rho1 are density matrices # X is linear operator #Jamiolkowski representation of the process # J(phi) = sum_ij Phi(Eij) otimes Eij #< A, B > = Tr(A.dag B) #def vec(matrix_in): # # Stack the columns of a matrix to return a vector # return _np.transpose(matrix_in).flatten() # #def unvec(vector_in): # # Slice a vector into columns of a matrix # d = int(_np.sqrt(vector_in.size)) # return _np.transpose(vector_in.reshape( (d,d) )) dim = A.shape[0] smallDim = int(_np.sqrt(dim)) assert (dim == A.shape[1] == B.shape[0] == B.shape[1]) #Code below assumes *un-normalized* Jamiol-isomorphism, so multiply by density mx dimension JAstd = smallDim * _jam.jamiolkowski_iso(A, mxBasis, "std", dimOrStateSpaceDims) JBstd = smallDim * _jam.jamiolkowski_iso(B, mxBasis, "std", dimOrStateSpaceDims) #CHECK: Kevin's jamiolowski, which implements the un-normalized isomorphism: # smallDim * _jam.jamiolkowski_iso(M, "std", "std") #def kevins_jamiolkowski(process, representation = 'superoperator'): # # Return the Choi-Jamiolkowski representation of a quantum process # # Add methods as necessary to accept different representations # process = _np.array(process) # if representation == 'superoperator': # # Superoperator is the linear operator acting on vec(rho) # dimension = int(_np.sqrt(process.shape[0])) # print "dim = ",dimension # jamiolkowski_matrix = _np.zeros([dimension**2, dimension**2], dtype='complex') # for i in range(dimension**2): # Ei_vec= _np.zeros(dimension**2) # Ei_vec[i] = 1 # output = unvec(_np.dot(process,Ei_vec)) # tmp = _np.kron(output, unvec(Ei_vec)) # print "E%d = \n" % i,unvec(Ei_vec) # #print "contrib =",_np.kron(output, unvec(Ei_vec)) # jamiolkowski_matrix += tmp # return jamiolkowski_matrix #JAstd_kev = jamiolkowski(A) #JBstd_kev = jamiolkowski(B) #print "diff A = ",_np.linalg.norm(JAstd_kev/2.0-JAstd) #print "diff B = ",_np.linalg.norm(JBstd_kev/2.0-JBstd) #Kevin's function: def diamondnorm( jamiolkowski_matrix ): jamiolkowski_matrix = JBstd - JAstd # Here we define a bunch of auxiliary matrices because CVXPY doesn't use complex numbers K = jamiolkowski_matrix.real # J.real L = jamiolkowski_matrix.imag # J.imag Y = _cvxpy.Variable(dim, dim) # X.real Z = _cvxpy.Variable(dim, dim) # X.imag sig0 = _cvxpy.Variable(smallDim, smallDim) # rho0.real sig1 = _cvxpy.Variable(smallDim, smallDim) # rho1.real tau0 = _cvxpy.Variable(smallDim, smallDim) # rho1.imag tau1 = _cvxpy.Variable(smallDim, smallDim) # rho1.imag ident = _np.identity(smallDim, 'd') objective = _cvxpy.Maximize(_cvxpy.trace(K.T * Y + L.T * Z)) constraints = [ _cvxpy.bmat( [[_cvxpy.kron(ident, sig0), Y, -_cvxpy.kron(ident, tau0), -Z], [Y.T, _cvxpy.kron(ident, sig1), Z.T, -_cvxpy.kron(ident, tau1)], [_cvxpy.kron(ident, tau0), Z, _cvxpy.kron(ident, sig0), Y], [-Z.T, _cvxpy.kron(ident, tau1), Y.T, _cvxpy.kron(ident, sig1)]]) >> 0, _cvxpy.bmat([[sig0, -tau0], [tau0, sig0]]) >> 0, _cvxpy.bmat([[sig1, -tau1], [tau1, sig1]]) >> 0, sig0 == sig0.T, sig1 == sig1.T, tau0 == -tau0.T, tau1 == -tau1.T, _cvxpy.trace(sig0) == 1., _cvxpy.trace(sig1) == 1. ] prob = _cvxpy.Problem(objective, constraints) try: prob.solve(solver="CVXOPT") # prob.solve(solver="ECOS") # prob.solve(solver="SCS")#This always fails except: _warnings.warn("CVXOPT failed - diamonddist returning -2!") return -2 return prob.value
def bmat(B): return Complex( re=cvxpy.bmat([[element.re for element in row] for row in B]), im=cvxpy.bmat([[element.re for element in row] for row in B]), )
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 cvx_bmat(mat_r, mat_i): """Block matrix for embedding complex matrix in reals""" return cvxpy.bmat([[mat_r, -mat_i], [mat_i, mat_r]])
def init_l2(self, mu=0.05, epsilon=1E-2, init_var=1.5, custom_seed=None): n = self.nx constraints = [] objective = 0.0 if custom_seed is not None: np.random.seed(custom_seed) P = cp.Variable((self.layers, n), 'P') E = [] H = [] M = [] for layer in range(self.layers): Id1 = np.eye(n) Id2 = np.eye(2 * n) # Initialize the forward dynamics W_star = np.random.normal(0, init_var / np.sqrt(n), (n, n)) E += [cp.Variable((n, n), 'E{0:d}'.format(layer))] H += [cp.Variable((n, n), 'H{0:d}'.format(layer))] # Check to see if it is the last layer. If so, loop condition if layer == self.layers - 1: Pc = cp.diag(P[layer]) Pn = cp.diag(P[0]) else: Pc = cp.diag(P[layer]) Pn = cp.diag(P[layer + 1]) M += [ cp.bmat([[E[layer] + E[layer].T - Pc - mu * Id1, H[layer].T], [H[layer], Pn]]) ] constraints += [M[layer] >> epsilon * Id2] objective += cp.norm(W_star @ E[layer] - H[layer], "fro")**2 prob = cp.Problem(cp.Minimize(objective), constraints) print("Beginning Initialization l2") prob.solve(verbose=False, solver=cp.SCS) if prob.status in ["infeasible", "unbounded"]: print("Unable to solve problem") print('Init Complete - status:', prob.status) # Reassign the values after projecting # Must convert from cvxpy -> numpy -> tensor E_np = np.stack(list(map(lambda M: M.value, E)), 0) P_np = np.stack(list(map(lambda M: M.value, P)), 0) self.E.data = torch.Tensor(E_np) self.P.data = torch.Tensor(P_np) for layer in range(self.layers): self.H[layer].weight.data = torch.Tensor(H[layer].value)
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] # Solve the problem prob = cvx.Problem(obj, constraints) prob.solve(solver=cvx.CVXOPT) print 'Status: {0}'.format(prob.status) print 'Results: {0}'.format(prob.value) print 'P: {0}'.format(P.value) print 'Lambda1: {0}'.format(lam1.value)
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")
f_pb = cost if verbose: print('f_PB: ', f_pb) print('x_PB: ', x_pb) return x_pb, f_pb def solve_DB(P0, q0, r0, verbose=True): pass if __name__ == '__main__': # Load data P0 = np.loadtxt('./obligatorio3/data/P.asc') q0 = np.loadtxt('./obligatorio3/data/q.asc').reshape(-1, 1) r0 = np.loadtxt('./obligatorio3/data/r.asc').reshape(1, 1) x_pb, f_pb = solve_PB(P0, q0, r0) t = cp.Variable() l = cp.Variable(n) X = cp.Variable((n + 1, n + 1)) P, q, r = get_P_q_r(P0, q0, r0, l) cost = t constraints = [X == cp.bmat([[P, q], [q.T, r - t]]), X >> 0] problem = cp.Problem(cp.Maximize(cost), constraints) result = problem.solve(verbose=True)
def test_expr_as_np_array(self): """Ensure return type is numpy object.""" expr = cvxpy.bmat([[1, 2], [3, 4]]) res_mat = expr_as_np_array(expr) self.assertEqual(isinstance(res_mat, np.ndarray), True)
def diamond_norm(choi, **kwargs): r"""Return the diamond norm of the input quantum channel object. This function computes the completely-bounded trace-norm (often referred to as the diamond-norm) of the input quantum channel object using the semidefinite-program from reference [1]. Args: choi(Choi or QuantumChannel): a quantum channel object or Choi-matrix array. kwargs: optional arguments to pass to CVXPY solver. Returns: float: The completely-bounded trace norm :math:`\|\mathcal{E}\|_{\diamond}`. Raises: QiskitError: if CVXPY package cannot be found. Additional Information: The input to this function is typically *not* a CPTP quantum channel, but rather the *difference* between two quantum channels :math:`\|\Delta\mathcal{E}\|_\diamond` where :math:`\Delta\mathcal{E} = \mathcal{E}_1 - \mathcal{E}_2`. Reference: J. Watrous. "Simpler semidefinite programs for completely bounded norms", arXiv:1207.5726 [quant-ph] (2012). .. note:: This function requires the optional CVXPY package to be installed. Any additional kwargs will be passed to the ``cvxpy.solve`` function. See the CVXPY documentation for information on available SDP solvers. """ _cvxpy_check("`diamond_norm`") # Check CVXPY is installed choi = Choi(_input_formatter(choi, Choi, "diamond_norm", "choi")) def cvx_bmat(mat_r, mat_i): """Block matrix for embedding complex matrix in reals""" return cvxpy.bmat([[mat_r, -mat_i], [mat_i, mat_r]]) # Dimension of input and output spaces dim_in = choi._input_dim dim_out = choi._output_dim size = dim_in * dim_out # SDP Variables to convert to real valued problem r0_r = cvxpy.Variable((dim_in, dim_in)) r0_i = cvxpy.Variable((dim_in, dim_in)) r0 = cvx_bmat(r0_r, r0_i) r1_r = cvxpy.Variable((dim_in, dim_in)) r1_i = cvxpy.Variable((dim_in, dim_in)) r1 = cvx_bmat(r1_r, r1_i) x_r = cvxpy.Variable((size, size)) x_i = cvxpy.Variable((size, size)) iden = sparse.eye(dim_out) # Watrous uses row-vec convention for his Choi matrix while we use # col-vec. It turns out row-vec convention is requried for CVXPY too # since the cvxpy.kron function must have a constant as its first argument. c_r = cvxpy.bmat([[cvxpy.kron(iden, r0_r), x_r], [x_r.T, cvxpy.kron(iden, r1_r)]]) c_i = cvxpy.bmat([[cvxpy.kron(iden, r0_i), x_i], [-x_i.T, cvxpy.kron(iden, r1_i)]]) c = cvx_bmat(c_r, c_i) # Convert col-vec convention Choi-matrix to row-vec convention and # then take Transpose: Choi_C -> Choi_R.T choi_rt = np.transpose( np.reshape(choi.data, (dim_in, dim_out, dim_in, dim_out)), (3, 2, 1, 0) ).reshape(choi.data.shape) choi_rt_r = choi_rt.real choi_rt_i = choi_rt.imag # Constraints cons = [ r0 >> 0, r0_r == r0_r.T, r0_i == -r0_i.T, cvxpy.trace(r0_r) == 1, r1 >> 0, r1_r == r1_r.T, r1_i == -r1_i.T, cvxpy.trace(r1_r) == 1, c >> 0, ] # Objective function obj = cvxpy.Maximize(cvxpy.trace(choi_rt_r @ x_r) + cvxpy.trace(choi_rt_i @ x_i)) prob = cvxpy.Problem(obj, cons) sol = prob.solve(**kwargs) return sol
def seb_lmi_init(self, epsilon=1E-3, gamma=1e3, init_var=1.5, custom_seed=None): n = self.nx m = self.nx p = self.nx # Take the all states as measurements W = self.width L = self.layers solver_res = 1E-5 if custom_seed is not None: np.random.seed(custom_seed) constraints = [] objective = 0.0 P0 = cp.Variable((n, n), 'P0') P = cp.Variable((self.layers + 1, W), 'P') E = [] H = [] B = np.eye(n) # C = cp.Variable((p, n), 'C') C = np.eye(p) # C = np.array([[1, 0, 0, 0], [0, 0, 1, 0]]) M = [] for layer in range(self.layers + 2): # First layer if layer == 0: # Initialize the forward dynamics W_star = np.random.normal(0, init_var / np.sqrt(n), (W, n)) E += [cp.Variable((n, n), 'E{0:d}'.format(layer))] H += [cp.Variable((W, n), 'H{0:d}'.format(layer))] Pc = (P0) # Pc = cp.diag(P0) Pn = cp.diag(P[0]) M = cp.bmat([[E[0] + E[0].T - Pc, H[0].T, C.T], [H[0], Pn, np.zeros((W, p))], [C, np.zeros((p, W)), np.eye(p)]]) # Last Layer elif layer == self.layers + 1: # Initialize the forward dynamics W_star = np.random.normal(0, init_var / np.sqrt(n), (n, W)) E += [cp.Variable((W, W), 'E{0:d}'.format(layer))] H += [cp.Variable((n, W), 'H{0:d}'.format(layer))] # Bad variable names :( # Indexing seems off becuase P0 is the first P not P[0] Pc = cp.diag(P[layer - 1]) # Pn = cp.diag(P0) Pn = (P0) M = cp.bmat([[ E[layer] + E[layer].T - Pc, np.zeros((W, m)), H[layer].T ], [np.zeros((m, W)), gamma**2 * np.eye(m), E[0].T], [H[layer], E[0], Pn]]) # Middle layers else: # Initialize the forward dynamics W_star = np.random.normal(0, init_var / np.sqrt(W), (W, W)) E += [cp.Variable((W, W), 'E{0:d}'.format(layer))] H += [cp.Variable((W, W), 'H{0:d}'.format(layer))] # Indexing seems off because the first P is actually P0 Pc = cp.diag(P[layer - 1]) Pn = cp.diag(P[layer]) M = cp.bmat([[E[layer] + E[layer].T - Pc, H[layer].T], [H[layer], Pn]]) q = M.shape[0] constraints += [M - (epsilon + solver_res) * np.eye(q) >> 0] objective += cp.norm(W_star @ E[layer] - H[layer], "fro")**2 prob = cp.Problem(cp.Minimize(objective), constraints) print("Beginning Initialization l2") prob.solve(verbose=False, solver=cp.SCS, max_iters=5000) if prob.status in ["infeasible", "unbounded"]: print("Unable to solve problem") else: print('Init Complete - status:' + prob.status) # Reassign the values after projecting # Must convert from cvxpy -> numpy -> tensor for layer in range(self.layers + 2): self.E[layer].data = torch.Tensor(E[layer].value) self.H[layer].weight.data = torch.Tensor(H[layer].value) if layer == 0: self.P[layer].data = torch.Tensor(P0.value) else: self.P[layer].data = torch.Tensor(P[layer - 1].value)
def build_solve_opt(self, x_orig, y, features_whitelist=None): """Builds and solves the SDP. Parameters ---------- x_orig : `numpy.ndarray` The original data point. y : `int` or `float` The requested prediction of the counterfactual - e.g. a class label. features_whitelist : `list(int)`, optional List of feature indices (dimensions of the input space) that can be used when computing the counterfactual. If `features_whitelist` is None, all features can be used. The default is None. Returns ------- `numpy.ndarray` The solution of the optimization problem. If no solution exists, `None` is returned. """ dim = x_orig.shape[0] # Variables X = cp.Variable((dim, dim), symmetric=True) x = cp.Variable((dim, 1)) one = np.array([[1]]).reshape(1, 1) I = np.eye(dim) # Construct constraints constraints = self._build_constraints(X, x, y) constraints += [cp.bmat([[X, x], [x.T, one]]) >> 0] # If requested, fix some features if features_whitelist is not None: A = [] a = [] for j in range(dim): if j not in features_whitelist: t = np.zeros(dim) t[j] = 1. A.append(t) a.append(x_orig[j]) if len(A) != 0: A = np.array(A) a = np.array(a) constraints += [A @ x == a] # Build the final program f = cp.Minimize(cp.trace(I @ X) - 2. * x.T @ x_orig) prob = cp.Problem(f, constraints) # Solve it! self._solve(prob) return x.value.reshape(dim)
def cvx_fit(data, basis_matrix, weights=None, PSD=True, trace=None, trace_preserving=False, **kwargs): """ Reconstruct a quantum state using CVXPY convex optimization. Args: data (vector like): vector of expectation values basis_matrix (matrix like): matrix of measurement operators weights (vector like, optional): vector of weights to apply to the objective function (default: None) PSD (bool, optional): Enforced the fitted matrix to be positive semidefinite (default: True) trace (int, optional): trace constraint for the fitted matrix (default: None). trace_preserving (bool, optional): Enforce the fitted matrix to be trace preserving when fitting a Choi-matrix in quantum process tomography (default: False). **kwargs (optional): kwargs for cvxpy solver. Returns: The fitted matrix rho that minimizes ||basis_matrix * vec(rho) - data||_2. Additional Information: Objective function ------------------ This fitter solves the constrained least-squares minimization: minimize: ||a * x - b ||_2 subject to: x >> 0 (PSD, optional) trace(x) = t (trace, optional) partial_trace(x) = identity (trace_preserving, optional) where: a is the matrix of measurement operators a[i] = vec(M_i).H b is the vector of expectation value data for each projector b[i] ~ Tr[M_i.H * x] = (a * x)[i] x is the vectorized density matrix (or Choi-matrix) to be fitted PSD constraint -------------- The PSD keyword constrains the fitted matrix to be postive-semidefinite, which makes the optimization problem a SDP. If PSD=False the fitted matrix will still be constrained to be Hermitian, but not PSD. In this case the optimization problem becomes a SOCP. Trace constraint ---------------- The trace keyword constrains the trace of the fitted matrix. If trace=None there will be no trace constraint on the fitted matrix. This constraint should not be used for process tomography and the trace preserving constraint should be used instead. Trace preserving (TP) constraint -------------------------------- The trace_preserving keyword constrains the fitted matrix to be TP. This should only be used for process tomography, not state tomography. Note that the TP constraint implicitly enforces the trace of the fitted matrix to be equal to the square-root of the matrix dimension. If a trace constraint is also specified that differs from this value the fit will likely fail. CVXPY Solvers: ------- Various solvers can be called in CVXPY using the `solver` keyword argument. Solvers included in CVXPY are: 'CVXOPT': SDP and SOCP (default solver) 'SCS' : SDP and SOCP 'ECOS' : SOCP only See the documentation on CVXPY for more information on solvers. """ # Check if CVXPY package is installed if cvxpy is None: raise Exception('CVXPY is not installed. Use `mle_fit` instead.') # Check CVXPY version else: version = cvxpy.__version__ if not (version[0] == '1' or version[:3] == '0.4'): raise Exception('Incompatible CVXPY version. Install 1.0 or 0.4') # SDP VARIABLES # Since CVXPY only works with real variables we must specify the real # and imaginary parts of rho seperately: rho = rho_r + 1j * rho_i dim = int(np.sqrt(basis_matrix.shape[1])) if version[:3] == '0.4': # Compatibility with legacy 0.4 rho_r = cvxpy.Variable(dim, dim) rho_i = cvxpy.Variable(dim, dim) else: rho_r = cvxpy.Variable((dim, dim)) rho_i = cvxpy.Variable((dim, dim)) # CONSTRAINTS # The constraint that rho is Hermitian (rho.H = rho) # transforms to the two constraints # 1. rho_r.T = rho_r.T (real part is symmetric) # 2. rho_i.T = -rho_i.T (imaginary part is anti-symmetric) cons = [rho_r == rho_r.T, rho_i == -rho_i.T] # Trace constraint: note this should not be used at the same # time as the trace preserving constraint. if trace is not None: cons.append(cvxpy.trace(rho_r) == trace) # Since we can only work with real matrices in CVXPY we can specify # a complex PSD constraint as # rho >> 0 iff [[rho_r, -rho_i], [rho_i, rho_r]] >> 0 if PSD is True: rho = cvxpy.bmat([[rho_r, -rho_i], [rho_i, rho_r]]) cons.append(rho >> 0) # Trace preserving constraint when fiting Choi-matrices for # quantum process tomography. Note that this adds an implicity # trace constraint of trace(rho) = sqrt(len(rho)) = dim # if a different trace constraint is specified above this will # cause the fitter to fail. if trace_preserving is True: sdim = int(np.sqrt(dim)) ptr = partial_trace_super(sdim, sdim) cons.append(ptr * cvxpy.vec(rho_r) == np.identity(sdim).ravel()) # OBJECTIVE FUNCTION # The function we wish to minimize is || arg ||_2 where # arg = bm * vec(rho) - data # Since we are working with real matrices in CVXPY we expand this as # bm * vec(rho) = (bm_r + 1j * bm_i) * vec(rho_r + 1j * rho_i) # = bm_r * vec(rho_r) - bm_i * vec(rho_i) # + 1j * (bm_r * vec(rho_i) + bm_i * vec(rho_r)) # = bm_r * vec(rho_r) - bm_i * vec(rho_i) # where we drop the imaginary part since the expectation value is real bm_r = np.real(basis_matrix) bm_i = np.imag(basis_matrix) # CVXPY doesn't seem to handle sparse matrices very well so we convert # sparse matrices to Numpy arrays. if isinstance(basis_matrix, sps.spmatrix): bm_r = bm_r.todense() bm_i = bm_i.todense() arg = bm_r * cvxpy.vec(rho_r) - bm_i * cvxpy.vec(rho_i) - np.array(data) # Add weights vector if specified if weights is not None: # normalie weights? weights = np.array(weights) weights = weights / np.sqrt(sum(weights**2)) arg = cvxpy.diag(weights) * arg # SDP objective function obj = cvxpy.Minimize(cvxpy.norm(arg, p=2)) # Solve SDP prob = cvxpy.Problem(obj, cons) iters = 5000 max_iters = kwargs.get('max_iters', 20000) if 'solver' not in kwargs: kwargs['solver'] = 'CVXOPT' # make CVXOPT default solver problem_solved = False while not problem_solved: kwargs['max_iters'] = iters kwargs['solver'] = 'CVXOPT' prob.solve(**kwargs) if prob.status in ["optimal_inaccurate", "optimal"]: problem_solved = True elif prob.status == "unbounded_inaccurate": if iters < max_iters: iters *= 2 else: raise RuntimeError( "CVX fit failed, probably not enough iterations for the " "solver") elif prob.status in ["infeasible", "unbounded"]: raise RuntimeError( "CVX fit failed, problem status {} which should not " "happen".format(prob.status)) else: raise RuntimeError("CVX fit failed, reason unknown") rho_fit = rho_r.value + 1j * rho_i.value return rho_fit
def setNashEqConstraints(self): ''' Creation of the set of Nash Equilibrium constraint. ''' for playerId in range(self.game.nbPlayers): payoutVec = [] # Payout if he follow advice for question in self.game.questions(): for validAnswer in self.game.validAnswerIt(question): payoutVec.append( self.genVecPlayerPayoutWin(validAnswer, question, playerId)) payoutVec = self.game.questionDistribution * np.array( payoutVec).transpose() # Payout for strat which diverge from advice for type in ['0', '1']: for noti in ['0', '1']: payoutVecNot = [] for question in self.game.questions(): #Answers where the player doesn't defect from its advice untouchedAnswers = lambda answer: question[ playerId] != type or answer[playerId] != noti #Answers where the player defect from its advice notAnswers = lambda answer: question[ playerId] == type and answer[playerId] == noti # if he is not involved, the set of accepted answer is the same if playerId not in self.game.involvedPlayers(question): #The player is not involved, the set of accepted question stay the same for validAnswer in filter( untouchedAnswers, self.game.validAnswerIt(question)): payoutVecNot.append( self.genVecPlayerPayoutWin( validAnswer, question, playerId)) for validAnswer in filter( notAnswers, self.game.validAnswerIt(question)): payoutVecNot.append( self.genVecPlayerNotPayoutWin( validAnswer, question, playerId)) #The player is involved. He loose on the accepted answer where he defect. But some rejected answers #are now accepted. else: for validAnswer in filter( untouchedAnswers, self.game.validAnswerIt(question)): payoutVecNot.append( self.genVecPlayerPayoutWin( validAnswer, question, playerId)) for validAnswer in filter( notAnswers, self.game.wrongAnswerIt(question)): payoutVecNot.append( self.genVecPlayerNotPayoutWin( validAnswer, question, playerId)) payoutVecNot = self.game.questionDistribution * np.array( payoutVecNot).transpose() self.constraints.append( cp.sum(self.X[0] @ cp.bmat( (payoutVec - payoutVecNot))) >= 0) self.updateProb()
def __init__(self, game, operatorsPlayers, level=1, other_monomes=None): self.game = game self.level = level # Creation of the list of monomials. self.operatorsPlayers = operatorsPlayers monomeList = [list(s) for s in itertools.product(*operatorsPlayers) ] # 1 + AB + AC + BC + ABC self.monomeList = reduce_monome_list(monomeList, operatorsPlayers) if level == 2: for player in range(self.game.nbPlayers): assert (self.game.nbPlayers == 3) # changer pour 5 joueurs self.monomeList += [ list(s) for s in itertools.product(operatorsPlayers[player], operatorsPlayers[player], [0]) ] # AA' self.monomeList = reduce_monome_list(self.monomeList, operatorsPlayers) if level == 3: monomes = [ list(s) for s in itertools.product(list( range(2 * self.game.nbPlayers + 1)), repeat=self.game.nbPlayers) ] #0....2*nbPlayer self.monomeList = reduce_monome_list(monomes, operatorsPlayers) if level == 6: #Add lvl 3 monomes monomes = [ list(s) for s in itertools.product(list( range(2 * self.game.nbPlayers + 1)), repeat=self.game.nbPlayers) ] #0....2*nbPlayer #Add lvl 6 ops = itertools.chain( *zip(operatorsPlayers, operatorsPlayers) ) # [ops1, ops1, ops2, ops2, ops3, ops3....] => AA'BB'CC' monomes += [list(s) for s in itertools.product(*ops)] self.monomeList = reduce_monome_list(monomes, operatorsPlayers, monomeSize=6) if other_monomes != None: assert (type(other_monomes) == list) size = max(map(lambda mon: len(mon), other_monomes)) self.monomeList += other_monomes self.monomeList = reduce_monome_list(self.monomeList, operatorsPlayers, monomeSize=size) self.n = len(self.monomeList) print(self.n) # Dict for reducing the numbers of SDP variables. self.variableDict = {} self.variablePosition = {} # Constraints and SDP variables. self.constraints = [] self.X = cp.bmat(self.init_variables()) self.constraints += [self.X >> 0] #SDP self.constraints += [self.X[0][0] == 1] #Normalization # Objectif function and cvxpy problem. self.objectifFunc = self.objectifFunctions(game) self.prob = cp.Problem( cp.Maximize(cp.sum(self.X[0] @ cp.bmat(self.objectifFunc))), self.constraints)
def diamonddist(A, B, mxBasis='gm', dimOrStateSpaceDims=None): """ Returns the approximate diamond norm describing the difference between gate matrices A and B given by : D = ||A - B ||_diamond = sup_rho || AxI(rho) - BxI(rho) ||_1 Parameters ---------- A, B : numpy array The *gate* matrices to use when computing the diamond norm. mxBasis : {"std","gm","pp"}, optional the basis of the gate matrices A and B : standard (matrix units), Gell-Mann, or Pauli-product, respectively. dimOrStateSpaceDims : int or list of ints, optional Structure of the density-matrix space, which further specifies the basis of gateMx (see BasisTools). Returns ------- float Diamond norm """ #currently cvxpy is only needed for this function, so don't import until here import cvxpy as _cvxpy # This SDP implementation is a modified version of Kevin's code #Compute the diamond norm #Uses the primal SDP from arXiv:1207.5726v2, Sec 3.2 #Maximize 1/2 ( < J(phi), X > + < J(phi).dag, X.dag > ) #Subject to [[ I otimes rho0, X], # [X.dag, I otimes rho1]] >> 0 # rho0, rho1 are density matrices # X is linear operator #Jamiolkowski representation of the process # J(phi) = sum_ij Phi(Eij) otimes Eij #< A, B > = Tr(A.dag B) #def vec(matrix_in): # # Stack the columns of a matrix to return a vector # return _np.transpose(matrix_in).flatten() # #def unvec(vector_in): # # Slice a vector into columns of a matrix # d = int(_np.sqrt(vector_in.size)) # return _np.transpose(vector_in.reshape( (d,d) )) dim = A.shape[0] smallDim = int(_np.sqrt(dim)) assert(dim == A.shape[1] == B.shape[0] == B.shape[1]) #Code below assumes *un-normalized* Jamiol-isomorphism, so multiply by density mx dimension JAstd = smallDim * _jam.jamiolkowski_iso(A, mxBasis, "std", dimOrStateSpaceDims) JBstd = smallDim * _jam.jamiolkowski_iso(B, mxBasis, "std", dimOrStateSpaceDims) #CHECK: Kevin's jamiolowski, which implements the un-normalized isomorphism: # smallDim * _jam.jamiolkowski_iso(M, "std", "std") #def kevins_jamiolkowski(process, representation = 'superoperator'): # # Return the Choi-Jamiolkowski representation of a quantum process # # Add methods as necessary to accept different representations # process = _np.array(process) # if representation == 'superoperator': # # Superoperator is the linear operator acting on vec(rho) # dimension = int(_np.sqrt(process.shape[0])) # print "dim = ",dimension # jamiolkowski_matrix = _np.zeros([dimension**2, dimension**2], dtype='complex') # for i in range(dimension**2): # Ei_vec= _np.zeros(dimension**2) # Ei_vec[i] = 1 # output = unvec(_np.dot(process,Ei_vec)) # tmp = _np.kron(output, unvec(Ei_vec)) # print "E%d = \n" % i,unvec(Ei_vec) # #print "contrib =",_np.kron(output, unvec(Ei_vec)) # jamiolkowski_matrix += tmp # return jamiolkowski_matrix #JAstd_kev = jamiolkowski(A) #JBstd_kev = jamiolkowski(B) #print "diff A = ",_np.linalg.norm(JAstd_kev/2.0-JAstd) #print "diff B = ",_np.linalg.norm(JBstd_kev/2.0-JBstd) #Kevin's function: def diamondnorm( jamiolkowski_matrix ): jamiolkowski_matrix = JBstd-JAstd # Here we define a bunch of auxiliary matrices because CVXPY doesn't use complex numbers K = jamiolkowski_matrix.real # J.real L = jamiolkowski_matrix.imag # J.imag Y = _cvxpy.Variable(dim, dim) # X.real Z = _cvxpy.Variable(dim, dim) # X.imag sig0 = _cvxpy.Variable(smallDim,smallDim) # rho0.real sig1 = _cvxpy.Variable(smallDim,smallDim) # rho1.real tau0 = _cvxpy.Variable(smallDim,smallDim) # rho1.imag tau1 = _cvxpy.Variable(smallDim,smallDim) # rho1.imag ident = _np.identity(smallDim, 'd') objective = _cvxpy.Maximize( _cvxpy.trace( K.T * Y + L.T * Z) ) constraints = [ _cvxpy.bmat( [ [ _cvxpy.kron(ident, sig0), Y, -_cvxpy.kron(ident, tau0), -Z], [ Y.T, _cvxpy.kron(ident, sig1), Z.T, -_cvxpy.kron(ident, tau1)], [ _cvxpy.kron(ident, tau0), Z, _cvxpy.kron(ident, sig0), Y], [ -Z.T, _cvxpy.kron(ident, tau1), Y.T, _cvxpy.kron(ident, sig1)]] ) >> 0, _cvxpy.bmat( [[sig0, -tau0], [tau0, sig0]] ) >> 0, _cvxpy.bmat( [[sig1, -tau1], [tau1, sig1]] ) >> 0, sig0 == sig0.T, sig1 == sig1.T, tau0 == -tau0.T, tau1 == -tau1.T, _cvxpy.trace(sig0) == 1., _cvxpy.trace(sig1) == 1. ] prob = _cvxpy.Problem(objective, constraints) # try: prob.solve(solver="CVXOPT") # prob.solve(solver="ECOS") # prob.solve(solver="SCS")#This always fails # except: # return -1 return prob.value
vecmat = M0.reshape(n * n, order='F') #Draw linear map A = np.random.randn(6 * n, n * n) #y = incomplete information about M0 y = np.matmul(A, vecmat) #Optimize X = cvxpy.Variable((n, n)) Y = cvxpy.Variable((n, n)) M = cvxpy.Variable((n, n)) Z = cvxpy.Variable((2 * n, 2 * n), PSD=True) objective = cvxpy.Minimize(cvxpy.trace(X + Y) / 2) constr1 = Z == cvxpy.bmat([[cvxpy.multiply(0.5, (X + X.T)), M], [M.T, cvxpy.multiply(0.5, (Y + Y.T))]]) constr2 = y == A * cvxpy.vec(M) constraints = [constr1, constr2] prob = cvxpy.Problem(objective, constraints) #Wallclock time start_inner = time.time() prob.solve(solver=s, verbose=True) end_inner = time.time() time_inner[j] = end_inner - start_inner print("\nsingle solve call wallclock time = " + str(time_inner[j])) #Get results M1 = M.value fmat.append(np.linalg.norm(M1.reshape(n * n, order='F') - vecmat))