def layer(params, q):
    """CV quantum neural network layer acting on ``N`` modes.

    Args:
        params (list[float]): list of length ``2*(max(1, N-1) + N**2 + n)`` containing
            the number of parameters for the layer
        q (list[RegRef]): list of Strawberry Fields quantum registers the layer
            is to be applied to
    """
    N = len(q)
    M = int(N * (N - 1)) + max(1, N - 1)

    int1 = params[:M]
    s = params[M:M + N]
    int2 = params[M + N:2 * M + N]
    dr = params[2 * M + N:2 * M + 2 * N]
    dp = params[2 * M + 2 * N:2 * M + 3 * N]
    k = params[2 * M + 3 * N:2 * M + 4 * N]

    # begin layer
    interferometer(int1, q)

    for i in range(N):
        ops.Sgate(s[i]) | q[i]

    interferometer(int2, q)

    for i in range(N):
        ops.Dgate(dr[i], dp[i]) | q[i]
        ops.Kgate(k[i]) | q[i]
    def test_extract_arbitrary_unitary_one_mode(self, setup_eng, cutoff, tol):
        """Test that arbitrary unitary extraction works for 1 mode"""
        S = ops.Sgate(0.4, -1.2)
        D = ops.Dgate(2, 0.9)
        K = ops.Kgate(-1.5)

        # not a state but it doesn't matter
        initial_state = np.random.rand(cutoff) + 1j * np.random.rand(cutoff)

        eng_ref, p0 = setup_eng(1)
        with p0.context as q:
            ops.Ket(initial_state) | q

        prog = sf.Program(p0)
        with prog.context as q:
            S | q
            D | q
            K | q

        U = utils.extract_unitary(prog,
                                  cutoff_dim=cutoff,
                                  backend=eng_ref.backend_name)

        if isinstance(U, tf.Tensor):
            U = U.numpy()

        final_state = U @ initial_state

        expected_state = eng_ref.run([p0, prog]).state.ket()

        assert np.allclose(final_state, expected_state, atol=tol, rtol=0)
Exemplo n.º 3
0
    def test_extract_arbitrary_unitary_one_mode(self, setup_eng, cutoff, tol):
        """Test that arbitrary unitary extraction works for 1 mode"""
        S = ops.Sgate(0.4, -1.2)
        D = ops.Dgate(2, 0.9)
        K = ops.Kgate(-1.5)

        # not a state but it doesn't matter
        initial_state = np.random.rand(cutoff) + 1j * np.random.rand(cutoff)

        eng_ref, p0 = setup_eng(1)
        with p0.context as q:
            ops.Ket(initial_state) | q

        prog = sf.Program(p0)
        with prog.context as q:
            S | q
            D | q
            K | q

        U = utils.extract_unitary(prog,
                                  cutoff_dim=cutoff,
                                  backend=eng_ref.backend_name)

        if isinstance(U, tf.Tensor):
            with tf.Session() as sess:
                sess.run(tf.global_variables_initializer())
                in_state = tf.constant(initial_state.reshape([-1]),
                                       dtype=tf.complex64)
                final_state = sess.run(tf.einsum("ab,b", U, in_state))
        else:
            final_state = U @ initial_state

        expected_state = eng_ref.run([p0, prog]).ket()
        assert np.allclose(final_state, expected_state, atol=tol, rtol=0)
Exemplo n.º 4
0
    def test_invalid_primitive(self):
        """Test that an exception is raised if the program
        contains a primitive not allowed on the circuit spec.

        Here, we can simply use the guassian circuit spec and
        the Kerr gate as an existing example.
        """
        prog = sf.Program(3)
        with prog.context as q:
            ops.Kgate(0.6) | q[0]

        with pytest.raises(program.CircuitError, match="Kgate cannot be used with the target"):
            new_prog = prog.compile(target='gaussian')
    def test_one_mode_gates_from_operators(self, drawer):
        prog = sf.Program(3)

        with prog.context as q:
            ops.Xgate(1) | (q[0])
            ops.Zgate(1) | (q[0])
            ops.Kgate(1) | (q[0])
            ops.Vgate(1) | (q[0])
            ops.Pgate(1) | (q[0])
            ops.Rgate(1) | (q[0])
            ops.Sgate(1) | (q[0])
            ops.Dgate(1) | (q[0])

        for op in prog.circuit:
            method, mode = drawer._gate_from_operator(op)
            assert callable(method) and hasattr(drawer, method.__name__)
            assert mode == 1
    def test_one_mode_gates_from_operators(self, drawer):
        eng, q = sf.Engine(3)

        with eng:
            ops.Xgate(1) | (q[0])
            ops.Zgate(1) | (q[0])
            ops.Kgate(1) | (q[0])
            ops.Vgate(1) | (q[0])
            ops.Pgate(1) | (q[0])
            ops.Rgate(1) | (q[0])
            ops.Sgate(1) | (q[0])
            ops.Dgate(1) | (q[0])

        for op in eng.cmd_queue:
            method, mode = drawer._gate_from_operator(op)
            assert callable(method) and hasattr(drawer, method.__name__)
            assert mode == 1
    def test_extract_kerr(self, backend_name, cutoff, tol):
        """test that the Kerr gate is correctly extracted"""

        prog = sf.Program(1)
        kappa = 0.432
        with prog.context as q:
            ops.Kgate(kappa) | q

        U = utils.extract_unitary(prog,
                                  cutoff_dim=cutoff,
                                  backend=backend_name)
        expected = np.diag(np.exp(1j * kappa * np.arange(cutoff)**2))

        if isinstance(U, tf.Tensor):
            U = U.numpy()

        assert np.allclose(U, expected, atol=tol, rtol=0)
    def test_parse_op(self, drawer):
        prog = sf.Program(3)

        with prog.context as q:
            ops.Xgate(1) | (q[0])
            ops.Zgate(1) | (q[0])
            ops.CXgate(1) | (q[0], q[1])
            ops.CZgate(1) | (q[0], q[1])
            ops.BSgate(0, 1) | (q[0], q[1])
            ops.S2gate(0, 1) | (q[0], q[1])
            ops.CKgate(1) | (q[0], q[1])
            ops.Kgate(1) | (q[0])
            ops.Vgate(1) | (q[0])
            ops.Pgate(1) | (q[0])
            ops.Rgate(1) | (q[0])
            ops.Sgate(1) | (q[0])
            ops.Dgate(1) | (q[0])

        for op in prog.circuit:
            drawer.parse_op(op)

        expected_circuit_matrix = [
            [
                "\\gate{X}",
                "\\gate{Z}",
                "\\ctrl{1}",
                "\\ctrl{1}",
                "\\multigate{1}{BS}",
                "\\multigate{1}{S}",
                "\\ctrl{1}",
                "\\gate{K}",
                "\\gate{V}",
                "\\gate{P}",
                "\\gate{R}",
                "\\gate{S}",
                "\\gate{D}",
            ],
            ["\\qw"] * 2 +
            ["\\targ", "\\gate{Z}", "\\ghost{BS}", "\\ghost{S}", "\\gate{K}"] +
            ["\\qw"] * 6,
            ["\\qw"] * 13,
        ]

        assert drawer._circuit_matrix == expected_circuit_matrix
    def test_parse_op(self, drawer):
        eng, q = sf.Engine(3)

        with eng:
            ops.Xgate(1) | (q[0])
            ops.Zgate(1) | (q[0])
            ops.CXgate(1) | (q[0], q[1])
            ops.CZgate(1) | (q[0], q[1])
            ops.BSgate(0, 1) | (q[0], q[1])
            ops.S2gate(0, 1) | (q[0], q[1])
            ops.CKgate(1) | (q[0], q[1])
            ops.Kgate(1) | (q[0])
            ops.Vgate(1) | (q[0])
            ops.Pgate(1) | (q[0])
            ops.Rgate(1) | (q[0])
            ops.Sgate(1) | (q[0])
            ops.Dgate(1) | (q[0])

        for op in eng.cmd_queue:
            drawer.parse_op(op)

        expected_circuit_matrix = [
            [
                "\\gate{X}",
                "\\gate{Z}",
                "\\ctrl{1}",
                "\\ctrl{1}",
                "\\multigate{1}{BS}",
                "\\multigate{1}{S}",
                "\\ctrl{1}",
                "\\gate{K}",
                "\\gate{V}",
                "\\gate{P}",
                "\\gate{R}",
                "\\gate{S}",
                "\\gate{D}",
            ],
            ["\\qw"] * 2 +
            ["\\targ", "\\gate{Z}", "\\ghost{BS}", "\\ghost{S}", "\\gate{K}"] +
            ["\\qw"] * 6,
            ["\\qw"] * 13,
        ]

        assert drawer._circuit_matrix == expected_circuit_matrix
Exemplo n.º 10
0
    def test_k_1(self, tmpdir):
        prog = sf.Program(3)

        with prog.context as q:
            ops.Kgate(1) | (q[1])

        k_test_1_output = dedent(r"""            \documentclass{article}
            \usepackage{qcircuit}
            \begin{document}
            \Qcircuit {
             & \qw  & \qw \\
             & \gate{K}  & \qw \\
             & \qw  & \qw \\
            }
            \end{document}""")

        result = prog.draw_circuit(tex_dir=tmpdir)[1]
        assert result == k_test_1_output, failure_message(
            result, k_test_1_output)
    def test_k_1(self, tmpdir):
        eng, q = sf.Engine(3)

        with eng:
            ops.Kgate(1) | (q[1])

        k_test_1_output = dedent(r"""            \documentclass{article}
            \usepackage{qcircuit}
            \begin{document}
            \Qcircuit {
             & \qw  & \qw \\
             & \gate{K}  & \qw \\
             & \qw  & \qw \\
            }
            \end{document}""")

        result = eng.draw_circuit(print_queued_ops=True, tex_dir=tmpdir)[1]
        assert result == k_test_1_output, failure_message(
            result, k_test_1_output)
    def test_extract_kerr(self, setup_backend, cutoff, tol):
        """test that the Kerr gate is correctly extracted"""
        backend = setup_backend(1)
        eng, q = sf.Engine(1)

        kappa = 0.432

        with eng:
            ops.Kgate(kappa) | q

        U = utils.extract_unitary(eng,
                                  cutoff_dim=cutoff,
                                  backend=backend._short_name)
        expected = np.diag(np.exp(1j * kappa * np.arange(cutoff)**2))

        if isinstance(U, tf.Tensor):
            U = tf.Session().run(U)

        assert np.allclose(U, expected, atol=tol, rtol=0)
def test_complex(init):
    modes = 4
    cutoff_dim = 6

    initial_state = np.zeros([cutoff_dim] * modes, dtype=complex)
    # The ket below corresponds to a single photon going into each of the modes
    initial_state[init] = 1

    prog = sf.Program(modes)
    s_d_params = 0.01
    with prog.context as q:
        ops.Ket(initial_state) | q  # Initial state preparation
        # Gaussian Layer
        ops.S2gate(s_d_params, s_d_params) | (q[0], q[1])
        ops.BSgate(1.9, 1.7) | (q[1], q[2])
        ops.BSgate(0.9, 0.2) | (q[0], q[1])
        # Non-Gaussian Layer
        ops.Kgate(0.5) | q[3]
        ops.CKgate(0.7) | (q[2], q[3])
        # Gaussian Layer
        ops.BSgate(1.0, 0.4) | (q[0], q[1])
        ops.BSgate(2.0, 1.5) | (q[1], q[2])
        ops.Dgate(s_d_params) | q[0]
        ops.Dgate(s_d_params) | q[0]
        ops.Sgate(s_d_params, s_d_params) | q[1]
        # Non-Gaussian Layer
        ops.Vgate(0.5) | q[2]

    # We run the simulation
    eng = sf.Engine("fock", backend_options={"cutoff_dim": cutoff_dim})
    results_norm = eng.run(prog)
    prog_merged = prog.compile(compiler="gaussian_merge")
    results_merged = eng.run(prog_merged)
    ket = results_norm.state.ket()
    ket_merged = results_merged.state.ket()
    assert np.allclose(np.abs(np.sum(np.conj(ket) * ket_merged)), 1)