Esempio n. 1
0
def beamsplitter(t, r, phi, trunc, save=False, directory=None):
    r"""
    The beamsplitter :math:`B(cos^{-1} t, phi)`.
    """
    # pylint: disable=bad-whitespace
    try:
        prefac = so.load_bs_factors(trunc, directory)
    except FileNotFoundError:
        prefac = so.generate_bs_factors(trunc)
        if save:
            so.save_bs_factors(prefac, directory)

    dim_array = np.arange(trunc)
    N = dim_array.reshape((-1, 1, 1, 1, 1))
    n = dim_array.reshape((1, -1, 1, 1, 1))
    M = dim_array.reshape((1, 1, -1, 1, 1))
    k = dim_array.reshape((1, 1, 1, 1, -1))

    tpwr = M - n + 2 * k
    rpwr = n + N - 2 * k

    T = np.power(t, tpwr) if t != 0 else np.where(tpwr != 0, 0, 1)
    R = np.power(r, rpwr) if r != 0 else np.where(rpwr != 0, 0, 1)

    BS = np.sum(exp(-1j * (pi + phi) * (n - N)) * T * R *
                prefac[:trunc, :trunc, :trunc, :trunc, :trunc],
                axis=-1)
    BS = BS.swapaxes(0, 1).swapaxes(2, 3)

    return BS
Esempio n. 2
0
    def test_save_load_bs_factors(self):
        factors = so.generate_bs_factors(4)
        so.save_bs_factors(factors, directory="./")

        factors = so.load_bs_factors(4, directory="./")
        factors_val = factors[factors != 0.]
        factors_idx = np.array(np.nonzero(factors))

        self.assertAllAlmostEqual(factors_val, bs_4_val, delta=self.tol)
        self.assertAllAlmostEqual(factors_idx, bs_4_idx, delta=self.tol)
    def test_save_load(self, tmpdir, tol):
        """test saving and loading of beamsplitter factors"""
        factors = so.generate_bs_factors(4)
        so.save_bs_factors(factors, directory=str(tmpdir))

        factors = so.load_bs_factors(4, directory=str(tmpdir))
        factors_val = factors[factors != 0.0]
        factors_idx = np.array(np.nonzero(factors))

        assert np.allclose(factors_val, BS_4_VAL, atol=tol, rtol=0)
        assert np.allclose(factors_idx, BS_4_IDX, atol=tol, rtol=0)
Esempio n. 4
0
def get_prefac_tensor(D, directory, save):
    """Equivalent to the functionality of shared_ops the bs_factors functions from shared_ops,
    but caches the return value as a tensor. This allows us to re-use the same prefactors and save
    space on the computational graph."""
    try:
        prefac = load_bs_factors(D, directory)
    except FileNotFoundError:
        prefac = generate_bs_factors(D)
        if save:
            save_bs_factors(prefac, directory)
    prefac = tf.expand_dims(tf.cast(prefac[:D, :D, :D, :D, :D], def_type), 0)
    return prefac
Esempio n. 5
0
def squeezing(r, theta, trunc, save=False, directory=None):
    r"""The squeezing operator :math:`S(re^{i\theta})`.

    Args:
            r (float): the magnitude of the squeezing in the
                    x direction
            theta (float): the squeezing angle
            trunc (int): the Fock cutoff
    """
    # pylint: disable=duplicate-code
    if r == 0:
        # return the identity
        ret = np.eye(trunc, dtype=def_type)
    else:
        # broadcast the index arrays
        dim_array = np.arange(trunc)
        N = dim_array.reshape((-1, 1, 1))
        n = dim_array.reshape((1, -1, 1))
        k = dim_array.reshape((1, 1, -1))

        try:
            prefac = so.load_squeeze_factors(trunc, directory)
        except FileNotFoundError:
            prefac = so.generate_squeeze_factors(trunc)
            if save:
                so.save_bs_factors(prefac, directory)

        # we only perform the sum when n+N is divisible by 2
        # in which case we sum 0 <= k <= min(N,n)
        # mask = np.logical_and((n+N)%2 == 0, k <= np.minimum(N, n))
        mask = np.logical_and((n + N) % 2 == 0, k <= np.minimum(N, n))

        # perform the summation over k
        scale = mask * np.power(sinh(r) / 2,
                                mask * (N + n - 2 * k) / 2) / (cosh(r)**(
                                    (N + n + 1) / 2))
        ph = exp(1j * theta * (N - n) / 2)
        ret = np.sum(scale * ph * prefac, axis=-1)

    return ret