示例#1
0
def is_projection(mat: np.ndarray) -> bool:
    r"""
    Check if matrix is a projection matrix [WIKPRJ]_.

    A matrix is a projection matrix if it is positive semidefinite (PSD) and if

    .. math::
        \begin{equation}
            X^2 = X
        \end{equation}

    where :math:`X` is the matrix in question.

    Examples
    ==========

    Consider the following matrix

    .. math::
        A = \begin{pmatrix}
                                0 & 1 \\
                                0 & 1
                           \end{pmatrix}

    our function indicates that this is indeed a projection matrix.

    >>> from toqito.linear_algebra.properties.is_projection import is_projection
    >>> import numpy as np
    >>> A = np.array([[0, 1], [0, 1]])
    >>> is_projection(A)
    True

    Alternatively, the following example matrix :math:`B` defined as

    .. math::
        B = \begin{pmatrix}
                                -1 & -1 \\
                                -1 & -1
                             \end{pmatrix}

    is not positive definite.

    >>> from toqito.linear_algebra.properties.is_projection import is_projection
    >>> import numpy as np
    >>> B = np.array([[-1, -1], [-1, -1]])
    >>> is_projection(B)
    False

    References
    ==========
    .. [WIKPRJ] Wikipedia: Projection matrix.
        https://en.wikipedia.org/wiki/Projection_matrix

    :param mat: Matrix to check.
    :return: Return True if matrix is a projection matrix, and False otherwise.
    """
    if not is_psd(mat):
        return False
    return np.allclose(np.linalg.matrix_power(mat, 2), mat)
示例#2
0
def is_ensemble(states: List[np.ndarray]) -> bool:
    r"""
    Determine if a set of states constitute an ensemble [WatEns18]_.

    An ensemble of quantum states is defined by a function

    .. math::
        \eta : \Gamma \rightarrow \text{Pos}(\mathcal{X})

    that satisfies

    .. math::
        \text{Tr}\left( \sum_{a \in \Gamma} \eta(a) \right) = 1.

    Examples
    ==========

    Consider the following set of matrices

    .. math::
        \eta = \left{ \rho_0, \rho_1 \right}

    where

    .. math::
        \rho_0 = \frac{1}{2} \begin{pmatrix} 1 & 0 \\ 0 & 0 \end{pmatrix}, \\
        \rho_1 = \frac{1}{2} \begin{pmatrix} 0 & 0 \\ 0 & 1 \end{pmatrix}.

    The set :math:`\eta` constitutes a valid ensemble

    >>> from toqito.states.properties.is_ensemble import is_ensemble
    >>> import numpy as np
    >>> rho_0 = np.array([[0.5, 0], [0, 0]])
    >>> rho_1 = np.array([[0, 0], [0, 0.5]])
    >>> states = [rho_0, rho_1]
    >>> is_ensemble(states)
    True

    References
    ==========
    .. [WatEns18] Watrous, John.
        "The theory of quantum information."
        Section: "Ensemble of quantum states".
        Cambridge University Press, 2018.

    :param states: The list of states to check.
    :return: True if states form an ensemble and False otherwise.
    """
    trace_sum = 0
    for state in states:
        trace_sum += np.trace(state)
        # Constraint: All states in ensemble must be positive semidefinite.
        if not is_psd(state):
            return False
    # Constraint: The sum of the traces of all states within the ensemble must
    # be equal to 1.
    return np.allclose(trace_sum, 1)
示例#3
0
 def test_is_not_psd(self):
     """Test that non-positive semidefinite matrix returns False."""
     mat = np.array([[-1, -1], [-1, -1]])
     self.assertEqual(is_psd(mat), False)
示例#4
0
 def test_is_psd(self):
     """Test that positive semidefinite matrix returns True."""
     mat = np.array([[1, -1], [-1, 1]])
     self.assertEqual(is_psd(mat), True)
示例#5
0
def is_completely_positive(
    phi: Union[np.ndarray, List[List[np.ndarray]]], tol: float = 1e-05
) -> bool:
    r"""
    Determine whether the given channel is completely positive [WatCP18]_.

    A map :math:`\Phi \in \text{T} \left(\mathcal{X}, \mathcal{Y} \right)` is
    completely positive if it holds that

    .. math::
        \Phi \otimes \mathbb{I}_{\text{L}(\mathcal{Z})

    is a positive map for every complex Euclidean space :math:`\mathcal{Z}`.

    Alternatively, a channel is completely positive if the corresponding Choi
    matrix of the channel is both Hermitian-preserving and positive
    semidefinite.

    Examples
    ==========

    We can specify the input as a list of Kraus operators. Consider the map
    :math:`\Phi` defined as

    .. math::
        \Phi(X) = X - U X U^*

    where

    .. math::
        U = \frac{1}{\sqrt{2}}
        \begin{pmatrix}
            1 & 1 \\
            -1 & 1
        \end{pmatrix}.

    This map is not completely positive, as we can verify as follows.

    >>> from toqito.channels.properties.is_completely_positive import is_completely_positive
    >>> import numpy as np
    >>> unitary_mat = np.array([[1, 1], [-1, 1]]) / np.sqrt(2)
    >>> kraus_ops = [[np.identity(2), np.identity(2)], [unitary_mat, -unitary_mat]]
    >>> is_completely_positive(kraus_ops)
    False

    We can also specify the input as a Choi matrix. For instance, consider the
    Choi matrix corresponding to the :math:`2`-dimensional completely
    depolarizing channel

    .. math::
        \frac{1}{2}
        \begin{pmatrix}
            1 & 0 & 0 & 0 \\
            0 & 1 & 0 & 0 \\
            0 & 0 & 1 & 0 \\
            0 & 0 & 0 & 1
        \end{pmatrix}.

    We may verify that this channel is completely positive

    >>> from toqito.channels.channels.depolarizing import depolarizing
    >>> from toqito.channels.properties.is_completely_positive import is_completely_positive
    >>> is_completely_positive(depolarizing(2))
    True

    References
    ==========
    .. [WatCP18] Watrous, John.
        "The theory of quantum information."
        Section: "Linear maps of square operators".
        Cambridge University Press, 2018.

    :param phi: The channel provided as either a Choi matrix or a list of
                Kraus operators.
    :param tol: The tolerance parameter to determine complete positivity.
    :return: True if the channel is completely positive, and False otherwise.
    """
    # If the variable `phi` is provided as a list, we assume this is a list
    # of Kraus operators.
    if isinstance(phi, list):
        phi = kraus_to_choi(phi)

    # Use Choi's theorem to determine whether `phi` is completely positive.
    return is_herm_preserving(phi, tol) and is_psd(phi, tol)
示例#6
0
文件: is_povm.py 项目: sgmenda/toqito
def is_povm(mat_list: List[np.ndarray]) -> bool:
    r"""
    Determine if a list of matrices constitute a valid set of POVMs [WIKPOVM]_.

    A valid set of measurements are defined by a set of positive semidefinite
    operators

    .. math::
         \{P_a : a \in \Gamma\} \subset \text{Pos}(\mathcal{X})

    indexed by the alphabet :math:`\Gamma` of measurement outcomes satisfying
    the constraint that

    .. math::
        \sum_{a \in \Gamma} P_a = I_{\mathcal{X}}.

    Examples
    ==========

    Consider the following matrices

    .. math::
        M_0 = \begin{pmatrix}
                                1 & 0 \\
                                0 & 0
                             \end{pmatrix}, \qquad
        M_1 = \begin{pmatrix}
                0 & 0 \\
                0 & 1
              \end{pmatrix}

    our function indicates that this set of operators constitute a POVM.

    >>> from toqito.measurements.properties.is_povm import is_povm
    >>> import numpy as np
    >>> meas_1 = np.array([[1, 0], [0, 0]])
    >>> meas_2 = np.array([[0, 0], [0, 1]])
    >>> meas = [meas_1, meas_2]
    >>> is_povm(meas)
    True

    We may also use the `random_povm` function from `toqito`, and can verify
    that a randomly generated set satisfies the criteria for being a POVM set.

    >>> from toqito.measurements.properties.is_povm import is_povm
    >>> from toqito.random.random_povm import random_povm
    >>> import numpy as np
    >>> dim, num_inputs, num_outputs = 2, 2, 2
    >>> measurements = random_povm(dim, num_inputs, num_outputs)
    >>> is_povm([measurements[:, :, 0, 0], measurements[:, :, 0, 1]])
    True

    Alternatively, the following matrices

    .. math::
        M_0 = \begin{pmatrix}
                                1 & 2 \\
                                3 & 4
                             \end{pmatrix}, \qquad
        M_1 = \begin{pmatrix}
                5 & 6 \\
                7 & 8
              \end{pmatrix}

    does not constitute a POVM set.

    >>> from toqito.measurements.properties.is_povm import is_povm
    >>> import numpy as np
    >>> non_meas_1 = np.array([[1, 2], [3, 4]])
    >>> non_meas_2 = np.array([[5, 6], [7, 8]])
    >>> non_meas = [non_meas_1, non_meas_2]
    >>> is_povm(non_meas)
    False

    References
    ==========
    .. [WIKPOVM] Wikipedia: POVM
        https://en.wikipedia.org/wiki/POVM

    :param mat_list: A list of matrices.
    :return: True if set of matrices constitutes a set of measurements, and
             False otherwise.
    """
    dim = mat_list[0].shape[0]

    mat_sum = np.zeros((dim, dim), dtype=complex)
    for mat in mat_list:
        # Each measurement in the set must be positive semidefinite.
        if not is_psd(mat):
            return False
        mat_sum += mat
    # Summing all the measurements from the set must be equal to the identity.
    if not np.allclose(np.identity(dim), mat_sum):
        return False
    return True
示例#7
0
def is_density(mat: np.ndarray) -> bool:
    r"""
    Check if matrix is a density matrix [WIKDEN]_.

    A matrix is a density matrix if its trace is equal to one and it has the
    property of being positive semidefinite (PSD).

    Examples
    ==========

    Consider the Bell state

    .. math::
       u = \frac{1}{\sqrt{2}} |00 \rangle + \frac{1}{\sqrt{2}} |11 \rangle.

    Constructing the matrix :math:`\rho = u u^*` defined as

    .. math::
        \rho = \frac{1}{2} \begin{pmatrix}
                                1 & 0 & 0 & 1 \\
                                0 & 0 & 0 & 0 \\
                                0 & 0 & 0 & 0 \\
                                1 & 0 & 0 & 1
                           \end{pmatrix}

    our function indicates that this is indeed a density operator as the trace
    of :math:`\rho` is equal to :math:`1` and the matrix is positive
    semidefinite:

    >>> from toqito.linear_algebra.properties.is_density import is_density
    >>> from toqito.states.states.bell import bell
    >>> import numpy as np
    >>> rho = bell(0) * bell(0).conj().T
    >>> is_density(rho)
    True

    Alternatively, the following example matrix :math:`\sigma` defined as

    .. math::
        \sigma = \frac{1}{2} \begin{pmatrix}
                                1 & 2 \\
                                3 & 1
                             \end{pmatrix}

    does satisfy :math:`\text{Tr}(\sigma) = 1`, however fails to be positive
    semidefinite, and is therefore not a density operator. This can be
    illustrated using `toqito` as follows.

    >>> from toqito.linear_algebra.properties.is_density import is_density
    >>> from toqito.states.states.bell import bell
    >>> import numpy as np
    >>> sigma = 1/2 * np.array([[1, 2], [3, 1]])
    >>> is_density(sigma)
    False

    References
    ==========
    .. [WIKDEN] Wikipedia: Density matrix
        https://en.wikipedia.org/wiki/Density_matrix

    :param mat: Matrix to check.
    :return: Return `True` if matrix is a density matrix, and `False`
             otherwise.
    """
    return is_psd(mat) and np.isclose(np.trace(mat), 1)
示例#8
0
文件: is_ppt.py 项目: sgmenda/toqito
def is_ppt(
    mat: np.ndarray, sys: int = 2, dim: Union[int, List[int]] = None, tol: float = None
) -> bool:
    r"""
    Determine whether or not a matrix has positive partial transpose [WIKPPT]_.

    Yields either `True` or `False`, indicating that `mat` does or does not
    have positive partial transpose (within numerical error). The variable
    `mat` is assumed to act on bipartite space.

    For shared systems of :math:`2 \otimes 2` or :math:`2 \otimes 3`, the PPT
    criterion serves as a method to determine whether a given state is entangled
    or separable. Therefore, for systems of this size, the return value "True"
    would indicate that the state is separable and a value of "False" would
    indicate the state is entangled.

    Examples
    ==========

    Consider the following matrix

    .. math::
        \begin{pmatrix}
            1 & 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 & 1 & 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 & 1 & 0 & 0 \\
            0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\
            0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\
        \end{pmatrix}.

    This matrix trivially satisfies the PPT criterion as can be seen using the
    `toqito` package.

    >>> from toqito.states.properties.is_ppt import is_ppt
    >>> import numpy as np
    >>> mat = np.identity(9)
    >>> is_ppt(mat)
    True

    Consider the following Bell state:

    .. math::
        u = \frac{1}{\sqrt{2}}\left( |01 \rangle + |10 \rangle \right)

    For the density matrix :math:`\rho = u u^*`, as this is an entangled state
    of dimension :math:`2`, it will violate the PPT criterion, which can be seen
    using the `toqito` package.

    >>> from toqito.states.states.bell import bell
    >>> from toqito.states.properties.is_ppt import is_ppt
    >>> rho = bell(2) * bell(2).conj().T
    >>> is_ppt(rho)
    False

    References
    ==========
    .. [WIKPPT] Quantiki: Positive partial transpose
        https://www.quantiki.org/wiki/positive-partial-transpose

    :param mat: A square matrix.
    :param sys: Scalar or vector indicating which subsystems the transpose
                should be applied on.
    :param dim: The dimension is a vector containing the dimensions of the
                subsystems on which `mat` acts.
    :param tol: Tolerance with which to check whether `mat` is PPT.
    :return: True if `mat` is PPT and False if not.
    """
    eps = np.finfo(float).eps

    sqrt_rho_dims = np.round(np.sqrt(list(mat.shape)))

    if dim is None:
        dim = np.array(
            [[sqrt_rho_dims[0], sqrt_rho_dims[0]], [sqrt_rho_dims[1], sqrt_rho_dims[1]]]
        )
    if tol is None:
        tol = np.sqrt(eps)
    return is_psd(partial_transpose(mat, sys, dim), tol)