Beispiel #1
0
 def test_nonexistent_index(self, prog):
     """Acting on a non-existent mode raises an error."""
     with prog.context as q:
         with pytest.raises(IndexError):
             ops.Dgate(0.5) | q[3]
         with pytest.raises(program.RegRefError, match="does not exist"):
             ops.Dgate(0.5) | 3
Beispiel #2
0
    def test_deleted_index(self, prog):
        """Test that acting on a deleted mode raises an error"""
        with prog.context as q:
            ops.Del | q[0]
            with pytest.raises(program.RegRefError, match="been deleted"):
                ops.Dgate(0.5) | 0

            with pytest.raises(program.RegRefError, match="been deleted"):
                ops.Dgate(0.5) | q[0]
    def test_nonexistent(self):
        """Test that acting on a non-existent mode raises an error"""
        eng, q = sf.Engine(2)

        with eng:
            with pytest.raises(IndexError):
                ops.Dgate(0.5) | q[3]

            with pytest.raises(engine.RegRefError, match="does not exist"):
                ops.Dgate(0.5) | 3
Beispiel #4
0
    def test_print_commands(self, eng, prog):
        """Program.print and Engine.print_applied return correct strings."""
        prog = sf.Program(2)

        # store the result of the print command in list res
        res = []
        # use a print function that simply appends the operation
        # name to the results list
        print_fn = lambda x: res.append(x.__str__())

        # prog should now be empty
        prog.print(print_fn)
        assert res == []

        # define some gates
        D = ops.Dgate(0.5)
        BS = ops.BSgate(2 * np.pi, np.pi / 2)
        R = ops.Rgate(np.pi)

        with prog.context as q:
            alice, bob = q
            D | alice
            BS | (alice, bob)
            ops.Del | alice
            R | bob
            charlie, = ops.New(1)
            BS | (bob, charlie)
            ops.MeasureX | bob
            ops.Dgate(bob.par).H | charlie
            ops.Del | bob
            ops.MeasureX | charlie

        res = []
        prog.print(print_fn)

        expected = [
            "Dgate(0.5, 0) | (q[0])",
            "BSgate(6.283, 1.571) | (q[0], q[1])",
            "Del | (q[0])",
            "Rgate(3.142) | (q[1])",
            "New(1)",
            "BSgate(6.283, 1.571) | (q[1], q[2])",
            "MeasureX | (q[1])",
            "Dgate(q1, 0).H | (q[2])",
            "Del | (q[1])",
            "MeasureX | (q[2])",
        ]

        assert res == expected

        # NOTE optimization can change gate order
        result = eng.run(prog, compile_options={'optimize': False})
        res = []
        eng.print_applied(print_fn)
        assert res == ["Run 0:"] + expected
    def test_deleted(self):
        """Test that acting on a deleted mode raises an error"""
        eng, q = sf.Engine(2)

        with eng:
            ops.Del | q[0]
            with pytest.raises(engine.RegRefError, match="been deleted"):
                ops.Dgate(0.5) | 0

            with pytest.raises(engine.RegRefError, match="been deleted"):
                ops.Dgate(0.5) | q[0]
    def test_print_commands(self, backend):
        """Test print_queue and print_applied returns correct strings."""
        eng, q = sf.Engine(2)

        # define some gates
        D = ops.Dgate(0.5)
        BS = ops.BSgate(2 * np.pi, np.pi / 2)
        R = ops.Rgate(np.pi)

        # get register references
        alice, bob = q

        with eng:
            D | alice
            BS | (alice, bob)
            ops.Del | alice
            R | bob
            charlie, = ops.New(1)
            BS | (bob, charlie)
            ops.MeasureX | bob
            ops.Dgate(bob).H | charlie
            ops.Del | bob
            ops.MeasureX | charlie

        res = []
        print_fn = lambda x: res.append(x.__str__())
        eng.print_queue(print_fn)

        expected = [
            "Dgate(0.5, 0) | (q[0])",
            "BSgate(6.283, 1.571) | (q[0], q[1])",
            "Del | (q[0])",
            "Rgate(3.142) | (q[1])",
            "New(1) ",
            "BSgate(6.283, 1.571) | (q[1], q[2])",
            "MeasureX | (q[1])",
            "Dgate(RR(q[1]), 0).H | (q[2])",
            "Del | (q[1])",
            "MeasureX | (q[2])",
        ]

        assert res == expected
        state = eng.run(backend)

        # queue should now be empty
        res = []
        eng.print_queue(print_fn)
        assert res == []

        # print_applied should now not be empty
        res = []
        eng.print_applied(print_fn)
        assert res == ["Run 0:"] + expected
Beispiel #7
0
    def test_GBS_compile_nonconsec_measurefock(self):
        """Tests that GBS compilation fails when Fock measurements are made with an intervening gate."""
        prog = sf.Program(2)
        with prog.context as q:
            ops.Dgate(1.0) | q[0]
            ops.MeasureFock() | q[0]
            ops.Dgate(-1.0) | q[1]
            ops.BSgate(-0.5, 2.0) | q  # intervening gate
            ops.MeasureFock() | q[1]

        with pytest.raises(program.CircuitError, match="The Fock measurements are not consecutive."):
            prog.compile('gbs')
Beispiel #8
0
    def test_print_commands(self, eng, prog):
        """Program.print and Engine.print_applied return correct strings."""
        prog = sf.Program(2)
        res = []
        print_fn = lambda x: res.append(x.__str__())

        # prog should now be empty
        prog.print(print_fn)
        assert res == []

        # define some gates
        D = ops.Dgate(0.5)
        BS = ops.BSgate(2 * np.pi, np.pi / 2)
        R = ops.Rgate(np.pi)

        with prog.context as q:
            alice, bob = q
            D | alice
            BS | (alice, bob)
            ops.Del | alice
            R | bob
            charlie, = ops.New(1)
            BS | (bob, charlie)
            ops.MeasureX | bob
            ops.Dgate(bob).H | charlie
            ops.Del | bob
            ops.MeasureX | charlie

        res = []
        prog.print(print_fn)

        expected = [
            "Dgate(0.5, 0) | (q[0])",
            "BSgate(6.283, 1.571) | (q[0], q[1])",
            "Del | (q[0])",
            "Rgate(3.142) | (q[1])",
            "New(1)",
            "BSgate(6.283, 1.571) | (q[1], q[2])",
            "MeasureX | (q[1])",
            "Dgate(RR(q[1]), 0).H | (q[2])",
            "Del | (q[1])",
            "MeasureX | (q[2])",
        ]

        assert res == expected

        state = eng.run(
            prog, compile=False
        )  # FIXME optimization can change gate order, however this is not a good way of avoiding it
        res = []
        eng.print_applied(print_fn)
        assert res == ["Run 0:"] + expected
Beispiel #9
0
    def test_regref_transform(self, setup_eng):
        """Test circuit with regref transforms doesn't raise any errors"""
        eng, prog = setup_eng(2)

        with prog.context as q:
            ops.MeasureX | q[0]
            ops.Sgate(q[0]) | q[1]
            # symbolic hermitian conjugate together with register reference
            ops.Dgate(q[0]).H | q[1]
            ops.Sgate(ops.RR(q[0], lambda x: x ** 2)) | q[1]
            ops.Dgate(ops.RR(q[0], lambda x: -x)).H | q[1]

        eng.run(prog)
    def test_measured_parameter(self, setup_eng):
        """Test that a circuit with measured parameters executes successfully."""
        eng, prog = setup_eng(2)

        with prog.context as q:
            ops.MeasureX | q[0]
            ops.Sgate(q[0].par) | q[1]
            # symbolic hermitian conjugate together with register reference
            ops.Dgate(q[0].par, 0).H | q[1]
            # algebraic transformation
            ops.Sgate(q[0].par**2) | q[1]
            # algebraic transformation and h.c.
            ops.Dgate(q[0].par, np.pi).H | q[1]

        eng.run(prog)
 def test_invalid_measurement(self, eng, prog):
     """Cannot use a measurement before it exists."""
     with prog.context as q:
         ops.Dgate(q[0]) | q[1]
     with pytest.raises(program.CircuitError,
                        match="nonexistent measurement result"):
         eng.run(prog)
 def test_corrupt_index(self, prog):
     """User messes up the RegRef indices."""
     with prog.context as q:
         q[0].ind = 1
         with pytest.raises(program.RegRefError,
                            match="RegRef state has become inconsistent"):
             ops.Dgate(0.5) | q[0]
Beispiel #13
0
def test_free_parameters(setup_eng, tol):
    """Programs with free parameters."""

    eng, prog = setup_eng(1)
    x = prog.params("x")  # free parameter
    with prog.context as q:
        ops.Dgate(x) | q
        ops.Sgate(-1.2 * x * pf.sin(x**2 - 0.1)) | q

    with pytest.raises(ParameterError, match="Unknown free parameter"):
        eng.run(prog, args={"foo": 1.0})
    with pytest.raises(ParameterError,
                       match="unbound parameter with no default value"):
        eng.run(prog)

    # successful run
    eng.run(prog, args={x: 0.0})
    assert np.all(eng.backend.is_vacuum(tol))
    eng.reset()

    # now set a default value for the free parameter
    x.default = 0.0
    eng.run(prog)
    assert np.all(eng.backend.is_vacuum(tol))
    eng.reset()

    # override the default
    x.default = 1.0
    eng.run(prog, args={x: 0.0})
    assert np.all(eng.backend.is_vacuum(tol))
Beispiel #14
0
    def test_no_return_state(self, eng, prog):
        """Engine returns None when no state is requested"""
        with prog.context as q:
            ops.Dgate(0.34) | q[0]

        res = eng.run(prog, return_state=False)
        assert res is None
Beispiel #15
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)
Beispiel #16
0
    def test_apply_history(self, setup_eng, pure):
        """Tests the reapply history argument works correctly with a backend"""
        eng, q = setup_eng(2)

        a = 0.23
        r = 0.1

        def inspect():
            res = []
            print_fn = lambda x: res.append(x.__str__())
            eng.print_applied(print_fn)
            return res

        with eng:
            ops.Dgate(a) | q[0]
            ops.Sgate(r) | q[1]

        state1 = eng.run()
        expected = [
            "Run 0:",
            "Dgate({}, 0) | (q[0])".format(a),
            "Sgate({}, 0) | (q[1])".format(r),
        ]

        assert inspect() == expected

        # reset backend, but reapply history
        eng.backend.reset(pure=pure)
        state2 = eng.run(apply_history=True)
        assert inspect() == expected
        assert state1 == state2

        # append more commands to the same backend
        with eng:
            ops.Rgate(r) | q[0]

        state3 = eng.run()
        expected = [
            "Run 0:",
            "Dgate({}, 0) | (q[0])".format(a),
            "Sgate({}, 0) | (q[1])".format(r),
            "Run 1:",
            "Rgate({}) | (q[0])".format(r),
        ]

        assert inspect() == expected
        assert not state2 == state3

        # reset backend, but reapply history
        eng.backend.reset(pure=pure)
        state4 = eng.run(apply_history=True)
        expected = [
            "Run 0:",
            "Dgate({}, 0) | (q[0])".format(a),
            "Sgate({}, 0) | (q[1])".format(r),
            "Rgate({}) | (q[0])".format(r),
        ]

        assert inspect() == expected
        assert state3 == state4
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_merge_regrefs():
    """Test merging two gates with regref parameters."""
    prog = Program(2)
    with prog.context as q:
        ops.MeasureX | q[0]
        D = ops.Dgate(q[0])
        F = ops.Dgate(q[0], 0.1)

    # gates that are the inverse of each other
    merged = D.merge(D.H)
    assert merged is None

    # gates that have different parameters
    with pytest.raises(MergeFailure,
                       match="Don't know how to merge these gates."):
        F.merge(D.H)
    def test_coherent(self, a, setup_eng, hbar, tol):
        """Test coherent function matches Gaussian backends"""
        eng, prog = setup_eng(1)

        with prog.context as q:
            ops.Dgate(np.abs(a), np.angle(a)) | q[0]

        state = eng.run(prog).state

        mu, cov = utils.coherent_state(np.abs(a),
                                       np.angle(a),
                                       basis="gaussian",
                                       hbar=hbar)

        if eng.backend_name == "gassian":
            mu_exp, cov_exp = state.reduced_gaussian(0)
            assert np.allclose(mu, mu_exp, atol=tol, rtol=0)
            assert np.allclose(cov, cov_exp, atol=tol, rtol=0)

        elif eng.backend_name == "bosonic":
            _, mu_exp, cov_exp = state.reduced_bosonic(0)
            assert np.allclose(np.expand_dims(mu, axis=0),
                               mu_exp,
                               atol=tol,
                               rtol=0)
            assert np.allclose(np.expand_dims(cov, axis=0),
                               cov_exp,
                               atol=tol,
                               rtol=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):
            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)
    def test_displaced_squeezed(self, setup_eng, hbar, cutoff, bsize, pure,
                                tol):
        """Test displaced squeezed function matches Fock backends"""
        eng, prog = setup_eng(1)
        a = 0.32 + 0.1j
        r = 0.112
        phi = 0.123

        with prog.context as q:
            ops.Sgate(r, phi) | q[0]
            ops.Dgate(np.abs(a), np.angle(a)) | q[0]

        state = eng.run(prog).state
        ket = utils.displaced_squeezed_state(np.abs(a),
                                             np.angle(a),
                                             r,
                                             phi,
                                             basis="fock",
                                             fock_dim=cutoff,
                                             hbar=hbar)

        if not pure:
            expected = state.dm()
            ket = np.tile(np.outer(ket, ket.conj()), (bsize, 1, 1))
        else:
            expected = state.ket()
            ket = np.tile(ket, (bsize, 1))

        assert np.allclose(expected, ket, atol=tol, rtol=0)
Beispiel #22
0
    def test_program_subroutine(self, setup_eng, tol):
        """Simple quantum program with a subroutine and references."""
        eng, prog = setup_eng(2)

        # define some gates
        D = ops.Dgate(0.5)
        BS = ops.BSgate(0.7 * np.pi, np.pi / 2)
        R = ops.Rgate(np.pi / 3)
        def subroutine(a, b):
            """Subroutine for the quantum program"""
            R | a
            BS | (a, b)
            R.H | a

        # main program
        with prog.context as q:
            # get register references
            alice, bob = q
            ops.All(ops.Vacuum()) | (alice, bob)
            D | alice
            subroutine(alice, bob)
            BS | (alice, bob)
            subroutine(bob, alice)

        state = eng.run(prog).state

        # state norm must be invariant
        if isinstance(eng.backend, BaseFock):
            assert np.allclose(state.trace(), 1, atol=tol, rtol=0)
    def test_apply_gate(self):
        """Test successful gate application"""
        eng, _ = sf.Engine(2)

        with eng:
            ops.Dgate(0.5) | 0

        assert len(eng.cmd_queue) == 1
    def test_invalid(self):
        """cannot referring to a register with a non-integral or RegRef object"""
        eng, _ = sf.Engine(2)

        with eng:
            with pytest.raises(engine.RegRefError,
                               match="using integers and RegRefs"):
                ops.Dgate(0) | 1.2
    def test_wrong_engine(self):
        """Test that acting on a mode not belonging to the engine raises error"""
        eng, _ = sf.Engine(2)
        q_new = engine.RegRef(3)

        with eng:
            with pytest.raises(engine.RegRefError, match="Unknown RegRef."):
                ops.Dgate(0.5) | q_new
Beispiel #26
0
    def test_checkpoints(self, setup_eng, tol):
        """Test history checkpoints work when creating and deleting modes."""
        eng, q = setup_eng(2)
        alice, bob = q

        # define some gates
        D = ops.Dgate(0.5)
        BS = ops.BSgate(2 * np.pi, np.pi / 2)
        R = ops.Rgate(np.pi)

        with eng:
            D | alice
            BS | (alice, bob)
            ops.Del | alice
            R | bob
            charlie, = ops.New(1)
            BS | (bob, charlie)
            ops.MeasureX | bob
            ops.Del | bob
            D.H | charlie
            ops.MeasureX | charlie

        eng.optimize()
        state = eng.run()

        # state norm must be invariant
        if isinstance(eng.backend, BaseFock):
            assert np.allclose(state.trace(), 1, atol=tol, rtol=0)

        def check_reg(self, expected_n=None):
            """Compare Engine.register with the mode list returned by the backend.
            They should always be in agreement after Engine.run(), Engine.reset_queue()
            and Engine.reset().
            """
            rr = eng.register
            modes = eng.backend.get_modes()
            # number of elements
            assert len(rr) == len(modes)

            if expected_n is not None:
                assert len(rr) == expected_n

            # check indices match
            assert np.all([r.ind for r in rr] == modes)
            # activity
            assert np.all([r.active for r in rr])

        # check that reset() works
        check_reg(1)
        eng.reset()

        new_reg = eng.register
        # original number of modes
        assert len(new_reg) == len(q)

        # the regrefs are reset as well
        assert np.all([r.val is None for r in new_reg])
        check_reg(2)
    def test_wrong_index(self):
        """This should never happen!"""
        eng, q = sf.Engine(2)
        q[0].ind = 1

        with eng:
            with pytest.raises(engine.RegRefError,
                               match="Should never happen!"):
                ops.Dgate(0.5) | q[0]
def test_no_return_state(backend):
    """Tests that engine returns None when no state is requested"""
    eng, q = sf.Engine(2)

    with eng:
        ops.Dgate(0.34) | q[0]

    res = eng.run(backend, return_state=False)
    assert res is None
Beispiel #29
0
    def test_GBS_compile_no_fock_meas(self):
        """Tests that GBS compilation fails when no fock measurements are made."""
        prog = sf.Program(2)
        with prog.context as q:
            ops.Dgate(1.0) | q[0]
            ops.Sgate(-0.5) | q[1]

        with pytest.raises(program.CircuitError, match="GBS circuits must contain Fock measurements."):
            prog.compile('gbs')
Beispiel #30
0
    def test_apply_history(self, eng):
        """Tests the reapply history argument"""
        a = 0.23
        r = 0.1

        def inspect():
            res = []
            print_fn = lambda x: res.append(x.__str__())
            eng.print_applied(print_fn)
            return res

        p1 = sf.Program(2)
        with p1.context as q:
            ops.Dgate(a) | q[1]
            ops.Sgate(r) | q[1]

        eng.run(p1)
        expected = [
            "Run 0:",
            "Dgate({}, 0) | (q[1])".format(a),
            "Sgate({}, 0) | (q[1])".format(r),
        ]
        assert inspect() == expected

        # run the program again
        eng.reset()
        eng.run(p1)
        assert inspect() == expected

        # apply more commands to the same backend
        p2 = sf.Program(2)
        with p2.context as q:
            ops.Rgate(r) | q[1]

        eng.run(p2)
        expected = [
            "Run 0:",
            "Dgate({}, 0) | (q[1])".format(a),
            "Sgate({}, 0) | (q[1])".format(r),
            "Run 1:",
            "Rgate({}) | (q[1])".format(r),
        ]

        assert inspect() == expected

        # reapply history
        eng.reset()
        eng.run([p1, p2])
        #expected = [
        #    "Run 0:",
        #    "Dgate({}, 0) | (q[1])".format(a),
        #    "Sgate({}, 0) | (q[1])".format(r),
        #    "Rgate({}) | (q[1])".format(r),
        #]

        assert inspect() == expected