Esempio n. 1
0
    def test_ghz_4_7(self):
        r"""
        The following generates the following GHZ state in `(C^4)^{\otimes 7}`.

        `1/sqrt(30) * (|0000000> + 2|1111111> + 3|2222222> + 4|3333333>)`.
        """
        e0_4 = np.array([[1], [0], [0], [0]])
        e1_4 = np.array([[0], [1], [0], [0]])
        e2_4 = np.array([[0], [0], [1], [0]])
        e3_4 = np.array([[0], [0], [0], [1]])

        expected_res = (
            1
            / np.sqrt(30)
            * (
                tensor(e0_4, e0_4, e0_4, e0_4, e0_4, e0_4, e0_4)
                + 2 * tensor(e1_4, e1_4, e1_4, e1_4, e1_4, e1_4, e1_4)
                + 3 * tensor(e2_4, e2_4, e2_4, e2_4, e2_4, e2_4, e2_4)
                + 4 * tensor(e3_4, e3_4, e3_4, e3_4, e3_4, e3_4, e3_4)
            )
        )

        res = ghz(4, 7, np.array([1, 2, 3, 4]) / np.sqrt(30)).toarray()

        bool_mat = np.isclose(res, expected_res)
        self.assertEqual(np.all(bool_mat), True)
Esempio n. 2
0
    def test_ghz_2_3(self):
        """Produces the 3-qubit GHZ state: `1/sqrt(2) * (|000> + |111>)`."""
        e_0, e_1 = ket(2, 0), ket(2, 1)
        expected_res = 1 / np.sqrt(2) * (tensor(e_0, e_0, e_0) + tensor(e_1, e_1, e_1))

        res = ghz(2, 3).toarray()

        bool_mat = np.isclose(res, expected_res)
        self.assertEqual(np.all(bool_mat), True)
Esempio n. 3
0
    def test_w_state_3(self):
        """The 3-qubit W-state."""
        e_0, e_1 = ket(2, 0), ket(2, 1)
        expected_res = (
            1
            / np.sqrt(3)
            * (tensor(e_1, e_0, e_0) + tensor(e_0, e_1, e_0) + tensor(e_0, e_0, e_1))
        )

        res = w_state(3)

        bool_mat = np.isclose(res, expected_res, atol=0.2)
        self.assertEqual(np.all(bool_mat), True)
Esempio n. 4
0
    def test_counterfeit_attack_wiesner_money(self):
        """Probability of counterfeit attack on Wiesner's quantum money."""
        e_0, e_1 = ket(2, 0), ket(2, 1)
        e_p = (e_0 + e_1) / np.sqrt(2)
        e_m = (e_0 - e_1) / np.sqrt(2)

        e_000 = tensor(e_0, e_0, e_0)
        e_111 = tensor(e_1, e_1, e_1)
        e_ppp = tensor(e_p, e_p, e_p)
        e_mmm = tensor(e_m, e_m, e_m)

        q_a = (1 / 4 * (e_000 * e_000.conj().T + e_111 * e_111.conj().T +
                        e_ppp * e_ppp.conj().T + e_mmm * e_mmm.conj().T))
        res = counterfeit_attack(q_a)
        self.assertEqual(np.isclose(res, 3 / 4), True)
Esempio n. 5
0
    def test_tensor_n_0(self):
        """Test tensor n=0 times."""
        e_0 = ket(2, 0)
        expected_res = None

        res = tensor(e_0, 0)
        self.assertEqual(res, expected_res)
Esempio n. 6
0
    def test_tensor_n_3(self):
        """Test tensor n=3 times."""
        e_0 = ket(2, 0)
        expected_res = np.kron(np.kron(e_0, e_0), e_0)

        res = tensor(e_0, 3)
        bool_mat = np.isclose(res, expected_res)
        self.assertEqual(np.all(bool_mat), True)
Esempio n. 7
0
    def test_tensor_n_1(self):
        """Test tensor n=1 times."""
        e_0 = ket(2, 0)
        expected_res = e_0

        res = tensor(e_0, 1)
        bool_mat = np.isclose(res, expected_res)
        self.assertEqual(np.all(bool_mat), True)
Esempio n. 8
0
    def test_tensor_list_3(self):
        """Test tensor list with three items."""
        e_0, e_1 = ket(2, 0), ket(2, 1)
        expected_res = np.kron(np.kron(e_0, e_1), e_0)

        res = tensor([e_0, e_1, e_0])

        bool_mat = np.isclose(res, expected_res)
        self.assertEqual(np.all(bool_mat), True)
Esempio n. 9
0
    def test_tensor_list_1(self):
        """Test tensor list with one item."""
        e_0 = ket(2, 0)
        expected_res = e_0

        res = tensor([e_0])

        bool_mat = np.isclose(res, expected_res)
        self.assertEqual(np.all(bool_mat), True)
Esempio n. 10
0
    def test_tensor(self):
        """Test standard tensor on vectors."""
        e_0 = ket(2, 0)
        expected_res = np.kron(e_0, e_0)

        res = tensor(e_0, e_0)

        bool_mat = np.isclose(res, expected_res)
        self.assertEqual(np.all(bool_mat), True)
Esempio n. 11
0
    def test_generalized_w_state(self):
        """Generalized 4-qubit W-state."""
        e_0, e_1 = ket(2, 0), ket(2, 1)
        expected_res = (
            1
            / np.sqrt(30)
            * (
                tensor(e_1, e_0, e_0, e_0)
                + 2 * tensor(e_0, e_1, e_0, e_0)
                + 3 * tensor(e_0, e_0, e_1, e_0)
                + 4 * tensor(e_0, e_0, e_0, e_1)
            )
        )

        coeffs = np.array([1, 2, 3, 4]) / np.sqrt(30)
        res = w_state(4, coeffs)

        bool_mat = np.isclose(res, expected_res, atol=0.2)
        self.assertEqual(np.all(bool_mat), True)
Esempio n. 12
0
def counterfeit_attack(q_a: np.ndarray, num_reps: int = 1) -> float:
    r"""
    Compute probability of counterfeiting quantum money [MVW12]_.

    The primal problem for the :math:`n`-fold parallel repetition is given as
    follows:

    .. math::
        \begin{equation}
            \begin{aligned}
                \text{maximize:} \quad & \langle W_{\pi} \left(Q^{\otimes n}
                                         \right) W_{\pi}^*, X \rangle \\
                \text{subject to:} \quad & \text{Tr}_{\mathcal{Y}^{\otimes n}
                                           \otimes \mathcal{Z}^{\otimes n}}(X)
                                           = \mathbb{I}_{\mathcal{X}^{\otimes
                                           n}},\\
                                           & X \in \text{Pos}(
                                           \mathcal{Y}^{\otimes n}
                                           \otimes \mathcal{Z}^{\otimes n}
                                           \otimes \mathcal{X}^{\otimes n})
            \end{aligned}
        \end{equation}

    The dual problem for the :math:`n`-fold parallel repetition is given as
    follows:

    .. math::
            \begin{equation}
                \begin{aligned}
                    \text{minimize:} \quad & \text{Tr}(Y) \\
                    \text{subject to:} \quad & \mathbb{I}_{\mathcal{Y}^{\otimes n}
                    \otimes \mathcal{Z}^{\otimes n}} \otimes Y \geq W_{\pi}
                    \left( Q^{\otimes n} \right) W_{\pi}^*, \\
                    & Y \in \text{Herm} \left(\mathcal{X}^{\otimes n} \right)
                \end{aligned}
            \end{equation}

    Examples
    ==========

    Wiesner's original quantum money scheme [Wies83]_ was shown in [MVW12]_ to
    have an optimal probability of 3/4 for succeeding a counterfeiting attack.

    Specifically, in the single-qubit case, Wiesner's quantum money scheme
    corresponds to the following ensemble:

    .. math::
        \left{
            \left( \frac{1}{4}, |0\rangle \right),
            \left( \frac{1}{4}, |1\rangle \right),
            \left( \frac{1}{4}, |+\rangle \right),
            \left( \frac{1}{4}, |-\rangle \right)
        \right},

    which yields the operator

    .. math::
        Q = \frac{1}{4} \left(
            |000\rangle + \langle 000| + |111\rangle \langle 111| +
            |+++\rangle + \langle +++| + |---\rangle \langle ---|
        \right)

    We can see that the optimal value we obtain in solving the SDP is 3/4.

    >>> from toqito.states.operations.tensor import tensor
    >>> from toqito.core.ket import ket
    >>> import numpy as np
    >>> e_0, e_1 = ket(2, 0), ket(2, 1)
    >>> e_p = (e_0 + e_1) / np.sqrt(2)
    >>> e_m = (e_0 - e_1) / np.sqrt(2)
    >>>
    >>> e_000 = tensor(e_0, e_0, e_0)
    >>> e_111 = tensor(e_1, e_1, e_1)
    >>> e_ppp = tensor(e_p, e_p, e_p)
    >>> e_mmm = tensor(e_m, e_m, e_m)
    >>>
    >>> q_a = 1 / 4 * (e_000 * e_000.conj().T + e_111 * e_111.conj().T + \
    >>> e_ppp * e_ppp.conj().T + e_mmm * e_mmm.conj().T)
    >>> print(counterfeit_attack(q_a))
    0.749999999967631

    References
    ==========
    .. [MVW12] Abel Molina, Thomas Vidick, and John Watrous.
        "Optimal counterfeiting attacks and generalizations for Wiesner’s
        quantum money."
        Conference on Quantum Computation, Communication, and Cryptography.
        Springer, Berlin, Heidelberg, 2012.
        https://arxiv.org/abs/1202.4010

    .. [Wies83] Stephen Wiesner
        "Conjugate coding."
        ACM Sigact News 15.1 (1983): 78-88.
        https://dl.acm.org/doi/pdf/10.1145/1008908.1008920

    :param q_a: The fixed SDP variable.
    :param num_reps: The number of parallel repetitions.
    :return: The optimal probability with of counterfeiting quantum money.
    """
    # The system is over:
    # Y_1 ⊗ Z_1 ⊗ X_1, ... , Y_n ⊗ Z_n ⊗ X_n.
    num_spaces = 3

    # In the event of more than a single repetition, one needs to apply a
    # permutation operator to the variables in the SDP to properly align
    # the spaces.
    if num_reps == 1:
        pperm = np.array([1])
    else:
        # The permutation vector `perm` contains elements of the
        # sequence from: https://oeis.org/A023123
        q_a = tensor(q_a, num_reps)
        perm = []
        for i in range(1, num_spaces + 1):
            perm.append(i)
            var = i
            for j in range(1, num_reps):
                perm.append(var + num_spaces * j)
        pperm = permutation_operator(2, perm)

    return dual_problem(q_a, pperm, num_reps)
Esempio n. 13
0
    def test_tensor_list_0(self):
        """Test tensor empty list."""
        expected_res = None

        res = tensor([])
        self.assertEqual(res, expected_res)
Esempio n. 14
0
def pauli(ind: Union[int, str, List[int], List[str]],
          is_sparse: bool = False) -> Union[np.ndarray, sparse.csr_matrix]:
    r"""
    Produce a Pauli operator [WIKPAU]_.

    Provides the 2-by-2 Pauli matrix indicated by the value of `ind`. The
    variable `ind = 1` gives the Pauli-X operator, `ind = 2` gives the Pauli-Y
    operator, `ind =3` gives the Pauli-Z operator, and `ind = 0`gives the
    identity operator. Alternatively, `ind` can be set to "I", "X", "Y", or "Z"
    (case insensitive) to indicate the Pauli identity, X, Y, or Z operator.

    The 2-by-2 Pauli matrices are defined as the following matrices:

    .. math::

        \begin{equation}
            \begin{aligned}
                X = \begin{pmatrix}
                        0 & 1 \\
                        1 & 0
                    \end{pmatrix}, \quad
                Y = \begin{pmatrix}
                        0 & -i \\
                        i & 0
                    \end{pmatrix}, \quad
                Z = \begin{pmatrix}
                        1 & 0 \\
                        0 & -1
                    \end{pmatrix}, \quad
                I = \begin{pmatrix}
                        1 & 0 \\
                        0 & 1
                    \end{pmatrix}.
                \end{aligned}
            \end{equation}

    Examples
    ==========

    Example for identity Pauli matrix.

    >>> from toqito.linear_algebra.matrices.pauli import pauli
    >>> pauli("I")
    array([[1., 0.],
           [0., 1.]])

    Example for Pauli-X matrix.

    >>> from toqito.linear_algebra.matrices.pauli import pauli
    >>> pauli("X")
    array([[0, 1],
           [1, 0]])

    Example for Pauli-Y matrix.

    >>> from toqito.linear_algebra.matrices.pauli import pauli
    >>> pauli("Y")
    array([[ 0.+0.j, -0.-1.j],
           [ 0.+1.j,  0.+0.j]])

    Example for Pauli-Z matrix.

    >>> from toqito.linear_algebra.matrices.pauli import pauli
    >>> pauli("Z")
    array([[ 1,  0],
           [ 0, -1]])

    References
    ==========
    .. [WIKPAU] Wikipedia: Pauli matrices
        https://en.wikipedia.org/wiki/Pauli_matrices

    :param ind: The index to indicate which Pauli operator to generate.
    :param is_sparse: Returns a sparse matrix if set to True and a non-sparse
                      matrix if set to False.
    """
    if isinstance(ind, (int, str)):
        if ind in ("x", "X", 1):
            pauli_mat = np.array([[0, 1], [1, 0]])
        elif ind in ("y", "Y", 2):
            pauli_mat = np.array([[0, -1j], [1j, 0]])
        elif ind in ("z", "Z", 3):
            pauli_mat = np.array([[1, 0], [0, -1]])
        else:
            pauli_mat = np.identity(2)

        if is_sparse:
            pauli_mat = sparse.csr_matrix(pauli_mat)

        return pauli_mat

    num_qubits = len(ind)
    pauli_mats = []
    for i in range(num_qubits - 1, -1, -1):
        pauli_mats.append(pauli(ind[i], is_sparse))
    return tensor(pauli_mats)