Exemple #1
0
def beamsplitter(t, r, phi, trunc):
    r""" The beamsplitter :math:`B(cos^{-1} t, phi)`.

    Uses the `BSgate operation from The Walrus`_ to calculate the beamsplitter.

    .. _`BSgate operation from The Walrus`: https://the-walrus.readthedocs.io/en/latest/code/api/thewalrus.fock_gradients.BSgate.html
    """
    # pylint: disable=bad-whitespace

    theta = np.arccos(t)
    BS_tw, _, _ = BSgate(theta, phi, cutoff=trunc)

    # TODO: Transpose needed because of different conventions in SF and The Walrus. Remove when The Walrus is updated.
    return BS_tw.transpose((0, 2, 1, 3))
Exemple #2
0
def test_BSgate():
    """Tests the value of the analytic gradient for the BSgate against finite differences"""
    cutoff = 4
    r = 1.0
    theta = np.pi / 8
    _, Dr, Dtheta = BSgate(r, theta, cutoff, grad=True)
    dr = 0.001
    dtheta = 0.001
    Drp, _, _ = BSgate(r + dr, theta, cutoff, grad=False)
    Drm, _, _ = BSgate(r - dr, theta, cutoff, grad=False)
    Dthetap, _, _ = BSgate(r, theta + dtheta, cutoff, grad=False)
    Dthetam, _, _ = BSgate(r, theta - dtheta, cutoff, grad=False)
    Drapprox = (Drp - Drm) / (2 * dr)
    Dthetaapprox = (Dthetap - Dthetam) / (2 * dtheta)
    assert np.allclose(Dr, Drapprox, atol=1e-4, rtol=0)
    assert np.allclose(Dtheta, Dthetaapprox, atol=1e-4, rtol=0)
Exemple #3
0
def test_sf_order_BSgate():
    """Test the correct sf ordering for BSgate"""
    T = BSgate(1.0, 0.5, 10)[0]
    Tsf = BSgate(1.0, 0.5, 10, sf_order=True)[0]
    assert np.allclose(T.transpose((0, 2, 1, 3)), Tsf)
    T, T1, T2 = BSgate(1.0, 0.5, 10, grad=True)
    Tsf, Tsf1, Tsf2 = BSgate(1.0, 0.5, 10, grad=True, sf_order=True)
    assert np.allclose(T.transpose((0, 2, 1, 3)), Tsf)
    assert np.allclose(T1.transpose((0, 2, 1, 3)), Tsf1)
    assert np.allclose(T2.transpose((0, 2, 1, 3)), Tsf2)
Exemple #4
0
def test_BS_hong_ou_mandel_interference(tol):
    r"""Tests Hong-Ou-Mandel interference for a 50:50 beamsplitter.
    If one writes :math:`U` for the Fock representation of a 50-50 beamsplitter
    then it must hold that :math:`\langle 1,1|U|1,1 \rangle = 0`.
    """
    cutoff = 2
    phi = 2 * np.pi * np.random.rand()
    T = BSgate(np.pi / 4, phi, cutoff)[0]  # a 50-50 beamsplitter with phase phi
    assert np.allclose(T[1, 1, 1, 1], 0.0, atol=tol, rtol=0)
Exemple #5
0
def test_BS_values(tol):
    r"""Test that the representation of an interferometer in the single
    excitation manifold is precisely the unitary matrix that represents it
    mode in space. This test in particular checks that the BS gate is
    consistent with strawberryfields
    """
    nmodes = 2
    vec_list = np.identity(nmodes, dtype=int).tolist()
    theta = 2 * np.pi * np.random.rand()
    phi = 2 * np.pi * np.random.rand()
    ct = np.cos(theta)
    st = np.sin(theta) * np.exp(1j * phi)
    U = np.array([[ct, -np.conj(st)], [st, ct]])
    # Calculate the matrix \langle i | U | j \rangle = T[i+j]
    T = BSgate(theta, phi, 3)[0]
    U_rec = np.empty([nmodes, nmodes], dtype=complex)
    for i, vec_i in enumerate(vec_list):
        for j, vec_j in enumerate(vec_list):
            U_rec[i, j] = T[tuple(vec_i + vec_j)]
    assert np.allclose(U, U_rec, atol=tol, rtol=0)
Exemple #6
0
def test_BS_selection_rules(tol):
    r"""Test the selection rules of a beamsplitter.
    If one writes the beamsplitter gate of :math:`U` and its matrix elements as
    :math:`\langle m, n |U|k,l \rangle` then these elements
    are nonzero if and only if :math:`m+n = k+l`. This test checks
    that this selection rule holds.
    """
    cutoff = 4
    T = BSgate(np.random.rand(), np.random.rand(), cutoff)[0]
    m = np.arange(cutoff).reshape(-1, 1, 1, 1)
    n = np.arange(cutoff).reshape(1, -1, 1, 1)
    k = np.arange(cutoff).reshape(1, 1, -1, 1)
    l = np.arange(cutoff).reshape(1, 1, 1, -1)

    # create a copy of T, but replace all elements where
    # m+n != k+l with 0.
    S = np.where(m + n != k + l, 0, T)

    # check that S and T remain equal
    assert np.allclose(S, T, atol=tol, rtol=0)