Example #1
0
    def test_missing_s2gates(self, chip, tol):
        """Test identity S2gates are inserted when some (but not all)
        S2gates are included."""
        prog = sf.Program(12)
        U = random_interferometer(6)

        with prog.context as q:
            ops.S2gate(SQ_AMPLITUDE) | (q[1], q[7])
            ops.S2gate(SQ_AMPLITUDE) | (q[3], q[9])
            ops.S2gate(SQ_AMPLITUDE) | (q[5], q[11])
            ops.Interferometer(U) | (q[0], q[1], q[2], q[3], q[4], q[5])
            ops.Interferometer(U) | (q[6], q[7], q[8], q[9], q[10], q[11])
            ops.MeasureFock() | q

        expected = sf.Program(12)

        with expected.context as q:
            ops.S2gate(0) | (q[0], q[6])
            ops.S2gate(SQ_AMPLITUDE) | (q[1], q[7])
            ops.S2gate(0) | (q[2], q[8])
            ops.S2gate(SQ_AMPLITUDE) | (q[3], q[9])
            ops.S2gate(0) | (q[4], q[10])
            ops.S2gate(SQ_AMPLITUDE) | (q[5], q[11])
            ops.Interferometer(U) | (q[0], q[1], q[2], q[3], q[4], q[5])
            ops.Interferometer(U) | (q[6], q[7], q[8], q[9], q[10], q[11])
            ops.MeasureFock() | q

        res = prog.compile(chip.short_name)
        expected = expected.compile(chip.short_name)
        assert program_equivalence(res, expected, atol=tol)
    def test_interferometers(self, tol):
        """Test interferometers correctly decompose to MZ gates"""
        prog = sf.Program(4)
        U = random_interferometer(2)

        with prog.context as q:
            ops.S2gate(0.5) | (q[0], q[2])
            ops.S2gate(0.5) | (q[1], q[3])
            ops.Interferometer(U) | (q[0], q[1])
            ops.Interferometer(U) | (q[2], q[3])
            ops.MeasureFock() | q

        res = prog.compile("chip0")

        expected = sf.Program(4)

        with expected.context as q:
            ops.S2gate(0.5, 0) | (q[0], q[2])
            ops.S2gate(0.5, 0) | (q[1], q[3])
            ops.Interferometer(U,
                               mesh="rectangular_symmetric",
                               drop_identity=False) | (q[0], q[1])
            ops.Interferometer(U,
                               mesh="rectangular_symmetric",
                               drop_identity=False) | (q[2], q[3])
            ops.MeasureFock() | q

        expected = expected.compile(DummyCircuit())

        assert program_equivalence(res, expected, atol=tol)
    def test_missing_s2gates(self, num_pairs, tol):
        """Test identity S2gates are inserted when some (but not all)
        S2gates are included."""
        prog = sf.Program(2 * num_pairs)
        U = random_interferometer(num_pairs)
        assert num_pairs > 3
        with prog.context as q:
            ops.S2gate(SQ_AMPLITUDE) | (q[1], q[num_pairs + 1])
            ops.S2gate(SQ_AMPLITUDE) | (q[3], q[num_pairs + 3])
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs))
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs, 2 * num_pairs))
            ops.MeasureFock() | q

        expected = sf.Program(2 * num_pairs)

        with expected.context as q:
            ops.S2gate(SQ_AMPLITUDE) | (q[1], q[num_pairs + 1])
            ops.S2gate(0) | (q[0], q[num_pairs + 0])
            ops.S2gate(SQ_AMPLITUDE) | (q[3], q[num_pairs + 3])
            ops.S2gate(0) | (q[2], q[num_pairs + 2])
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs))
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs, 2 * num_pairs))
            ops.MeasureFock() | q

        res = prog.compile("Xunitary")
        expected = expected.compile("Xunitary")
        assert program_equivalence(res, expected, atol=tol)
    def test_no_s2gates(self, num_pairs, tol):
        """Test identity S2gates are inserted when no S2gates
        are provided."""
        prog = sf.Program(2 * num_pairs)
        U = random_interferometer(num_pairs)

        with prog.context as q:
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs))
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs, 2 * num_pairs))
            ops.MeasureFock() | q

        expected = sf.Program(2 * num_pairs)

        with expected.context as q:
            for i in range(num_pairs):
                ops.S2gate(0) | (q[i], q[i + num_pairs])
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs))
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs, 2 * num_pairs))
            ops.MeasureFock() | q

        # with pytest.raises(CircuitError, match="There can be no operations before the S2gates."):
        res = prog.compile("Xunitary")
        # with pytest.raises(CircuitError, match="There can be no operations before the S2gates."):
        expected = expected.compile("Xunitary")
        assert program_equivalence(res, expected, atol=tol)
    def test_interferometers(self, num_pairs, tol):
        """Test that the compilation correctly decomposes the interferometer using
        the rectangular_symmetric mesh"""
        prog = sf.Program(2 * num_pairs)
        U = random_interferometer(num_pairs)

        with prog.context as q:
            for i in range(0, num_pairs):
                ops.S2gate(SQ_AMPLITUDE) | (q[i], q[i + num_pairs])
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs))
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs, 2 * num_pairs))
            ops.MeasureFock() | q

        res = prog.compile("Xunitary")

        expected = sf.Program(2 * num_pairs)

        with expected.context as q:
            for i in range(0, num_pairs):
                ops.S2gate(SQ_AMPLITUDE) | (q[i], q[i + num_pairs])
            ops.Interferometer(U, mesh="rectangular_symmetric", drop_identity=False) | tuple(
                q[i] for i in range(num_pairs)
            )
            ops.Interferometer(U, mesh="rectangular_symmetric", drop_identity=False) | tuple(
                q[i] for i in range(num_pairs, 2 * num_pairs)
            )
            ops.MeasureFock() | q

        expected = expected.compile(DummyCircuit())
        # Note that since DummyCircuit() has a hard coded limit of 8 modes we only check for this number
        assert program_equivalence(res, expected, atol=tol, compare_params=False)
Example #6
0
    def test_interferometers(self, tol):
        """Test that the compilation correctly decomposes the interferometer using
        the rectangular_symmetric mesh"""
        prog = sf.Program(8)
        U = random_interferometer(4)

        with prog.context as q:
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[0], q[4])
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[1], q[5])
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[2], q[6])
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[3], q[7])
            ops.Interferometer(U) | (q[0], q[1], q[2], q[3])
            ops.Interferometer(U) | (q[4], q[5], q[6], q[7])
            ops.MeasureFock() | q

        res = prog.compile("X8_01")

        expected = sf.Program(8)

        with expected.context as q:
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[0], q[4])
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[1], q[5])
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[2], q[6])
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[3], q[7])
            ops.Interferometer(U,
                               mesh="rectangular_symmetric",
                               drop_identity=False) | (q[0], q[1], q[2], q[3])
            ops.Interferometer(U,
                               mesh="rectangular_symmetric",
                               drop_identity=False) | (q[4], q[5], q[6], q[7])
            ops.MeasureFock() | q

        expected = expected.compile(DummyCircuit())

        assert program_equivalence(res, expected, atol=tol)
Example #7
0
    def test_no_s2gates(self, tol):
        """Test identity S2gates are inserted when no S2gates
        are provided."""
        prog = sf.Program(8)
        U = random_interferometer(4)

        with prog.context as q:
            ops.Interferometer(U) | (q[0], q[1], q[2], q[3])
            ops.Interferometer(U) | (q[4], q[5], q[6], q[7])
            ops.MeasureFock() | q

        expected = sf.Program(8)

        with expected.context as q:
            ops.S2gate(0) | (q[0], q[4])
            ops.S2gate(0) | (q[1], q[5])
            ops.S2gate(0) | (q[2], q[6])
            ops.S2gate(0) | (q[3], q[7])
            ops.Interferometer(U) | (q[0], q[1], q[2], q[3])
            ops.Interferometer(U) | (q[4], q[5], q[6], q[7])
            ops.MeasureFock() | q

        res = prog.compile("X8_01")
        expected = expected.compile("X8_01")
        assert program_equivalence(res, expected, atol=tol)
def test_modes_subset(depth):
    """Tests that the compiler recognizes which modes are not being modified and acts accordingly"""

    width = 10
    eng = sf.LocalEngine(backend="gaussian")
    eng1 = sf.LocalEngine(backend="gaussian")
    circuit = sf.Program(width)
    indices = (1, 4, 2, 6, 7)
    active_modes = len(indices)
    with circuit.context as q:
        for _ in range(depth):
            U, s, V, _ = random_params(active_modes, 2.0 / depth, 1.0)
            ops.Interferometer(U) | tuple(q[i] for i in indices)
            for i, index in enumerate(indices):
                ops.Sgate(s[i]) | q[index]
            ops.Interferometer(V) | tuple(q[i] for i in indices)
    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)
    assert len(compiled_circuit.circuit[0].reg) == 5
    indices = [compiled_circuit.circuit[0].reg[i].ind for i in range(5)]
    assert indices == sorted(list(indices))
Example #9
0
    def runJob(self, eng):
        num_subsystem = 8
        prog = sf.Program(num_subsystem, name="remote_job")
        U = random_interferometer(4)
        with prog.context as q:
            # Initial squeezed states
            # Allowed values are r=1.0 or r=0.0
            ops.S2gate(1.0) | (q[0], q[4])
            ops.S2gate(1.0) | (q[1], q[5])
            ops.S2gate(1.0) | (q[3], q[7])

            # Interferometer on the signal modes (0-3)
            ops.Interferometer(U) | (q[0], q[1], q[2], q[3])
            ops.BSgate(0.543, 0.123) | (q[2], q[0])
            ops.Rgate(0.453) | q[1]
            ops.MZgate(0.65, -0.54) | (q[2], q[3])

            # *Same* interferometer on the idler modes (4-7)
            ops.Interferometer(U) | (q[4], q[5], q[6], q[7])
            ops.BSgate(0.543, 0.123) | (q[6], q[4])
            ops.Rgate(0.453) | q[5]
            ops.MZgate(0.65, -0.54) | (q[6], q[7])

            ops.MeasureFock() | q


        eng = eng
        results =eng.run(prog, shots=10)
        # state = results.state
        # measurements = results.samples
        return results.samples
Example #10
0
    def test_no_s2gates(self, num_pairs, tol):
        """Test identity S2gates are inserted when no S2gates
        are provided."""
        prog = sf.Program(2 * num_pairs)
        U = random_interferometer(num_pairs)

        with prog.context as q:
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs))
            ops.Interferometer(U) | tuple(
                q[i] for i in range(num_pairs, 2 * num_pairs))
            ops.MeasureFock() | q

        expected = sf.Program(2 * num_pairs)

        with expected.context as q:
            for i in range(num_pairs):
                ops.S2gate(0) | (q[i], q[i + num_pairs])
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs))
            ops.Interferometer(U) | tuple(
                q[i] for i in range(num_pairs, 2 * num_pairs))
            ops.MeasureFock() | q

        res = prog.compile(compiler="Xcov")
        expected = expected.compile(compiler="Xcov")
        assert program_equivalence(res, expected, atol=tol)
Example #11
0
    def test_interferometers(self, chip, tol):
        """Test that the compilation correctly decomposes the interferometer using
        the rectangular_symmetric mesh"""
        prog = sf.Program(12)
        U = random_interferometer(6)

        with prog.context as q:
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[0], q[6])
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[1], q[7])
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[2], q[8])
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[3], q[9])
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[4], q[10])
            ops.S2gate(SQ_AMPLITUDE, 0) | (q[5], q[11])
            ops.Interferometer(U) | (q[0], q[1], q[2], q[3], q[4], q[5])
            ops.Interferometer(U) | (q[6], q[7], q[8], q[9], q[10], q[11])
            ops.MeasureFock() | q

        res = prog.compile(chip.short_name)

        expected = sf.Program(12)

        with expected.context as q:
            for i, j in np.arange(12).reshape(2, -1).T:
                ops.S2gate(SQ_AMPLITUDE, 0) | (q[i], q[j])

            ops.Interferometer(U, mesh="rectangular_symmetric", drop_identity=False) | (q[0], q[1], q[2], q[3], q[4], q[5])
            ops.Interferometer(U, mesh="rectangular_symmetric", drop_identity=False) | (q[6], q[7], q[8], q[9], q[10], q[11])
            ops.MeasureFock() | q

        expected = expected.compile(DummyCircuit())

        assert program_equivalence(res, expected, atol=tol)
Example #12
0
def test_all_passive_gates(hbar, tol):
    """test that all gates run and do not cause anything to crash"""

    eng = sf.LocalEngine(backend="gaussian")
    circuit = sf.Program(4)

    with circuit.context as q:
        for i in range(4):
            ops.Sgate(1, 0.3) | q[i]
        ops.Rgate(np.pi) | q[0]
        ops.PassiveChannel(np.ones((2, 2))) | (q[1], q[2])
        ops.LossChannel(0.9) | q[1]
        ops.MZgate(0.25 * np.pi, 0) | (q[2], q[3])
        ops.PassiveChannel(np.array([[0.83]])) | q[0]
        ops.sMZgate(0.11, -2.1) | (q[0], q[3])
        ops.Interferometer(np.array([[np.exp(1j * 2)]])) | q[1]
        ops.BSgate(0.8, 0.4) | (q[1], q[3])
        ops.Interferometer(0.5**0.5 * np.fft.fft(np.eye(2))) | (q[0], q[2])
        ops.PassiveChannel(0.1 * np.ones((3, 3))) | (q[3], q[1], q[0])

    cov = eng.run(circuit).state.cov()

    circuit = sf.Program(4)
    with circuit.context as q:
        ops.Rgate(np.pi) | q[0]
        ops.PassiveChannel(np.ones((2, 2))) | (q[1], q[2])
        ops.LossChannel(0.9) | q[1]
        ops.MZgate(0.25 * np.pi, 0) | (q[2], q[3])
        ops.PassiveChannel(np.array([[0.83]])) | q[0]
        ops.sMZgate(0.11, -2.1) | (q[0], q[3])
        ops.Interferometer(np.array([[np.exp(1j * 2)]])) | q[1]
        ops.BSgate(0.8, 0.4) | (q[1], q[3])
        ops.Interferometer(0.5**0.5 * np.fft.fft(np.eye(2))) | (q[0], q[2])
        ops.PassiveChannel(0.1 * np.ones((3, 3))) | (q[3], q[1], q[0])

    compiled_circuit = circuit.compile(compiler="passive")
    T = compiled_circuit.circuit[0].op.p[0]

    S_sq = np.eye(8, dtype=np.complex128)
    r = 1
    phi = 0.3
    for i in range(4):
        S_sq[i, i] = np.cosh(r) - np.sinh(r) * np.cos(phi)
        S_sq[i, i + 4] = -np.sinh(r) * np.sin(phi)
        S_sq[i + 4, i] = -np.sinh(r) * np.sin(phi)
        S_sq[i + 4, i + 4] = np.cosh(r) + np.sinh(r) * np.cos(phi)

    cov_sq = (hbar / 2) * S_sq @ S_sq.T
    mu = np.zeros(8)

    P = interferometer(T)
    L = (hbar / 2) * (np.eye(P.shape[0]) - P @ P.T)
    cov2 = P @ cov_sq @ P.T + L

    assert np.allclose(cov, cov2, atol=tol, rtol=0)
    def test_no_s2gates(self):
        """Test exceptions raised if no S2gates are present"""
        prog = sf.Program(4)
        U = random_interferometer(2)

        with prog.context as q:
            ops.Interferometer(U) | (q[0], q[1])
            ops.Interferometer(U) | (q[2], q[3])
            ops.MeasureFock() | q

        with pytest.raises(CircuitError, match="must start with two S2gates"):
            res = prog.compile("chip0")
 def test_not_all_modes_measured(self, num_pairs):
     """Test exceptions raised if not all modes are measured"""
     prog = sf.Program(2 * num_pairs)
     U = random_interferometer(num_pairs)
     with prog.context as q:
         for i in range(num_pairs):
             ops.S2gate(SQ_AMPLITUDE) | (q[i], q[i + num_pairs])
         ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs))
         ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs, 2 * num_pairs))
         ops.MeasureFock() | (q[0], q[num_pairs])
     with pytest.raises(CircuitError, match="All modes must be measured"):
         prog.compile("Xunitary")
Example #15
0
    def test_s2gate_repeated_modes(self):
        """Test exceptions raised if S2gates are repeated"""
        prog = sf.Program(8)
        U = random_interferometer(4)

        with prog.context as q:
            ops.S2gate(SQ_AMPLITUDE) | (q[0], q[4])
            ops.S2gate(SQ_AMPLITUDE) | (q[0], q[4])
            ops.Interferometer(U) | (q[0], q[1], q[2], q[3])
            ops.Interferometer(U) | (q[4], q[5], q[6], q[7])
            ops.MeasureFock() | q

        with pytest.raises(CircuitError, match="incompatible topology."):
            res = prog.compile("X8_01")
    def test_incorrect_s2gates(self):
        """Test exceptions raised if S2gates do not appear on correct modes"""
        prog = sf.Program(4)
        U = random_interferometer(2)

        with prog.context as q:
            ops.S2gate(0.5) | (q[0], q[2])
            ops.Interferometer(U) | (q[0], q[1])
            ops.Interferometer(U) | (q[2], q[3])
            ops.MeasureFock() | q

        with pytest.raises(CircuitError,
                           match="S2gates do not appear on the correct modes"):
            res = prog.compile("chip0")
    def test_not_all_modes_measured(self):
        """Test exceptions raised if not all modes are measured"""
        prog = sf.Program(4)
        U = random_interferometer(2)

        with prog.context as q:
            ops.S2gate(0.5) | (q[0], q[2])
            ops.S2gate(0.5) | (q[1], q[3])
            ops.Interferometer(U) | (q[0], q[1])
            ops.Interferometer(U) | (q[2], q[3])
            ops.MeasureFock() | (q[0], q[1])

        with pytest.raises(CircuitError, match="All modes must be measured"):
            res = prog.compile("chip0")
Example #18
0
    def test_s2gate_repeated_modes(self, chip):
        """Test exceptions raised if S2gates are repeated"""
        prog = sf.Program(12)
        U = random_interferometer(6)

        with prog.context as q:
            ops.S2gate(SQ_AMPLITUDE) | (q[0], q[6])
            ops.S2gate(SQ_AMPLITUDE) | (q[0], q[6])
            ops.Interferometer(U) | (q[0], q[1], q[2], q[3], q[4], q[5])
            ops.Interferometer(U) | (q[6], q[7], q[8], q[9], q[10], q[11])
            ops.MeasureFock() | q

        with pytest.raises(CircuitError, match="incompatible topology."):
            res = prog.compile(chip.short_name)
Example #19
0
    def test_merge(self, tol):
        """Test that two interferometers merge: U = U1 @ U2"""
        n = 3
        U1 = random_interferometer(n)
        U2 = random_interferometer(n)

        int1 = ops.Interferometer(U1)
        int1inv = ops.Interferometer(U1.conj().T)
        int2 = ops.Interferometer(U2)

        # an interferometer merged with its inverse is identity
        assert int1.merge(int1inv) is None

        # two merged unitaries are the same as their product
        assert np.allclose(int1.merge(int2).p[0].x, U2 @ U1, atol=tol, rtol=0)
    def test_s2gate_repeated_modes(self, num_pairs):
        """Test exceptions raised if S2gates are repeated"""
        prog = sf.Program(2 * num_pairs)
        U = random_interferometer(num_pairs)
        with prog.context as q:
            for i in range(num_pairs):
                ops.S2gate(SQ_AMPLITUDE) | (q[i], q[i + num_pairs])

            ops.S2gate(SQ_AMPLITUDE + 0.1) | (q[0], q[num_pairs])
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs))
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs, 2 * num_pairs))
            ops.MeasureFock() | q

        with pytest.raises(CircuitError, match=r"Incorrect squeezing val"):
            prog.compile("Xunitary")
    def test_incorrect_s2gate_modes(self, num_pairs):
        """Test exceptions raised if S2gates do not appear on correct modes"""
        prog = sf.Program(2 * num_pairs)
        U = random_interferometer(num_pairs)
        n_modes = 2 * num_pairs
        half_n_modes = n_modes // 2
        with prog.context as q:
            for i in range(num_pairs):
                ops.S2gate(SQ_AMPLITUDE) | (q[2 * i], q[2 * i + 1])
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs))
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs, 2 * num_pairs))
            ops.MeasureFock() | q

        with pytest.raises(CircuitError, match="S2gates do not appear on the correct modes."):
            res = prog.compile("Xunitary")
Example #22
0
    def test_decomposition(self, tol):
        """Test that an interferometer is correctly decomposed"""
        n = 3
        prog = sf.Program(n)
        U = random_interferometer(n)
        BS1, BS2, R = dec.clements(U)

        G = ops.Interferometer(U)
        cmds = G.decompose(prog.register)

        S = np.identity(2 * n)

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

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

            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

        # the resulting applied unitary
        X1 = S[:n, :n]
        P1 = S[n:, :n]
        U_applied = X1 + 1j * P1

        assert np.allclose(U, U_applied, atol=tol, rtol=0)
Example #23
0
    def test_not_all_modes_measured(self):
        """Test exceptions raised if not all modes are measured"""
        prog = sf.Program(8)
        U = random_interferometer(4)

        with prog.context as q:
            ops.S2gate(SQ_AMPLITUDE) | (q[0], q[4])
            ops.S2gate(SQ_AMPLITUDE) | (q[1], q[5])
            ops.S2gate(SQ_AMPLITUDE) | (q[2], q[6])
            ops.S2gate(SQ_AMPLITUDE) | (q[3], q[7])
            ops.Interferometer(U) | (q[0], q[1], q[2], q[3])
            ops.Interferometer(U) | (q[4], q[5], q[6], q[7])
            ops.MeasureFock() | (q[0], q[1])

        with pytest.raises(CircuitError, match="All modes must be measured"):
            res = prog.compile("X8_01")
    def test_unitaries_do_not_match(self, num_pairs):
        """Test exception raised if the unitary applied to modes [0, 1, 2, 3] is
        different to the unitary applied to modes [4, 5, 6, 7]"""
        prog = sf.Program(2 * num_pairs)
        U = random_interferometer(num_pairs)

        with prog.context as q:
            for i in range(0, num_pairs):
                ops.S2gate(SQ_AMPLITUDE) | (q[i], q[i + num_pairs])
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs))
            ops.Interferometer(U) | tuple(q[i] for i in range(num_pairs, 2 * num_pairs))
            ops.BSgate() | (q[2], q[3])
            ops.MeasureFock() | q

        with pytest.raises(CircuitError, match="The applied unitary on modes"):
            prog.compile("Xunitary")
Example #25
0
    def test_invalid_decompositions(self, monkeypatch):
        """Test that an exception is raised if the device spec
        requests a decomposition that doesn't exist"""

        class DummyDevice(DeviceSpecs):
            modes = None
            remote = False
            local = True
            interactive = True
            primitives = {'Rgate', 'Interferometer'}
            decompositions = {'Rgate': {}}

        dev = DummyDevice()

        prog = sf.Program(3)
        U = np.array([[0, 1], [1, 0]])

        with prog.context as q:
            ops.Rgate(0.6) | q[0]
            ops.Interferometer(U) | [q[0], q[1]]

        with monkeypatch.context() as m:
            # monkeypatch our DummyDevice into the
            # backend database
            db =  {'dummy': DummyDevice}
            m.setattr("strawberryfields.devicespecs.backend_specs", db)

            with pytest.raises(NotImplementedError, match="No decomposition available: Rgate"):
                new_prog = prog.compile(backend='dummy')
Example #26
0
    def test_no_decompositions(self, monkeypatch):
        """Test that no decompositions take
        place if the device doesn't support it."""
        class DummyDevice(DeviceSpecs):
            """A device with no decompositions"""
            modes = None
            remote = False
            local = True
            interactive = True
            primitives = {'S2gate', 'Interferometer'}
            decompositions = set()

        dev = DummyDevice()

        prog = sf.Program(3)
        U = np.array([[0, 1], [1, 0]])

        with prog.context as q:
            ops.S2gate(0.6) | [q[0], q[1]]
            ops.Interferometer(U) | [q[0], q[1]]

        with monkeypatch.context() as m:
            # monkeypatch our DummyDevice into the
            # backend database
            db = {'dummy': DummyDevice}
            m.setattr("strawberryfields.devicespecs.backend_specs", db)
            new_prog = prog.compile(backend='dummy')

        # check compiled program only has two gates
        assert len(new_prog) == 2

        # test gates are correct
        circuit = new_prog.circuit
        assert circuit[0].op.__class__.__name__ == "S2gate"
        assert circuit[1].op.__class__.__name__ == "Interferometer"
Example #27
0
    def test_incorrect_s2gate_params(self):
        """Test exceptions raised if S2gates have illegal parameters"""
        prog = sf.Program(8)
        U = random_interferometer(4)

        with prog.context as q:
            ops.S2gate(SQ_AMPLITUDE) | (q[0], q[4])
            ops.S2gate(0) | (q[1], q[5])
            ops.S2gate(SQ_AMPLITUDE) | (q[2], q[6])
            ops.S2gate(SQ_AMPLITUDE+0.1) | (q[3], q[7])
            ops.Interferometer(U) | (q[0], q[1], q[2], q[3])
            ops.Interferometer(U) | (q[4], q[5], q[6], q[7])
            ops.MeasureFock() | q

        with pytest.raises(CircuitError, match=r"Incorrect squeezing value\(s\) \(r, phi\)={\(1.1, 0.0\)}"):
            res = prog.compile("X8_01")
Example #28
0
    def test_no_decompositions(self):
        """Test that no decompositions take
        place if the circuit spec doesn't support it."""

        class DummyCircuit(CircuitSpecs):
            """A circuit spec with no decompositions"""
            modes = None
            remote = False
            local = True
            interactive = True
            primitives = {'S2gate', 'Interferometer'}
            decompositions = set()

        prog = sf.Program(3)
        U = np.array([[0, 1], [1, 0]])
        with prog.context as q:
            ops.S2gate(0.6) | [q[0], q[1]]
            ops.Interferometer(U) | [q[0], q[1]]

        new_prog = prog.compile(target=DummyCircuit())

        # check compiled program only has two gates
        assert len(new_prog) == 2

        # test gates are correct
        circuit = new_prog.circuit
        assert circuit[0].op.__class__.__name__ == "S2gate"
        assert circuit[1].op.__class__.__name__ == "Interferometer"
Example #29
0
    def test_decompositions(self):
        """Test that decompositions take
        place if the circuit spec requests it."""

        class DummyCircuit(CircuitSpecs):
            modes = None
            remote = False
            local = True
            interactive = True
            primitives = {'S2gate', 'Interferometer', 'BSgate', 'Sgate'}
            decompositions = {'S2gate': {}}

        prog = sf.Program(3)
        U = np.array([[0, 1], [1, 0]])
        with prog.context as q:
            ops.S2gate(0.6) | [q[0], q[1]]
            ops.Interferometer(U) | [q[0], q[1]]

        new_prog = prog.compile(target=DummyCircuit())

        # check compiled program now has 5 gates
        # the S2gate should decompose into two BS and two Sgates
        assert len(new_prog) == 5

        # test gates are correct
        circuit = new_prog.circuit
        assert circuit[0].op.__class__.__name__ == "BSgate"
        assert circuit[1].op.__class__.__name__ == "Sgate"
        assert circuit[2].op.__class__.__name__ == "Sgate"
        assert circuit[3].op.__class__.__name__ == "BSgate"
        assert circuit[4].op.__class__.__name__ == "Interferometer"
Example #30
0
    def test_nothing_happens_and_nothing_crashes(self):
        """Test that even a program that does nothing compiles correctly"""
        n_modes = 4
        squeezing_amplitudes = [0] * n_modes
        unitary = np.identity(n_modes)

        prog = sf.Program(n_modes * 2)

        with prog.context as q:
            for i in range(n_modes):
                ops.S2gate(squeezing_amplitudes[i]) | (q[i], q[i + n_modes])
            for qumodes in (q[:n_modes], q[n_modes:]):
                ops.Interferometer(unitary) | qumodes
            ops.MeasureFock() | q

        res = prog.compile(compiler="Xcov")

        # check that all squeezing is 0
        assert all(cmd.op.p[0] == 0 for cmd in res.circuit
                   if isinstance(cmd.op, ops.S2gate))

        # check that all phase shifts are 0
        assert all(cmd.op.p[0] == 0 for cmd in res.circuit
                   if isinstance(cmd.op, ops.Rgate))

        # check that all MZgate angles are pi
        assert all(cmd.op.p[0] == np.pi for cmd in res.circuit
                   if isinstance(cmd.op, ops.MZgate))