diff --git a/qiskit/quantum_info/states/densitymatrix.py b/qiskit/quantum_info/states/densitymatrix.py index ac7b672b77ef..124a382f01d1 100644 --- a/qiskit/quantum_info/states/densitymatrix.py +++ b/qiskit/quantum_info/states/densitymatrix.py @@ -814,3 +814,22 @@ def to_statevector(self, atol=None, rtol=None): psi = evecs[:, np.argmax(evals)] # eigenvectors returned in columns. return Statevector(psi) + + def partial_transpose(self, qargs): + """Return partially transposed density matrix. + + Args: + qargs (list): The subsystems to be transposed. + + Returns: + DensityMatrix: The partially transposed density matrix. + """ + arr = self._data.reshape(self._op_shape.tensor_shape) + qargs = len(self._op_shape.dims_l()) - 1 - np.array(qargs) + n = len(self.dims()) + lst = list(range(2 * n)) + for i in qargs: + lst[i], lst[i + n] = lst[i + n], lst[i] + rho = np.transpose(arr, lst) + rho = np.reshape(rho, self._op_shape.shape) + return DensityMatrix(rho) diff --git a/releasenotes/notes/adding-partial-transpose-040a6ff00228841b.yaml b/releasenotes/notes/adding-partial-transpose-040a6ff00228841b.yaml new file mode 100644 index 000000000000..6744ea4bcfcc --- /dev/null +++ b/releasenotes/notes/adding-partial-transpose-040a6ff00228841b.yaml @@ -0,0 +1,5 @@ + +features: + - | + The partial transpose operation has been integrated into the quantum_info module, allowing for partial transposition of matrices. + This operation is key in detecting entanglement between bipartite quantum system. diff --git a/test/python/quantum_info/states/test_densitymatrix.py b/test/python/quantum_info/states/test_densitymatrix.py index 17f2b22f174e..8886e35cc288 100644 --- a/test/python/quantum_info/states/test_densitymatrix.py +++ b/test/python/quantum_info/states/test_densitymatrix.py @@ -12,21 +12,20 @@ """Tests for DensityMatrix quantum state class.""" -import unittest import logging -from ddt import ddt, data +import unittest + import numpy as np +from ddt import data, ddt from numpy.testing import assert_allclose -from qiskit.test import QiskitTestCase -from qiskit import QiskitError -from qiskit import QuantumRegister, QuantumCircuit -from qiskit.circuit.library import HGate, QFT - -from qiskit.quantum_info.random import random_unitary, random_density_matrix, random_pauli -from qiskit.quantum_info.states import DensityMatrix, Statevector +from qiskit import QiskitError, QuantumCircuit, QuantumRegister +from qiskit.circuit.library import QFT, HGate from qiskit.quantum_info.operators.operator import Operator from qiskit.quantum_info.operators.symplectic import Pauli, SparsePauliOp +from qiskit.quantum_info.random import random_density_matrix, random_pauli, random_unitary +from qiskit.quantum_info.states import DensityMatrix, Statevector +from qiskit.test import QiskitTestCase logger = logging.getLogger(__name__) @@ -1202,6 +1201,24 @@ def test_drawings(self): with self.subTest(msg=f"draw('{drawtype}')"): dm.draw(drawtype) + def test_density_matrix_partial_transpose(self): + """Test partial_transpose function on density matrices""" + with self.subTest(msg="separable"): + rho = DensityMatrix.from_label("10+") + rho1 = np.zeros((8, 8), complex) + rho1[4, 4] = 0.5 + rho1[4, 5] = 0.5 + rho1[5, 4] = 0.5 + rho1[5, 5] = 0.5 + self.assertEqual(rho.partial_transpose([0, 1]), DensityMatrix(rho1)) + self.assertEqual(rho.partial_transpose([0, 2]), DensityMatrix(rho1)) + + with self.subTest(msg="entangled"): + rho = DensityMatrix([[0, 0, 0, 0], [0, 0.5, -0.5, 0], [0, -0.5, 0.5, 0], [0, 0, 0, 0]]) + rho1 = DensityMatrix([[0, 0, 0, -0.5], [0, 0.5, 0, 0], [0, 0, 0.5, 0], [-0.5, 0, 0, 0]]) + self.assertEqual(rho.partial_transpose([0]), DensityMatrix(rho1)) + self.assertEqual(rho.partial_transpose([1]), DensityMatrix(rho1)) + def test_clip_probabilities(self): """Test probabilities are clipped to [0, 1].""" dm = DensityMatrix([[1.1, 0], [0, 0]])