Skip to content

Commit

Permalink
add pytest in unit tests for is_separable
Browse files Browse the repository at this point in the history
  • Loading branch information
purva-thakre committed Mar 14, 2024
1 parent 86fa4c9 commit 9b62413
Showing 1 changed file with 63 additions and 50 deletions.
113 changes: 63 additions & 50 deletions toqito/state_props/tests/test_is_separable.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Test is_separable."""

import numpy as np
import pytest

from toqito.channels import partial_trace
from toqito.matrix_props import is_density
Expand All @@ -9,34 +10,63 @@
from toqito.states import basis, bell, tile


def test_non_positive_semidefinite_matrix():
"""Ensure separability of non-positive semidefinite matrix is invalid."""
with np.testing.assert_raises(ValueError):
state = np.array([[-1, -1], [-1, -1]])
is_separable(state)


def test_psd_matrix_local_dim_one():
"""Every positive semidefinite matrix is separable when one of the local dimensions is 1."""
np.testing.assert_equal(is_separable(np.identity(2)), True)



def test_entangled_ppt_criterion():
"""Determined to be entangled via the PPT criterion."""
rho = bell(0) * bell(0).conj().T
np.testing.assert_equal(is_separable(rho), False)


def test_ppt_small_dimensions():
"""Determined to be separable via sufficiency of the PPT criterion in small dimensions."""
e_0, e_1, e_2 = basis(3, 0), basis(3, 1), basis(3, 2)
psi = 1 / np.sqrt(3) * e_0 + 1 / np.sqrt(3) * e_1 + 1 / np.sqrt(3) * e_2

e_0, e_1 = basis(2, 0), basis(2, 1)
phi = np.kron((1 / np.sqrt(2) * e_0 + 1 / np.sqrt(2) * e_1), psi)
sigma = phi * phi.conj().T
np.testing.assert_equal(is_separable(sigma), True)
@pytest.mark.parametrize(
"test_input",
[
# Ensure separability of non-positive semidefinite matrix is invalid
(np.array([[-1, -1], [-1, -1]])),
],
)
def test_werner_state_invalid(test_input):
"""Test function works as expected for an invalid input."""
with pytest.raises(ValueError):
is_separable(test_input)


p_var, a_var, b_var = 0.4, 0.8, 0.64
rho_chen = np.array(
[
[p_var * a_var**2, 0, 0, p_var * a_var * b_var],
[0, (1 - p_var) * a_var**2, (1 - p_var) * a_var * b_var, 0],
[0, (1 - p_var) * a_var * b_var, (1 - p_var) * a_var**2, 0],
[p_var * a_var * b_var, 0, 0, p_var * a_var**2],
]
)


@pytest.mark.parametrize(
"test_input",
[
# Determined to be entangled via the PPT criterion.
(bell(0) * bell(0).conj().T),
# Determined to be entangled by using Theorem 1 and Remark 1 of :cite:`Chen_2003_Matrix`.
(rho_chen),
],
)
def test_not_is_separable(test_input):
"""Check an expected non seperable test input is identified correctly."""
assert not is_separable(test_input)


e_0, e_1, e_2 = basis(3, 0), basis(3, 1), basis(3, 2)
psi = 1 / np.sqrt(3) * e_0 + 1 / np.sqrt(3) * e_1 + 1 / np.sqrt(3) * e_2

e_0, e_1 = basis(2, 0), basis(2, 1)
phi = np.kron((1 / np.sqrt(2) * e_0 + 1 / np.sqrt(2) * e_1), psi)


@pytest.mark.parametrize(
"test_input",
[
# Every positive semidefinite matrix is separable when one of the local dimensions is 1.
(np.identity(2)),
# Determined to be separable via sufficiency of the PPT criterion in small dimensions.
(phi * phi.conj().T),
],
)
def test_is_separable(test_input):
"""Check an expected seperable test input is identified correctly."""
assert is_separable(test_input)


def test_ppt_low_rank():
Expand All @@ -49,12 +79,9 @@ def test_ppt_low_rank():
rho_cut = rho_cut / np.trace(rho_cut)
pt_state_alice = partial_trace(rho_cut, [1], [3, 2])

np.testing.assert_equal(is_density(rho_cut), True)
np.testing.assert_equal(is_density(np.array(pt_state_alice)), True)
np.testing.assert_equal(
np.linalg.matrix_rank(rho_cut) + np.linalg.matrix_rank(pt_state_alice) <= 2 * m * n - m - n + 2,
True,
)
assert is_density(rho_cut)
assert is_density(np.array(pt_state_alice))
assert np.linalg.matrix_rank(rho_cut) + np.linalg.matrix_rank(pt_state_alice) - 2 * m * n - m - n + 2 <= 1e-1
# TODO
# np.testing.assert_equal(is_separable(rho), True)

Expand All @@ -67,19 +94,5 @@ def test_entangled_realignment_criterion():
for i in range(5):
rho = rho - tile(i) * tile(i).conj().T
rho = rho / 4
np.testing.assert_equal(is_density(rho), True)
np.testing.assert_equal(is_separable(rho), False)


def test_entangled_cross_norm_realignment_criterion():
"""Determined to be entangled by using Theorem 1 and Remark 1 of :cite:`Chen_2003_Matrix`."""
p_var, a_var, b_var = 0.4, 0.8, 0.64
rho = np.array(
[
[p_var * a_var**2, 0, 0, p_var * a_var * b_var],
[0, (1 - p_var) * a_var**2, (1 - p_var) * a_var * b_var, 0],
[0, (1 - p_var) * a_var * b_var, (1 - p_var) * a_var**2, 0],
[p_var * a_var * b_var, 0, 0, p_var * a_var**2],
]
)
np.testing.assert_equal(is_separable(rho), False)
assert is_density(rho)
assert not is_separable(rho)

0 comments on commit 9b62413

Please sign in to comment.