def is_density(mat: np.ndarray) -> bool: """ Check if matrix is a density matrix. A matrix is a density matrix if its trace is equal to one and it has the property of being positive semidefinite (PSD). References: [1] 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: """ Determine whether or not a matrix has positive partial transpose. 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 2 ⊗ 2 or 2 ⊗ 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. References: [1] 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)
def is_projection(mat: np.ndarray) -> bool: r""" Check if matrix is a projection matrix. 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. References: [1] 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_povm(mat_list: List[np.ndarray]) -> bool: r""" Determine if a list of matrices constitute a valid set of POVMs. 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}}. References: [1] 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 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 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)