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
示例#2
0
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
示例#4
0
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
示例#5
0
def test_is_unitary_random():
    """Test that random unitary matrix returns True."""
    mat = random_unitary(2)
    np.testing.assert_equal(is_unitary(mat), True)
示例#6
0
def test_random_unitary_not_real():
    """Generate random non-real unitary matrix."""
    mat = random_unitary(2)
    np.testing.assert_equal(is_unitary(mat), True)
示例#7
0
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)
示例#8
0
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)
示例#9
0
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)
示例#10
0
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))