def genPOVMs(self): ''' Initialise each player with random POVMs ''' opDict = {} for playerId in range(self.nbJoueurs): povms = random_povm( self.dimension, 2, self.dimension) # dim = 2, nbInput = 2, nbOutput = 2 for type in ["0", "1"]: # Generate a unitary to use to make a random projective measurement U = random_unitary(self.dimension) for answer in ["0", "1"]: # TODO: Generalise to higher dimension if (self.dimension > 2): print( "Mauvaise implémentation de la dimension, cf seesaw - ligne 63" ) exit(0) proj = np.transpose([U[int(answer)]]) opDict[str(playerId) + answer + type] = pure_to_mixed(proj) return opDict
def test_in_separable_ball_eigs_false(): """Test eigenvalues of matrix not in separable ball returns False.""" u_mat = random_unitary(4) lam = np.array([1.01, 1, 0.99, 0]) / 3 rho = u_mat @ np.diag(lam) @ u_mat.conj().T eig_vals = np.linalg.eigvalsh(rho) np.testing.assert_equal(in_separable_ball(eig_vals), False)
def quantum_value_lower_bound(self, iters: int = 5, tol: float = 10e-6) -> float: r""" Calculate lower bound on the quantum value of an extended nonlocal game. Test :return: The quantum value of the extended nonlocal game. """ # Get number of inputs and outputs for Bob's measurements. _, _, _, num_outputs_bob, _, num_inputs_bob = self.pred_mat.shape best_lower_bound = float("-inf") for _ in range(iters): # Generate a set of random POVMs for Bob. These measurements serve as a # rough starting point for the alternating projection algorithm. bob_povms = defaultdict(int) for y_ques in range(num_inputs_bob): random_mat = random_unitary(num_outputs_bob) for b_ans in range(num_outputs_bob): random_mat_trans = random_mat[:, b_ans].conj().T.reshape( -1, 1) bob_povms[y_ques, b_ans] = random_mat[:, b_ans] * random_mat_trans # Run the alternating projection algorithm between the two SDPs. it_diff = 1 prev_win = -1 best = float("-inf") while it_diff > tol: # Optimize over Alice's measurement operators while fixing Bob's. # If this is the first iteration, then the previously randomly # generated operators in the outer loop are Bob's. Otherwise, Bob's # operators come from running the next SDP. rho, lower_bound = self.__optimize_alice(bob_povms) bob_povms, lower_bound = self.__optimize_bob(rho) it_diff = lower_bound - prev_win prev_win = lower_bound # As the SDPs keep alternating, check if the winning probability # becomes any higher. If so, replace with new best. if best < lower_bound: best = lower_bound if best_lower_bound < best: best_lower_bound = best return best_lower_bound
def genRandomPOVMs(nbJoueurs, dimension=2): ''' Initialise each player with random POVMs ''' opDict = {} for playerId in range(nbJoueurs): for type in ["0", "1"]: U = random_unitary(dimension) for answer in ["0", "1"]: if (dimension > 2): print( "Mauvaise implémentation de la dimension, cf seesaw - ligne 63" ) exit(0) proj = np.transpose([U[int(answer)]]) opDict[str(playerId) + answer + type] = pure_to_mixed(proj) return opDict
def test_is_unitary_random(): """Test that random unitary matrix returns True.""" mat = random_unitary(2) np.testing.assert_equal(is_unitary(mat), True)
def test_random_unitary_not_real(): """Generate random non-real unitary matrix.""" mat = random_unitary(2) np.testing.assert_equal(is_unitary(mat), True)
def test_random_unitary_vec_dim(): """Generate random non-real unitary matrix.""" mat = random_unitary([4, 4], True) np.testing.assert_equal(is_unitary(mat), True)
def test_in_separable_ball_matrix_true(): """Test matrix in separable ball returns True.""" u_mat = random_unitary(4) lam = np.array([1, 1, 1, 0]) / 3 rho = u_mat @ np.diag(lam) @ u_mat.conj().T np.testing.assert_equal(in_separable_ball(rho), True)
def test_in_separable_ball_matrix_false(): """Test matrix not in separable ball returns False.""" u_mat = random_unitary(4) lam = np.array([1.01, 1, 0.99, 0]) / 3 rho = u_mat @ np.diag(lam) @ u_mat.conj().T np.testing.assert_equal(in_separable_ball(rho), False)
def random_density_matrix( dim: int, is_real: bool = False, k_param: Union[List[int], int] = None, distance_metric: str = "haar", ) -> np.ndarray: r""" Generate a random density matrix. Generates a random :code:`dim`-by-:code:`dim` density matrix distributed according to the Hilbert-Schmidt measure. The matrix is of rank <= :code:`k_param` distributed according to the distribution :code:`distance_metric` If :code:`is_real = True`, then all of its entries will be real. The variable :code:`distance_metric` must be one of: - :code:`haar` (default): Generate a larger pure state according to the Haar measure and trace out the extra dimensions. Sometimes called the Hilbert-Schmidt measure when :code:`k_param = dim`. - :code:`bures`: The Bures measure. Examples ========== Using :code:`toqito`, we may generate a random complex-valued :math:`n`- dimensional density matrix. For :math:`d=2`, this can be accomplished as follows. >>> from toqito.random import random_density_matrix >>> complex_dm = random_density_matrix(2) >>> complex_dm [[0.34903796+0.j 0.4324904 +0.103298j] [0.4324904 -0.103298j 0.65096204+0.j ]] We can verify that this is in fact a valid density matrix using the :code:`is_denisty` function from :code:`toqito` as follows >>> from toqito.matrix_props import is_density >>> is_density(complex_dm) True We can also generate random density matrices that are real-valued as follows. >>> from toqito.random import random_density_matrix >>> real_dm = random_density_matrix(2, is_real=True) >>> real_dm [[0.37330805 0.46466224] [0.46466224 0.62669195]] Again, verifying that this is a valid density matrix can be done as follows. >>> from toqito.matrix_props import is_density >>> is_density(real_dm) True By default, the random density operators are constructed using the Haar measure. We can select to generate the random density matrix according to the Bures metric instead as follows. >>> from toqito.random import random_density_matrix >>> bures_mat = random_density_matrix(2, distance_metric="bures") >>> bures_mat [[0.59937164+0.j 0.45355087-0.18473365j] [0.45355087+0.18473365j 0.40062836+0.j ]] As before, we can verify that this matrix generated is a valid density matrix. >>> from toqito.matrix_props import is_density >>> is_density(bures_mat) True :param dim: The number of rows (and columns) of the density matrix. :param is_real: Boolean denoting whether the returned matrix will have all real entries or not. :param k_param: Default value is equal to :code:`dim`. :param distance_metric: The distance metric used to randomly generate the density matrix. This metric is either the Haar measure or the Bures measure. Default value is to use the Haar measure. :return: A :code:`dim`-by-:code:`dim` random density matrix. """ if k_param is None: k_param = dim # Haar / Hilbert-Schmidt measure. gin = np.random.rand(dim, k_param) if not is_real: gin = gin + 1j * np.random.rand(dim, k_param) if distance_metric == "bures": gin = np.matmul(random_unitary(dim, is_real) + np.identity(dim), gin) rho = np.matmul(gin, np.array(gin).conj().T) return np.divide(rho, np.trace(rho))