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)
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)
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)
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)
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)
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
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)
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)