From 5ba48567fa8689ec7841f3773f86bce0ee0d7448 Mon Sep 17 00:00:00 2001 From: Payal Solanki Date: Thu, 9 Feb 2023 20:33:01 +0530 Subject: [PATCH 01/24] partial_transpose included --- qiskit/quantum_info/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qiskit/quantum_info/__init__.py b/qiskit/quantum_info/__init__.py index 45a8d46e4765..19b7513e41c9 100644 --- a/qiskit/quantum_info/__init__.py +++ b/qiskit/quantum_info/__init__.py @@ -131,6 +131,7 @@ from .states import Statevector, DensityMatrix, StabilizerState from .states import ( partial_trace, + partial_transpose, state_fidelity, purity, entropy, From a93623a77c580203af434bd25d03235198526086 Mon Sep 17 00:00:00 2001 From: Payal Solanki Date: Thu, 9 Feb 2023 20:33:42 +0530 Subject: [PATCH 02/24] included partial_transpose --- qiskit/quantum_info/states/utils.py | 53 ++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/qiskit/quantum_info/states/utils.py b/qiskit/quantum_info/states/utils.py index 04be491855d8..66ec434fa080 100644 --- a/qiskit/quantum_info/states/utils.py +++ b/qiskit/quantum_info/states/utils.py @@ -15,7 +15,7 @@ """ import numpy as np - +import math from qiskit.exceptions import QiskitError from qiskit.quantum_info.states.statevector import Statevector from qiskit.quantum_info.states.densitymatrix import DensityMatrix @@ -155,3 +155,54 @@ def _funm_svd(matrix, func): unitary1, singular_values, unitary2 = la.svd(matrix) diag_func_singular = np.diag(func(singular_values)) return unitary1.dot(diag_func_singular).dot(unitary2) + + + + +def partial_transpose(state,qargs): + """Return partially transposed density matrix. + + Args: + state (DensityMatrix): the input state. + qargs (list): The subsystems to be transposed. + + Returns: + DensityMatrix: The partially transposed density matrix. + + Raises: + QiskitError: if input state is invalid. + QiskitError: if indices of subsystems are invalid + + """ + state = _format_state(state, validate=False) + n = len(state.dims()) + l = np.zeros(2**n,int) + for i in range(2**n): + x = 0 + for k in qargs: + x = x + (((i >> (k)) % 2)*2**k) + l[i] = x + if not(set(qargs).issubset(set(np.arange(n)))): + raise QiskitError("Indices of subsystems to be transposed are invalid") + ptden = np.empty((2**n, 2**n),complex) + ptden[:] = np.nan + if isinstance(state, Statevector): + state = np.array(state) + for i in range(2**n): + for j in range(2**n): + if math.isnan(ptden[i,j]): + x = i - l[i] + l[j] + y = j - l[j] + l[i] + ptden[i,j] = state[x]*np.conjugate(state[y]) + ptden[x,y] = state[i]*np.conjugate(state[j]) + else: + state = np.array(state) + for i in range(2**n): + for j in range(2**n): + if math.isnan(ptden[i,j]): + x = i - l[i] + l[j] + y = j - l[j] + l[i] + ptden[i,j] = state[x,y] + ptden[x,y] = state[i,j] + + return(DensityMatrix(ptden)) \ No newline at end of file From 1a162dd159ff2353297a4802070db5bf1864e6de Mon Sep 17 00:00:00 2001 From: Payal Solanki Date: Thu, 9 Feb 2023 20:33:52 +0530 Subject: [PATCH 03/24] included partial_transpose --- qiskit/quantum_info/states/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/quantum_info/states/__init__.py b/qiskit/quantum_info/states/__init__.py index 1e49ee353b7b..c303e592f450 100644 --- a/qiskit/quantum_info/states/__init__.py +++ b/qiskit/quantum_info/states/__init__.py @@ -15,7 +15,7 @@ from .statevector import Statevector from .stabilizerstate import StabilizerState from .densitymatrix import DensityMatrix -from .utils import partial_trace, shannon_entropy +from .utils import partial_trace, shannon_entropy,partial_transpose from .measures import ( state_fidelity, purity, From a7cbffe49a3ae40eb48c1781c998e514a93c1a45 Mon Sep 17 00:00:00 2001 From: Payal Solanki Date: Thu, 9 Feb 2023 20:46:07 +0530 Subject: [PATCH 04/24] included partial_transpose --- qiskit/quantum_info/states/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/quantum_info/states/__init__.py b/qiskit/quantum_info/states/__init__.py index c303e592f450..ab231932c4fc 100644 --- a/qiskit/quantum_info/states/__init__.py +++ b/qiskit/quantum_info/states/__init__.py @@ -15,7 +15,7 @@ from .statevector import Statevector from .stabilizerstate import StabilizerState from .densitymatrix import DensityMatrix -from .utils import partial_trace, shannon_entropy,partial_transpose +from .utils import partial_trace, shannon_entropy, partial_transpose from .measures import ( state_fidelity, purity, From 95d99a58cdc1f1bb6748bd5b2e01c5c732090c90 Mon Sep 17 00:00:00 2001 From: Payal Solanki Date: Thu, 9 Feb 2023 20:46:34 +0530 Subject: [PATCH 05/24] included partial_transpose --- qiskit/quantum_info/states/utils.py | 34 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/qiskit/quantum_info/states/utils.py b/qiskit/quantum_info/states/utils.py index 66ec434fa080..b91a2d45f1f6 100644 --- a/qiskit/quantum_info/states/utils.py +++ b/qiskit/quantum_info/states/utils.py @@ -157,10 +157,8 @@ def _funm_svd(matrix, func): return unitary1.dot(diag_func_singular).dot(unitary2) - - -def partial_transpose(state,qargs): - """Return partially transposed density matrix. +def partial_transpose(state, qargs): + """Return partially transposed density matrix. Args: state (DensityMatrix): the input state. @@ -172,37 +170,37 @@ def partial_transpose(state,qargs): Raises: QiskitError: if input state is invalid. QiskitError: if indices of subsystems are invalid - + """ state = _format_state(state, validate=False) n = len(state.dims()) - l = np.zeros(2**n,int) + l = np.zeros(2**n, int) for i in range(2**n): x = 0 for k in qargs: - x = x + (((i >> (k)) % 2)*2**k) + x = x + (((i >> (k)) % 2) * 2**k) l[i] = x - if not(set(qargs).issubset(set(np.arange(n)))): - raise QiskitError("Indices of subsystems to be transposed are invalid") - ptden = np.empty((2**n, 2**n),complex) + if not (set(qargs).issubset(set(np.arange(n)))): + raise QiskitError("Indices of subsystems to be transposed are invalid") + ptden = np.empty((2**n, 2**n), complex) ptden[:] = np.nan if isinstance(state, Statevector): state = np.array(state) for i in range(2**n): for j in range(2**n): - if math.isnan(ptden[i,j]): + if math.isnan(ptden[i, j]): x = i - l[i] + l[j] y = j - l[j] + l[i] - ptden[i,j] = state[x]*np.conjugate(state[y]) - ptden[x,y] = state[i]*np.conjugate(state[j]) + ptden[i, j] = state[x] * np.conjugate(state[y]) + ptden[x, y] = state[i] * np.conjugate(state[j]) else: state = np.array(state) for i in range(2**n): for j in range(2**n): - if math.isnan(ptden[i,j]): + if math.isnan(ptden[i, j]): x = i - l[i] + l[j] y = j - l[j] + l[i] - ptden[i,j] = state[x,y] - ptden[x,y] = state[i,j] - - return(DensityMatrix(ptden)) \ No newline at end of file + ptden[i, j] = state[x, y] + ptden[x, y] = state[i, j] + + return DensityMatrix(ptden) From ea9f8f089a2b9c0771d569a79be407e54d9d8c3e Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 13:13:43 +0530 Subject: [PATCH 06/24] included partial_transpose --- qiskit/quantum_info/states/utils.py | 50 ++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/qiskit/quantum_info/states/utils.py b/qiskit/quantum_info/states/utils.py index 04be491855d8..e5ba664238ec 100644 --- a/qiskit/quantum_info/states/utils.py +++ b/qiskit/quantum_info/states/utils.py @@ -15,7 +15,7 @@ """ import numpy as np - +import math from qiskit.exceptions import QiskitError from qiskit.quantum_info.states.statevector import Statevector from qiskit.quantum_info.states.densitymatrix import DensityMatrix @@ -155,3 +155,51 @@ def _funm_svd(matrix, func): unitary1, singular_values, unitary2 = la.svd(matrix) diag_func_singular = np.diag(func(singular_values)) return unitary1.dot(diag_func_singular).dot(unitary2) + +def partial_transpose(state,qargs): + """Return partially transposed density matrix. + + Args: + state (DensityMatrix): the input state. + qargs (list): The subsystems to be transposed. + + Returns: + DensityMatrix: The partially transposed density matrix. + + Raises: + QiskitError: if input state is invalid. + QiskitError: if indices of subsystems are invalid + + """ + state = _format_state(state, validate=False) + n = len(state.dims()) + l = np.zeros(2**n,int) + for i in range(2**n): + x = 0 + for k in qargs: + x = x + (((i >> (k)) % 2)*2**k) + l[i] = x + if not(set(qargs).issubset(set(np.arange(n)))): + raise QiskitError("Indices of subsystems to be transposed are invalid") + ptden = np.empty((2**n, 2**n),complex) + ptden[:] = np.nan + if isinstance(state, Statevector): + state = np.array(state) + for i in range(2**n): + for j in range(2**n): + if math.isnan(ptden[i,j]): + x = i - l[i] + l[j] + y = j - l[j] + l[i] + ptden[i,j] = state[x]*np.conjugate(state[y]) + ptden[x,y] = state[i]*np.conjugate(state[j]) + else: + state = np.array(state) + for i in range(2**n): + for j in range(2**n): + if math.isnan(ptden[i,j]): + x = i - l[i] + l[j] + y = j - l[j] + l[i] + ptden[i,j] = state[x,y] + ptden[x,y] = state[i,j] + + return(DensityMatrix(ptden)) From 2ff52941d251659c814f107cda4be2eb9e173535 Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 13:14:42 +0530 Subject: [PATCH 07/24] included partial_transpose --- qiskit/quantum_info/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qiskit/quantum_info/__init__.py b/qiskit/quantum_info/__init__.py index 45a8d46e4765..19b7513e41c9 100644 --- a/qiskit/quantum_info/__init__.py +++ b/qiskit/quantum_info/__init__.py @@ -131,6 +131,7 @@ from .states import Statevector, DensityMatrix, StabilizerState from .states import ( partial_trace, + partial_transpose, state_fidelity, purity, entropy, From ae400f1e9e4706dc542d1ddbc8b9684c644c4fe5 Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 13:15:21 +0530 Subject: [PATCH 08/24] included partial_transpose --- qiskit/quantum_info/states/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/quantum_info/states/__init__.py b/qiskit/quantum_info/states/__init__.py index 1e49ee353b7b..c303e592f450 100644 --- a/qiskit/quantum_info/states/__init__.py +++ b/qiskit/quantum_info/states/__init__.py @@ -15,7 +15,7 @@ from .statevector import Statevector from .stabilizerstate import StabilizerState from .densitymatrix import DensityMatrix -from .utils import partial_trace, shannon_entropy +from .utils import partial_trace, shannon_entropy,partial_transpose from .measures import ( state_fidelity, purity, From 28ba225b10e8b751c8bc3b4942111a68cf2b5e03 Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 13:20:17 +0530 Subject: [PATCH 09/24] included partial_transpose --- qiskit/quantum_info/states/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/quantum_info/states/__init__.py b/qiskit/quantum_info/states/__init__.py index c303e592f450..ab231932c4fc 100644 --- a/qiskit/quantum_info/states/__init__.py +++ b/qiskit/quantum_info/states/__init__.py @@ -15,7 +15,7 @@ from .statevector import Statevector from .stabilizerstate import StabilizerState from .densitymatrix import DensityMatrix -from .utils import partial_trace, shannon_entropy,partial_transpose +from .utils import partial_trace, shannon_entropy, partial_transpose from .measures import ( state_fidelity, purity, From 91cc3c16afc5a5e03164063f05582e5ff0aa2e15 Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 13:20:25 +0530 Subject: [PATCH 10/24] included partial_transpose --- qiskit/quantum_info/states/utils.py | 33 +++++++++++++++-------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/qiskit/quantum_info/states/utils.py b/qiskit/quantum_info/states/utils.py index e5ba664238ec..b91a2d45f1f6 100644 --- a/qiskit/quantum_info/states/utils.py +++ b/qiskit/quantum_info/states/utils.py @@ -156,8 +156,9 @@ def _funm_svd(matrix, func): diag_func_singular = np.diag(func(singular_values)) return unitary1.dot(diag_func_singular).dot(unitary2) -def partial_transpose(state,qargs): - """Return partially transposed density matrix. + +def partial_transpose(state, qargs): + """Return partially transposed density matrix. Args: state (DensityMatrix): the input state. @@ -169,37 +170,37 @@ def partial_transpose(state,qargs): Raises: QiskitError: if input state is invalid. QiskitError: if indices of subsystems are invalid - + """ state = _format_state(state, validate=False) n = len(state.dims()) - l = np.zeros(2**n,int) + l = np.zeros(2**n, int) for i in range(2**n): x = 0 for k in qargs: - x = x + (((i >> (k)) % 2)*2**k) + x = x + (((i >> (k)) % 2) * 2**k) l[i] = x - if not(set(qargs).issubset(set(np.arange(n)))): - raise QiskitError("Indices of subsystems to be transposed are invalid") - ptden = np.empty((2**n, 2**n),complex) + if not (set(qargs).issubset(set(np.arange(n)))): + raise QiskitError("Indices of subsystems to be transposed are invalid") + ptden = np.empty((2**n, 2**n), complex) ptden[:] = np.nan if isinstance(state, Statevector): state = np.array(state) for i in range(2**n): for j in range(2**n): - if math.isnan(ptden[i,j]): + if math.isnan(ptden[i, j]): x = i - l[i] + l[j] y = j - l[j] + l[i] - ptden[i,j] = state[x]*np.conjugate(state[y]) - ptden[x,y] = state[i]*np.conjugate(state[j]) + ptden[i, j] = state[x] * np.conjugate(state[y]) + ptden[x, y] = state[i] * np.conjugate(state[j]) else: state = np.array(state) for i in range(2**n): for j in range(2**n): - if math.isnan(ptden[i,j]): + if math.isnan(ptden[i, j]): x = i - l[i] + l[j] y = j - l[j] + l[i] - ptden[i,j] = state[x,y] - ptden[x,y] = state[i,j] - - return(DensityMatrix(ptden)) + ptden[i, j] = state[x, y] + ptden[x, y] = state[i, j] + + return DensityMatrix(ptden) From d03e70e867c92f4ed4031f70a44fecd744882f7c Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 14:18:34 +0530 Subject: [PATCH 11/24] included partial_transpose --- qiskit/quantum_info/states/utils.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/qiskit/quantum_info/states/utils.py b/qiskit/quantum_info/states/utils.py index b91a2d45f1f6..8009d13450bd 100644 --- a/qiskit/quantum_info/states/utils.py +++ b/qiskit/quantum_info/states/utils.py @@ -13,9 +13,8 @@ """ Quantum information utility functions for states. """ - -import numpy as np import math +import numpy as np from qiskit.exceptions import QiskitError from qiskit.quantum_info.states.statevector import Statevector from qiskit.quantum_info.states.densitymatrix import DensityMatrix @@ -174,13 +173,13 @@ def partial_transpose(state, qargs): """ state = _format_state(state, validate=False) n = len(state.dims()) - l = np.zeros(2**n, int) + lst = np.zeros(2**n, int) for i in range(2**n): x = 0 for k in qargs: x = x + (((i >> (k)) % 2) * 2**k) l[i] = x - if not (set(qargs).issubset(set(np.arange(n)))): + if not set(qargs).issubset(set(np.arange(n))): raise QiskitError("Indices of subsystems to be transposed are invalid") ptden = np.empty((2**n, 2**n), complex) ptden[:] = np.nan @@ -189,8 +188,8 @@ def partial_transpose(state, qargs): for i in range(2**n): for j in range(2**n): if math.isnan(ptden[i, j]): - x = i - l[i] + l[j] - y = j - l[j] + l[i] + x = i - lst[i] + lst[j] + y = j - lst[j] + lst[i] ptden[i, j] = state[x] * np.conjugate(state[y]) ptden[x, y] = state[i] * np.conjugate(state[j]) else: @@ -198,8 +197,8 @@ def partial_transpose(state, qargs): for i in range(2**n): for j in range(2**n): if math.isnan(ptden[i, j]): - x = i - l[i] + l[j] - y = j - l[j] + l[i] + x = i - lst[i] + lst[j] + y = j - lst[j] + lst[i] ptden[i, j] = state[x, y] ptden[x, y] = state[i, j] From fc1d6552dd590d7e581d2822264d867b5f200346 Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 14:26:52 +0530 Subject: [PATCH 12/24] included partial_transpose --- qiskit/quantum_info/states/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/quantum_info/states/utils.py b/qiskit/quantum_info/states/utils.py index 8009d13450bd..6dc4f533aff9 100644 --- a/qiskit/quantum_info/states/utils.py +++ b/qiskit/quantum_info/states/utils.py @@ -178,7 +178,7 @@ def partial_transpose(state, qargs): x = 0 for k in qargs: x = x + (((i >> (k)) % 2) * 2**k) - l[i] = x + lst[i] = x if not set(qargs).issubset(set(np.arange(n))): raise QiskitError("Indices of subsystems to be transposed are invalid") ptden = np.empty((2**n, 2**n), complex) From a2c8a05cf22cfe7e2cb1d1af86ac0912141651a8 Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 15:33:28 +0530 Subject: [PATCH 13/24] included test for partial transpose --- test/python/quantum_info/states/test_utils.py | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/test/python/quantum_info/states/test_utils.py b/test/python/quantum_info/states/test_utils.py index 2ea9038eb631..6f4e145fdea2 100644 --- a/test/python/quantum_info/states/test_utils.py +++ b/test/python/quantum_info/states/test_utils.py @@ -17,7 +17,7 @@ from qiskit.test import QiskitTestCase from qiskit.quantum_info.states import Statevector, DensityMatrix -from qiskit.quantum_info.states import partial_trace, shannon_entropy +from qiskit.quantum_info.states import partial_trace, shannon_entropy, partial_transpose class TestStateUtils(QiskitTestCase): @@ -54,7 +54,27 @@ def test_shannon_entropy(self): self.assertAlmostEqual(1.229368880382052, shannon_entropy(input_pvec, np.e)) # Base 10 self.assertAlmostEqual(0.533908120973504, shannon_entropy(input_pvec, 10)) - + + def test_statevector_partial_transpose(self): + psi = Statevector.from_label("10+") + rho1=[[0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j], + [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j], + [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j], + [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j], + [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0.5+0.j, 0.5+0.j, + 0. +0.j, 0. +0.j], + [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0.5+0.j, 0.5+0.j, + 0. +0.j, 0. +0.j], + [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j], + [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, + 0. +0.j, 0. +0.j]] + self.assertEqual(partial_transpose(rho, [0, 1]), rho1) + if __name__ == "__main__": unittest.main() From 35882a4504e9f5954d071a54dfacdafd64c5d305 Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 15:52:55 +0530 Subject: [PATCH 14/24] included test for partial transpose --- test/python/quantum_info/states/test_utils.py | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/test/python/quantum_info/states/test_utils.py b/test/python/quantum_info/states/test_utils.py index 6f4e145fdea2..c7aee09cdb7a 100644 --- a/test/python/quantum_info/states/test_utils.py +++ b/test/python/quantum_info/states/test_utils.py @@ -57,23 +57,30 @@ def test_shannon_entropy(self): def test_statevector_partial_transpose(self): psi = Statevector.from_label("10+") - rho1=[[0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j], - [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j], - [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j], - [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j], - [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0.5+0.j, 0.5+0.j, - 0. +0.j, 0. +0.j], - [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0.5+0.j, 0.5+0.j, - 0. +0.j, 0. +0.j], - [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j], - [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j, - 0. +0.j, 0. +0.j]] - self.assertEqual(partial_transpose(rho, [0, 1]), rho1) + rho1= [[0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0.5, 0.5, 0, 0], + [0, 0, 0, 0, 0.5, 0.5, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0]] + self.assertEqual(partial_transpose(psi, [0, 1]), rho1) + self.assertEqual(partial_transpose(psi, [0, 2]), rho1) + + + def test_density_matrix_partial_transpose(self): + rho = DensityMatrix.from_label("10+") + rho1= [[0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0.5, 0.5, 0, 0], + [0, 0, 0, 0, 0.5, 0.5, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0]] + self.assertEqual(partial_transpose(rho, [0, 1]), rho1) + self.assertEqual(partial_transpose(rho, [0, 2]), rho1) if __name__ == "__main__": From 3934c8cf00ca82d0ef79279bac2e6fa7986dc762 Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 15:54:35 +0530 Subject: [PATCH 15/24] included test for partial transpose --- test/python/quantum_info/states/test_utils.py | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/test/python/quantum_info/states/test_utils.py b/test/python/quantum_info/states/test_utils.py index c7aee09cdb7a..5813446781ad 100644 --- a/test/python/quantum_info/states/test_utils.py +++ b/test/python/quantum_info/states/test_utils.py @@ -54,34 +54,37 @@ def test_shannon_entropy(self): self.assertAlmostEqual(1.229368880382052, shannon_entropy(input_pvec, np.e)) # Base 10 self.assertAlmostEqual(0.533908120973504, shannon_entropy(input_pvec, 10)) - + def test_statevector_partial_transpose(self): psi = Statevector.from_label("10+") - rho1= [[0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0.5, 0.5, 0, 0], - [0, 0, 0, 0, 0.5, 0.5, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0]] + rho1 = [ + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0.5, 0.5, 0, 0], + [0, 0, 0, 0, 0.5, 0.5, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + ] self.assertEqual(partial_transpose(psi, [0, 1]), rho1) self.assertEqual(partial_transpose(psi, [0, 2]), rho1) - def test_density_matrix_partial_transpose(self): rho = DensityMatrix.from_label("10+") - rho1= [[0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0.5, 0.5, 0, 0], - [0, 0, 0, 0, 0.5, 0.5, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0]] + rho1 = [ + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0.5, 0.5, 0, 0], + [0, 0, 0, 0, 0.5, 0.5, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + ] self.assertEqual(partial_transpose(rho, [0, 1]), rho1) self.assertEqual(partial_transpose(rho, [0, 2]), rho1) - + if __name__ == "__main__": unittest.main() From 2a220785f8ad19548fcf7d7507637ce9dd6a0aa2 Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 16:08:57 +0530 Subject: [PATCH 16/24] added docstring --- test/python/quantum_info/states/test_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/python/quantum_info/states/test_utils.py b/test/python/quantum_info/states/test_utils.py index 5813446781ad..661d507e5e25 100644 --- a/test/python/quantum_info/states/test_utils.py +++ b/test/python/quantum_info/states/test_utils.py @@ -56,6 +56,7 @@ def test_shannon_entropy(self): self.assertAlmostEqual(0.533908120973504, shannon_entropy(input_pvec, 10)) def test_statevector_partial_transpose(self): + """Test partial_transpose function on statevectors""" psi = Statevector.from_label("10+") rho1 = [ [0, 0, 0, 0, 0, 0, 0, 0], @@ -71,6 +72,7 @@ def test_statevector_partial_transpose(self): self.assertEqual(partial_transpose(psi, [0, 2]), rho1) def test_density_matrix_partial_transpose(self): + """Test partial_transpose function on density matrices""" rho = DensityMatrix.from_label("10+") rho1 = [ [0, 0, 0, 0, 0, 0, 0, 0], From 788f960622bcaefad82d38ff6dd8ea7094f74c0a Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 16:39:17 +0530 Subject: [PATCH 17/24] included DensityMatrix(rho1) --- test/python/quantum_info/states/test_utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/python/quantum_info/states/test_utils.py b/test/python/quantum_info/states/test_utils.py index 661d507e5e25..522726a115e3 100644 --- a/test/python/quantum_info/states/test_utils.py +++ b/test/python/quantum_info/states/test_utils.py @@ -68,8 +68,8 @@ def test_statevector_partial_transpose(self): [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], ] - self.assertEqual(partial_transpose(psi, [0, 1]), rho1) - self.assertEqual(partial_transpose(psi, [0, 2]), rho1) + self.assertEqual(partial_transpose(psi, [0, 1]), DensityMatrix(rho1)) + self.assertEqual(partial_transpose(psi, [0, 2]), DensityMatrix(rho1)) def test_density_matrix_partial_transpose(self): """Test partial_transpose function on density matrices""" @@ -84,8 +84,8 @@ def test_density_matrix_partial_transpose(self): [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], ] - self.assertEqual(partial_transpose(rho, [0, 1]), rho1) - self.assertEqual(partial_transpose(rho, [0, 2]), rho1) + self.assertEqual(partial_transpose(rho, [0, 1]), DensityMatrix(rho1)) + self.assertEqual(partial_transpose(rho, [0, 2]), DensityMatrix(rho1)) if __name__ == "__main__": From a3a16fb8e42b6f63e6d688c336d4bb4f959eb316 Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 16:48:39 +0530 Subject: [PATCH 18/24] changed rho1 --- test/python/quantum_info/states/test_utils.py | 30 +++++++------------ 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/test/python/quantum_info/states/test_utils.py b/test/python/quantum_info/states/test_utils.py index 522726a115e3..7ab3bedc8edf 100644 --- a/test/python/quantum_info/states/test_utils.py +++ b/test/python/quantum_info/states/test_utils.py @@ -58,32 +58,22 @@ def test_shannon_entropy(self): def test_statevector_partial_transpose(self): """Test partial_transpose function on statevectors""" psi = Statevector.from_label("10+") - rho1 = [ - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0.5, 0.5, 0, 0], - [0, 0, 0, 0, 0.5, 0.5, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - ] + 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(partial_transpose(psi, [0, 1]), DensityMatrix(rho1)) self.assertEqual(partial_transpose(psi, [0, 2]), DensityMatrix(rho1)) def test_density_matrix_partial_transpose(self): """Test partial_transpose function on density matrices""" rho = DensityMatrix.from_label("10+") - rho1 = [ - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0.5, 0.5, 0, 0], - [0, 0, 0, 0, 0.5, 0.5, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0], - ] + 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(partial_transpose(rho, [0, 1]), DensityMatrix(rho1)) self.assertEqual(partial_transpose(rho, [0, 2]), DensityMatrix(rho1)) From c498c77f806c3183d62f7621e2e33abfe65917d7 Mon Sep 17 00:00:00 2001 From: PayalSolanki2906 Date: Fri, 10 Feb 2023 17:11:30 +0530 Subject: [PATCH 19/24] addition of release note --- .../notes/adding-partial-transpose-040a6ff00228841b.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 releasenotes/notes/adding-partial-transpose-040a6ff00228841b.yaml 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. From 3832e745eaa0fe32fe90218aaec32b286c9874e4 Mon Sep 17 00:00:00 2001 From: PayalSolanki29 Date: Thu, 16 Feb 2023 08:56:07 +0530 Subject: [PATCH 20/24] fix --- qiskit/quantum_info/states/utils.py | 72 +---------------------------- 1 file changed, 1 insertion(+), 71 deletions(-) diff --git a/qiskit/quantum_info/states/utils.py b/qiskit/quantum_info/states/utils.py index e9f82996b1b2..21abb6d5b344 100644 --- a/qiskit/quantum_info/states/utils.py +++ b/qiskit/quantum_info/states/utils.py @@ -13,12 +13,8 @@ """ Quantum information utility functions for states. """ -import math + import numpy as np -<<<<<<< HEAD -import math -======= ->>>>>>> 8e2684ac7e3791a12afaa700959173c7627362ef from qiskit.exceptions import QiskitError from qiskit.quantum_info.states.statevector import Statevector from qiskit.quantum_info.states.densitymatrix import DensityMatrix @@ -160,69 +156,3 @@ def _funm_svd(matrix, func): return unitary1.dot(diag_func_singular).dot(unitary2) -def partial_transpose(state, qargs): - """Return partially transposed density matrix. - - Args: - state (DensityMatrix): the input state. - qargs (list): The subsystems to be transposed. - - Returns: - DensityMatrix: The partially transposed density matrix. - - Raises: - QiskitError: if input state is invalid. - QiskitError: if indices of subsystems are invalid - - """ - state = _format_state(state, validate=False) - n = len(state.dims()) -<<<<<<< HEAD - l = np.zeros(2**n, int) -======= - lst = np.zeros(2**n, int) ->>>>>>> 8e2684ac7e3791a12afaa700959173c7627362ef - for i in range(2**n): - x = 0 - for k in qargs: - x = x + (((i >> (k)) % 2) * 2**k) -<<<<<<< HEAD - l[i] = x - if not (set(qargs).issubset(set(np.arange(n)))): -======= - lst[i] = x - if not set(qargs).issubset(set(np.arange(n))): ->>>>>>> 8e2684ac7e3791a12afaa700959173c7627362ef - raise QiskitError("Indices of subsystems to be transposed are invalid") - ptden = np.empty((2**n, 2**n), complex) - ptden[:] = np.nan - if isinstance(state, Statevector): - state = np.array(state) - for i in range(2**n): - for j in range(2**n): - if math.isnan(ptden[i, j]): -<<<<<<< HEAD - x = i - l[i] + l[j] - y = j - l[j] + l[i] -======= - x = i - lst[i] + lst[j] - y = j - lst[j] + lst[i] ->>>>>>> 8e2684ac7e3791a12afaa700959173c7627362ef - ptden[i, j] = state[x] * np.conjugate(state[y]) - ptden[x, y] = state[i] * np.conjugate(state[j]) - else: - state = np.array(state) - for i in range(2**n): - for j in range(2**n): - if math.isnan(ptden[i, j]): -<<<<<<< HEAD - x = i - l[i] + l[j] - y = j - l[j] + l[i] -======= - x = i - lst[i] + lst[j] - y = j - lst[j] + lst[i] ->>>>>>> 8e2684ac7e3791a12afaa700959173c7627362ef - ptden[i, j] = state[x, y] - ptden[x, y] = state[i, j] - - return DensityMatrix(ptden) From 11d5adc80a395081ce964b8025110004b4b4cc4c Mon Sep 17 00:00:00 2001 From: PayalSolanki29 Date: Thu, 16 Feb 2023 09:43:13 +0530 Subject: [PATCH 21/24] fix --- qiskit/quantum_info/__init__.py | 1 - qiskit/quantum_info/states/__init__.py | 2 +- test/python/quantum_info/states/test_utils.py | 23 +------------------ 3 files changed, 2 insertions(+), 24 deletions(-) diff --git a/qiskit/quantum_info/__init__.py b/qiskit/quantum_info/__init__.py index 19b7513e41c9..45a8d46e4765 100644 --- a/qiskit/quantum_info/__init__.py +++ b/qiskit/quantum_info/__init__.py @@ -131,7 +131,6 @@ from .states import Statevector, DensityMatrix, StabilizerState from .states import ( partial_trace, - partial_transpose, state_fidelity, purity, entropy, diff --git a/qiskit/quantum_info/states/__init__.py b/qiskit/quantum_info/states/__init__.py index ab231932c4fc..1e49ee353b7b 100644 --- a/qiskit/quantum_info/states/__init__.py +++ b/qiskit/quantum_info/states/__init__.py @@ -15,7 +15,7 @@ from .statevector import Statevector from .stabilizerstate import StabilizerState from .densitymatrix import DensityMatrix -from .utils import partial_trace, shannon_entropy, partial_transpose +from .utils import partial_trace, shannon_entropy from .measures import ( state_fidelity, purity, diff --git a/test/python/quantum_info/states/test_utils.py b/test/python/quantum_info/states/test_utils.py index 7ab3bedc8edf..a791e146588a 100644 --- a/test/python/quantum_info/states/test_utils.py +++ b/test/python/quantum_info/states/test_utils.py @@ -55,28 +55,7 @@ def test_shannon_entropy(self): # Base 10 self.assertAlmostEqual(0.533908120973504, shannon_entropy(input_pvec, 10)) - def test_statevector_partial_transpose(self): - """Test partial_transpose function on statevectors""" - psi = Statevector.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(partial_transpose(psi, [0, 1]), DensityMatrix(rho1)) - self.assertEqual(partial_transpose(psi, [0, 2]), DensityMatrix(rho1)) - - def test_density_matrix_partial_transpose(self): - """Test partial_transpose function on density matrices""" - 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(partial_transpose(rho, [0, 1]), DensityMatrix(rho1)) - self.assertEqual(partial_transpose(rho, [0, 2]), DensityMatrix(rho1)) - + if __name__ == "__main__": unittest.main() From 0ab74ea29131d4b4654635ec94a509da185e2882 Mon Sep 17 00:00:00 2001 From: PayalSolanki29 Date: Thu, 16 Feb 2023 11:26:21 +0530 Subject: [PATCH 22/24] fir partial_transpose --- qiskit/quantum_info/states/densitymatrix.py | 26 +++++++++++++++++++ qiskit/quantum_info/states/utils.py | 2 -- .../quantum_info/states/test_densitymatrix.py | 11 ++++++++ test/python/quantum_info/states/test_utils.py | 3 +-- 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/qiskit/quantum_info/states/densitymatrix.py b/qiskit/quantum_info/states/densitymatrix.py index 435c02e535cf..33cfb5912ee7 100644 --- a/qiskit/quantum_info/states/densitymatrix.py +++ b/qiskit/quantum_info/states/densitymatrix.py @@ -809,3 +809,29 @@ 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. + + Raises: + QiskitError: if input state is invalid. + + """ + from qiskit.quantum_info.states import utils + + state = utils._format_state(self, validate=False) + arr = state._data.reshape(state._op_shape.tensor_shape) + qargs = len(state._op_shape.dims_l()) - 1 - np.array(qargs) + n = len(state.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, state._op_shape.shape) + return DensityMatrix(rho) diff --git a/qiskit/quantum_info/states/utils.py b/qiskit/quantum_info/states/utils.py index 21abb6d5b344..88cbcc6e3330 100644 --- a/qiskit/quantum_info/states/utils.py +++ b/qiskit/quantum_info/states/utils.py @@ -154,5 +154,3 @@ def _funm_svd(matrix, func): unitary1, singular_values, unitary2 = la.svd(matrix) diag_func_singular = np.diag(func(singular_values)) return unitary1.dot(diag_func_singular).dot(unitary2) - - diff --git a/test/python/quantum_info/states/test_densitymatrix.py b/test/python/quantum_info/states/test_densitymatrix.py index 6a619094ce3e..9f596fa1f13c 100644 --- a/test/python/quantum_info/states/test_densitymatrix.py +++ b/test/python/quantum_info/states/test_densitymatrix.py @@ -1202,6 +1202,17 @@ 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""" + 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(DensityMatrix.partial_transpose(rho, [0, 1]), DensityMatrix(rho1)) + self.assertEqual(DensityMatrix.partial_transpose(rho, [0, 2]), DensityMatrix(rho1)) + if __name__ == "__main__": unittest.main() diff --git a/test/python/quantum_info/states/test_utils.py b/test/python/quantum_info/states/test_utils.py index a791e146588a..2ea9038eb631 100644 --- a/test/python/quantum_info/states/test_utils.py +++ b/test/python/quantum_info/states/test_utils.py @@ -17,7 +17,7 @@ from qiskit.test import QiskitTestCase from qiskit.quantum_info.states import Statevector, DensityMatrix -from qiskit.quantum_info.states import partial_trace, shannon_entropy, partial_transpose +from qiskit.quantum_info.states import partial_trace, shannon_entropy class TestStateUtils(QiskitTestCase): @@ -55,7 +55,6 @@ def test_shannon_entropy(self): # Base 10 self.assertAlmostEqual(0.533908120973504, shannon_entropy(input_pvec, 10)) - if __name__ == "__main__": unittest.main() From d944e23aea202baf966340a6baa7856339dd862b Mon Sep 17 00:00:00 2001 From: "Payal D. Solanki" Date: Thu, 16 Feb 2023 12:04:18 +0530 Subject: [PATCH 23/24] Update utils.py --- qiskit/quantum_info/states/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qiskit/quantum_info/states/utils.py b/qiskit/quantum_info/states/utils.py index 88cbcc6e3330..04be491855d8 100644 --- a/qiskit/quantum_info/states/utils.py +++ b/qiskit/quantum_info/states/utils.py @@ -15,6 +15,7 @@ """ import numpy as np + from qiskit.exceptions import QiskitError from qiskit.quantum_info.states.statevector import Statevector from qiskit.quantum_info.states.densitymatrix import DensityMatrix From 84bd4502d2f00799a0ede9db10b6fd84b99e3621 Mon Sep 17 00:00:00 2001 From: ikkoham Date: Wed, 12 Apr 2023 23:17:25 +0900 Subject: [PATCH 24/24] refactor and add tests --- qiskit/quantum_info/states/densitymatrix.py | 15 ++----- .../quantum_info/states/test_densitymatrix.py | 40 +++++++++++-------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/qiskit/quantum_info/states/densitymatrix.py b/qiskit/quantum_info/states/densitymatrix.py index 8a7c41022daa..124a382f01d1 100644 --- a/qiskit/quantum_info/states/densitymatrix.py +++ b/qiskit/quantum_info/states/densitymatrix.py @@ -823,20 +823,13 @@ def partial_transpose(self, qargs): Returns: DensityMatrix: The partially transposed density matrix. - - Raises: - QiskitError: if input state is invalid. - """ - from qiskit.quantum_info.states import utils - - state = utils._format_state(self, validate=False) - arr = state._data.reshape(state._op_shape.tensor_shape) - qargs = len(state._op_shape.dims_l()) - 1 - np.array(qargs) - n = len(state.dims()) + 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, state._op_shape.shape) + rho = np.reshape(rho, self._op_shape.shape) return DensityMatrix(rho) diff --git a/test/python/quantum_info/states/test_densitymatrix.py b/test/python/quantum_info/states/test_densitymatrix.py index eeb5b07685f9..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__) @@ -1204,14 +1203,21 @@ def test_drawings(self): def test_density_matrix_partial_transpose(self): """Test partial_transpose function on density matrices""" - 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(DensityMatrix.partial_transpose(rho, [0, 1]), DensityMatrix(rho1)) - self.assertEqual(DensityMatrix.partial_transpose(rho, [0, 2]), DensityMatrix(rho1)) + 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]."""