diff --git a/tests/test_quantum_info_entropies.py b/tests/test_quantum_info_entropies.py index d78ceca58a..2ef5689ee4 100644 --- a/tests/test_quantum_info_entropies.py +++ b/tests/test_quantum_info_entropies.py @@ -6,9 +6,14 @@ classical_relative_entropy, entanglement_entropy, entropy, + relative_entropy, shannon_entropy, ) -from qibo.quantum_info.random_ensembles import random_statevector, random_unitary +from qibo.quantum_info.random_ensembles import ( + random_density_matrix, + random_statevector, + random_unitary, +) def test_shannon_entropy_errors(backend): @@ -103,77 +108,54 @@ def test_entropy(backend, base, check_hermitian): @pytest.mark.parametrize("check_hermitian", [False, True]) @pytest.mark.parametrize("base", [2, 10, np.e, 5]) -@pytest.mark.parametrize("bipartition", [[0], [1]]) -def test_entanglement_entropy(backend, bipartition, base, check_hermitian): +def test_relative_entropy(backend, base, check_hermitian): with pytest.raises(TypeError): state = np.random.rand(2, 3) state = backend.cast(state, dtype=state.dtype) - test = entanglement_entropy( - state, - bipartition=bipartition, - base=base, - check_hermitian=check_hermitian, - backend=backend, + target = random_density_matrix(2, pure=True, backend=backend) + test = relative_entropy( + state, target, base=base, check_hermitian=check_hermitian, backend=backend + ) + with pytest.raises(TypeError): + target = np.random.rand(2, 3) + target = backend.cast(target, dtype=target.dtype) + state = random_density_matrix(2, pure=True, backend=backend) + test = relative_entropy( + state, target, base=base, check_hermitian=check_hermitian, backend=backend ) with pytest.raises(ValueError): state = np.array([1.0, 0.0]) state = backend.cast(state, dtype=state.dtype) - test = entanglement_entropy( - state, - bipartition=bipartition, - base=0, - check_hermitian=check_hermitian, - backend=backend, + target = np.array([0.0, 1.0]) + target = backend.cast(target, dtype=target.dtype) + test = relative_entropy( + state, target, base=0, check_hermitian=check_hermitian, backend=backend + ) + with pytest.raises(TypeError): + state = np.array([1.0, 0.0]) + state = backend.cast(state, dtype=state.dtype) + target = np.array([0.0, 1.0]) + target = backend.cast(target, dtype=target.dtype) + test = relative_entropy( + state, target, base=base, check_hermitian="False", backend=backend ) - if backend.__class__.__name__ == "CupyBackend": - with pytest.raises(NotImplementedError): - state = random_unitary(4, backend=backend) - test = entanglement_entropy( - state, - bipartition=bipartition, - base=base, - check_hermitian=True, - backend=backend, - ) - - # Bell state - state = np.array([1.0, 0.0, 0.0, 1.0]) / np.sqrt(2) - state = backend.cast(state, dtype=state.dtype) - - entang_entrop = entanglement_entropy( - state, - bipartition=bipartition, - base=base, - check_hermitian=check_hermitian, - backend=backend, - ) - if base == 2: - test = 1.0 - elif base == 10: - test = 0.30102999566398125 - elif base == np.e: - test = 0.6931471805599454 - else: - test = 0.4306765580733931 + nqubits = 2 + dims = 2**nqubits - backend.assert_allclose(entang_entrop, test, atol=PRECISION_TOL) + state = random_density_matrix(dims, backend=backend) + target = backend.identity_density_matrix(nqubits, normalize=True) - # Product state - state = np.kron( - random_statevector(2, backend=backend), random_statevector(2, backend=backend) - ) + print(relative_entropy(state, target, base, check_hermitian, backend)) + print(entropy(state, base, check_hermitian=check_hermitian, backend=backend)) - entang_entrop = entanglement_entropy( - state, - bipartition=bipartition, - base=base, - check_hermitian=check_hermitian, - backend=backend, + backend.assert_allclose( + relative_entropy(state, target, base, check_hermitian, backend), + np.log(dims) / np.log(base) + - entropy(state, base=base, check_hermitian=check_hermitian, backend=backend), + atol=1e-5, ) - backend.assert_allclose(entang_entrop, 0.0, atol=PRECISION_TOL) - @pytest.mark.parametrize("kind", [None, list]) @pytest.mark.parametrize("validate", [False, True]) @@ -233,3 +215,77 @@ def test_classical_relative_entropy(backend, base, validate, kind): ) backend.assert_allclose(divergence, target, atol=1e-5) + + +@pytest.mark.parametrize("check_hermitian", [False, True]) +@pytest.mark.parametrize("base", [2, 10, np.e, 5]) +@pytest.mark.parametrize("bipartition", [[0], [1]]) +def test_entanglement_entropy(backend, bipartition, base, check_hermitian): + with pytest.raises(TypeError): + state = np.random.rand(2, 3) + state = backend.cast(state, dtype=state.dtype) + test = entanglement_entropy( + state, + bipartition=bipartition, + base=base, + check_hermitian=check_hermitian, + backend=backend, + ) + with pytest.raises(ValueError): + state = np.array([1.0, 0.0]) + state = backend.cast(state, dtype=state.dtype) + test = entanglement_entropy( + state, + bipartition=bipartition, + base=0, + check_hermitian=check_hermitian, + backend=backend, + ) + if backend.__class__.__name__ == "CupyBackend": + with pytest.raises(NotImplementedError): + state = random_unitary(4, backend=backend) + test = entanglement_entropy( + state, + bipartition=bipartition, + base=base, + check_hermitian=True, + backend=backend, + ) + + # Bell state + state = np.array([1.0, 0.0, 0.0, 1.0]) / np.sqrt(2) + state = backend.cast(state, dtype=state.dtype) + + entang_entrop = entanglement_entropy( + state, + bipartition=bipartition, + base=base, + check_hermitian=check_hermitian, + backend=backend, + ) + + if base == 2: + test = 1.0 + elif base == 10: + test = 0.30102999566398125 + elif base == np.e: + test = 0.6931471805599454 + else: + test = 0.4306765580733931 + + backend.assert_allclose(entang_entrop, test, atol=PRECISION_TOL) + + # Product state + state = np.kron( + random_statevector(2, backend=backend), random_statevector(2, backend=backend) + ) + + entang_entrop = entanglement_entropy( + state, + bipartition=bipartition, + base=base, + check_hermitian=check_hermitian, + backend=backend, + ) + + backend.assert_allclose(entang_entrop, 0.0, atol=PRECISION_TOL)