示例#1
0
    def test_decomposition_interferometer_with_zero(self, tol):
        """Test that an graph is correctly decomposed when the interferometer
        has one zero somewhere in the unitary matrix, which is the case for the
        adjacency matrix below"""
        n = 6
        prog = sf.Program(n)

        A = np.array(
            [
                [0, 1, 0, 0, 1, 1],
                [1, 0, 1, 0, 1, 1],
                [0, 1, 0, 1, 1, 0],
                [0, 0, 1, 0, 1, 0],
                [1, 1, 1, 1, 0, 1],
                [1, 1, 0, 0, 1, 0],
            ]
        )
        _, U = dec.graph_embed(A)
        assert not np.allclose(U, np.identity(n))

        G = ops.GraphEmbed(A)
        cmds = G.decompose(prog.register)
        last_op = cmds[-1].op
        param_val = last_op.p[0]

        assert isinstance(last_op, ops.Interferometer)
        assert last_op.ns == n
        assert np.allclose(param_val, U, atol=tol, rtol=0)
示例#2
0
    def test_decomposition(self, tol):
        """Test that an graph is correctly decomposed"""
        n = 3
        prog = sf.Program(n)

        A = np.random.random([n, n]) + 1j * np.random.random([n, n])
        A += A.T
        A -= np.trace(A) * np.identity(n) / n

        sq, U = dec.graph_embed(A)

        G = ops.GraphEmbed(A)
        cmds = G.decompose(prog.register)

        assert np.all(sq == G.sq)
        assert np.all(U == G.U)

        S = np.identity(2 * n)

        # calculating the resulting decomposed symplectic
        for cmd in cmds:
            # all operations should be BSgates, Rgates, or Sgates
            assert isinstance(
                cmd.op, (ops.Interferometer, ops.BSgate, ops.Rgate, ops.Sgate)
            )

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

            if isinstance(cmd.op, ops.Sgate):
                S = _squeezing(cmd.op.p[0], cmd.op.p[1], modes, n) @ S

            if isinstance(cmd.op, ops.Rgate):
                S = _rotation(cmd.op.p[0], modes, n) @ S

            if isinstance(cmd.op, ops.BSgate):
                S = _beamsplitter(cmd.op.p[0], cmd.op.p[1], modes, n) @ S

            if isinstance(cmd.op, ops.Interferometer):
                U1 = cmd.op.p[0]
                S_U = np.vstack(
                    [np.hstack([U1.real, -U1.imag]), np.hstack([U1.imag, U1.real])]
                )
                S = S_U @ S

        # the resulting covariance state
        cov = S @ S.T

        # calculate Hamilton's A matrix: A = X.(I-Q^{-1})*
        A_res = np.real_if_close(Amat(cov))

        # The bottom right corner of A_res should be identical to A,
        # up to some constant scaling factor. Check if the ratio
        # of all elements is one
        ratio = np.real_if_close(A_res[n:, n:] / A)
        ratio /= ratio[0, 0]

        assert np.allclose(ratio, np.ones([n, n]), atol=tol, rtol=0)
    def test_mean_photon(self, tol):
        """Test that the mean photon number is correct in graph_embed"""
        num_modes = 6
        A = np.random.random([num_modes, num_modes]) + 1j * np.random.random([num_modes, num_modes])
        A += A.T
        n_mean = 10.0 / num_modes
        sc, _ = dec.graph_embed(A, mean_photon_per_mode=n_mean)
        n_mean_calc = np.mean(np.sinh(sc) ** 2)

        assert np.allclose(n_mean, n_mean_calc, atol=tol, rtol=0)
    def test_mean_photon(self, tol):
        """This test verifies that the maximum amount of squeezing used to encode
        the graph is indeed capped by the parameter max_mean_photon"""
        max_mean_photon = 2
        A = np.random.random([6, 6]) + 1j * np.random.random([6, 6])
        A += A.T
        sc, _ = dec.graph_embed(A, max_mean_photon=max_mean_photon)
        res_mean_photon = np.sinh(np.max(np.abs(sc)))**2

        assert np.allclose(res_mean_photon, max_mean_photon, atol=tol, rtol=0)
示例#5
0
    def test_takagi_fixed_random_symm(self):
        """This test verifies that the maximum amount of squeezing used to encode the graph is indeed capped by the parameter max_mean_photon"""
        self.logTestName()
        error = np.empty(nsamples)
        max_mean_photon = 2
        for i in range(nsamples):
            X = random_degenerate_symmetric()
            sc, U = dec.graph_embed(X, max_mean_photon=max_mean_photon)
            error[i] = np.sinh(np.max(np.abs(sc)))**2 - max_mean_photon

        self.assertAlmostEqual(error.mean(), 0, delta=self.tol)
    def test_make_traceless(self, monkeypatch, tol):
        """Test that A is properly made traceless"""
        A = np.random.random([6, 6]) + 1j * np.random.random([6, 6])
        A += A.T

        assert not np.allclose(np.trace(A), 0, atol=tol, rtol=0)

        with monkeypatch.context() as m:
            # monkeypatch the takagi function to simply return A,
            # so that we can inspect it and make sure it is now traceless
            m.setattr(dec, "takagi", lambda A, tol: (np.ones([6]), A))
            _, A_out = dec.graph_embed(A, make_traceless=True)

        assert np.allclose(np.trace(A_out), 0, atol=tol, rtol=0)
示例#7
0
    def test_decomposition(self, hbar, tol):
        """Test that an graph is correctly decomposed"""
        n = 3
        prog = sf.Program(n)

        A = np.random.random([n, n]) + 1j * np.random.random([n, n])
        A += A.T
        A -= np.trace(A) * np.identity(n) / 3

        sq, U = dec.graph_embed(A)

        G = ops.GraphEmbed(A)
        cmds = G.decompose(prog.register)

        assert np.all(sq == G.sq)
        assert np.all(U == G.U)

        S = np.identity(2 * n)

        # calculating the resulting decomposed symplectic
        for cmd in cmds:
            # all operations should be BSgates, Rgates, or Sgates
            assert isinstance(
                cmd.op, (ops.Interferometer, ops.BSgate, ops.Rgate, ops.Sgate))

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

            if isinstance(cmd.op, ops.Sgate):
                S = _squeezing(cmd.op.p[0].x, cmd.op.p[1].x, modes, n) @ S

            if isinstance(cmd.op, ops.Rgate):
                S = _rotation(cmd.op.p[0].x, modes, n) @ S

            if isinstance(cmd.op, ops.BSgate):
                S = _beamsplitter(cmd.op.p[0].x, cmd.op.p[1].x, modes, n) @ S

            if isinstance(cmd.op, ops.Interferometer):
                U1 = cmd.op.p[0].x
                S_U = np.vstack([
                    np.hstack([U1.real, -U1.imag]),
                    np.hstack([U1.imag, U1.real])
                ])
                S = S_U @ S

        # the resulting covariance state
        cov = S @ S.T

        # calculate Hamilton's A matrix: A = X.(I-Q^{-1})*
        I = np.identity(n)
        O = np.zeros_like(I)
        X = np.block([[O, I], [I, O]])

        x = cov[:n, :n]
        xp = cov[:n, n:]
        p = cov[n:, n:]

        aidaj = (x + p + 1j * (xp - xp.T) - 2 * I) / 4
        aiaj = (x - p + 1j * (xp + xp.T)) / 4

        Q = np.block([[aidaj, aiaj.conj()], [aiaj, aidaj.conj()]
                      ]) + np.identity(2 * n)

        A_res = X @ (np.identity(2 * n) - np.linalg.inv(Q)).conj()

        # The bottom right corner of A_res should be identical to A,
        # up to some constant scaling factor. Check if the ratio
        # of all elements is one
        ratio = np.real_if_close(A_res[n:, n:] / A)
        ratio /= ratio[0, 0]

        assert np.allclose(ratio, np.ones([n, n]), atol=tol, rtol=0)
 def test_symmetric_validation(self):
     """Test that the graph_embed decomposition raises exception if not symmetric"""
     A = np.random.random([5, 5]) + 1j * np.random.random([5, 5])
     with pytest.raises(ValueError, match="matrix is not symmetric"):
         dec.graph_embed(A)