mirror of https://github.com/Qiskit/qiskit.git
134 lines
6.4 KiB
Python
134 lines
6.4 KiB
Python
# This code is part of Qiskit.
|
|
#
|
|
# (C) Copyright IBM 2017, 2020.
|
|
#
|
|
# This code is licensed under the Apache License, Version 2.0. You may
|
|
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
|
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
|
#
|
|
# Any modifications or derivative works of this code must retain this
|
|
# copyright notice, and modified files need to carry a notice indicating
|
|
# that they have been altered from the originals.
|
|
|
|
"""Tests utility functions for QuantumState classes."""
|
|
|
|
import unittest
|
|
import numpy as np
|
|
|
|
from qiskit.quantum_info.states import Statevector, DensityMatrix
|
|
from qiskit.quantum_info.states import partial_trace, shannon_entropy, schmidt_decomposition
|
|
from test import QiskitTestCase # pylint: disable=wrong-import-order
|
|
|
|
|
|
class TestStateUtils(QiskitTestCase):
|
|
"""Test utility functions for QuantumState classes."""
|
|
|
|
def test_statevector_partial_trace(self):
|
|
"""Test partial_trace function on statevectors"""
|
|
psi = Statevector.from_label("10+")
|
|
self.assertEqual(partial_trace(psi, [0, 1]), DensityMatrix.from_label("1"))
|
|
self.assertEqual(partial_trace(psi, [0, 2]), DensityMatrix.from_label("0"))
|
|
self.assertEqual(partial_trace(psi, [1, 2]), DensityMatrix.from_label("+"))
|
|
self.assertEqual(partial_trace(psi, [0]), DensityMatrix.from_label("10"))
|
|
self.assertEqual(partial_trace(psi, [1]), DensityMatrix.from_label("1+"))
|
|
self.assertEqual(partial_trace(psi, [2]), DensityMatrix.from_label("0+"))
|
|
self.assertEqual(partial_trace(psi, []), DensityMatrix(psi))
|
|
|
|
def test_density_matrix_partial_trace(self):
|
|
"""Test partial_trace function on density matrices"""
|
|
rho = DensityMatrix.from_label("10+")
|
|
self.assertEqual(partial_trace(rho, [0, 1]), DensityMatrix.from_label("1"))
|
|
self.assertEqual(partial_trace(rho, [0, 2]), DensityMatrix.from_label("0"))
|
|
self.assertEqual(partial_trace(rho, [1, 2]), DensityMatrix.from_label("+"))
|
|
self.assertEqual(partial_trace(rho, [0]), DensityMatrix.from_label("10"))
|
|
self.assertEqual(partial_trace(rho, [1]), DensityMatrix.from_label("1+"))
|
|
self.assertEqual(partial_trace(rho, [2]), DensityMatrix.from_label("0+"))
|
|
self.assertEqual(partial_trace(rho, []), rho)
|
|
|
|
def test_shannon_entropy(self):
|
|
"""Test shannon_entropy function"""
|
|
input_pvec = np.array([0.5, 0.3, 0.07, 0.1, 0.03])
|
|
# Base 2
|
|
self.assertAlmostEqual(1.7736043871504037, shannon_entropy(input_pvec))
|
|
# Base e
|
|
self.assertAlmostEqual(1.229368880382052, shannon_entropy(input_pvec, np.e))
|
|
# Base 10
|
|
self.assertAlmostEqual(0.533908120973504, shannon_entropy(input_pvec, 10))
|
|
|
|
def test_schmidt_decomposition_separable(self):
|
|
"""Test schmidt_decomposition for separable 2-level system without subsystem permutation"""
|
|
|
|
target = Statevector.from_label("l10")
|
|
schmidt_comps = schmidt_decomposition(target, [0])
|
|
|
|
# check decomposition elements
|
|
self.assertAlmostEqual(schmidt_comps[0][0], 1)
|
|
self.assertEqual(schmidt_comps[0][1], -1 * Statevector.from_label("l1"))
|
|
self.assertEqual(schmidt_comps[0][2], -1 * Statevector.from_label("0"))
|
|
|
|
# check that state can be properly reconstructed
|
|
state = Statevector(sum(suv[0] * np.kron(suv[1], suv[2]) for suv in schmidt_comps))
|
|
self.assertEqual(state, target)
|
|
|
|
def test_schmidt_decomposition_separable_with_permutation(self):
|
|
"""Test schmidt_decomposition for separable 2-level system with subsystem permutation"""
|
|
|
|
target = Statevector.from_label("0l1")
|
|
schmidt_comps = schmidt_decomposition(Statevector.from_label("l10"), [2, 1])
|
|
|
|
# check decomposition elements
|
|
self.assertAlmostEqual(schmidt_comps[0][0], 1)
|
|
self.assertEqual(schmidt_comps[0][1], Statevector.from_label("0"))
|
|
self.assertEqual(schmidt_comps[0][2], Statevector.from_label("l1"))
|
|
|
|
# check that state can be properly reconstructed
|
|
state = Statevector(sum(suv[0] * np.kron(suv[1], suv[2]) for suv in schmidt_comps))
|
|
self.assertEqual(state, target)
|
|
|
|
def test_schmidt_decomposition_entangled(self):
|
|
"""Test schmidt_decomposition for entangled 2-level system"""
|
|
|
|
target = np.sqrt(1 / 3) * Statevector.from_label("00") + np.sqrt(
|
|
2 / 3
|
|
) * Statevector.from_label("11")
|
|
schmidt_comps = schmidt_decomposition(target, [0])
|
|
|
|
# check decomposition elements
|
|
self.assertAlmostEqual(schmidt_comps[0][0], np.sqrt(2 / 3))
|
|
self.assertEqual(schmidt_comps[0][1], Statevector.from_label("1"))
|
|
self.assertEqual(schmidt_comps[0][2], Statevector.from_label("1"))
|
|
self.assertAlmostEqual(schmidt_comps[1][0], np.sqrt(1 / 3))
|
|
self.assertEqual(schmidt_comps[1][1], Statevector.from_label("0"))
|
|
self.assertEqual(schmidt_comps[1][2], Statevector.from_label("0"))
|
|
|
|
# check that state can be properly reconstructed
|
|
state = Statevector(sum(suv[0] * np.kron(suv[1], suv[2]) for suv in schmidt_comps))
|
|
self.assertEqual(state, target)
|
|
|
|
def test_schmidt_decomposition_3_level_system(self):
|
|
"""Test schmidt_decomposition for entangled 3-level system"""
|
|
|
|
target = Statevector(np.array([1, 0, 0, 0, 1, 0, 0, 0, 1]) * 1 / np.sqrt(3), dims=(3, 3))
|
|
schmidt_comps = schmidt_decomposition(target, [0])
|
|
|
|
# check decomposition elements
|
|
self.assertAlmostEqual(schmidt_comps[0][0], 1 / np.sqrt(3))
|
|
self.assertEqual(schmidt_comps[0][1], Statevector(np.array([1, 0, 0]), dims=3))
|
|
self.assertEqual(schmidt_comps[0][2], Statevector(np.array([1, 0, 0]), dims=3))
|
|
self.assertAlmostEqual(schmidt_comps[1][0], 1 / np.sqrt(3))
|
|
self.assertEqual(schmidt_comps[1][1], Statevector(np.array([0, 1, 0]), dims=3))
|
|
self.assertEqual(schmidt_comps[1][2], Statevector(np.array([0, 1, 0]), dims=3))
|
|
self.assertAlmostEqual(schmidt_comps[2][0], 1 / np.sqrt(3))
|
|
self.assertEqual(schmidt_comps[2][1], Statevector(np.array([0, 0, 1]), dims=3))
|
|
self.assertEqual(schmidt_comps[2][2], Statevector(np.array([0, 0, 1]), dims=3))
|
|
|
|
# check that state can be properly reconstructed
|
|
state = Statevector(
|
|
sum(suv[0] * np.kron(suv[1], suv[2]) for suv in schmidt_comps), dims=(3, 3)
|
|
)
|
|
self.assertEqual(state, target)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|