def test_permutation_matrix_inconsistent_tuple_sizes(): initial_order = (0, 1, 2) final_order = (0, 2, 1) dimension_subsystems = (2, 2) with assert_raises(RuntimeError): nlg.permutation_matrix(initial_order, final_order, dimension_subsystems)
def linear_constraint_Bob(self): # Permutation matrix (T1...Tn1)(T1...Tn2)(SS) -> (Tn2...T1)(T1...Tn1)(SS) order = np.arange(self.n1 + self.n2 + 2) maskA = order[:self.n1] maskB = np.flip(order[self.n1:self.n1 + self.n2]) maskS = order[self.n1 + self.n2:] mask = np.concatenate((maskB, maskA, maskS)) P = cp.Constant(nlg.permutation_matrix(order, mask, self.subs_TTSS_ext)) # Create dimension tuple for the partial tracing sub_dim = (self.dimT, self.dimT**(self.n1 + self.n2 - 1) * self.dimS**2) for q2 in range(self.dimQ2): for index_else in self.indices_but_A2Q2: indices_a1q1A2q2_ext = [ np.append(index_else, np.array([a2, q2])) for a2 in range(self.dimA2) ] indices_a1q1A2Q2_ext = [ np.append(index_else, index_A2Q2) for index_A2Q2 in self.indices_A2Q2 ] lhs_variable = sum([ self.rho_variable[self.StI(index)] for index in indices_a1q1A2q2_ext ]) lhs = P @ lhs_variable @ P.T rhs_variable = sum([ self.rho_variable[self.StI(index)] for index in indices_a1q1A2Q2_ext ]) rhs_permuted = P @ rhs_variable @ P.T rhs_partial = nlg.partial_trace(rhs_permuted, sub_dim) rhs = self.probQ2[q2] * cp.kron(self.rhoT, rhs_partial) self.constraints.append(lhs - rhs == 0)
def _permutation_constraint(self, order_Alice, order_Bob): # Order for the quantum systems init_order_QS = np.arange(self.n1 + self.n2 + 2) order_SS = np.arange(self.n1 + self.n2, self.n1 + self.n2 + 2) fin_order_qs = np.concatenate( (order_Alice, order_Bob + self.n1, order_SS)) # The permutation matrix swapping the quantum subsystems P = nlg.permutation_matrix(init_order_QS, fin_order_qs, self.subs_TTSS_ext) # The permutation function for the classical indices perm = lambda index: self._permute_index(index, order_Alice, order_Bob) for index in self.indices_A1Q1A2Q2_ext: lhs = self.rho_variable[self.StI(index)] rhs_variable = self.rho_variable[self.StI(perm(index))] rhs = P @ rhs_variable @ P.T self.constraints.append(lhs - rhs == 0)
def test_permutation_matrix_three_subsystems(): initial_order = (0, 1, 2) final_order = (0, 2, 1) dimension_subsystems = (2, 2, 3) expected_matrix = np.array( [[1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.], [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]]) obtained_matrix = nlg.permutation_matrix(initial_order, final_order, dimension_subsystems) np.testing.assert_allclose(expected_matrix, obtained_matrix)
def __init__(self, level, answers, questions, dim_assistance, rule_function, distributions): # Level of the SDP relaxation self.n1, self.n2 = level # Dimension of questions and answers for the game self.dimA1, self.dimA2 = answers self.dimQ1, self.dimQ2 = questions # Dimension of the assisting quantum system self.dimT = dim_assistance self.dimS = dim_assistance # Copy due to swap-trick # Rules of the game self.rule = rule_function # Probability distribution of questions asked by referee self.probQ1, self.probQ2 = distributions # Useful variables for the methods of the class self.subs_A1Q1 = (self.dimA1, self.dimQ1) self.indices_A1Q1 = nlg.indices_list(self.subs_A1Q1) self.subs_A2Q2 = (self.dimA2, self.dimQ2) self.indices_A2Q2 = nlg.indices_list(self.subs_A2Q2) self.subs_A1Q1A2Q2 = self.subs_A1Q1 + self.subs_A2Q2 self.indices_A1Q1A2Q2 = nlg.indices_list(self.subs_A1Q1A2Q2) self.subs_A1Q1A2Q2_ext = self.subs_A1Q1 * self.n1 + self.subs_A2Q2 * self.n2 self.indices_A1Q1A2Q2_ext = nlg.indices_list(self.subs_A1Q1A2Q2_ext) self.subs_but_A1Q1A2Q2 = self.subs_A1Q1 * ( self.n1 - 1) + self.subs_A2Q2 * (self.n2 - 1) self.indices_but_A1Q1A2Q2 = nlg.indices_list(self.subs_but_A1Q1A2Q2) self.subs_but_A1Q1 = self.subs_A1Q1 * (self.n1 - 1) + self.subs_A2Q2 * self.n2 self.indices_but_A1Q1 = nlg.indices_list(self.subs_but_A1Q1) self.subs_but_A2Q2 = self.subs_A1Q1 * self.n1 + self.subs_A2Q2 * ( self.n2 - 1) self.indices_but_A2Q2 = nlg.indices_list(self.subs_but_A2Q2) self.subs_TTSS = (self.dimT, self.dimT, self.dimS, self.dimS) self.subs_TTSS_ext = (self.dimT, ) * (self.n1 + self.n2) + (self.dimS, self.dimS) self.dim_TTSS_ext = fc.reduce(mul, self.subs_TTSS_ext, 1) # Maximally-entangled states between TT|SS self.F_TTSS = cp.Constant( nlg.permutation_matrix((0, 1, 2, 3), (2, 3, 0, 1), self.subs_TTSS)) self.Phi_TTSS = nlg.partial_transpose(self.F_TTSS, self.subs_TTSS, (0, 0, 1, 1)) # Maximally-mixed state on T self.rhoT = np.identity(self.dimT) / self.dimT # Function mapping a sequence of indices to integers self.StI = lambda seq: nlg.seqtoint(seq, self.subs_A1Q1A2Q2_ext) # List of SDP variable self.rho_variable = [] # Objective function of the problem self.object_function = 0 # The list of constraints self.constraints = []