コード例 #1
0
    def test_not_bipartite(self, tol):
        """Test exception raised if the graph is not bipartite"""
        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]])

        with pytest.raises(ValueError,
                           match="does not represent a bipartite graph"):
            ops.BipartiteGraphEmbed(A)

        A = np.array([[0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 1,
                                           1], [0, 0, 0, 1, 1, 0],
                      [0, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0],
                      [1, 1, 0, 0, 0, 0]])

        with pytest.raises(ValueError,
                           match="does not represent a bipartite graph"):
            ops.BipartiteGraphEmbed(A)

        A = np.array([[0, 0, 1, 0, 1, 1], [0, 0, 0, 0, 1,
                                           1], [0, 0, 0, 1, 1, 0],
                      [0, 0, 1, 0, 0, 0], [1, 1, 1, 0, 0, 0],
                      [1, 1, 0, 0, 0, 0]])

        with pytest.raises(ValueError,
                           match="does not represent a bipartite graph"):
            ops.BipartiteGraphEmbed(A)
コード例 #2
0
def test_non_primitive_gates():
    """Tests that the compiler is able to compile a number of non-primitive Gaussian gates"""

    width = 6
    eng = sf.LocalEngine(backend="gaussian")
    eng1 = sf.LocalEngine(backend="gaussian")
    circuit = sf.Program(width)
    A = np.random.rand(width, width) + 1j * np.random.rand(width, width)
    A = A + A.T
    valsA = np.linalg.svd(A, compute_uv=False)
    A = A / 2 * np.max(valsA)
    B = np.random.rand(
        width // 2, width // 2) + 1j * np.random.rand(width // 2, width // 2)
    valsB = np.linalg.svd(B, compute_uv=False)
    B = B / 2 * valsB
    B = np.block([[0 * B, B], [B.T, 0 * B]])
    with circuit.context as q:
        ops.GraphEmbed(A) | q
        ops.BipartiteGraphEmbed(B) | q
        ops.Pgate(0.1) | q[1]
        ops.CXgate(0.2) | (q[0], q[1])
        ops.MZgate(0.4, 0.5) | (q[2], q[3])
        ops.Fourier | q[0]
        ops.Xgate(0.4) | q[1]
        ops.Zgate(0.5) | q[3]
    compiled_circuit = circuit.compile(compiler="gaussian_unitary")
    cv = eng.run(circuit).state.cov()
    mean = eng.run(circuit).state.means()

    cv1 = eng1.run(compiled_circuit).state.cov()
    mean1 = eng1.run(compiled_circuit).state.means()
    assert np.allclose(cv, cv1)
    assert np.allclose(mean, mean1)
コード例 #3
0
    def test_bipartite_graph_embed_edgeset(self, setup_eng, tol):
        """Test that embedding a bipartite edge set B
        results in the property Amat/A = c J, where c is a real constant,
        and J is the all ones matrix"""
        N = 6
        eng, prog = setup_eng(6)
        B = Abp[:N//2, N//2:]
        print(B)

        with prog.context as q:
            ops.BipartiteGraphEmbed(B, edges=True) | q

        state = eng.run(prog).state
        Amat = eng.backend.circuit.Amat()

        # check that the matrix Amat is constructed to be of the form
        # Amat = [[B^\dagger, 0], [0, B]]
        assert np.allclose(Amat[:N, :N], Amat[N:, N:].conj().T, atol=tol)
        assert np.allclose(Amat[:N, N:], np.zeros([N, N]), atol=tol)
        assert np.allclose(Amat[N:, :N], np.zeros([N, N]), atol=tol)

        # final Amat
        Amat = Amat[:N, :N]
        n = N // 2

        ratio = np.real_if_close(Amat[n:, :n] / B.T)
        ratio /= ratio[0, 0]
        assert np.allclose(ratio, np.ones([n, n]), atol=tol)
コード例 #4
0
    def test_decomposition(self, tol):
        """Test that a graph is correctly decomposed"""
        n = 3
        prog = sf.Program(2*n)

        A = np.zeros([2*n, 2*n])
        B = np.random.random([n, n])

        A[:n, n:] = B
        A += A.T

        sq, U, V = dec.bipartite_graph_embed(B)

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

        S = np.identity(4 * n)

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

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

            if isinstance(cmd.op, ops.S2gate):
                # check that the registers are i, i+n
                assert len(modes) == 2
                assert modes[1] == modes[0] + n

                r, phi = par_evaluate(cmd.op.p)
                assert -r in sq
                assert phi == 0

                S = _two_mode_squeezing(r, phi, modes, 2*n) @ S

            if isinstance(cmd.op, ops.Interferometer):
                # check that each unitary only applies to half the modes
                assert len(modes) == n
                assert modes in ([0, 1, 2], [3, 4, 5])

                # check matrix is unitary
                U1 = par_evaluate(cmd.op.p[0])
                assert np.allclose(U1 @ U1.conj().T, np.identity(n), atol=tol, rtol=0)

                if modes[0] == 0:
                    assert np.allclose(U1, U, atol=tol, rtol=0)
                else:
                    assert modes[0] == 3
                    assert np.allclose(U1, V, atol=tol, rtol=0)

                S_U = np.vstack(
                    [np.hstack([U1.real, -U1.imag]), np.hstack([U1.imag, U1.real])]
                )

                S = expand(S_U, modes, 2*n) @ S

        # the resulting covariance state
        cov = S @ S.T
        A_res = Amat(cov)[:2*n, :2*n]

        # 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] / B.T)
        ratio /= ratio[0, 0]

        assert np.allclose(ratio, np.ones([n, n]), atol=tol, rtol=0)