Exemple #1
0
def test_schmidt_decomp_dim_list_pure_state():
    """Schmidt decomposition of a pure state with a dimension list."""
    pure_vec = -1 / np.sqrt(2) * np.array([[1], [0], [1], [0]])

    # Test when dimension default and k_param is default (0):
    singular_vals, vt_mat, u_mat = schmidt_decomposition(pure_vec)

    expected_singular_vals = np.array([[1]])
    bool_mat = np.isclose(expected_singular_vals, singular_vals)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_vt_mat = 1 / np.sqrt(2) * np.array([[-1], [-1]])
    bool_mat = np.isclose(expected_vt_mat, vt_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_u_mat = np.array([[1], [0]])
    bool_mat = np.isclose(expected_u_mat, u_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    # Test when dimension [2, 2] and k_param is 1:
    singular_vals, vt_mat, u_mat = schmidt_decomposition(pure_vec, [2, 2], 1)

    expected_singular_vals = np.array([[1]])
    bool_mat = np.isclose(expected_singular_vals, singular_vals)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_vt_mat = 1 / np.sqrt(2) * np.array([[-1], [-1]])
    bool_mat = np.isclose(expected_vt_mat, vt_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_u_mat = np.array([[1], [0]])
    bool_mat = np.isclose(expected_u_mat, u_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    # Test when dimension [2, 2] and k_param is 2:
    singular_vals, vt_mat, u_mat = schmidt_decomposition(pure_vec, [2, 2], 2)

    expected_singular_vals = np.array([[1], [0]])
    bool_mat = np.isclose(expected_singular_vals, singular_vals)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_vt_mat = 1 / np.sqrt(2) * np.array([[-1, -1], [-1, 1]])
    bool_mat = np.isclose(expected_vt_mat, vt_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_u_mat = np.identity(2)
    bool_mat = np.isclose(expected_u_mat, u_mat)
    np.testing.assert_equal(np.all(bool_mat), True)
Exemple #2
0
def test_schmidt_decomp_two_qubit_3():
    """
    Schmidt decomposition of two-qubit state.

    The Schmidt decomposition of 1/2* (|00> + |11>) has Schmidt coefficients
    equal to 1/2[1, 1]
    """
    e_0, e_1 = basis(2, 0), basis(2, 1)

    phi = 1 / 2 * (np.kron(e_0, e_0) + np.kron(e_1, e_1))
    singular_vals, vt_mat, u_mat = schmidt_decomposition(phi)

    expected_singular_vals = 1 / 2 * np.array([[1], [1]])
    bool_mat = np.isclose(expected_singular_vals, singular_vals)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_vt_mat = np.array([[1, 0], [0, 1]])
    bool_mat = np.isclose(expected_vt_mat, vt_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_u_mat = np.array([[1, 0], [0, 1]])
    bool_mat = np.isclose(expected_u_mat, u_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    s_decomp = (
        singular_vals[0] * np.atleast_2d(np.kron(vt_mat[:, 0], u_mat[:, 0])).T
        +
        singular_vals[1] * np.atleast_2d(np.kron(vt_mat[:, 1], u_mat[:, 1])).T)

    np.testing.assert_equal(np.isclose(np.linalg.norm(phi - s_decomp), 0),
                            True)
Exemple #3
0
def test_schmidt_decomp_two_qubit_2():
    """
    Schmidt decomposition of two-qubit state.

    The Schmidt decomposition of | phi > = 1/2(|00> + |01> + |10> - |11>) is
    the state 1/sqrt(2) * (|0>|+> + |1>|->).
    """
    e_0, e_1 = basis(2, 0), basis(2, 1)

    phi = 1 / 2 * (np.kron(e_0, e_0) + np.kron(e_0, e_1) + np.kron(e_1, e_0) -
                   np.kron(e_1, e_1))
    singular_vals, vt_mat, u_mat = schmidt_decomposition(phi)

    expected_singular_vals = 1 / np.sqrt(2) * np.array([[1], [1]])
    bool_mat = np.isclose(expected_singular_vals, singular_vals)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_vt_mat = np.array([[-1, 0], [0, -1]])
    bool_mat = np.isclose(expected_vt_mat, vt_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_u_mat = 1 / np.sqrt(2) * np.array([[-1, -1], [-1, 1]])
    bool_mat = np.isclose(expected_u_mat, u_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    s_decomp = (
        singular_vals[0] * np.atleast_2d(np.kron(vt_mat[:, 0], u_mat[:, 0])).T
        +
        singular_vals[1] * np.atleast_2d(np.kron(vt_mat[:, 1], u_mat[:, 1])).T)

    np.testing.assert_equal(np.isclose(np.linalg.norm(phi - s_decomp), 0),
                            True)
Exemple #4
0
def _is_product(rho: np.ndarray,
                dim: Union[int, List[int]] = None) -> [int, bool]:
    """
    Determine if input is a product state recursive helper.

    :param rho: The vector or matrix to check.
    :param dim: The dimension of the input.
    :return: :code:`True` if :code:`rho` is a product vector and :code:`False` otherwise.
    """
    # If the input is provided as a matrix, compute the operator Schmidt rank.
    if len(rho.shape) == 2:
        if rho.shape[0] != 1 and rho.shape[1] != 1:
            return _operator_is_product(rho, dim)

    if dim is None:
        dim = np.round(np.sqrt(len(rho)))
    if isinstance(dim, list):
        dim = np.array(dim)

    # Allow the user to enter a single number for dim.
    if isinstance(dim, float):
        num_sys = 1
    else:
        num_sys = len(dim)

    if num_sys == 1:
        dim = np.array([dim, len(rho) // dim])
        dim[1] = np.round(dim[1])
        num_sys = 2

    dec = None
    # If there are only two subsystems, just use the Schmidt decomposition.
    if num_sys == 2:
        singular_vals, u_mat, vt_mat = schmidt_decomposition(rho, dim, 2)
        ipv = singular_vals[1] <= np.prod(dim) * np.spacing(singular_vals[0])

        # Provide this even if not requested, since it is needed if this
        # function was called as part of its recursive algorithm (see below)
        if ipv:
            u_mat = u_mat * np.sqrt(singular_vals[0])
            vt_mat = vt_mat * np.sqrt(singular_vals[0])
            dec = [u_mat[:, 0], vt_mat[:, 0]]
    else:
        new_dim = [dim[0] * dim[1]]
        new_dim.extend(dim[2:])
        ipv, dec = _is_product(rho, new_dim)
        if ipv:
            ipv, tdec = _is_product(dec[0], [dim[0], dim[1]])
            if ipv:
                dec = [tdec, dec[1:]]
    return ipv, dec
Exemple #5
0
def test_schmidt_decomp_max_ent():
    """Schmidt decomposition of the 3-D maximally entangled state."""
    singular_vals, u_mat, vt_mat = schmidt_decomposition(max_entangled(3))

    expected_u_mat = np.identity(3)
    expected_vt_mat = np.identity(3)
    expected_singular_vals = 1 / np.sqrt(3) * np.array([[1], [1], [1]])

    bool_mat = np.isclose(expected_u_mat, u_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    bool_mat = np.isclose(expected_vt_mat, vt_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    bool_mat = np.isclose(expected_singular_vals, singular_vals)
    np.testing.assert_equal(np.all(bool_mat), True)
Exemple #6
0
def test_schmidt_decomp_standard_basis():
    """Test on standard basis vectors."""
    e_1 = basis(2, 1)
    singular_vals, vt_mat, u_mat = schmidt_decomposition(np.kron(e_1, e_1))

    expected_singular_vals = np.array([[1]])
    bool_mat = np.isclose(expected_singular_vals, singular_vals)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_vt_mat = np.array([[0], [1]])
    bool_mat = np.isclose(expected_vt_mat, vt_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_u_mat = np.array([[0], [1]])
    bool_mat = np.isclose(expected_u_mat, u_mat)
    np.testing.assert_equal(np.all(bool_mat), True)
Exemple #7
0
def test_schmidt_decomp_dim_list():
    """Schmidt decomposition with list specifying dimension."""
    singular_vals, u_mat, vt_mat = schmidt_decomposition(max_entangled(3),
                                                         dim=[3, 3])

    expected_u_mat = np.identity(3)
    expected_vt_mat = np.identity(3)
    expected_singular_vals = 1 / np.sqrt(3) * np.array([[1], [1], [1]])

    bool_mat = np.isclose(expected_u_mat, u_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    bool_mat = np.isclose(expected_vt_mat, vt_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    bool_mat = np.isclose(expected_singular_vals, singular_vals)
    np.testing.assert_equal(np.all(bool_mat), True)
Exemple #8
0
def test_schmidt_decomp_example():
    """Test for example Schmidt decomposition."""
    e_0, e_1 = basis(2, 0), basis(2, 1)
    phi = ((1 + np.sqrt(6)) / (2 * np.sqrt(6)) * np.kron(e_0, e_0) +
           (1 - np.sqrt(6)) / (2 * np.sqrt(6)) * np.kron(e_0, e_1) +
           (np.sqrt(2) - np.sqrt(3)) / (2 * np.sqrt(6)) * np.kron(e_1, e_0) +
           (np.sqrt(2) + np.sqrt(3)) / (2 * np.sqrt(6)) * np.kron(e_1, e_1))

    singular_vals, vt_mat, u_mat = schmidt_decomposition(phi)

    expected_singular_vals = np.array([[np.sqrt(3 / 4)], [np.sqrt(1 / 4)]])
    bool_mat = np.isclose(expected_singular_vals, singular_vals)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_vt_mat = np.array([[-0.81649658, 0.57735027],
                                [0.57735027, 0.81649658]])
    bool_mat = np.isclose(expected_vt_mat, vt_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_u_mat = 1 / np.sqrt(2) * np.array([[-1, 1], [1, 1]])
    bool_mat = np.isclose(expected_u_mat, u_mat)
    np.testing.assert_equal(np.all(bool_mat), True)
Exemple #9
0
def test_schmidt_decomp_two_qubit_4():
    """
    Schmidt decomposition of two-qubit state.

    The Schmidt decomposition of 1/2 * (|00> - |01> + |10> + |11>) has Schmidt coefficients
    equal to [1, 1]
    """
    e_0, e_1 = basis(2, 0), basis(2, 1)

    phi = 1 / 2 * (np.kron(e_0, e_0) - np.kron(e_0, e_1) + np.kron(e_1, e_0) +
                   np.kron(e_1, e_1))
    singular_vals, vt_mat, u_mat = schmidt_decomposition(phi)

    expected_singular_vals = 1 / np.sqrt(2) * np.array([[1], [1]])
    bool_mat = np.isclose(expected_singular_vals, singular_vals)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_vt_mat = np.array([[-1, 0], [0, 1]])
    bool_mat = np.isclose(expected_vt_mat, vt_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_u_mat = 1 / np.sqrt(2) * np.array([[-1, 1], [1, 1]])
    bool_mat = np.isclose(expected_u_mat, u_mat)
    np.testing.assert_equal(np.all(bool_mat), True)
Exemple #10
0
def test_schmidt_decomp_two_qubit_1():
    """
    Schmidt decomposition of two-qubit state.

    The Schmidt decomposition of | phi > = 1/2(|00> + |01> + |10> + |11>) is
    the state |+>|+> where |+> = 1/sqrt(2) * (|0> + |1>).
    """
    e_0, e_1 = basis(2, 0), basis(2, 1)

    phi = 1 / 2 * (np.kron(e_0, e_0) + np.kron(e_0, e_1) + np.kron(e_1, e_0) +
                   np.kron(e_1, e_1))
    singular_vals, vt_mat, u_mat = schmidt_decomposition(phi)

    expected_singular_vals = np.array([[1]])
    bool_mat = np.isclose(expected_singular_vals, singular_vals)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_vt_mat = 1 / np.sqrt(2) * np.array([[-1], [-1]])
    bool_mat = np.isclose(expected_vt_mat, vt_mat)
    np.testing.assert_equal(np.all(bool_mat), True)

    expected_u_mat = 1 / np.sqrt(2) * np.array([[-1], [-1]])
    bool_mat = np.isclose(expected_u_mat, u_mat)
    np.testing.assert_equal(np.all(bool_mat), True)