Repository: Qiskit/qiskit — pull request #10163 (python)
Title: Fix output of `DensityMatrix.partial_transpose` to match input dimensions

<!--\r\n⚠️ If you do not respect this template, your pull request will be closed.\r\n⚠️ Your pull request title should be short detailed and understandable for all.\r\n⚠️ Also, please add a release note file using reno if the change needs to be\r\n  documented in the release notes.\r\n⚠️ If your pull request fixes an open issue, please link to the issue.\r\n\r\n- [ ] I have added the tests to cover my changes.\r\n- [ ] I have updated the documentation accordingly.\r\n- [ ] I have read the CONTRIBUTING document.\r\n-->\r\n\r\n### Summary\r\nAdd dimensions to the `DensityMatrix` returned by `partial_transpose` so its dimensions match those of the input density matrix.\r\n\r\n\r\n### Details and comments\r\nFix #10155 \r\n\r\n

Resolved issues:
title: `DensityMatrix.partial_transpose` does not preserve input dimensions
body: ### Environment\r\n\r\n- **Qiskit Terra version**: to be released in 0.24.0\r\n- **Python version**: 3.10\r\n- **Operating system**: MacOS\r\n\r\n\r\n### What is happening?\r\n\r\nThe `partial_transpose` should return a density matrix of the same dimensionality as the input `DensityMatrix` object. When the dimensions are for systems different than qubits, the dimensions are currently not preserved. \r\n\r\n### How can we reproduce the issue?\r\n\r\nFor in the following example, the dimensions of the output density matrix ρ2 are (9,) but they should be (3,3).\r\n\r\n```python\r\n>>> import numpy as np\r\n>>> from qiskit.quantum_info import Statevector, DensityMatrix\r\n>>> ψ = Statevector(np.array([1,0,0,0,1,0,0,0,1])*1/np.sqrt(3),dims=(3,3))\r\n>>> ρ1 = DensityMatrix(ψ)\r\n>>> ρ1.dims()\r\n(3, 3)\r\n>>> ρ2 = ρ1.partial_transpose([0])\r\n>>> ρ2.dims()\r\n(9,)\r\n```\r\n\r\n### What should happen?\r\n\r\nIt should be an easy fix. The function should return:\r\n```python\r\nreturn DensityMatrix(rho, dims=self.dims())\r\n```\r\n\r\ninstead of just:\r\n```python\r\nreturn DensityMatrix(rho)\r\n```\r\n\r\n### Any suggestions?\r\n\r\n_No response_

Hints:

Fix patch:
diff --git a/qiskit/quantum_info/states/densitymatrix.py b/qiskit/quantum_info/states/densitymatrix.py\nindex 124a382f01d1..3103ef23036a 100644\n--- a/qiskit/quantum_info/states/densitymatrix.py\n+++ b/qiskit/quantum_info/states/densitymatrix.py\n@@ -832,4 +832,4 @@ def partial_transpose(self, qargs):\n             lst[i], lst[i + n] = lst[i + n], lst[i]\n         rho = np.transpose(arr, lst)\n         rho = np.reshape(rho, self._op_shape.shape)\n-        return DensityMatrix(rho)\n+        return DensityMatrix(rho, dims=self.dims())\ndiff --git a/releasenotes/notes/fix-partial-transpose-output-dims-3082fcf4147055dc.yaml b/releasenotes/notes/fix-partial-transpose-output-dims-3082fcf4147055dc.yaml\nnew file mode 100644\nindex 000000000000..edba41333ce8\n--- /dev/null\n+++ b/releasenotes/notes/fix-partial-transpose-output-dims-3082fcf4147055dc.yaml\n@@ -0,0 +1,5 @@\n+---\n+fixes:\n+  - |\n+    Fixed the dimensions of the output density matrix from :meth:`.DensityMatrix.partial_transpose`\n+    so they match the dimensions of the corresponding input density matrix.\n

Test patch:
diff --git a/test/python/quantum_info/states/test_densitymatrix.py b/test/python/quantum_info/states/test_densitymatrix.py\nindex 8886e35cc288..16fbbbc1b9a4 100644\n--- a/test/python/quantum_info/states/test_densitymatrix.py\n+++ b/test/python/quantum_info/states/test_densitymatrix.py\n@@ -1219,6 +1219,15 @@ def test_density_matrix_partial_transpose(self):\n             self.assertEqual(rho.partial_transpose([0]), DensityMatrix(rho1))\n             self.assertEqual(rho.partial_transpose([1]), DensityMatrix(rho1))\n \n+        with self.subTest(msg="dims(3,3)"):\n+            mat = np.zeros((9, 9))\n+            mat1 = np.zeros((9, 9))\n+            mat[8, 0] = 1\n+            mat1[0, 8] = 1\n+            rho = DensityMatrix(mat, dims=(3, 3))\n+            rho1 = DensityMatrix(mat1, dims=(3, 3))\n+            self.assertEqual(rho.partial_transpose([0, 1]), rho1)\n+\n     def test_clip_probabilities(self):\n         """Test probabilities are clipped to [0, 1]."""\n         dm = DensityMatrix([[1.1, 0], [0, 0]])\n