def test_merge(self, hbar, tol):
        """Test that two covariances matrices overwrite each other on merge"""
        n = 3
        V1 = random_covariance(n, pure=False, hbar=hbar)
        V2 = random_covariance(n, pure=True, hbar=hbar)

        cov1 = ops.Gaussian(V1, hbar=hbar)
        cov2 = ops.Gaussian(V2, hbar=hbar)

        # applying a second covariance matrix replaces the first
        assert cov1.merge(cov2) == cov2

        # the same is true of state preparations
        assert ops.Squeezed(2).merge(cov2) == cov2
Beispiel #2
0
    def test_multimode_gaussian_random_state(self, setup_backend, batch_size,
                                             pure, tol, hbar):
        """Test multimode Gaussian state preparation on a random state"""
        N = 4
        backend = setup_backend(N)

        means = 2 * np.random.random(size=[2 * N]) - 1
        cov = random_covariance(N, pure=pure)

        backend.reset(pure=pure)

        # circuit is initially in a random state
        backend.prepare_gaussian_state(means, cov, modes=range(N))

        # test Gaussian state is correct
        state = backend.state()
        assert np.allclose(state.means(),
                           np.array([means[from_xp(N)]]) * np.sqrt(hbar / 2),
                           atol=tol,
                           rtol=0)
        assert np.allclose(state.covs(),
                           np.array([cov[from_xp(N), :][:, from_xp(N)]]) *
                           hbar / 2,
                           atol=tol,
                           rtol=0)
Beispiel #3
0
    def test_singlemode_gaussian_state(self, setup_backend, batch_size, pure,
                                       tol):
        """Test single mode Gaussian state preparation"""
        N = 4
        backend = setup_backend(N)

        means = 2 * np.random.random(size=[2]) - 1
        cov = random_covariance(1, pure=pure)

        a = 0.2 + 0.4j
        r = 1
        phi = 0

        # circuit is initially in displaced squeezed state
        for i in range(N):
            backend.prepare_displaced_squeezed_state(a, r, phi, mode=i)

        # prepare Gaussian state in mode 1
        backend.prepare_gaussian_state(means, cov, modes=1)

        # test Gaussian state is correct
        state = backend.state([1])
        assert np.allclose(state.means(), means, atol=tol, rtol=0)
        assert np.allclose(state.cov(), cov, atol=tol, rtol=0)

        # test that displaced squeezed states are unchanged
        ex_means, ex_V = displaced_squeezed_state(a, r, phi, basis="gaussian")
        for i in [0, 2, 3]:
            state = backend.state([i])
            assert np.allclose(state.means(), ex_means, atol=tol, rtol=0)
            assert np.allclose(state.cov(), ex_V, atol=tol, rtol=0)
Beispiel #4
0
    def test_decomposition(self, hbar, tol):
        """Test that an arbitrary decomposition provides the right covariance matrix"""
        n = 3
        prog = sf.Program(n)
        cov = random_covariance(n)

        G = ops.Gaussian(cov)
        cmds = G.decompose(prog.register)

        S = np.identity(2 * n)
        cov_init = np.identity(2 * n) * hbar / 2

        # calculating the resulting decomposed symplectic
        for cmd in cmds:
            # all operations should be BSgates, Rgates, or Sgates
            assert isinstance(cmd.op,
                              (ops.Vacuum, ops.Thermal, ops.GaussianTransform))

            # build up the symplectic transform
            modes = [i.ind for i in cmd.reg]

            if isinstance(cmd.op, ops.Thermal):
                cov_init[cmd.reg[0].ind,
                         cmd.reg[0].ind] = ((2 * cmd.op.p[0].x + 1) * hbar / 2)
                cov_init[cmd.reg[0].ind + n, cmd.reg[0].ind +
                         n] = ((2 * cmd.op.p[0].x + 1) * hbar / 2)

            if isinstance(cmd.op, ops.GaussianTransform):
                S = cmd.op.p[0].x @ S

        # the resulting covariance state
        cov_res = S @ cov_init @ S.T

        assert np.allclose(cov, cov_res, atol=tol, rtol=0)
 def test_random_covariance_square(self, modes, hbar, pure_state,
                                   block_diag):
     """Test that a random covariance matrix is the right shape"""
     V = utils.random_covariance(modes,
                                 hbar=hbar,
                                 pure=pure_state,
                                 block_diag=block_diag)
     assert np.all(V.shape == np.array([2 * modes, 2 * modes]))
 def test_random_covariance_symmetric(self, modes, hbar, pure_state, tol,
                                      block_diag):
     """Test that a random covariance matrix is symmetric"""
     V = utils.random_covariance(modes,
                                 hbar=hbar,
                                 pure=pure_state,
                                 block_diag=block_diag)
     assert np.allclose(V.T, V, atol=tol, rtol=0)
 def test_random_covariance_mixed(self, modes, hbar, tol, block_diag):
     """Test that a mixed random covariance matrix has correct purity"""
     V = utils.random_covariance(modes,
                                 hbar=hbar,
                                 pure=False,
                                 block_diag=block_diag)
     det = np.linalg.det(V) - (hbar / 2)**(2 * modes)
     assert not np.allclose(det, 0, atol=tol, rtol=0)
Beispiel #8
0
    def test_merge(self, hbar, tol):
        """Test that merging two Preparations only keeps the latter one."""
        n = 3
        V1 = random_covariance(n, pure=False, hbar=hbar)
        V2 = random_covariance(n, pure=True, hbar=hbar)
        r1 = np.random.randn(2 * n)
        r2 = np.random.randn(2 * n)

        G1 = ops.Gaussian(V1, r1)
        G2 = ops.Gaussian(V2, r2)

        # applying a second state preparation replaces the first
        assert G1.merge(G2) is G2

        # the same is true of all state preparations
        S = ops.Squeezed(2)
        assert S.merge(G2) is G2
        assert G2.merge(S) is S
    def test_apply_decomp(self, hbar):
        """Test that the apply method, when decomp = True, raises a NotImplemented error."""
        prog = sf.Program(3, hbar=hbar)
        cov = random_covariance(3, hbar=hbar)

        with eng:
            G = ops.Gaussian(cov, decomp=True)

        with pytest.raises(NotImplementedError):
            G._apply(q, None)
Beispiel #10
0
    def test_random_covariance_valid(self, modes, hbar, pure_state, tol, block_diag):
        """Test that a random covariance matrix satisfies the uncertainty principle V+i hbar O/2 >=0"""
        V = utils.random_covariance(modes, hbar=hbar, pure=pure_state, block_diag=block_diag)

        idm = np.identity(modes)
        omega = np.concatenate(
            (np.concatenate((0 * idm, idm), axis=1), np.concatenate((-idm, 0 * idm), axis=1)),
            axis=0,
        )

        eigs = np.linalg.eigvalsh(V + 1j * (hbar / 2) * omega)
        eigs[np.abs(eigs) < tol] = 0
        assert np.all(eigs >= 0)
Beispiel #11
0
    def test_apply_decomp(self, hbar):
        """Test that the apply method, when decomp = False, calls the Backend directly."""
        prog = sf.Program(3)
        cov = random_covariance(3, hbar=hbar)

        class DummyBackend:
            """Dummy backend class"""
            def prepare_gaussian_state(*args):
                """Raises a syntax error when called"""
                raise SyntaxError

        G = ops.Gaussian(cov, decomp=False)
        with pytest.raises(SyntaxError):
            G._apply(prog.register, DummyBackend())
    def test_setting_hbar(self, hbar):
        """Test that an exception is raised if hbar not provided"""
        prog = sf.Program(3, hbar=hbar)
        cov = random_covariance(3, hbar=hbar)

        with pytest.raises(ValueError, match="specify the hbar keyword argument"):
            ops.Gaussian(cov)

        # hbar can be passed as a keyword arg
        G = ops.Gaussian(cov, hbar=hbar)
        assert G.hbar == hbar

        # or determined via the engine context
        with eng:
            G = ops.Gaussian(cov)

        assert G.hbar == hbar
Beispiel #13
0
 def test_random_covariance_pure(self, modes, hbar, tol):
     """Test that a pure random covariance matrix has correct purity"""
     V = utils.random_covariance(modes, hbar=hbar, pure=True)
     det = np.linalg.det(V) - (hbar / 2)**(2 * modes)
     assert np.allclose(det, 0, atol=tol, rtol=0)
Beispiel #14
0
def V_pure(hbar):
    return random_covariance(3, hbar=hbar, pure=True)
Beispiel #15
0
def V_mixed(hbar):
    return random_covariance(3, hbar=hbar, pure=False)
Beispiel #16
0
    def test_multimode_gaussian_random_state_with_replacement(
            self, setup_backend, batch_size, pure, tol, hbar):
        """Test multimode Gaussian state preparation on a random state with replacement"""
        N = 4
        backend = setup_backend(N)

        means = 2 * np.random.random(size=[2 * N]) - 1
        cov = random_covariance(N, pure=pure)

        backend.reset(pure=pure)

        # circuit is initially in a random state
        backend.prepare_gaussian_state(means, cov, modes=range(N))

        # test Gaussian state is correct
        state = backend.state()

        # prepare Gaussian state in mode 2 and 1
        means2 = 2 * np.random.random(size=[4]) - 1
        cov2 = random_covariance(2, pure=pure)
        backend.prepare_gaussian_state(means2, cov2, modes=[2, 1])

        # test resulting Gaussian state is correct
        state = backend.state()

        # in the new means vector, the modes 0 and 3 remain unchanged
        # Modes 1 and 2, however, now have values given from elements
        # means2[1] and means2[0].
        ex_means = np.array([
            means[0],
            means2[1],
            means2[0],
            means[3],  # position
            means[4],
            means2[3],
            means2[2],
            means[7],
        ])  # momentum

        ex_cov = np.zeros([8, 8])

        # in the new covariance matrix, modes 0 and 3 remain unchanged
        idx = np.array([0, 3, 4, 7])
        rows = idx.reshape(-1, 1)
        cols = idx.reshape(1, -1)
        ex_cov[rows, cols] = cov[rows, cols]

        # in the new covariance matrix, modes 1 and 2 have values given by
        # rows 1 and 0 respectively from cov2
        idx = np.array([1, 2, 5, 6])
        rows = idx.reshape(-1, 1)
        cols = idx.reshape(1, -1)

        idx = np.array([1, 0, 3, 2])
        rows2 = idx.reshape(-1, 1)
        cols2 = idx.reshape(1, -1)

        ex_cov[rows, cols] = cov2[rows2, cols2]

        assert np.allclose(state.means(),
                           np.array([ex_means[from_xp(4)]]) *
                           np.sqrt(hbar / 2),
                           atol=tol,
                           rtol=0)
        assert np.allclose(
            state.covs(),
            np.array([ex_cov[from_xp(4), :][:, from_xp(4)]]) * hbar / 2,
            atol=tol,
            rtol=0,
        )
Beispiel #17
0
    def test_incorrect_means_length(self, hbar):
        """Test that an exception is raised len(means)!=len(cov)"""
        cov = random_covariance(3, hbar=hbar)

        with pytest.raises(ValueError, match="must have the same length"):
            ops.Gaussian(cov, r=np.array([0]))