diff --git a/qiskit/quantum_info/__init__.py b/qiskit/quantum_info/__init__.py index c20d0a0b4fbf..c5a601bbce77 100644 --- a/qiskit/quantum_info/__init__.py +++ b/qiskit/quantum_info/__init__.py @@ -173,6 +173,7 @@ purity, shannon_entropy, state_fidelity, + negativity, ) from .synthesis import ( OneQubitEulerDecomposer, diff --git a/qiskit/quantum_info/states/__init__.py b/qiskit/quantum_info/states/__init__.py index 1e49ee353b7b..20dd370d32e3 100644 --- a/qiskit/quantum_info/states/__init__.py +++ b/qiskit/quantum_info/states/__init__.py @@ -23,4 +23,5 @@ concurrence, mutual_information, entanglement_of_formation, + negativity, ) diff --git a/qiskit/quantum_info/states/measures.py b/qiskit/quantum_info/states/measures.py index b0b1451fbe95..a23dbfe3540f 100644 --- a/qiskit/quantum_info/states/measures.py +++ b/qiskit/quantum_info/states/measures.py @@ -252,3 +252,34 @@ def entanglement_of_formation(state): conc = concurrence(state) val = (1 + np.sqrt(1 - (conc**2))) / 2 return shannon_entropy([val, 1 - val]) + + +def negativity(state, qargs): + r"""Calculates the negativity + + The mathematical expression for negativity is given by: + .. math:: + {\cal{N}}(\rho) = \frac{|| \rho^{T_A}|| - 1 }{2} + + Args: + state (Statevector or DensityMatrix): a quantum state. + qargs (list): The subsystems to be transposed. + + Returns: + negv (float): Negativity value of the quantum state + + Raises: + QiskitError: if the input state is not a valid QuantumState. + """ + + if isinstance(state, Statevector): + # If input is statevector then converting it into density matrix + state = DensityMatrix(state) + # Generating partially transposed state + state = state.partial_transpose(qargs) + # Calculating SVD + singular_values = np.linalg.svd(state.data, compute_uv=False) + eigvals = np.sum(singular_values) + # Calculating negativity + negv = (eigvals - 1) / 2 + return negv diff --git a/releasenotes/notes/add-feature-negativity-logarithmic-negativity-fce5d8392460a0e9.yaml b/releasenotes/notes/add-feature-negativity-logarithmic-negativity-fce5d8392460a0e9.yaml new file mode 100644 index 000000000000..2a62f886e0f0 --- /dev/null +++ b/releasenotes/notes/add-feature-negativity-logarithmic-negativity-fce5d8392460a0e9.yaml @@ -0,0 +1,24 @@ +--- +features: + - | + Added a new function , :func:`negativity` that adds support for calculating + entanglement measures negativity of an quantum state. + An illustrative example for using the above function is given below: + + .. code-block: + from qiskit.quantum_info.states.densitymatrix import DensityMatrix + from qiskit.quantum_info.states.statevector import Statevector + from qiskit.quantum_info import negativity + import numpy as np + + # Constructing a two-qubit bell state vector + state = np.array([0, 1/np.sqrt(2), -1/np.sqrt(2), 0]) + # Calculating negativity of statevector + negv = negativity(Statevector(state), [1]) + + # Creating the Density Matrix (DM) + rho = DensityMatrix.from_label("10+") + # Calculating negativity of DM + negv2 = negativity(rho, [0, 1]) + + diff --git a/test/python/quantum_info/states/test_measures.py b/test/python/quantum_info/states/test_measures.py index 7d585f193d55..a22e2e427aee 100644 --- a/test/python/quantum_info/states/test_measures.py +++ b/test/python/quantum_info/states/test_measures.py @@ -25,6 +25,7 @@ from qiskit.quantum_info import entanglement_of_formation from qiskit.quantum_info import mutual_information from qiskit.quantum_info.states import shannon_entropy +from qiskit.quantum_info import negativity class TestStateMeasures(QiskitTestCase): @@ -341,6 +342,32 @@ def test_mutual_information_equivalence(self): rho = DensityMatrix(psi) self.assertAlmostEqual(mutual_information(psi), mutual_information(rho)) + def test_negativity_statevector(self): + """Test negativity function on statevector inputs""" + # Constructing separable quantum statevector + state = Statevector([1 / np.sqrt(2), 1 / np.sqrt(2), 0, 0]) + negv = negativity(state, [0]) + self.assertAlmostEqual(negv, 0, places=7) + # Constructing entangled quantum statevector + state = Statevector([0, 1 / np.sqrt(2), -1 / np.sqrt(2), 0]) + negv = negativity(state, [1]) + self.assertAlmostEqual(negv, 0.5, places=7) + + def test_negativity_density_matrix(self): + """Test negativity function on density matrix inputs""" + # Constructing separable quantum state + rho = DensityMatrix.from_label("10+") + negv = negativity(rho, [0, 1]) + self.assertAlmostEqual(negv, 0, places=7) + negv = negativity(rho, [0, 2]) + self.assertAlmostEqual(negv, 0, places=7) + # Constructing entangled quantum state + rho = DensityMatrix([[0, 0, 0, 0], [0, 0.5, -0.5, 0], [0, -0.5, 0.5, 0], [0, 0, 0, 0]]) + negv = negativity(rho, [0]) + self.assertAlmostEqual(negv, 0.5, places=7) + negv = negativity(rho, [1]) + self.assertAlmostEqual(negv, 0.5, places=7) + if __name__ == "__main__": unittest.main()